Merge branch 'main' of http://18.167.251.121:10003/aidlab/FiDA_Front
11
src/App.vue
@@ -1,13 +1,13 @@
|
||||
<template>
|
||||
<!-- <RouteCache /> -->
|
||||
<router-view ></router-view>
|
||||
<router-view v-if="show"></router-view>
|
||||
<div id="loading" v-if="loading" v-loading="true"></div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import RouteCache from '@/components/RouteCache.vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { computed } from 'vue'
|
||||
import { computed, provide, nextTick, ref } from 'vue'
|
||||
import { useGlobalStore } from '@/stores'
|
||||
const router = useRouter()
|
||||
const globalStore = useGlobalStore()
|
||||
@@ -22,6 +22,13 @@
|
||||
window['onClickRegister'] = () => {
|
||||
router.push({ name: 'register' })
|
||||
}
|
||||
const show = ref(true)
|
||||
provide('reload', () => {
|
||||
show.value = false
|
||||
nextTick(() => {
|
||||
show.value = true
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
|
||||
111
src/api/login.ts
@@ -1,77 +1,48 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
interface LoginParamsType {
|
||||
name?: string // 姓名
|
||||
email: string // 邮箱
|
||||
password?: string // 密码
|
||||
operationType: 'REGISTER' | 'LOGIN' | 'FORGET_PWD'
|
||||
verifyCode?: string // 验证码
|
||||
/**
|
||||
*
|
||||
* 发送验证码
|
||||
* @param params 发送验证码的参数
|
||||
* @param params.email 邮箱
|
||||
* @returns 验证码发送成功的响应
|
||||
*/
|
||||
export const SendVerificationCode = (params) => {
|
||||
return request({
|
||||
url: '/api/user/send-verification-code',
|
||||
method: 'post',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// 发送验证码
|
||||
export const precheckEmail = (params: { email: string }): Promise<ApiResponse> => {
|
||||
return request({
|
||||
url: '/api/auth/precheckEmail',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export const fetchRegisterOrLogin = (data: LoginParamsType): Promise<LoginResponse> => {
|
||||
return request({
|
||||
url: '/api/auth/registerOrLogin',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export const resetPassword = (data: LoginParamsType): Promise<ApiResponse> => {
|
||||
return request({
|
||||
url: '/api/auth/forgotPwd',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export const checkLoginStatus = (): Promise<ApiResponse<LoginResponse>> => {
|
||||
return request({
|
||||
url: '/api/auth/checkLoginStatus',
|
||||
method: 'get',
|
||||
meta: { responseAll: true }
|
||||
})
|
||||
}
|
||||
|
||||
export const LogOut = (): Promise<ApiResponse> => {
|
||||
return request({
|
||||
url: '/api/auth/logout',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// Google登录/注册参数类型
|
||||
interface GoogleAuthParamsType {
|
||||
accessToken?: string // Google ID Token (用于One Tap登录)
|
||||
}
|
||||
export const googleAuth = (data: GoogleAuthParamsType): Promise<LoginResponse> => {
|
||||
return request({
|
||||
url: '/api/auth/parseGoogleAccessToken',
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/** 更改用户信息
|
||||
* @param data 包含用户信息的对象
|
||||
* @param data.username 用户名
|
||||
* @param data.email 邮箱
|
||||
/**
|
||||
* 注册用户
|
||||
* @param data 注册用户的参数
|
||||
* @param data.username 姓名
|
||||
* @param data.password 密码
|
||||
* @returns 包含更新后的用户信息的对象
|
||||
* @param data.email 邮箱
|
||||
* @param data.verificationCode 验证码
|
||||
* @returns 注册成功后的token
|
||||
*/
|
||||
export const updateUserInfo = (data: any) => {
|
||||
return request({
|
||||
url: '/api/auth/updateUserInfo',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
export const Register = (data) => {
|
||||
return request({
|
||||
url: '/api/user/register',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
/**
|
||||
* 登录用户
|
||||
* @param data 登录用户的参数
|
||||
* @param data.username 姓名
|
||||
* @param data.password 密码
|
||||
* @param data.verificationCode 验证码
|
||||
* @returns 登录成功后的token
|
||||
*/
|
||||
export const Login = (data) => {
|
||||
return request({
|
||||
url: '/api/user/login',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
28
src/api/versitonTree.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
/**
|
||||
* 获取节点详情
|
||||
* @param data 获取节点详情的参数
|
||||
* @param data.projectId 项目id
|
||||
* @param data.id 节点id
|
||||
* @returns 获取节点详情
|
||||
*/
|
||||
export const getChatNodeDetail = (data) => {
|
||||
return request({
|
||||
url: `/api/project/${data.projectId}/chat/node/${data.id}`,
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取版本树
|
||||
* @param data 获取版本树的参数
|
||||
* @param data.projectId 项目id
|
||||
* @returns 获取版本树
|
||||
*/
|
||||
export const versionTree = (data) => {
|
||||
return request({
|
||||
url: `/api/project/${data.projectId}/chat/tree`,
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
3
src/assets/icons/arrow-bottom.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="11" height="7" viewBox="0 0 11 7" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1 1L5.04979 5.04979L9.09958 1" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 223 B |
5
src/assets/icons/learn-more.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M9.75 9C9.75 8.58579 9.41421 8.25 9 8.25C8.58579 8.25 8.25 8.58579 8.25 9V12C8.25 12.4142 8.58579 12.75 9 12.75C9.41421 12.75 9.75 12.4142 9.75 12V9Z" fill="#0D0D0D"/>
|
||||
<path d="M9 1.5C4.85786 1.5 1.5 4.85786 1.5 9C1.5 13.1421 4.85786 16.5 9 16.5C13.1421 16.5 16.5 13.1421 16.5 9C16.5 4.85786 13.1421 1.5 9 1.5ZM3 9C3 5.68629 5.68629 3 9 3C12.3137 3 15 5.68629 15 9C15 12.3137 12.3137 15 9 15C5.68629 15 3 12.3137 3 9Z" fill="#0D0D0D"/>
|
||||
<path d="M9 6.97504C9.47635 6.97504 9.8625 6.58888 9.8625 6.11254C9.8625 5.63619 9.47635 5.25004 9 5.25004C8.52365 5.25004 8.1375 5.63619 8.1375 6.11254C8.1375 6.58888 8.52365 6.97504 9 6.97504Z" fill="#0D0D0D"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 761 B |
5
src/assets/icons/logout.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M6.6731 1.77832H3.95313C3.1247 1.77832 2.45312 2.44989 2.45312 3.27832V12.7214C2.45312 13.5499 3.1247 14.2214 3.95313 14.2214H6.6731" stroke="black" stroke-width="1.5" stroke-linecap="round"/>
|
||||
<path d="M13.2461 7.99854L7.18701 7.99853" stroke="black" stroke-width="1.5" stroke-linecap="round"/>
|
||||
<path d="M10.8088 5.26001L13.5488 8L10.8088 10.74" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 541 B |
8
src/assets/icons/profile.svg
Normal file
@@ -0,0 +1,8 @@
|
||||
<svg width="13" height="14" viewBox="0 0 13 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M5.91235 5.97704C7.35576 5.97704 8.52587 4.80693 8.52587 3.36352C8.52587 1.92011 7.35576 0.75 5.91235 0.75C4.46894 0.75 3.29883 1.92011 3.29883 3.36352C3.29883 4.80693 4.46894 5.97704 5.91235 5.97704Z" stroke="black" stroke-width="1.5" stroke-linecap="round"/>
|
||||
<path d="M0.75 13.1317C0.75 13.1317 0.75 12.9684 0.75 12.903C0.75 10.5835 2.48146 8.65606 4.73562 8.3457" stroke="black" stroke-width="1.5" stroke-linecap="round"/>
|
||||
<path d="M8.39466 10.3384C9.01713 10.3384 9.52174 9.83378 9.52174 9.21131C9.52174 8.58884 9.01713 8.08423 8.39466 8.08423C7.77219 8.08423 7.26758 8.58884 7.26758 9.21131C7.26758 9.83378 7.77219 10.3384 8.39466 10.3384Z" fill="black"/>
|
||||
<path d="M11.5138 10.3384C12.1363 10.3384 12.6409 9.83378 12.6409 9.21131C12.6409 8.58884 12.1363 8.08423 11.5138 8.08423C10.8913 8.08423 10.3867 8.58884 10.3867 9.21131C10.3867 9.83378 10.8913 10.3384 11.5138 10.3384Z" fill="black"/>
|
||||
<path d="M8.39466 13.4583C9.01713 13.4583 9.52174 12.9537 9.52174 12.3312C9.52174 11.7087 9.01713 11.2041 8.39466 11.2041C7.77219 11.2041 7.26758 11.7087 7.26758 12.3312C7.26758 12.9537 7.77219 13.4583 8.39466 13.4583Z" fill="black"/>
|
||||
<path d="M11.5138 13.4583C12.1363 13.4583 12.6409 12.9537 12.6409 12.3312C12.6409 11.7087 12.1363 11.2041 11.5138 11.2041C10.8913 11.2041 10.3867 11.7087 10.3867 12.3312C10.3867 12.9537 10.8913 13.4583 11.5138 13.4583Z" fill="black"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
4
src/assets/icons/reportDown.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M5.1384 6.86193C4.87805 6.60158 4.45594 6.60158 4.19559 6.86193C3.93524 7.12228 3.93524 7.54439 4.19559 7.80474L7.52892 11.1381C7.78927 11.3984 8.21138 11.3984 8.47173 11.1381L11.8051 7.80474C12.0654 7.54439 12.0654 7.12228 11.8051 6.86193C11.5447 6.60158 11.1226 6.60158 10.8623 6.86193L8.66699 9.05719L8.66699 2.66667C8.66699 2.29848 8.36852 2 8.00033 2C7.63214 2 7.33366 2.29848 7.33366 2.66667L7.33366 9.05719L5.1384 6.86193Z" fill="white"/>
|
||||
<path d="M3.33366 12.6667C2.96547 12.6667 2.66699 12.9651 2.66699 13.3333C2.66699 13.7015 2.96547 14 3.33366 14H12.667C13.0352 14 13.3337 13.7015 13.3337 13.3333C13.3337 12.9651 13.0352 12.6667 12.667 12.6667L3.33366 12.6667Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 800 B |
4
src/assets/icons/setting.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg width="19" height="19" viewBox="0 0 19 19" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M7.40886 2.76749C8.30078 1.44443 10.2483 1.44443 11.1402 2.76749L11.5451 3.3681C11.9325 3.94273 12.563 4.30679 13.2544 4.35495L13.977 4.4053C15.5687 4.51619 16.5425 6.20275 15.8426 7.63671L15.5249 8.28767C15.221 8.91046 15.221 9.63858 15.5249 10.2614L15.8426 10.9123C16.5425 12.3463 15.5687 14.0328 13.9769 14.1437L13.2544 14.1941C12.563 14.2423 11.9325 14.6063 11.5451 15.1809L11.1402 15.7816C10.2483 17.1046 8.30078 17.1046 7.40886 15.7816L7.00397 15.1809C6.61659 14.6063 5.98602 14.2423 5.29469 14.1941L4.57209 14.1437C2.98033 14.0328 2.00659 12.3463 2.70643 10.9123L3.02413 10.2614C3.32809 9.63858 3.32809 8.91046 3.02413 8.28767L2.70644 7.63671C2.00659 6.20276 2.98033 4.51619 4.57209 4.4053L5.29469 4.35495C5.98602 4.30679 6.61659 3.94273 7.00397 3.3681L7.40886 2.76749Z" stroke="black" stroke-width="1.6875"/>
|
||||
<circle cx="9.27539" cy="9.27441" r="1.93359" stroke="black" stroke-width="1.6875"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1014 B |
4
src/assets/icons/versionExport.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M5.669 7.56092C5.37611 7.25718 4.90123 7.25718 4.60834 7.56092C4.31545 7.86466 4.31545 8.35713 4.60834 8.66087L8.35834 12.5498C8.65123 12.8535 9.12611 12.8535 9.419 12.5498L13.169 8.66087C13.4619 8.35712 13.4619 7.86466 13.169 7.56092C12.8761 7.25718 12.4012 7.25718 12.1083 7.56092L9.63867 10.1221L9.63867 2.66645C9.63867 2.23689 9.30289 1.88867 8.88867 1.88867C8.47446 1.88867 8.13867 2.23689 8.13867 2.66645L8.13867 10.1221L5.669 7.56092Z" fill="#5A5A5A"/>
|
||||
<path d="M3.63867 14.3331C3.22446 14.3331 2.88867 14.6813 2.88867 15.1109C2.88867 15.5404 3.22446 15.8887 3.63867 15.8887H14.1387C14.5529 15.8887 14.8887 15.5404 14.8887 15.1109C14.8887 14.6813 14.5529 14.3331 14.1387 14.3331L3.63867 14.3331Z" fill="#5A5A5A"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 833 B |
34
src/assets/icons/xiang.svg
Normal file
@@ -0,0 +1,34 @@
|
||||
<svg width="18" height="13" viewBox="0 0 18 13" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g filter="url(#filter0_n_692_30137)">
|
||||
<path d="M14.1922 7.86884C15.1626 6.8473 15.4839 5.58249 15.8809 4.28415C15.9364 4.1025 15.959 3.91214 15.945 3.72254L15.76 1.19999C15.727 0.749411 15.4047 0.372032 14.9647 0.26874L14.2145 0.0926218C14.1812 0.0848104 14.1471 0.0808921 14.113 0.0808993C11.5893 0.0814305 9.05569 -0.0851513 6.6376 0.0893913C5.05504 0.202548 3.62996 1.08793 3.0211 2.56473C2.95266 2.73066 2.74058 3.33271 2.74106 3.46776L2.75196 6.51746C2.75251 6.67298 2.67121 6.81713 2.53792 6.89694L0.958446 7.84263C0.915651 7.86826 0.889546 7.91454 0.889725 7.96447C0.890124 8.07621 1.01361 8.14388 1.10778 8.08398L2.16799 7.40964C2.38037 7.27455 2.66002 7.41962 2.67245 7.67132L2.76518 9.54984L2.77334 11.8342C2.77421 12.0781 2.97261 12.2755 3.21647 12.2753L5.29787 12.2729C5.55742 12.2726 5.75463 12.0403 5.71286 11.784L5.37608 9.71745C5.37352 9.70169 5.37243 9.68568 5.37671 9.67032C5.38393 9.64442 5.39803 9.60614 5.40506 9.56942C5.41219 9.53216 5.42374 9.49297 5.45097 9.46659C5.47163 9.44658 5.49928 9.43537 5.52808 9.43534L9.6298 9.43068C9.89861 9.43037 10.1059 9.66831 10.0687 9.93443L9.81285 11.7635C9.77563 12.0296 9.98292 12.2676 10.2517 12.2673L12.7476 12.2644C12.8771 12.2643 12.9816 12.1592 12.9812 12.0297L12.9706 9.07613C12.9702 8.94553 13.0271 8.82104 13.1296 8.74029C13.4912 8.45529 13.8743 8.20332 14.1922 7.86884Z" fill="#272727"/>
|
||||
<path d="M16.9689 8.63445C18.729 1.99586 16.9384 0.0927843 14.123 0.0959828L15.0919 6.48998C15.2358 6.43615 15.317 6.46736 15.3396 6.48969C15.7923 7.11527 15.5346 8.53918 15.3492 9.17294C15.0405 11.0824 15.9378 11.9107 16.6669 12.1803C16.8842 12.2607 17.094 12.0939 17.1212 11.8641L17.1937 11.2521C17.2225 11.0093 17.0039 10.7773 16.8926 10.5592C16.6655 10.1145 16.8233 9.16971 16.9689 8.63445Z" fill="#272727"/>
|
||||
<path d="M0.861304 8.40801C0.764736 8.51498 0.58841 8.47735 0.543626 8.34022L0.408584 7.92673C0.363724 7.78937 0.484462 7.65523 0.625813 7.6854L1.05205 7.77636C1.1934 7.80652 1.24923 7.97834 1.1525 8.08548L0.861304 8.40801Z" fill="#272727"/>
|
||||
</g>
|
||||
<path d="M17.043 5.93021C17.0438 5.93021 17.0446 5.93021 17.0777 5.93017C17.1108 5.93013 17.1762 5.93006 17.2733 5.93962" stroke="#E4E5D7" stroke-width="0.187554" stroke-linecap="round"/>
|
||||
<path d="M17.043 6.30082C17.0438 6.30082 17.0446 6.30081 17.0777 6.30078C17.1108 6.30074 17.1762 6.30067 17.2733 6.31022" stroke="#E4E5D7" stroke-width="0.187554" stroke-linecap="round"/>
|
||||
<path d="M12.393 1.62356C11.6861 0.960209 10.0414 0.0322616 8.74643 1.6277C8.19193 2.46239 7.80275 4.03743 10.0856 5.88913C10.5515 6.26701 11.4827 6.88377 12.1553 6.60499C12.3639 6.48891 12.6836 6.27077 12.6629 5.67769L12.6103 3.94013" stroke="#E4E5D7" stroke-width="0.281331" stroke-linecap="round"/>
|
||||
<path d="M15.6617 2.4319C15.8624 2.43177 15.9885 2.62095 15.9892 2.8036C15.9898 2.98623 15.8651 3.17571 15.6643 3.17604C15.5537 3.17616 15.4649 3.10285 15.4109 3.03179C15.3545 2.95765 15.3137 2.8585 15.3132 2.75847C15.3129 2.65183 15.3586 2.56581 15.4295 2.50931C15.4974 2.45537 15.5827 2.43199 15.6617 2.4319Z" stroke="#E4E5D7" stroke-width="0.234443"/>
|
||||
<path d="M14.4761 2.43312C14.6879 2.43298 14.8265 2.63062 14.8272 2.82823C14.8275 2.94411 14.7707 3.04327 14.6993 3.1106C14.6288 3.17686 14.5316 3.2231 14.4321 3.22321C14.3223 3.22324 14.2397 3.16682 14.1904 3.08579C14.1447 3.01068 14.1283 2.91761 14.1279 2.82902C14.1272 2.63136 14.2643 2.43336 14.4761 2.43312Z" stroke="#E4E5D7" stroke-width="0.234443"/>
|
||||
<path d="M12.4615 11.4724C12.4612 11.3826 12.5337 11.3098 12.6235 11.3097C12.7133 11.3096 12.7864 11.3823 12.7867 11.4721L12.7888 12.0503C12.7888 12.0762 12.7679 12.0972 12.742 12.0972L12.5106 12.0975C12.4847 12.0975 12.4637 12.0766 12.4636 12.0507L12.4615 11.4724Z" fill="#E4E5D7"/>
|
||||
<path d="M4.33481 11.6446C4.33436 11.5164 4.43797 11.4123 4.56625 11.4121C4.69452 11.412 4.79888 11.5158 4.79934 11.6441L4.80083 12.06C4.80092 12.0859 4.78 12.1069 4.7541 12.107L4.38336 12.1074C4.35746 12.1074 4.33639 12.0864 4.3363 12.0605L4.33481 11.6446Z" fill="#E4E5D7"/>
|
||||
<path d="M4.99442 11.3379C4.98887 11.2355 5.06744 11.1481 5.16992 11.1428C5.27239 11.1376 5.35996 11.2164 5.36551 11.3188L5.40304 12.0119C5.40445 12.0378 5.38462 12.0598 5.35876 12.0612L5.08132 12.0755C5.05546 12.0768 5.03336 12.0569 5.03196 12.031L4.99442 11.3379Z" fill="#E4E5D7"/>
|
||||
<path d="M12.0006 11.7974C12.0003 11.7076 12.0728 11.6347 12.1626 11.6346C12.2524 11.6345 12.3254 11.7072 12.3257 11.797L12.3267 12.0509C12.3267 12.0768 12.3058 12.0978 12.2799 12.0978L12.0485 12.0981C12.0226 12.0981 12.0016 12.0772 12.0015 12.0513L12.0006 11.7974Z" fill="#E4E5D7"/>
|
||||
<defs>
|
||||
<filter id="filter0_n_692_30137" x="0.398438" y="0.00955702" width="17.2695" height="12.2656" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feTurbulence type="fractalNoise" baseFrequency="21.327169418334961 21.327169418334961" stitchTiles="stitch" numOctaves="3" result="noise" seed="4152" />
|
||||
<feColorMatrix in="noise" type="luminanceToAlpha" result="alphaNoise" />
|
||||
<feComponentTransfer in="alphaNoise" result="coloredNoise1">
|
||||
<feFuncA type="discrete" tableValues="1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "/>
|
||||
</feComponentTransfer>
|
||||
<feComposite operator="in" in2="shape" in="coloredNoise1" result="noise1Clipped" />
|
||||
<feFlood flood-color="#3B3B3B" result="color1Flood" />
|
||||
<feComposite operator="in" in2="noise1Clipped" in="color1Flood" result="color1" />
|
||||
<feMerge result="effect1_noise_692_30137">
|
||||
<feMergeNode in="shape" />
|
||||
<feMergeNode in="color1" />
|
||||
</feMerge>
|
||||
</filter>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.7 KiB |
BIN
src/assets/images/nuic/xiang.gif
Normal file
|
After Width: | Height: | Size: 167 KiB |
|
Before Width: | Height: | Size: 4.1 KiB |
BIN
src/assets/images/reportNull.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
64
src/components/dropdown-menu.vue
Normal file
@@ -0,0 +1,64 @@
|
||||
<template>
|
||||
<el-dropdown trigger="click" placement="bottom-end">
|
||||
<div class="title">
|
||||
<span class="label">{{ title }}</span>
|
||||
<span class="icon"><svg-icon name="arrow-bottom" size="10" color="#000" /></span>
|
||||
</div>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item
|
||||
v-for="item in list"
|
||||
:key="item.value"
|
||||
:disabled="item.value === modelValue"
|
||||
@click="onItemClick(item.value)"
|
||||
style="--el-font-size-base: 1.4rem; --el-text-color-regular: #000"
|
||||
>
|
||||
<span>{{ item.label }}</span>
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref, computed, watch, nextTick } from 'vue'
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
list: {
|
||||
type: [Array, Object],
|
||||
default: () => []
|
||||
},
|
||||
icon: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
})
|
||||
const title = computed(() => {
|
||||
return props.list.find((v) => v.value === props.modelValue)?.label || '---'
|
||||
})
|
||||
const emit = defineEmits(['update:modelValue', 'change'])
|
||||
const onItemClick = (value: string) => {
|
||||
emit('update:modelValue', value)
|
||||
emit('change', value)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.title {
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 1.4rem;
|
||||
color: #000;
|
||||
> .label {
|
||||
// min-width: 7rem;
|
||||
}
|
||||
> .icon {
|
||||
margin-left: 1.6rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -103,11 +103,12 @@ export default {
|
||||
france: 'France',
|
||||
japan: 'Japan',
|
||||
canada: 'Canada',
|
||||
germany: 'Germany'
|
||||
germany: 'Germany',
|
||||
},
|
||||
agent: {
|
||||
copySuccess: 'Text copied to clipboard',
|
||||
copyFaild: 'Copy failed. Your browser may be restricting clipboard access. Please try copying manually.'
|
||||
copyFaild: 'Copy failed. Your browser may be restricting clipboard access. Please try copying manually.',
|
||||
Download: 'Download'
|
||||
},
|
||||
|
||||
// Version Tree
|
||||
@@ -128,6 +129,7 @@ export default {
|
||||
restoreHint:'Once deleted, you won’t be able to view this conversation again.',
|
||||
cancel: 'cancel',
|
||||
Confirm: 'Confirm',
|
||||
export: 'Export',
|
||||
},
|
||||
//generateSketch
|
||||
generateSketch: {
|
||||
|
||||
@@ -97,12 +97,13 @@ export default {
|
||||
france: '法国',
|
||||
japan: '日本',
|
||||
canada: '加拿大',
|
||||
germany: '德国'
|
||||
germany: '德国',
|
||||
},
|
||||
agent: {
|
||||
copySuccess: '文本已复制到剪贴板',
|
||||
copyFaild:
|
||||
'复制失败。您的浏览器可能限制了剪贴板访问,请允许浏览器访问剪贴板或尝试手动复制。'
|
||||
'复制失败。您的浏览器可能限制了剪贴板访问,请允许浏览器访问剪贴板或尝试手动复制。',
|
||||
Download: '下载'
|
||||
},
|
||||
|
||||
// Version Tree
|
||||
@@ -123,6 +124,7 @@ export default {
|
||||
restoreHint:'恢复后将显示该对话。',
|
||||
cancel: '取消',
|
||||
Confirm: '确认',
|
||||
export: '导出',
|
||||
},
|
||||
//generateSketch
|
||||
generateSketch: {
|
||||
|
||||
@@ -1,70 +1,46 @@
|
||||
// 每一个存储的模块,命名规则use开头,store结尾
|
||||
import router from '@/router'
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref, computed } from 'vue'
|
||||
import { removeLocal, setLocal } from '@/utils/local'
|
||||
import MyEvent from '@/utils/myEvent'
|
||||
export const useUserInfoStore = defineStore('userInfo', () => {
|
||||
const state = ref({
|
||||
const state = ref({
|
||||
userInfo: {},
|
||||
token: '',
|
||||
generateParams: {
|
||||
stylist: '',
|
||||
sex: '',
|
||||
stylistImage: ''
|
||||
}
|
||||
})
|
||||
|
||||
// getters
|
||||
const getUserInfo = computed(() => state.value.userInfo)
|
||||
})
|
||||
|
||||
// actions
|
||||
const setUserInfo = (data: any) => {
|
||||
state.value.userInfo = data
|
||||
}
|
||||
// getters
|
||||
const getUserInfo = computed(() => state.value.userInfo)
|
||||
|
||||
const setToken = (data: string) => {
|
||||
state.value.token = data
|
||||
setLocal(data, 'token')
|
||||
}
|
||||
// actions
|
||||
const setUserInfo = (data: any) => {
|
||||
state.value.userInfo = data
|
||||
}
|
||||
|
||||
const getGenerateParams = () => {
|
||||
return state.value.generateParams
|
||||
}
|
||||
const setToken = (data: string) => {
|
||||
state.value.token = data
|
||||
// setLocal(data, 'token')
|
||||
}
|
||||
|
||||
const setGenerateParams = (data: any) => {
|
||||
state.value.generateParams = data
|
||||
}
|
||||
const logOut = async () => {
|
||||
// 处理退出登录的一些逻辑
|
||||
state.value.token = ''
|
||||
state.value.userInfo = {}
|
||||
// removeLocal('token')
|
||||
// MyEvent.emit('clear-generate-state')
|
||||
// MyEvent.emit('clear-client-state')
|
||||
// MyEvent.emit('clearAllCache')
|
||||
router.push({ name: 'login' })
|
||||
return ""
|
||||
}
|
||||
|
||||
const resetGenerateParams = () => {
|
||||
state.value.generateParams = {
|
||||
stylist: '',
|
||||
sex: '',
|
||||
stylistImage: ''
|
||||
}
|
||||
}
|
||||
|
||||
const logOut = () => {
|
||||
// 处理退出登录的一些逻辑
|
||||
return new Promise((resolve) => {
|
||||
state.value.token = ''
|
||||
state.value.userInfo = {}
|
||||
removeLocal('token')
|
||||
resetGenerateParams()
|
||||
MyEvent.emit('clear-generate-state')
|
||||
MyEvent.emit('clear-client-state')
|
||||
MyEvent.emit('clearAllCache')
|
||||
resolve('')
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
state,
|
||||
getUserInfo,
|
||||
setToken,
|
||||
setUserInfo,
|
||||
setGenerateParams,
|
||||
getGenerateParams,
|
||||
resetGenerateParams,
|
||||
logOut
|
||||
}
|
||||
return {
|
||||
state,
|
||||
getUserInfo,
|
||||
setToken,
|
||||
setUserInfo,
|
||||
logOut
|
||||
}
|
||||
})
|
||||
|
||||
@@ -79,7 +79,7 @@ service.interceptors.response.use(
|
||||
const res = response.data
|
||||
// 处理异常的情况
|
||||
// console.log(res)
|
||||
if (res.code != 0) {
|
||||
if (res.code != 200) {
|
||||
// showToast({
|
||||
// message: res.errMsg || res.message,
|
||||
// // type: 'fail',
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onUnmounted, reactive, toRefs, computed } from "vue";
|
||||
import VersionTreeIndex from './versionTree/index.vue'
|
||||
import VersionTreeIndex from '@/views/home/agent/components/versionTree/index.vue'
|
||||
|
||||
import GenerateSketch from './generateSketch/index.vue'
|
||||
//const props = defineProps({
|
||||
//})
|
||||
@@ -73,14 +74,25 @@ const generateSketch = ()=>{
|
||||
sketchRestore('2')
|
||||
}
|
||||
|
||||
const sketchRestore = (id)=>{
|
||||
generateData.value.list.forEach((item)=>{
|
||||
if(item.id == id){
|
||||
item.type = 'waiting'
|
||||
const sketchRestore = (item)=>{
|
||||
generateData.value.list.forEach((generateDataItem)=>{
|
||||
if(item.id == generateDataItem.id){
|
||||
generateDataItem.type = 'waiting'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const sketchDelete = (item)=>{
|
||||
console.log(item)
|
||||
generateData.value.list.forEach((generateDataItem,index)=>{
|
||||
if(item.id == generateDataItem.id){
|
||||
generateData.value.list.splice(index,1)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
onMounted(()=>{
|
||||
})
|
||||
onUnmounted(()=>{
|
||||
@@ -99,7 +111,7 @@ const {} = toRefs(data);
|
||||
</div>
|
||||
<VersionTreeIndex v-model:versionTreeData="versionTreeData" />
|
||||
<div class="generateSketchBox">
|
||||
<GenerateSketch v-model:generateData="generateData"></GenerateSketch>
|
||||
<GenerateSketch v-model:generateData="generateData" @sketchRestore="sketchRestore" @sketchDelete="sketchDelete"></GenerateSketch>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -13,6 +13,30 @@
|
||||
<img :src="LoadingImg" alt="" />
|
||||
</div>
|
||||
</template>
|
||||
<div v-else class="reportBorder">
|
||||
<div class="report">
|
||||
<div v-if="false" class="report-content-null">
|
||||
<img :src="reportNull" alt="" />
|
||||
</div>
|
||||
<div v-else class="report-content">
|
||||
<div class="">
|
||||
|
||||
</div>
|
||||
<div class="downBtnBox">
|
||||
<div class="downBtn">
|
||||
<div class="icon">
|
||||
<SvgIcon name="reportDown" size="16"></SvgIcon>
|
||||
</div>
|
||||
<span>{{ $t('agent.Download') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
# 一级标题
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -20,6 +44,7 @@
|
||||
import { ref } from 'vue'
|
||||
import Menu from './Menu.vue'
|
||||
import LoadingImg from '@/assets/images/sketch-loading.gif'
|
||||
import reportNull from '@/assets/images/reportNull.png'
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
@@ -45,6 +70,8 @@
|
||||
|
||||
<style lang="less" scoped>
|
||||
.preview-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
gap: 1.2rem;
|
||||
flex-wrap: wrap;
|
||||
.sketch-item {
|
||||
@@ -71,12 +98,75 @@
|
||||
border: 0.2rem solid #e5e5e5;
|
||||
font-family: 'GeneralMedium';
|
||||
font-size: 1.4rem;
|
||||
padding: 0 0.9rem 0 1.4rem;
|
||||
cursor: pointer;
|
||||
img{
|
||||
width: 1.8rem;
|
||||
height: 1.8rem;
|
||||
}
|
||||
padding: 0 0.9rem 0 1.4rem;
|
||||
cursor: pointer;
|
||||
img{
|
||||
width: 1.8rem;
|
||||
height: 1.8rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
.reportBorder{
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
--border-width: 3px;
|
||||
flex: 1;
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
background: linear-gradient(119.03deg, rgba(233, 121, 60, 0.3) 1.61%, rgba(255, 207, 144, 0.3) 101.01%);
|
||||
border-radius: 2.3rem;
|
||||
z-index: -1;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
left: -50%;
|
||||
top: -50%;
|
||||
transform: translate(50%, 50%);
|
||||
}
|
||||
.report {
|
||||
background-color: #fff;
|
||||
width: calc(100% - var(--border-width) * 2);
|
||||
height: calc(100% - var(--border-width) * 2);
|
||||
border-radius: 2rem;
|
||||
display: flex;
|
||||
.report-content-null{
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.report-content{
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.downBtnBox{
|
||||
padding: 2.2rem 5.2rem 0;
|
||||
.downBtn{
|
||||
display: flex;
|
||||
width: 11.2rem;
|
||||
justify-content: center;
|
||||
margin-left: auto;
|
||||
line-height: 3.2rem;
|
||||
border-radius: 5px;
|
||||
background-color: #ff7a51;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
.icon{
|
||||
margin-right: .02rem;
|
||||
}
|
||||
span{
|
||||
font-weight: 500;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
.content{
|
||||
word-break: break-word;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,6 +89,14 @@ const {} = toRefs(data)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="expandBtnBox">
|
||||
<div class="btn" @click="openTree(true)">
|
||||
<div class="versionExport">
|
||||
<SvgIcon name="versionExport" size="17" color="rgba(0, 0, 0, 0.6)" />
|
||||
</div>
|
||||
<span>{{ $t('VersionTree.export') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="expandBtnBox">
|
||||
<div class="btn" @click="openTree(true)">
|
||||
<div class="bg left" :class="{'active':treeState}"></div>
|
||||
@@ -135,96 +143,47 @@ const {} = toRefs(data)
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.versionTreeTitle {
|
||||
.versionTreeTitle{
|
||||
width: 100%;
|
||||
height: 8rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 0.8rem 0 2.4rem;
|
||||
border-bottom: 1px solid #c9c9c9;
|
||||
> span {
|
||||
padding: 0 .8rem 0 2.4rem;
|
||||
border-bottom: 1px solid #C9C9C9;
|
||||
> span{
|
||||
font-size: 2rem;
|
||||
font-weight: 600;
|
||||
font-family: 'SemiBold';
|
||||
}
|
||||
.versionTreeTitle{
|
||||
width: 100%;
|
||||
height: 8rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 .8rem 0 2.4rem;
|
||||
border-bottom: 1px solid #C9C9C9;
|
||||
> span{
|
||||
font-size: 2rem;
|
||||
font-weight: 600;
|
||||
font-family: 'SemiBold';
|
||||
}
|
||||
> .closeBtn{
|
||||
width: 2.4rem;
|
||||
height: 2.4rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.expandBtnBox{
|
||||
padding: .4rem .7rem;
|
||||
border-radius: 1.1rem;
|
||||
background-color: #f3f3f3;
|
||||
display: flex;
|
||||
margin-left: auto;
|
||||
margin-top: 2.1rem;
|
||||
margin-right: 3rem;
|
||||
> .btn{
|
||||
padding: .6rem .5rem;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
> .bg{
|
||||
position: absolute;
|
||||
background-color: #fff;
|
||||
border-radius: .6rem;
|
||||
width: 0;
|
||||
height: 100%;
|
||||
transition: all .3s;
|
||||
top: 0;
|
||||
&.active{
|
||||
width: 100%;
|
||||
}
|
||||
&.left{
|
||||
right: 0;
|
||||
}
|
||||
&.right{
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
> span{
|
||||
position: relative;
|
||||
font-size: 1.3rem;
|
||||
line-height: 1.8rem;
|
||||
font-weight: 500;
|
||||
letter-spacing: -0.08px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.versionTreeBox{
|
||||
flex: 1;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
> .tree{
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
padding: 2.1rem 0 5.4rem 2.2rem;
|
||||
}
|
||||
> .detail{
|
||||
width: 35rem;
|
||||
margin: 2.1rem 3rem 5.4rem 3.4rem;
|
||||
height: calc(100% - 2.1rem - 5.4rem);
|
||||
overflow: hidden;
|
||||
}
|
||||
> .closeBtn{
|
||||
width: 2.4rem;
|
||||
height: 2.4rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.expandBtnBox {
|
||||
.expandBtnBox{
|
||||
margin-left: auto;
|
||||
margin-top: 2.2rem;
|
||||
margin-right: 3rem;
|
||||
> .btn{
|
||||
padding: .6rem 1.8rem;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 8px;
|
||||
border: 1.5px solid #D9D9D9;
|
||||
color: rgba(0, 0, 0, 0.6);
|
||||
> .versionExport{
|
||||
margin-right: .6rem;
|
||||
}
|
||||
> span{
|
||||
font-weight: 500;
|
||||
font-size: 1.4rem;
|
||||
letter-spacing: Letter Spacing;
|
||||
}
|
||||
}
|
||||
}
|
||||
.versionTreeBox {
|
||||
flex: 1;
|
||||
@@ -234,11 +193,11 @@ const {} = toRefs(data)
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
padding: 2.1rem 0 5.4rem 2.2rem;
|
||||
padding: 2.5rem 0 5.4rem 2.2rem;
|
||||
}
|
||||
> .detail {
|
||||
width: 35rem;
|
||||
margin: 2.1rem 3rem 5.4rem 3.4rem;
|
||||
margin: 2.5rem 3rem 5.4rem 3.4rem;
|
||||
height: calc(100% - 2.1rem - 5.4rem);
|
||||
overflow: hidden;
|
||||
}
|
||||
@@ -1,19 +1,35 @@
|
||||
<template>
|
||||
<div class="agent-wrapper flex space-between">
|
||||
<Agent :title="agentTitle" />
|
||||
<div class="preview-wrapper">
|
||||
<Preview :type="previewType" />
|
||||
<div class="openVersionTree">
|
||||
<div class="btn" @click="versionTreeData.drawer = true">
|
||||
Version Tree
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-wrapper">
|
||||
<Agent :title="agentTitle" />
|
||||
<div class="preview-wrapper">
|
||||
<Preview :type="previewType" />
|
||||
</div>
|
||||
</div>
|
||||
<VersionTreeIndex v-model:versionTreeData="versionTreeData" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import Agent from './components/Agent.vue'
|
||||
import Preview from './components/Preview.vue'
|
||||
import VersionTreeIndex from './components/versionTree/index.vue'
|
||||
|
||||
const agentTitle = ref('Retro Sofa Sketch')
|
||||
const previewType = ref<'sketch' | 'report'>('sketch')
|
||||
const previewType = ref<'sketch' | 'report'>('report')
|
||||
|
||||
const versionTreeData = ref({
|
||||
drawer:false,
|
||||
list:computed(()=>{
|
||||
return []
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@@ -21,7 +37,39 @@
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-top: 0.1rem solid #c9c9c9;
|
||||
padding: 8rem 2.3rem 6rem 2.8rem;
|
||||
padding: 0rem 2.3rem 6rem 2.8rem;
|
||||
flex-direction: column;
|
||||
.openVersionTree{
|
||||
padding: 2rem 0rem;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
height: min-content;
|
||||
> .btn{
|
||||
padding: 1.5rem 1.45rem;
|
||||
font-weight: 500;
|
||||
font-size: 1.4rem;
|
||||
border-radius: 2rem;
|
||||
position: relative;
|
||||
background: white;
|
||||
cursor: pointer;
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: -1px;
|
||||
background: linear-gradient(119.03deg, rgba(233, 121, 60, 0.8) 1.61%, rgba(255, 207, 144, 0.8) 101.01%);
|
||||
border-radius: 2.2rem;
|
||||
z-index: -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content-wrapper{
|
||||
display: flex;
|
||||
flex: 1;
|
||||
justify-content: space-between;
|
||||
// overflow: hidden;
|
||||
}
|
||||
|
||||
.c-svg {
|
||||
width: initial;
|
||||
|
||||
@@ -12,8 +12,10 @@ const props = defineProps({
|
||||
},
|
||||
},
|
||||
})
|
||||
//const emit = defineEmits([
|
||||
//])
|
||||
const emit = defineEmits([
|
||||
'sketchRestore',
|
||||
'sketchDelete',
|
||||
])
|
||||
let data = reactive({
|
||||
})
|
||||
onMounted(()=>{
|
||||
@@ -26,7 +28,7 @@ const {} = toRefs(data);
|
||||
<template>
|
||||
<div class="generateSketch">
|
||||
<div v-for="item in generateData.list" :key="item.id" class="item">
|
||||
<GenerateItem :item="item" />
|
||||
<GenerateItem :item="item" @sketchRestore="()=>emit('sketchRestore',item)" @sketchDelete="()=>emit('sketchDelete',item)" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -15,12 +15,14 @@
|
||||
<div class="bottom-view"><router-view></router-view></div>
|
||||
</div>
|
||||
</div>
|
||||
<setting />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import LeftNav from './left-nav.vue'
|
||||
import TopNav from './top-nav.vue'
|
||||
import setting from './setting/index.vue'
|
||||
import { useGlobalStore } from '@/stores'
|
||||
const globalStore = useGlobalStore()
|
||||
const loading = computed(() => globalStore.state.loading)
|
||||
|
||||
52
src/views/home/setting/General.vue
Normal file
@@ -0,0 +1,52 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="label">User Name</div>
|
||||
<div class="value">张三</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="label">Email</div>
|
||||
<div class="value">zhangsan@example.com</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="label">Language</div>
|
||||
<dropdown-menu v-model="locale" :list="langs" @change="changeLang" />
|
||||
</div>
|
||||
<div>
|
||||
<div class="label">Log out on this device</div>
|
||||
<button class="logout-btn" @click="logout">Log out</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, onBeforeUnmount, inject } from 'vue'
|
||||
import dropdownMenu from '@/components/dropdown-menu.vue'
|
||||
import { useUserInfoStore } from '@/stores'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
const { locale } = useI18n()
|
||||
const reload = inject('reload')
|
||||
const userInfoStore = useUserInfoStore()
|
||||
const langs = ref([
|
||||
{ label: 'English', value: 'ENGLISH' },
|
||||
{ label: '中文', value: 'CHINESE_SIMPLIFIED' }
|
||||
])
|
||||
const changeLang = (value: string) => {
|
||||
locale.value = value
|
||||
reload()
|
||||
}
|
||||
const logout = () => {
|
||||
userInfoStore.logOut()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.logout-btn {
|
||||
cursor: pointer;
|
||||
height: 3.7rem;
|
||||
width: 9.6rem;
|
||||
border-radius: 3.7rem;
|
||||
border: none;
|
||||
background-color: #ff7a51;
|
||||
color: #fff;
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
</style>
|
||||
33
src/views/home/setting/LearnMore.vue
Normal file
@@ -0,0 +1,33 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="label">User Agreement</div>
|
||||
<button @click="onClickUserAgreement">View</button>
|
||||
</div>
|
||||
<div>
|
||||
<div class="label">Privacy Policy</div>
|
||||
<button @click="onClickPrivacy">View</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, onBeforeUnmount, inject } from 'vue'
|
||||
|
||||
const onClickUserAgreement = () => {
|
||||
console.log('onClickUserAgreement')
|
||||
}
|
||||
const onClickPrivacy = () => {
|
||||
console.log('onClickPrivacy')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
button {
|
||||
width: 10rem;
|
||||
height: 3.73rem;
|
||||
background-color: transparent;
|
||||
border: 0.01rem solid #b5b5b5;
|
||||
color: #000;
|
||||
font-size: 1.4rem;
|
||||
border-radius: 3rem;
|
||||
}
|
||||
</style>
|
||||
75
src/views/home/setting/Profile.vue
Normal file
@@ -0,0 +1,75 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="label">Region</div>
|
||||
<dropdown-menu v-model="region" :list="regions" @change="changeRegion" />
|
||||
</div>
|
||||
<div>
|
||||
<div class="label">Role</div>
|
||||
<dropdown-menu v-model="role" :list="roles" @change="changeRole" />
|
||||
</div>
|
||||
<div>
|
||||
<div class="label">Current Agent Profile</div>
|
||||
<div class="group">
|
||||
<span class="icon"><svg-icon name="xiang" size="20" color="#000" /></span>
|
||||
<dropdown-menu v-model="agent" :list="agents" @change="changeAgent" />
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="label">Current Notification Frequency</div>
|
||||
<div class="value">3–6 times per hour</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, onBeforeUnmount, inject } from 'vue'
|
||||
import dropdownMenu from '@/components/dropdown-menu.vue'
|
||||
import { useUserInfoStore } from '@/stores'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
const { locale } = useI18n()
|
||||
const region = ref('China')
|
||||
const regions = ref([
|
||||
{ label: 'United States', value: 'United States' },
|
||||
{ label: 'Singapore', value: 'Singapore' },
|
||||
{ label: 'Australia', value: 'Australia' },
|
||||
{ label: 'South Korea', value: 'South Korea' },
|
||||
{ label: 'China', value: 'China' },
|
||||
{ label: 'Italy', value: 'Italy' },
|
||||
{ label: 'France', value: 'France' },
|
||||
{ label: 'Japan', value: 'Japan' },
|
||||
{ label: 'Canada', value: 'Canada' },
|
||||
{ label: 'Germany', value: 'Germany' }
|
||||
])
|
||||
const changeRegion = (value: string) => {
|
||||
console.log(value)
|
||||
}
|
||||
|
||||
const role = ref('Designer')
|
||||
const roles = ref([
|
||||
{ label: 'Designer', value: 'Designer' },
|
||||
{ label: 'Student', value: 'Student' },
|
||||
{ label: 'Teacher', value: 'Teacher' },
|
||||
{ label: 'Parent', value: 'Parent' }
|
||||
])
|
||||
const changeRole = (value: string) => {
|
||||
console.log(value)
|
||||
}
|
||||
|
||||
const agent = ref('Partner')
|
||||
const agents = ref([
|
||||
{ label: 'Partner', value: 'Partner' },
|
||||
{ label: 'Observer', value: 'Observer' },
|
||||
{ label: 'Mentor', value: 'Mentor' }
|
||||
])
|
||||
const changeAgent = (value: string) => {
|
||||
console.log(value)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 1rem;
|
||||
}
|
||||
</style>
|
||||
126
src/views/home/setting/index.vue
Normal file
@@ -0,0 +1,126 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
class="setting"
|
||||
v-model="showDialog"
|
||||
align-center
|
||||
:show-close="false"
|
||||
width="70rem"
|
||||
style="border-radius: 2rem; padding: 3.8rem; --el-dialog-padding-primary: 1rem"
|
||||
>
|
||||
<template #header="{ close }">
|
||||
<div class="setting-header">
|
||||
<div class="title">Setting</div>
|
||||
<span class="close" @click="close">
|
||||
<svg-icon name="close" size="10" color="#000" />
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
<div class="setting-box">
|
||||
<div class="left">
|
||||
<div
|
||||
v-for="v in navs"
|
||||
:key="v.icon"
|
||||
:class="{ active: nav === v.icon }"
|
||||
@click="nav = v.icon"
|
||||
>
|
||||
<span class="icon"><svg-icon :name="v.icon" size="18" color="#000" /></span>
|
||||
<span class="label">{{ v.label }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="view">
|
||||
<component :is="navs.find((v) => v.icon === nav).component" />
|
||||
</div>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import General from './General.vue'
|
||||
import Profile from './Profile.vue'
|
||||
import LearnMore from './LearnMore.vue'
|
||||
import MyEvent from '@/utils/myEvent'
|
||||
import { computed, ref, onBeforeUnmount, shallowRef } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
const { t: $t } = useI18n()
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const showDialog = ref(false)
|
||||
const openSetting = () => {
|
||||
showDialog.value = true
|
||||
}
|
||||
MyEvent.add('openSettingDialog', openSetting)
|
||||
onBeforeUnmount(() => {
|
||||
MyEvent.remove('openSettingDialog', openSetting)
|
||||
})
|
||||
|
||||
const nav = ref('setting')
|
||||
const navs = shallowRef([
|
||||
{ icon: 'setting', label: 'General', component: General },
|
||||
{ icon: 'profile', label: 'Profile', component: Profile },
|
||||
{ icon: 'learn-more', label: 'Learn more', component: LearnMore }
|
||||
])
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.setting-header {
|
||||
margin-top: 0.2rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding-bottom: 3.3rem;
|
||||
border-bottom: 0.1rem solid rgba(0, 0, 0, 0.1);
|
||||
> .title {
|
||||
font-family: Semibold;
|
||||
font-size: 1.6rem;
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
.setting-box {
|
||||
width: 100%;
|
||||
height: 50rem;
|
||||
display: flex;
|
||||
> .left {
|
||||
margin-top: 1.8rem;
|
||||
> div {
|
||||
width: 16.4rem;
|
||||
height: 3.4rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
// justify-content: center;
|
||||
cursor: pointer;
|
||||
&.active {
|
||||
background: rgba(0, 0, 0, 0.04);
|
||||
border-radius: 1rem;
|
||||
}
|
||||
> .icon {
|
||||
margin: 0 1rem;
|
||||
}
|
||||
> .label {
|
||||
color: #000;
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
> .view {
|
||||
margin-left: 3.5rem;
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
&::v-deep(> div) {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 6rem;
|
||||
border-bottom: 0.1rem solid rgba(0, 0, 0, 0.1);
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
> .value,
|
||||
> .label {
|
||||
font-size: 1.4rem;
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -12,13 +12,38 @@
|
||||
<span class="link"></span>
|
||||
<span class="icon" @click="onShop"><svg-icon name="shop" size="21" /></span>
|
||||
</div>
|
||||
<img class="pic" src="@/assets/images/pic.jpg" />
|
||||
<el-popover
|
||||
placement="bottom-end"
|
||||
popper-style="width:auto; min-width: 22rem; padding: 0.8rem; border-radius: 1.4rem;"
|
||||
>
|
||||
<template #reference>
|
||||
<img class="pic" src="@/assets/images/pic.jpg" />
|
||||
</template>
|
||||
<div class="menu-box">
|
||||
<div>
|
||||
<span class="label">{{ email }}</span>
|
||||
</div>
|
||||
<p></p>
|
||||
<div class="btn" @click="onSetting">
|
||||
<span class="icon"><svg-icon name="setting" size="18" /></span>
|
||||
<span class="label">Settings</span>
|
||||
</div>
|
||||
<div class="btn" @click="onLogout">
|
||||
<span class="icon"><svg-icon name="logout" size="18" /></span>
|
||||
<span class="label">Log out</span>
|
||||
</div>
|
||||
</div>
|
||||
</el-popover>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import MyEvent from '@/utils/myEvent'
|
||||
import { computed, ref } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { useUserInfoStore } from '@/stores'
|
||||
const userInfoStore = useUserInfoStore()
|
||||
const email = computed(() => userInfoStore.state.userInfo.email || '------')
|
||||
const route = useRoute()
|
||||
const topNavStyle = computed(() => route.meta.topNavStyle)
|
||||
const router = useRouter()
|
||||
@@ -37,6 +62,12 @@
|
||||
loading.value = false
|
||||
}, 1500)
|
||||
}
|
||||
const onSetting = () => {
|
||||
MyEvent.emit('openSettingDialog')
|
||||
}
|
||||
const onLogout = () => {
|
||||
userInfoStore.logOut()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@@ -68,7 +99,7 @@
|
||||
height: 4.3rem;
|
||||
margin-right: 1rem;
|
||||
background-color: rgba(255, 252, 244, 1);
|
||||
border: 1px solid #FFCF90;
|
||||
border: 1px solid #ffcf90;
|
||||
border-radius: 0.8rem;
|
||||
> .credits {
|
||||
flex: 1;
|
||||
@@ -78,7 +109,7 @@
|
||||
> .link {
|
||||
height: 100%;
|
||||
width: 0;
|
||||
border-right: 1px solid #FFCF90;
|
||||
border-right: 1px solid #ffcf90;
|
||||
}
|
||||
> .icon {
|
||||
cursor: pointer;
|
||||
@@ -88,10 +119,46 @@
|
||||
animation: loading 0.6s linear infinite;
|
||||
}
|
||||
}
|
||||
> .pic {
|
||||
.pic {
|
||||
width: 4.65rem;
|
||||
height: 4.65rem;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
.menu-box {
|
||||
user-select: none;
|
||||
> * {
|
||||
margin-bottom: 0.4rem;
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
> div {
|
||||
height: 3.7rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
// justify-content: center;
|
||||
&.btn {
|
||||
cursor: pointer;
|
||||
}
|
||||
&.btn:hover {
|
||||
background-color: rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
> .label {
|
||||
font-size: 1.4rem;
|
||||
color: #000;
|
||||
margin-left: 0.8rem;
|
||||
}
|
||||
> .icon {
|
||||
margin-left: 1rem;
|
||||
--svg-icon-color: #000;
|
||||
}
|
||||
}
|
||||
> p {
|
||||
width: 100%;
|
||||
height: 0;
|
||||
border-bottom: 0.1rem solid #e5e5e5;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -56,11 +56,14 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Login } from '@/api/login'
|
||||
import { computed, reactive, ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { validateEmail, validatePass, validatePrivacy } from './tools'
|
||||
import OtherLogin from './other-login.vue'
|
||||
import VisibleCode from './visible-code.vue'
|
||||
import { useUserInfoStore } from '@/stores'
|
||||
const userInfoStore = useUserInfoStore()
|
||||
const router = useRouter()
|
||||
const ruleForm = reactive({
|
||||
email: [{ validator: validateEmail, trigger: 'blur' }],
|
||||
@@ -84,16 +87,32 @@
|
||||
const onSubmit = () => {
|
||||
formRef.value?.validate?.((valid) => {
|
||||
if (valid) {
|
||||
console.log('submit!')
|
||||
// console.log('submit!')
|
||||
isVisible.value = true
|
||||
} else {
|
||||
console.log('error submit!')
|
||||
console.warn('error submit!')
|
||||
}
|
||||
})
|
||||
}
|
||||
const onVerifyCode = (code: string) => {
|
||||
console.log(code)
|
||||
router.push({ name: 'mainInput' })
|
||||
// console.log(code)
|
||||
Login({
|
||||
email: formData.email,
|
||||
password: formData.password,
|
||||
verificationCode: code
|
||||
})
|
||||
.then((res) => {
|
||||
if (res) {
|
||||
userInfoStore.setToken(res)
|
||||
userInfoStore.setUserInfo({
|
||||
email: formData.email
|
||||
})
|
||||
router.push({ name: 'mainInput' })
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
console.warn('error verify code!')
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -60,11 +60,14 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Register } from '@/api/login'
|
||||
import { computed, reactive, ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { validateName, validateEmail, validatePass, validatePrivacy } from './tools'
|
||||
import OtherLogin from './other-login.vue'
|
||||
import VisibleCode from './visible-code.vue'
|
||||
import { useUserInfoStore } from '@/stores'
|
||||
const userInfoStore = useUserInfoStore()
|
||||
const router = useRouter()
|
||||
const ruleForm = reactive({
|
||||
name: [{ validator: validateName, trigger: 'blur' }],
|
||||
@@ -90,16 +93,34 @@
|
||||
const onSubmit = () => {
|
||||
formRef.value?.validate?.((valid) => {
|
||||
if (valid) {
|
||||
console.log('submit!')
|
||||
// console.log('submit!')
|
||||
isVisible.value = true
|
||||
} else {
|
||||
console.log('error submit!')
|
||||
console.warn('error submit!')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const onVerifyCode = (code: string) => {
|
||||
console.log(code)
|
||||
router.push({ name: 'nuic' })
|
||||
Register({
|
||||
username: formData.name,
|
||||
email: formData.email,
|
||||
password: formData.password,
|
||||
verificationCode: code
|
||||
})
|
||||
.then((res) => {
|
||||
if (res) {
|
||||
userInfoStore.setToken(res)
|
||||
userInfoStore.setUserInfo({
|
||||
email: formData.email
|
||||
})
|
||||
router.push({ name: 'nuic' })
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
console.warn('error verify code!')
|
||||
})
|
||||
// router.push({ name: 'nuic' })
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { SendVerificationCode } from '@/api/login'
|
||||
import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
|
||||
import { CountDown } from '@/utils/tools'
|
||||
import InputCode from '@/components/input-code.vue'
|
||||
@@ -44,11 +45,20 @@
|
||||
clearTime()
|
||||
})
|
||||
onMounted(() => {
|
||||
setTime()
|
||||
onSendCode()
|
||||
})
|
||||
const onSendCode = async () => {
|
||||
const email = props.email
|
||||
if (!email) {
|
||||
console.warn('请输入邮箱')
|
||||
return
|
||||
}
|
||||
setTime()
|
||||
await SendVerificationCode({ email })
|
||||
}
|
||||
const onResend = () => {
|
||||
if (time.value > 0) return
|
||||
setTime()
|
||||
onSendCode()
|
||||
}
|
||||
const onVerify = () => {
|
||||
if (code.value.length !== 6) return
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<div class="bg-2"></div>
|
||||
<div class="bg-1"></div>
|
||||
</div>
|
||||
<img class="loading-img" :class="{ loading }" src="@/assets/images/nuic/xiang.png" />
|
||||
<img class="loading-img" :class="{ loading }" src="@/assets/images/nuic/xiang.gif" />
|
||||
<div class="loading-tip" :class="{ loading }">{{ $t('Nuic.loadingTip') }}</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -167,7 +167,7 @@
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 14.4rem;
|
||||
width: 60rem;
|
||||
height: auto;
|
||||
opacity: 0;
|
||||
&.loading {
|
||||
|
||||