diff --git a/package-lock.json b/package-lock.json index 646ae0f..ea04592 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "pinia": "^2.0.32", "pinia-persistedstate-plugin": "^0.1.0", "pinia-plugin-persistedstate": "^3.1.0", + "swiper": "^12.1.3", "vue": "^3.2.47", "vue-i18n": "^11.2.8", "vue-router": "^4.1.6" @@ -7611,6 +7612,25 @@ "node": ">= 10" } }, + "node_modules/swiper": { + "version": "12.1.3", + "resolved": "https://registry.npmmirror.com/swiper/-/swiper-12.1.3.tgz", + "integrity": "sha512-XcWlVmkHFICI4fuoJKgbp8PscDcS4i7pBH8nwJRBi3dpQvhCySwsWRYm4bOf/BzKVWkHOYaFw7qz9uBSrY3oug==", + "funding": [ + { + "type": "patreon", + "url": "https://www.patreon.com/swiperjs" + }, + { + "type": "open_collective", + "url": "http://opencollective.com/swiper" + } + ], + "license": "MIT", + "engines": { + "node": ">= 4.7.0" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmmirror.com/text-table/-/text-table-0.2.0.tgz", @@ -14245,6 +14265,11 @@ } } }, + "swiper": { + "version": "12.1.3", + "resolved": "https://registry.npmmirror.com/swiper/-/swiper-12.1.3.tgz", + "integrity": "sha512-XcWlVmkHFICI4fuoJKgbp8PscDcS4i7pBH8nwJRBi3dpQvhCySwsWRYm4bOf/BzKVWkHOYaFw7qz9uBSrY3oug==" + }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmmirror.com/text-table/-/text-table-0.2.0.tgz", diff --git a/package.json b/package.json index 7af1ef2..67c6294 100644 --- a/package.json +++ b/package.json @@ -17,14 +17,15 @@ "crypto-js": "^4.2.0", "element-plus": "^2.13.2", "gsap": "^3.13.0", - "vue-i18n": "^11.2.8", "markdown-it": "^14.1.0", "md5": "^2.3.0", "normalize.css": "^8.0.1", "pinia": "^2.0.32", "pinia-persistedstate-plugin": "^0.1.0", "pinia-plugin-persistedstate": "^3.1.0", + "swiper": "^12.1.3", "vue": "^3.2.47", + "vue-i18n": "^11.2.8", "vue-router": "^4.1.6" }, "devDependencies": { @@ -57,4 +58,4 @@ "npm run lint" ] } -} \ No newline at end of file +} diff --git a/src/App.vue b/src/App.vue index f693f9f..9280810 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,16 +1,34 @@ \ No newline at end of file diff --git a/src/components/Footer.vue b/src/components/Footer.vue new file mode 100644 index 0000000..9f693f5 --- /dev/null +++ b/src/components/Footer.vue @@ -0,0 +1,62 @@ + + + + + diff --git a/src/components/input-code.vue b/src/components/input-code.vue new file mode 100644 index 0000000..b353073 --- /dev/null +++ b/src/components/input-code.vue @@ -0,0 +1,109 @@ + + + + + diff --git a/src/lang/en.ts b/src/lang/en.ts index a0b49e0..42fe27c 100644 --- a/src/lang/en.ts +++ b/src/lang/en.ts @@ -2,5 +2,40 @@ export default { Login: { login: 'Log in', register: 'Register', - } + loginTo: 'Log on to FiDA', + loginTitle: 'A multi-agent canvas for rapid, trend driven design iteration.', + name: 'Name', + email: 'Email', + password: 'Password', + enterName: 'Enter your name', + enterEmail: 'Enter your email', + enterPassword: 'Enter your password', + forgotPassword: 'Forget password?', + pleaseInputName: 'Please input the name', + nameLengthError: 'Name length must be between {min} and {max} characters', + passwordSpecial: 'Must contain special characters', + passwordCase: 'Mix of uppercase, lowercase and numbers', + pleaseInputEmail: 'Please input the email', + emailFormatError: 'Please input the email again', + pleaseInputPassword: 'Please input the password', + passwordLengthError: 'Password length must be between {min} and {max} characters', + pleaseTermsPolicy: 'Please agree to the Terms, Policy and Fees', + agreeTermsPolicy: + 'I agree to the Terms, Policy and Fees.', + noAccountToSignUp: `Don't have an account? Sign up`, + signUpFor: 'Sign up for FiDA', + registerTip: 'A multi-agent canvas for rapid, trend driven design iteration.', + havenAccountToLogin: `Already have an account? Log in`, + verifyEmail: 'Verify your email address', + verifyCodeHasSent: 'A verification code has been sent to
{email}', + verify: 'Verify', + resendCode: 'Resend Code', + resendCodeIn: 'Resend Code in {time}', + orContinueWith: 'or continue with', + googleLogin: 'Sign in with Google', + wechatLogin: 'Sign in with Wechat', + indexTip: 'A multi-agent canvas for rapid, trend driven design iteration.', + sendCodeError: 'Send code error', + retrievePassword: 'Retrieve password' + }, } diff --git a/src/lang/zh-cn.ts b/src/lang/zh-cn.ts index a3dc01a..1afe79a 100644 --- a/src/lang/zh-cn.ts +++ b/src/lang/zh-cn.ts @@ -2,5 +2,41 @@ export default { Login: { login: '登录', register: '注册', - } + signUp: '注册', + loginTo: '登录到 FiDA条款、政策 和费用。', + noAccountToSignUp: `还没有账号? 注册`, + signUpFor: '注册账号', + registerTip: '一个多智能体画布,用于快速、趋势驱动的设计迭代。', + havenAccountToLogin: `已经有账号? 登录`, + verifyEmail: '验证您的邮箱地址', + verifyCodeHasSent: '已发送验证码到
{email}', + verifyCode: '请输入验证码', + verify: '验证', + resendCode: '重新发送验证码', + resendCodeIn: '重新发送验证码倒计时 {time}', + orContinueWith: '或者使用', + googleLogin: '使用 Google 登录', + wechatLogin: '使用微信登录', + indexTip: '一个多智能体画布,用于快速、趋势驱动的设计迭代。', + sendCodeError: '发送验证码失败', + retrievePassword: '找回密码' + }, } diff --git a/src/router/index.ts b/src/router/index.ts index 77bf7f4..08508be 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -41,6 +41,30 @@ const router = createRouter({ component: () => import('../views/404.vue') } ] + history: createWebHistory('/'), + // history: createWebHistory(import.meta.env.VITE_APP_URL), + routes: [ + { + path: '/', + name: 'home', + component: () => import('../views/home/index.vue'), + }, + { + path: '/collectionStory', + name: 'collectionStory', + component: () => import('../views/collectionStory/index.vue'), + }, + { + path: '/brand', + name: 'brand', + component: () => import('../views/brand/index.vue'), + }, + { + path: '/:pathMatch(.*)', + name: '404', + component: () => import('../views/404.vue'), + }, + ] }) router.beforeEach((to, from, next) => { diff --git a/src/utils/tools.ts b/src/utils/tools.ts index eac100e..69403ed 100644 --- a/src/utils/tools.ts +++ b/src/utils/tools.ts @@ -183,4 +183,15 @@ export async function shareImageToWhatsapp (url: string){ const whatsappLink = `https://api.whatsapp.com/send/?text=${encodeURIComponent(message)}` window.open(whatsappLink, '_blank') } -} \ No newline at end of file +} + +/** + * 倒计时 + * @param time 倒计时时间,单位秒 + * @returns 倒计时字符串,格式为 mm:ss +*/ +export function CountDown(time: number) { + const mm = String(Math.floor(time / 60)).padStart(2, '0'); + const ss = String(time % 60).padStart(2, '0'); + return `${mm}:${ss}`; +} diff --git a/src/views/brand/commodity-list.vue b/src/views/brand/commodity-list.vue new file mode 100644 index 0000000..012e2da --- /dev/null +++ b/src/views/brand/commodity-list.vue @@ -0,0 +1,169 @@ + + + \ No newline at end of file diff --git a/src/views/brand/index.vue b/src/views/brand/index.vue new file mode 100644 index 0000000..9e2999d --- /dev/null +++ b/src/views/brand/index.vue @@ -0,0 +1,72 @@ + + + \ No newline at end of file diff --git a/src/views/brand/merchant-info.vue b/src/views/brand/merchant-info.vue new file mode 100644 index 0000000..674b516 --- /dev/null +++ b/src/views/brand/merchant-info.vue @@ -0,0 +1,129 @@ + + + \ No newline at end of file diff --git a/src/views/collectionStory/detail/coreConcept.vue b/src/views/collectionStory/detail/coreConcept.vue new file mode 100644 index 0000000..807180e --- /dev/null +++ b/src/views/collectionStory/detail/coreConcept.vue @@ -0,0 +1,142 @@ + + + \ No newline at end of file diff --git a/src/views/collectionStory/detail/feelingWithAiDA.vue b/src/views/collectionStory/detail/feelingWithAiDA.vue new file mode 100644 index 0000000..e0686d8 --- /dev/null +++ b/src/views/collectionStory/detail/feelingWithAiDA.vue @@ -0,0 +1,85 @@ + + + \ No newline at end of file diff --git a/src/views/collectionStory/detail/index.vue b/src/views/collectionStory/detail/index.vue new file mode 100644 index 0000000..9633a5f --- /dev/null +++ b/src/views/collectionStory/detail/index.vue @@ -0,0 +1,142 @@ + + + \ No newline at end of file diff --git a/src/views/collectionStory/detail/inspiration.vue b/src/views/collectionStory/detail/inspiration.vue new file mode 100644 index 0000000..158fe4d --- /dev/null +++ b/src/views/collectionStory/detail/inspiration.vue @@ -0,0 +1,87 @@ + + + \ No newline at end of file diff --git a/src/views/collectionStory/index.vue b/src/views/collectionStory/index.vue index e29ef80..3fc0a59 100644 --- a/src/views/collectionStory/index.vue +++ b/src/views/collectionStory/index.vue @@ -1,11 +1,13 @@ \ No newline at end of file diff --git a/src/views/home/index.vue b/src/views/home/index.vue index 6788ffc..872f9be 100644 --- a/src/views/home/index.vue +++ b/src/views/home/index.vue @@ -1,18 +1,22 @@ diff --git a/src/views/home/section-designers.vue b/src/views/home/section-designers.vue new file mode 100644 index 0000000..fae0680 --- /dev/null +++ b/src/views/home/section-designers.vue @@ -0,0 +1,130 @@ + + + + + diff --git a/src/views/home/section-digital-items1.vue b/src/views/home/section-digital-items1.vue new file mode 100644 index 0000000..e84a307 --- /dev/null +++ b/src/views/home/section-digital-items1.vue @@ -0,0 +1,101 @@ + + + + + diff --git a/src/views/home/section-digital-items2.vue b/src/views/home/section-digital-items2.vue new file mode 100644 index 0000000..83e7c51 --- /dev/null +++ b/src/views/home/section-digital-items2.vue @@ -0,0 +1,94 @@ + + + + + diff --git a/src/views/home/section-footer.vue b/src/views/home/section-footer.vue new file mode 100644 index 0000000..6605cc8 --- /dev/null +++ b/src/views/home/section-footer.vue @@ -0,0 +1,157 @@ + + + + + diff --git a/src/views/home/section-index.vue b/src/views/home/section-index.vue new file mode 100644 index 0000000..16ddfc0 --- /dev/null +++ b/src/views/home/section-index.vue @@ -0,0 +1,75 @@ + + + + + diff --git a/src/views/login/css/style.css b/src/views/login/css/style.css new file mode 100644 index 0000000..d2a446c --- /dev/null +++ b/src/views/login/css/style.css @@ -0,0 +1,130 @@ +.retrieve-password, +.register, +.login { + width: 100%; + display: flex; + flex-direction: column; + align-items: center; + margin-top: 2rem; +} +.retrieve-password:deep(.el-form), +.register:deep(.el-form), +.login:deep(.el-form) { + width: 100%; +} +.retrieve-password:deep(.el-form) .el-form-item, +.register:deep(.el-form) .el-form-item, +.login:deep(.el-form) .el-form-item { + position: relative; + margin-bottom: 1.6rem; +} +.retrieve-password:deep(.el-form) .el-form-item__content, +.register:deep(.el-form) .el-form-item__content, +.login:deep(.el-form) .el-form-item__content { + position: relative; +} +.retrieve-password:deep(.el-form) .el-form-item__label, +.register:deep(.el-form) .el-form-item__label, +.login:deep(.el-form) .el-form-item__label { + color: #232323; + font-size: 1.2rem; + margin-bottom: 0.8rem; + line-height: 1.5rem; +} +.retrieve-password:deep(.el-form) .el-input, +.register:deep(.el-form) .el-input, +.login:deep(.el-form) .el-input { + --el-input-height: 3.4rem; + --el-input-border-radius: 0; + --el-input-text-color: #232323; + --el-border-color: #C4C4C4; + font-size: 1.4rem; +} +.retrieve-password:deep(.el-form) .el-input::placeholder, +.register:deep(.el-form) .el-input::placeholder, +.login:deep(.el-form) .el-input::placeholder { + color: #9F9F9F; +} +.retrieve-password:deep(.el-form) .password-tip, +.register:deep(.el-form) .password-tip, +.login:deep(.el-form) .password-tip { + position: absolute; + z-index: 10; + top: -1rem; + right: 0; + transform: translateY(-100%); +} +.retrieve-password:deep(.el-form) .password-warning, +.register:deep(.el-form) .password-warning, +.login:deep(.el-form) .password-warning { + --el-checkbox-height: auto; + margin-top: -0.6rem; + margin-bottom: 1.6rem; + display: flex; + align-items: center; +} +.retrieve-password:deep(.el-form) .password-warning > .icon, +.register:deep(.el-form) .password-warning > .icon, +.login:deep(.el-form) .password-warning > .icon { + width: 1.4rem; + height: 1.4rem; + margin-right: 0.8rem; +} +.retrieve-password:deep(.el-form) .password-warning > .label, +.register:deep(.el-form) .password-warning > .label, +.login:deep(.el-form) .password-warning > .label { + font-family: KaiseiOpti-Regular; + font-size: 1rem; + color: #9F9F9F; +} +.retrieve-password:deep(.el-form) .forgotPassword, +.register:deep(.el-form) .forgotPassword, +.login:deep(.el-form) .forgotPassword { + margin-top: -0.8rem; + margin-bottom: 5rem; + font-size: 1.1rem; + text-align: right; + color: #666666; + cursor: pointer; + text-decoration: underline; + font-family: KaiseiOpti-Regular; +} +.retrieve-password:deep(.el-form) .el-form-item__error, +.register:deep(.el-form) .el-form-item__error, +.login:deep(.el-form) .el-form-item__error { + padding-top: 1px; + font-size: 1rem; +} +.retrieve-password:deep(.el-form) .submit, +.register:deep(.el-form) .submit, +.login:deep(.el-form) .submit { + width: 100%; + height: 4rem; + font-size: 1.36rem; +} +.retrieve-password:deep(.el-form) .privacy, +.register:deep(.el-form) .privacy, +.login:deep(.el-form) .privacy { + margin-top: -0.6rem; + --el-checkbox-height: auto; +} +.retrieve-password:deep(.el-form) .privacy .el-checkbox__label, +.register:deep(.el-form) .privacy .el-checkbox__label, +.login:deep(.el-form) .privacy .el-checkbox__label { + font-size: 1.1rem; + color: #666666; + font-family: KaiseiOpti-Regular; +} +.retrieve-password:deep(.el-form) .privacy .el-checkbox__label > div > span, +.register:deep(.el-form) .privacy .el-checkbox__label > div > span, +.login:deep(.el-form) .privacy .el-checkbox__label > div > span { + font-family: KaiseiOpti-Bold; + text-decoration: underline; + cursor: pointer; + color: #232323; +} +.retrieve-password > .other-login, +.register > .other-login, +.login > .other-login { + margin-top: 4rem; +} diff --git a/src/views/login/email-verify.vue b/src/views/login/email-verify.vue new file mode 100644 index 0000000..e402574 --- /dev/null +++ b/src/views/login/email-verify.vue @@ -0,0 +1,143 @@ + + + + + diff --git a/src/views/login/index.vue b/src/views/login/index.vue new file mode 100644 index 0000000..b6df949 --- /dev/null +++ b/src/views/login/index.vue @@ -0,0 +1,117 @@ + + + + + diff --git a/src/views/login/less/style.less b/src/views/login/less/style.less new file mode 100644 index 0000000..bac666c --- /dev/null +++ b/src/views/login/less/style.less @@ -0,0 +1,120 @@ +.retrieve-password, +.register, +.login { + width: 100%; + display: flex; + flex-direction: column; + align-items: center; + margin-top: 2rem; + + &:deep(.el-form) { + width: 100%; + + .el-form-item { + position: relative; + margin-bottom: 1.6rem; + } + + .el-form-item__content { + position: relative; + } + + + .el-form-item__label { + color: #232323; + font-size: 1.2rem; + margin-bottom: 0.8rem; + line-height: 1.5rem; + } + + .el-input { + --el-input-height: 3.4rem; + --el-input-border-radius: 0; + --el-input-text-color: #232323; + --el-border-color: #C4C4C4; + font-size: 1.4rem; + + &::placeholder { + color: #9F9F9F; + } + } + + .password-tip { + position: absolute; + z-index: 10; + top: -1rem; + right: 0; + transform: translateY(-100%); + } + + .password-warning { + --el-checkbox-height: auto; + margin-top: -0.6rem; + margin-bottom: 1.6rem; + display: flex; + align-items: center; + + >.icon { + width: 1.4rem; + height: 1.4rem; + margin-right: 0.8rem; + } + + >.label { + font-family: KaiseiOpti-Regular; + font-size: 1rem; + color: #9F9F9F; + } + } + + .forgotPassword { + margin-top: -0.8rem; + margin-bottom: 5rem; + font-size: 1.1rem; + text-align: right; + color: #666666; + cursor: pointer; + text-decoration: underline; + font-family: KaiseiOpti-Regular; + } + + + .el-form-item__error { + padding-top: 1px; + font-size: 1rem; + } + + + .submit { + width: 100%; + height: 4rem; + font-size: 1.36rem; + } + + .privacy { + margin-top: -0.6rem; + --el-checkbox-height: auto; + + .el-checkbox__label { + font-size: 1.1rem; + color: #666666; + font-family: KaiseiOpti-Regular; + + >div { + >span { + font-family: KaiseiOpti-Bold; + text-decoration: underline; + cursor: pointer; + color: #232323; + } + } + } + } + + } + + >.other-login { + margin-top: 4rem; + } + +} \ No newline at end of file diff --git a/src/views/login/login-dialog.vue b/src/views/login/login-dialog.vue new file mode 100644 index 0000000..1d9c038 --- /dev/null +++ b/src/views/login/login-dialog.vue @@ -0,0 +1,231 @@ + + + + + diff --git a/src/views/login/login.vue b/src/views/login/login.vue new file mode 100644 index 0000000..87f251e --- /dev/null +++ b/src/views/login/login.vue @@ -0,0 +1,75 @@ + + + + + diff --git a/src/views/login/other-login.vue b/src/views/login/other-login.vue new file mode 100644 index 0000000..b9d795c --- /dev/null +++ b/src/views/login/other-login.vue @@ -0,0 +1,83 @@ + + + + + diff --git a/src/views/login/password-tip.vue b/src/views/login/password-tip.vue new file mode 100644 index 0000000..0ca3f14 --- /dev/null +++ b/src/views/login/password-tip.vue @@ -0,0 +1,60 @@ + + + + + diff --git a/src/views/login/register.vue b/src/views/login/register.vue new file mode 100644 index 0000000..4f0dabe --- /dev/null +++ b/src/views/login/register.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/src/views/login/retrieve-password.vue b/src/views/login/retrieve-password.vue new file mode 100644 index 0000000..1f65234 --- /dev/null +++ b/src/views/login/retrieve-password.vue @@ -0,0 +1,120 @@ + + + + + diff --git a/src/views/login/tools.js b/src/views/login/tools.js new file mode 100644 index 0000000..b89ba0d --- /dev/null +++ b/src/views/login/tools.js @@ -0,0 +1,54 @@ +import i18n from '@/lang' +const t = i18n.global.t +export const validateName = (rule, value, callback) => { + var str = "" + if (!value) { + str = t('Login.pleaseInputName') + } else if (value.length < 2 || value.length > 20) { + str = t('Login.nameLengthError', { min: 2, max: 20 }) + } + callback(str ? new Error(str) : undefined) +} +export const validateEmail = (rule, value, callback) => { + const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}(\.[a-zA-Z]{2,})?$/ + var str = '' + if (!value) { + str = t('Login.pleaseInputEmail') + } else if (!emailRegex.test(value)) { + str = t('Login.emailFormatError') + } + callback(str ? new Error(str) : undefined) +} +// 检查长度 +export const validateLength = (v, min = 6, max = 20) => (v.length < 6 || v.length > 20); +//检查特殊字符 +export const validateSpecial = (v) => (!/[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test(v)); +//检查大小写字母和数字 +export const validateCase = (v) => (!/[a-z]/.test(v) || !/[A-Z]/.test(v) || !/\d/.test(v)); +// 检查密码 +export const validatePass = (rule, value, callback) => { + var str = '' + if (validateLength(value)) { + str = t('Login.passwordLengthError', { min: 6, max: 20 }) + } else if (validateSpecial(value)) { + str = t('Login.passwordSpecial') + } else if (validateCase(value)) { + str = t('Login.passwordCase') + } + callback(str ? new Error(str) : undefined) +} +// 检查密码长度 +export const validatePassLength = (rule, value, callback) => { + var str = '' + if (validateLength(value)) { + str = t('Login.passwordLengthError', { min: 6, max: 20 }) + } + callback(str ? new Error(str) : undefined) +} +export const validatePrivacy = (rule, value, callback) => { + if (!value) { + callback(new Error(t('Login.pleaseTermsPolicy'))) + } else { + callback() + } +} \ No newline at end of file diff --git a/src/views/main-header.vue b/src/views/main-header.vue index f8c15d5..406d949 100644 --- a/src/views/main-header.vue +++ b/src/views/main-header.vue @@ -24,8 +24,44 @@ > -
Login
-
+
Login
+ + + + @@ -33,6 +69,7 @@