Author | SHA1 | Message | Date |
---|---|---|---|
congzc | fedcf416d9 | 1 | 1 year ago |
congzc | a9617aecf0 | 1 | 1 year ago |
congzc | 18fff628ca | Merge branch 'dev' of https://git.malls.iformall.com/suimang/Metavatar_Neuver_Admin into dev | 1 year ago |
congzc | caf94c1922 | Merge remote-tracking branch 'origin/dev_czc' into dev | 1 year ago |
congzc | 16a2b1a3fa | 1 | 1 year ago |
HolyKnightIX | 2cc33377a5 | upload | 1 year ago |
HolyKnightIX | fe636bfa31 | add | 1 year ago |
congzc | 850a644381 | Merge branch 'dev' of https://git.malls.iformall.com/suimang/Metavatar_Neuver_Admin into dev | 1 year ago |
congzc | 57d44bc461 | 1 | 1 year ago |
HolyKnightIX | 761197b8d2 | upload | 1 year ago |
HolyKnightIX | c07bcb67c9 | upload | 1 year ago |
HolyKnightIX | bdd6f53bfe | upload | 1 year ago |
@@ -5,6 +5,8 @@ NODE_ENV='development' | |||||
VITE_APP_TITLE = 'Metavatar-PC' | VITE_APP_TITLE = 'Metavatar-PC' | ||||
VITE_APP_PORT = 3000 | VITE_APP_PORT = 3000 | ||||
## VITE_APP_BASE_API = 'https://photo.metavatar.cc/C' | |||||
VITE_APP_BASE_API = 'https://test.metavatar.cc/C' | |||||
## VITE_APP_BASE_API = 'https://photo.metavatar.cc/C' alitest 123456 | |||||
VITE_APP_BASE_API = 'https://mtest.metavatar.cc/A' | |||||
@@ -1,4 +1,4 @@ | |||||
<!-- 照片说话 慧影 --> | |||||
<!-- 邃芒A端--> | |||||
git commit -m "feat: " | git commit -m "feat: " | ||||
git commit --no-verify -m "提交时的注释" 跳过检验 | git commit --no-verify -m "提交时的注释" 跳过检验 | ||||
git merge origin/dev_ | git merge origin/dev_ |
@@ -5,7 +5,7 @@ | |||||
<meta charset="UTF-8" /> | <meta charset="UTF-8" /> | ||||
<link rel="icon" href="/favicon.ico" /> | <link rel="icon" href="/favicon.ico" /> | ||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||||
<title>Metavatar-慧影</title> | |||||
<title>Metavatar-邃芒管理端</title> | |||||
</head> | </head> | ||||
<body> | <body> | ||||
@@ -24,6 +24,7 @@ | |||||
"echarts": "^5.2.2", | "echarts": "^5.2.2", | ||||
"element-plus": "^2.3.1", | "element-plus": "^2.3.1", | ||||
"js-audio-recorder": "^1.0.7", | "js-audio-recorder": "^1.0.7", | ||||
"js-cookie": "^3.0.5", | |||||
"nprogress": "^0.2.0", | "nprogress": "^0.2.0", | ||||
"path-browserify": "^1.0.1", | "path-browserify": "^1.0.1", | ||||
"path-to-regexp": "^6.2.0", | "path-to-regexp": "^6.2.0", | ||||
@@ -0,0 +1,13 @@ | |||||
import request from "@/utils/request.js"; | |||||
/** | |||||
* @description:全查询导航菜单 | |||||
* @param | |||||
* @return: | |||||
*/ | |||||
export function getMenuNavApi() { | |||||
return request({ | |||||
url: `/menu/nav`, | |||||
method: 'get', | |||||
}) | |||||
} |
@@ -2,29 +2,16 @@ import request from "@/utils/request.js"; | |||||
const baseURL = import.meta.env.VITE_APP_BASE_API | const baseURL = import.meta.env.VITE_APP_BASE_API | ||||
/** | |||||
* @description 注册 | |||||
* @params email,password | |||||
* @returns data | |||||
*/ | |||||
export function register(data) { | |||||
return request({ | |||||
// url: `/api/user/doRegisterByEmail`, | |||||
url: `/api/user/doRegisterByPhone`, | |||||
method: 'post', | |||||
data | |||||
}) | |||||
} | |||||
/** | /** | ||||
* @description 登录 | * @description 登录 | ||||
* @params email,password,code | * @params email,password,code | ||||
* @returns data | * @returns data | ||||
*/ | */ | ||||
export function login(data) { | |||||
export function loginApi(data) { | |||||
return request({ | return request({ | ||||
// url: `/api/user/loginByEmail`, | // url: `/api/user/loginByEmail`, | ||||
url: `/api/user/login`, | |||||
url: `/doLogin`, | |||||
method: 'post', | method: 'post', | ||||
data | data | ||||
}) | }) | ||||
@@ -175,5 +162,5 @@ export function resetPwdFormApi(data) { | |||||
* @description:获取图形验证码 | * @description:获取图形验证码 | ||||
* @return: 验证码地址 | * @return: 验证码地址 | ||||
*/ | */ | ||||
export const getCodeImgUrl = baseURL + '/api/user/captcha.jpg' | |||||
export const getCodeImgUrl = baseURL + '/captcha.jpg' | |||||
@@ -70,7 +70,7 @@ export function updUserInfoApi(data) { | |||||
*/ | */ | ||||
export function getUserInfoApi() { | export function getUserInfoApi() { | ||||
return request({ | return request({ | ||||
url: `api/user/getUserInfo`, | |||||
url: `getUserInfo`, | |||||
method: 'get', | method: 'get', | ||||
}) | }) | ||||
} | } |
@@ -0,0 +1,13 @@ | |||||
import request from "@/utils/request.js"; | |||||
/** | |||||
* @description 获取用户列表 | |||||
* @param sex ,pageNum,pageSize | |||||
* @returns data | |||||
*/ | |||||
export function modeListApi(sex, pageNum, pageSize, videoType) { | |||||
return request({ | |||||
url: `/api/personPatch/list?sex=${sex}&pageNum=${pageNum}&pageSize=${pageSize}&videoType=${videoType}`, | |||||
method: 'get' | |||||
}) | |||||
} |
@@ -15,7 +15,7 @@ export default { | |||||
// 登录页面国际化 | // 登录页面国际化 | ||||
login: { | login: { | ||||
// title: "Metavatar-MetaTalker", | // title: "Metavatar-MetaTalker", | ||||
title: "MetaTalker", | |||||
title: "MetaTalker-Admin", | |||||
username: "Username", | username: "Username", | ||||
email: "Phone", | email: "Phone", | ||||
password: "Password", | password: "Password", | ||||
@@ -24,7 +24,7 @@ export default { | |||||
register: "Sign up", | register: "Sign up", | ||||
loginBtn: "Sign in", | loginBtn: "Sign in", | ||||
registerBtn: "Sign up", | registerBtn: "Sign up", | ||||
verifyCode: "Verify code", | |||||
captcha: "Verify code", | |||||
signIn: "Already got an account? Sign in here", | signIn: "Already got an account? Sign in here", | ||||
signUp: "Don't have an account? Sign up here", | signUp: "Don't have an account? Sign up here", | ||||
forgetPwd: "I forgot my password", | forgetPwd: "I forgot my password", | ||||
@@ -203,10 +203,6 @@ export default { | |||||
comingSoon: "Coming Soon", | comingSoon: "Coming Soon", | ||||
}, | }, | ||||
apiMangage: { | |||||
title: "API Mangage", | |||||
}, | |||||
signSucceed: { | signSucceed: { | ||||
title: "Confirm your email", | title: "Confirm your email", | ||||
succeed: "Sign Succeed !", | succeed: "Sign Succeed !", | ||||
@@ -221,6 +217,26 @@ export default { | |||||
}, | }, | ||||
modelMangage: { | modelMangage: { | ||||
title: "Model Set", | |||||
title: "Model", | |||||
}, | |||||
businessMangage: { | |||||
title: "Business", | |||||
}, | |||||
keyMangage: { | |||||
title: "Key", | |||||
}, | |||||
priceMangage: { | |||||
title: "Price", | |||||
}, | |||||
dataCount: { | |||||
title: "DataBoard", | |||||
}, | |||||
apiMangage: { | |||||
title: "API", | |||||
}, | }, | ||||
}; | }; |
@@ -14,7 +14,7 @@ export default { | |||||
}, | }, | ||||
// 登录页面国际化 | // 登录页面国际化 | ||||
login: { | login: { | ||||
title: "慧影", | |||||
title: "邃芒管理端", | |||||
username: "用户名", | username: "用户名", | ||||
email: "手机号", | email: "手机号", | ||||
password: "密码", | password: "密码", | ||||
@@ -23,7 +23,7 @@ export default { | |||||
register: "注册", | register: "注册", | ||||
loginBtn: "登 录", | loginBtn: "登 录", | ||||
registerBtn: "注 册", | registerBtn: "注 册", | ||||
verifyCode: "验证码", | |||||
captcha: "验证码", | |||||
// signIn: "已有账号?现在登录!", | // signIn: "已有账号?现在登录!", | ||||
// signUp: "没有账号?现在加入!", | // signUp: "没有账号?现在加入!", | ||||
signIn: "立即登录", | signIn: "立即登录", | ||||
@@ -203,10 +203,6 @@ export default { | |||||
comingSoon: "敬请期待", | comingSoon: "敬请期待", | ||||
}, | }, | ||||
apiMangage: { | |||||
title: "API 管理", | |||||
}, | |||||
signSucceed: { | signSucceed: { | ||||
title: "确认邮箱", | title: "确认邮箱", | ||||
succeed: "注册成功", | succeed: "注册成功", | ||||
@@ -222,4 +218,24 @@ export default { | |||||
modelMangage: { | modelMangage: { | ||||
title: "模板管理", | title: "模板管理", | ||||
}, | }, | ||||
businessMangage: { | |||||
title: "商务管理", | |||||
}, | |||||
keyMangage: { | |||||
title: "密钥管理", | |||||
}, | |||||
priceMangage: { | |||||
title: "价格管理", | |||||
}, | |||||
dataCount: { | |||||
title: "数据统计", | |||||
}, | |||||
apiMangage: { | |||||
title: "API 管理", | |||||
}, | |||||
}; | }; |
@@ -1,119 +0,0 @@ | |||||
<template> | |||||
<div> | |||||
<!-- 侧边栏 --> | |||||
<div><Sidebar class="sidebar-container" /></div> | |||||
<!-- 页面主体 --> | |||||
<div> | |||||
<!-- nav --> | |||||
<div><navbar /></div> | |||||
<!-- 页面主体 --> | |||||
<div><app-main /></div> | |||||
</div> | |||||
</div> | |||||
</template> | |||||
<script setup lang="ts"> | |||||
import { computed, watchEffect } from "vue"; | |||||
import { useWindowSize } from "@vueuse/core"; | |||||
import { AppMain, Navbar } from "./components/index"; | |||||
import SignSucceed from "../views/signSucceed/index.vue"; | |||||
import Sidebar from "./components/Sidebar/index.vue"; | |||||
import { useAppStore } from "@/store/modules/app"; | |||||
import { useSettingsStore } from "@/store/modules/settings"; | |||||
import { useRoute, useRouter } from "vue-router"; | |||||
const route = useRoute(); | |||||
const { params } = route; | |||||
const { width } = useWindowSize(); | |||||
/** | |||||
* 响应式布局容器固定宽度 | |||||
* | |||||
* 大屏(>=1200px) | |||||
* 中屏(>=992px) | |||||
* 小屏(>=768px) | |||||
*/ | |||||
const WIDTH = 992; | |||||
const appStore = useAppStore(); | |||||
const settingsStore = useSettingsStore(); | |||||
const fixedHeader = computed(() => settingsStore.fixedHeader); | |||||
const showTagsView = computed(() => settingsStore.tagsView); | |||||
const showSettings = computed(() => settingsStore.showSettings); | |||||
const classObj = computed(() => ({ | |||||
hideSidebar: !appStore.sidebar.opened, | |||||
openSidebar: appStore.sidebar.opened, | |||||
withoutAnimation: appStore.sidebar.withoutAnimation, | |||||
mobile: appStore.device === "mobile", | |||||
})); | |||||
watchEffect(() => { | |||||
if (width.value < WIDTH) { | |||||
appStore.toggleDevice("mobile"); | |||||
appStore.closeSideBar(true); | |||||
} else { | |||||
appStore.toggleDevice("desktop"); | |||||
if (width.value >= 1200) { | |||||
//大屏 | |||||
appStore.openSideBar(true); | |||||
} else { | |||||
appStore.closeSideBar(true); | |||||
} | |||||
} | |||||
}); | |||||
function handleOutsideClick() { | |||||
appStore.closeSideBar(false); | |||||
} | |||||
onMounted(() => {}); | |||||
</script> | |||||
<style lang="scss" scoped> | |||||
.app-wrapper { | |||||
&::after { | |||||
display: table; | |||||
clear: both; | |||||
content: ""; | |||||
} | |||||
position: relative; | |||||
width: 100%; | |||||
height: 100%; | |||||
e &.mobile.openSidebar { | |||||
position: fixed; | |||||
top: 0; | |||||
} | |||||
} | |||||
.fixed-header { | |||||
position: fixed; | |||||
top: 0; | |||||
right: 0; | |||||
z-index: 9; | |||||
width: calc(100% - #{$sideBarWidth}); | |||||
transition: width 0.28s; | |||||
} | |||||
.hideSidebar .fixed-header { | |||||
width: calc(100% - 54px); | |||||
} | |||||
.mobile .fixed-header { | |||||
width: 100%; | |||||
} | |||||
.drawer-bg { | |||||
position: absolute; | |||||
top: 0; | |||||
z-index: 999; | |||||
width: 100%; | |||||
height: 100%; | |||||
// background: #1b213a; | |||||
background: #000; | |||||
opacity: 0.3; | |||||
} | |||||
</style> |
@@ -1,131 +0,0 @@ | |||||
<template> | |||||
<div :class="classObj" class="app-wrapper"> | |||||
<!-- 手机设备侧边栏打开遮罩层 --> | |||||
<div | |||||
v-if="classObj.mobile && classObj.openSidebar" | |||||
class="drawer-bg" | |||||
@click="handleOutsideClick" | |||||
></div> | |||||
<Sidebar class="sidebar-container" /> | |||||
<div :class="{ hasTagsView: showTagsView }" class="main-container"> | |||||
<div | |||||
:class="{ 'fixed-header': fixedHeader }" | |||||
style="box-shadow: rgba(0, 0, 0, 0.05) 0px 4px 4px; height: 80px" | |||||
> | |||||
<navbar /> | |||||
<tags-view v-if="showTagsView" /> | |||||
</div> | |||||
<!-- 主页面 --> | |||||
<app-main /> | |||||
</div> | |||||
</div> | |||||
</template> | |||||
<script setup lang="ts"> | |||||
import { computed, watchEffect } from "vue"; | |||||
import { useWindowSize } from "@vueuse/core"; | |||||
import { AppMain, Navbar } from "./components/index"; | |||||
import SignSucceed from "../views/signSucceed/index.vue"; | |||||
import Sidebar from "./components/Sidebar/index.vue"; | |||||
import { useAppStore } from "@/store/modules/app"; | |||||
import { useSettingsStore } from "@/store/modules/settings"; | |||||
import { useRoute, useRouter } from "vue-router"; | |||||
const route = useRoute(); | |||||
const { params } = route; | |||||
const { width } = useWindowSize(); | |||||
/** | |||||
* 响应式布局容器固定宽度 | |||||
* | |||||
* 大屏(>=1200px) | |||||
* 中屏(>=992px) | |||||
* 小屏(>=768px) | |||||
*/ | |||||
const WIDTH = 992; | |||||
const appStore = useAppStore(); | |||||
const settingsStore = useSettingsStore(); | |||||
const fixedHeader = computed(() => settingsStore.fixedHeader); | |||||
const showTagsView = computed(() => settingsStore.tagsView); | |||||
const showSettings = computed(() => settingsStore.showSettings); | |||||
const classObj = computed(() => ({ | |||||
hideSidebar: !appStore.sidebar.opened, | |||||
openSidebar: appStore.sidebar.opened, | |||||
withoutAnimation: appStore.sidebar.withoutAnimation, | |||||
mobile: appStore.device === "mobile", | |||||
})); | |||||
watchEffect(() => { | |||||
if (width.value < WIDTH) { | |||||
appStore.toggleDevice("mobile"); | |||||
appStore.closeSideBar(true); | |||||
} else { | |||||
appStore.toggleDevice("desktop"); | |||||
if (width.value >= 1200) { | |||||
//大屏 | |||||
appStore.openSideBar(true); | |||||
} else { | |||||
appStore.closeSideBar(true); | |||||
} | |||||
} | |||||
}); | |||||
function handleOutsideClick() { | |||||
appStore.closeSideBar(false); | |||||
} | |||||
onMounted(() => {}); | |||||
</script> | |||||
<style lang="scss" scoped> | |||||
.app-wrapper { | |||||
&::after { | |||||
display: table; | |||||
clear: both; | |||||
content: ""; | |||||
} | |||||
position: relative; | |||||
width: 100%; | |||||
height: 100%; | |||||
e &.mobile.openSidebar { | |||||
position: fixed; | |||||
top: 0; | |||||
} | |||||
} | |||||
.fixed-header { | |||||
position: fixed; | |||||
top: 0; | |||||
right: 0; | |||||
z-index: 9; | |||||
width: calc(100% - #{$sideBarWidth}); | |||||
transition: width 0.28s; | |||||
} | |||||
.hideSidebar .fixed-header { | |||||
width: calc(100% - 54px); | |||||
} | |||||
.mobile .fixed-header { | |||||
width: 100%; | |||||
} | |||||
.drawer-bg { | |||||
position: absolute; | |||||
top: 0; | |||||
z-index: 999; | |||||
width: 100%; | |||||
height: 100%; | |||||
// background: #1b213a; | |||||
background: #000; | |||||
opacity: 0.3; | |||||
} | |||||
</style> |
@@ -11,19 +11,69 @@ | |||||
</div> | </div> | ||||
<!-- 侧边路由列表 --> | <!-- 侧边路由列表 --> | ||||
<div class="myRouter"> | <div class="myRouter"> | ||||
<div class="myRouter-item" @click="router.push('/createVideo')"> | |||||
<!-- 动态路由 --> | |||||
<div | |||||
v-for="item in MenuList" | |||||
:key="item.id" | |||||
class="myRouter-item" | |||||
@click="showChildrenRouter = item.name" | |||||
> | |||||
<div class="icon"> | |||||
<el-icon><i-ep-edit /></el-icon> | |||||
<span>{{ item.name }}</span> | |||||
</div> | |||||
<div | |||||
v-show="showChildrenRouter == item.name" | |||||
v-for="childrens in item.children" | |||||
:key="childrens.id" | |||||
class="childrenRouter" | |||||
@click="router.push(`/${childrens.url}`)" | |||||
> | |||||
{{ childrens.name }} | |||||
</div> | |||||
</div> | |||||
<!-- 固定路由 --> | |||||
<div class="myRouter-item" @click="router.push('/model')"> | |||||
<div class="icon"> | |||||
<el-icon><i-ep-edit /></el-icon> | |||||
{{ $t("modelMangage.title") }} | |||||
</div> | |||||
</div> | |||||
<div class="myRouter-item" @click="router.push('/model')"> | |||||
<div class="icon"> | |||||
<el-icon><i-ep-edit /></el-icon> | |||||
{{ $t("businessMangage.title") }} | |||||
</div> | |||||
</div> | |||||
<div class="myRouter-item" @click="router.push('/keyCheck')"> | |||||
<div class="icon"> | |||||
<el-icon><i-ep-edit /></el-icon> | |||||
{{ $t("keyMangage.title") }} | |||||
</div> | |||||
</div> | |||||
<div class="myRouter-item" @click="router.push('/model')"> | |||||
<div class="icon"> | <div class="icon"> | ||||
<el-icon><i-ep-edit /></el-icon> | <el-icon><i-ep-edit /></el-icon> | ||||
{{ $t("priceMangage.title") }} | |||||
</div> | |||||
</div> | |||||
<div class="myRouter-item" @click="router.push('/model')"> | |||||
<div class="icon"> | |||||
<el-icon><i-ep-edit /></el-icon> | |||||
{{ $t("dataCount.title") }} | |||||
</div> | </div> | ||||
{{ $t("modelMangage.title") }} | |||||
</div> | </div> | ||||
<div class="bottomBtx"> | <div class="bottomBtx"> | ||||
<div class="myRouter-item" @click="router.push('/myAPI')"> | |||||
<div class="myRouter-item" @click="router.push('/model')"> | |||||
<div class="icon"> | <div class="icon"> | ||||
<el-icon><i-ep-DocumentAdd /></el-icon> | <el-icon><i-ep-DocumentAdd /></el-icon> | ||||
{{ $t("apiMangage.title") }} | |||||
</div> | </div> | ||||
{{ $t("apiMangage.title") }} | |||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
@@ -77,7 +127,7 @@ import { useAppStore } from "@/store/modules/app"; | |||||
// import { useSettingsStore } from "@/store/modules/settings"; | // import { useSettingsStore } from "@/store/modules/settings"; | ||||
import { useRoute, useRouter } from "vue-router"; | import { useRoute, useRouter } from "vue-router"; | ||||
import { useI18n } from "vue-i18n"; | import { useI18n } from "vue-i18n"; | ||||
import { getMenuNavApi } from "@/apis/Permission.js"; | |||||
import { userInfoModules } from "@/store/modules/userInfo"; | import { userInfoModules } from "@/store/modules/userInfo"; | ||||
const userInfoPinia = userInfoModules(); | const userInfoPinia = userInfoModules(); | ||||
@@ -138,12 +188,31 @@ function handleOutsideClick() { | |||||
appStore.closeSideBar(false); | appStore.closeSideBar(false); | ||||
} | } | ||||
onMounted(() => {}); | |||||
onMounted(() => { | |||||
getMenuNavFunc(); | |||||
}); | |||||
//#region 联系我们弹窗 | //#region 联系我们弹窗 | ||||
const showTalkUsDialog = ref(false); | const showTalkUsDialog = ref(false); | ||||
const updateShowTalkUsDialog = (newValue: any) => { | const updateShowTalkUsDialog = (newValue: any) => { | ||||
showTalkUsDialog.value = newValue; | showTalkUsDialog.value = newValue; | ||||
}; | }; | ||||
//#endregion ------------------------------------ | |||||
//#region 获取路由列表 | |||||
const MenuList = ref([{ id: "", name: "" }]); | |||||
async function getMenuNavFunc() { | |||||
try { | |||||
const res = await getMenuNavApi(); | |||||
MenuList.value = res.data.menuList; | |||||
} catch (error) { | |||||
console.log(error); | |||||
} | |||||
} | |||||
//#endregion ------------------------------------ | |||||
//#region 路由及子路由 | |||||
const showChildrenRouter = ref(""); | |||||
//#endregion ------------------------------------ | //#endregion ------------------------------------ | ||||
</script> | </script> | ||||
@@ -179,10 +248,10 @@ const updateShowTalkUsDialog = (newValue: any) => { | |||||
bottom: 30px; | bottom: 30px; | ||||
} | } | ||||
&-item { | &-item { | ||||
display: flex; | |||||
// display: flex; | |||||
width: 100%; | width: 100%; | ||||
height: 50px; | |||||
padding-left: 10px; | |||||
// height: 50px; | |||||
// padding-left: 10px; | |||||
font-size: 20px; | font-size: 20px; | ||||
font-weight: 500; | font-weight: 500; | ||||
line-height: 50px; | line-height: 50px; | ||||
@@ -193,14 +262,20 @@ const updateShowTalkUsDialog = (newValue: any) => { | |||||
border-radius: 5px; | border-radius: 5px; | ||||
margin-bottom: 20px; | margin-bottom: 20px; | ||||
margin-right: 20px; | margin-right: 20px; | ||||
overflow: hidden; | |||||
.icon { | .icon { | ||||
width: 40px; | |||||
height: 40px; | |||||
display: flex; | |||||
color: #fff; | color: #fff; | ||||
border-radius: 50%; | border-radius: 50%; | ||||
margin-right: 10px; | |||||
width: 100%; | |||||
height: 50px; | |||||
line-height: 50px; | |||||
.el-icon { | .el-icon { | ||||
margin-left: 10px; | |||||
margin-top: 12px; | |||||
margin-right: 10px; | |||||
width: 25px; | width: 25px; | ||||
height: 25px; | height: 25px; | ||||
font-size: 25px; | font-size: 25px; | ||||
@@ -210,11 +285,20 @@ const updateShowTalkUsDialog = (newValue: any) => { | |||||
vertical-align: sub; | vertical-align: sub; | ||||
} | } | ||||
} | } | ||||
.childrenRouter { | |||||
cursor: pointer; | |||||
} | |||||
.childrenRouter:hover { | |||||
background-color: #304156; | |||||
} | |||||
&:hover { | &:hover { | ||||
// background: rgba(255, 255, 255, 0.2); | // background: rgba(255, 255, 255, 0.2); | ||||
color: #000; | color: #000; | ||||
background: #fff; | background: #fff; | ||||
.icon { | |||||
color: #000; | |||||
} | |||||
.el-icon { | .el-icon { | ||||
// color: #d4d0ff; | // color: #d4d0ff; | ||||
color: #000; | color: #000; | ||||
@@ -9,35 +9,36 @@ NProgress.configure({ showSpinner: false }); // 进度条 | |||||
const permissionStore = usePermissionStoreHook(); | const permissionStore = usePermissionStoreHook(); | ||||
// 白名单路由 | // 白名单路由 | ||||
const whiteList = ["/login", "/signSucceed",'/createVideo','/moveImg']; | |||||
const whiteList = ["/login", "/signSucceed", "/createVideo", "/moveImg"]; | |||||
router.beforeEach(async (to, from, next) => { | router.beforeEach(async (to, from, next) => { | ||||
NProgress.start(); | NProgress.start(); | ||||
const AccessToken = localStorage.getItem("AccessToken"); | const AccessToken = localStorage.getItem("AccessToken"); | ||||
next(); | |||||
// 已登录 | // 已登录 | ||||
if (AccessToken) { | |||||
// 重置密码时可以去往login页面 | |||||
if ((to.params.type as string) == "4") { | |||||
next(); | |||||
} | |||||
if (to.query.resetPwd) { | |||||
next(); | |||||
} | |||||
if (to.path === "/login") { | |||||
next({ path: "/createVideo" }); | |||||
} else { | |||||
next(); | |||||
} | |||||
// 未登录 | |||||
} else { | |||||
// 未登录可以访问白名单页面 | |||||
if (whiteList.indexOf(to.path) !== -1) { | |||||
next(); | |||||
} else { | |||||
// 不在白名单内,跳转登录页 | |||||
next({ path: "/login" }); | |||||
} | |||||
} | |||||
// if (AccessToken) { | |||||
// // 重置密码时可以去往login页面 | |||||
// if ((to.params.type as string) == "4") { | |||||
// next(); | |||||
// } | |||||
// if (to.query.resetPwd) { | |||||
// next(); | |||||
// } | |||||
// if (to.path === "/login") { | |||||
// next({ path: "/createVideo" }); | |||||
// } else { | |||||
// next(); | |||||
// } | |||||
// // 未登录 | |||||
// } else { | |||||
// // 未登录可以访问白名单页面 | |||||
// if (whiteList.indexOf(to.path) !== -1) { | |||||
// next(); | |||||
// } else { | |||||
// // 不在白名单内,跳转登录页 | |||||
// next({ path: "/login" }); | |||||
// } | |||||
// } | |||||
}); | }); | ||||
router.afterEach(() => { | router.afterEach(() => { | ||||
@@ -5,87 +5,72 @@ export const Layout = () => import("@/layout/index.vue"); | |||||
// 静态路由 | // 静态路由 | ||||
export const constantRoutes: RouteRecordRaw[] = [ | export const constantRoutes: RouteRecordRaw[] = [ | ||||
// 登录 | // 登录 | ||||
{ | { | ||||
path: "/login", | path: "/login", | ||||
component: () => import("@/views/login/index.vue"), | component: () => import("@/views/login/index.vue"), | ||||
meta: { hidden: true }, | meta: { hidden: true }, | ||||
name:'login' | |||||
name: "login", | |||||
}, | }, | ||||
{ | { | ||||
path: "/signSucceed", | path: "/signSucceed", | ||||
component: () => import("@/views/signSucceed/index.vue"), | component: () => import("@/views/signSucceed/index.vue"), | ||||
meta: { hidden: true }, | meta: { hidden: true }, | ||||
}, | }, | ||||
// 创建视频 | |||||
{ | { | ||||
path: "/", | path: "/", | ||||
component: Layout, | component: Layout, | ||||
redirect: "/createVideo", | |||||
redirect: "/model", | |||||
children: [ | children: [ | ||||
{ | { | ||||
path: "createVideo", | |||||
component: () => import("@/views/createVideo/index.vue"), | |||||
name: "createVideo", | |||||
path: "model", | |||||
component: () => import("@/views/mangage/model.vue"), | |||||
name: "model", | |||||
meta: { | meta: { | ||||
title: "createVideo", | |||||
title: "model", | |||||
icon: "homepage", | icon: "homepage", | ||||
affix: true, | affix: true, | ||||
name: "createVideo.title", | |||||
name: "modelMangage.title", | |||||
}, | }, | ||||
}, | }, | ||||
], | ], | ||||
}, | }, | ||||
// 视频列表 | |||||
{ | { | ||||
path: "/", | path: "/", | ||||
component: Layout, | component: Layout, | ||||
redirect: "/myCreating", | |||||
redirect: "/keyCheck", | |||||
children: [ | children: [ | ||||
{ | { | ||||
path: "myCreating", | |||||
component: () => import("@/views/myCreating/index.vue"), | |||||
name: "myCreating", | |||||
path: "keyCheck", | |||||
component: () => import("@/views/mangage/keyCheck.vue"), | |||||
name: "keyCheck", | |||||
meta: { | meta: { | ||||
title: "myCreating", | |||||
title: "keyCheck", | |||||
icon: "homepage", | icon: "homepage", | ||||
affix: true, | affix: true, | ||||
name: "myCreating.title", | |||||
name: "keyMangage.title", | |||||
}, | }, | ||||
}, | }, | ||||
], | ], | ||||
}, { | |||||
path: "/", | |||||
component: Layout, | |||||
redirect: "/myStore", | |||||
children: [ | |||||
{ | |||||
path: "myStore", | |||||
component: () => import("@/views/myStore/index.vue"), | |||||
name: "myStore", | |||||
meta: { | |||||
title: "myStore", | |||||
icon: "homepage", | |||||
affix: true, | |||||
name: "myStore.title", | |||||
}, | |||||
}, | |||||
], | |||||
}, { | |||||
}, | |||||
// 系统设置路由 | |||||
{ | |||||
path: "/", | path: "/", | ||||
component: Layout, | component: Layout, | ||||
redirect: "/myAPI", | |||||
redirect: "/userList", | |||||
children: [ | children: [ | ||||
{ | { | ||||
path: "myAPI", | |||||
component: () => import("@/views/myAPI/index.vue"), | |||||
name: "myAPI", | |||||
path: "userList", | |||||
component: () => import("@/views/dict/index.vue"), | |||||
name: "userList", | |||||
meta: { | meta: { | ||||
title: "myAPI", | |||||
title: "userList", | |||||
icon: "homepage", | icon: "homepage", | ||||
affix: true, | affix: true, | ||||
name: "API.title", | |||||
name: "userListMangage.title", | |||||
}, | }, | ||||
}, | }, | ||||
], | ], | ||||
@@ -93,22 +78,21 @@ export const constantRoutes: RouteRecordRaw[] = [ | |||||
{ | { | ||||
path: "/", | path: "/", | ||||
component: Layout, | component: Layout, | ||||
redirect: "/moveImg", | |||||
redirect: "/ruleList", | |||||
children: [ | children: [ | ||||
{ | { | ||||
path: "moveImg", | |||||
component: () => import("@/views/moveImg/index.vue"), | |||||
name: "moveImg", | |||||
path: "ruleList", | |||||
component: () => import("@/views/mangage/ruleList.vue"), | |||||
name: "ruleList", | |||||
meta: { | meta: { | ||||
title: "moveImg", | |||||
title: "ruleList", | |||||
icon: "homepage", | icon: "homepage", | ||||
affix: true, | affix: true, | ||||
name: "moveImg.title", | |||||
name: "ruleListMangage.title", | |||||
}, | }, | ||||
}, | }, | ||||
], | ], | ||||
}, | }, | ||||
]; | ]; | ||||
/** | /** | ||||
@@ -2,7 +2,6 @@ | |||||
export {} | export {} | ||||
declare global { | declare global { | ||||
const EffectScope: typeof import('vue')['EffectScope'] | const EffectScope: typeof import('vue')['EffectScope'] | ||||
const ElForm: typeof import('element-plus/es')['ElForm'] | |||||
const ElMessage: typeof import('element-plus/es')['ElMessage'] | const ElMessage: typeof import('element-plus/es')['ElMessage'] | ||||
const ElMessageBox: typeof import('element-plus/es')['ElMessageBox'] | const ElMessageBox: typeof import('element-plus/es')['ElMessageBox'] | ||||
const asyncComputed: typeof import('@vueuse/core')['asyncComputed'] | const asyncComputed: typeof import('@vueuse/core')['asyncComputed'] | ||||
@@ -271,7 +270,6 @@ import { UnwrapRef } from 'vue' | |||||
declare module 'vue' { | declare module 'vue' { | ||||
interface ComponentCustomProperties { | interface ComponentCustomProperties { | ||||
readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']> | readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']> | ||||
readonly ElForm: UnwrapRef<typeof import('element-plus/es')['ElForm']> | |||||
readonly ElMessage: UnwrapRef<typeof import('element-plus/es')['ElMessage']> | readonly ElMessage: UnwrapRef<typeof import('element-plus/es')['ElMessage']> | ||||
readonly ElMessageBox: UnwrapRef<typeof import('element-plus/es')['ElMessageBox']> | readonly ElMessageBox: UnwrapRef<typeof import('element-plus/es')['ElMessageBox']> | ||||
readonly asyncComputed: UnwrapRef<typeof import('@vueuse/core')['asyncComputed']> | readonly asyncComputed: UnwrapRef<typeof import('@vueuse/core')['asyncComputed']> | ||||
@@ -14,6 +14,7 @@ declare module '@vue/runtime-core' { | |||||
EditPosition: typeof import('./../components/EditPosition.vue')['default'] | EditPosition: typeof import('./../components/EditPosition.vue')['default'] | ||||
'EditPosition copy': typeof import('./../components/EditPosition copy.vue')['default'] | 'EditPosition copy': typeof import('./../components/EditPosition copy.vue')['default'] | ||||
ElButton: typeof import('element-plus/es')['ElButton'] | ElButton: typeof import('element-plus/es')['ElButton'] | ||||
ElCard: typeof import('element-plus/es')['ElCard'] | |||||
ElDialog: typeof import('element-plus/es')['ElDialog'] | ElDialog: typeof import('element-plus/es')['ElDialog'] | ||||
ElDropdown: typeof import('element-plus/es')['ElDropdown'] | ElDropdown: typeof import('element-plus/es')['ElDropdown'] | ||||
ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem'] | ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem'] | ||||
@@ -25,26 +26,25 @@ declare module '@vue/runtime-core' { | |||||
ElInputNumber: typeof import('element-plus/es')['ElInputNumber'] | ElInputNumber: typeof import('element-plus/es')['ElInputNumber'] | ||||
ElOption: typeof import('element-plus/es')['ElOption'] | ElOption: typeof import('element-plus/es')['ElOption'] | ||||
ElPagination: typeof import('element-plus/es')['ElPagination'] | ElPagination: typeof import('element-plus/es')['ElPagination'] | ||||
ElRadio: typeof import('element-plus/es')['ElRadio'] | |||||
ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup'] | |||||
ElSelect: typeof import('element-plus/es')['ElSelect'] | ElSelect: typeof import('element-plus/es')['ElSelect'] | ||||
ElSwitch: typeof import('element-plus/es')['ElSwitch'] | ElSwitch: typeof import('element-plus/es')['ElSwitch'] | ||||
ElTable: typeof import('element-plus/es')['ElTable'] | |||||
ElTableColumn: typeof import('element-plus/es')['ElTableColumn'] | |||||
ElTag: typeof import('element-plus/es')['ElTag'] | |||||
ElTooltip: typeof import('element-plus/es')['ElTooltip'] | ElTooltip: typeof import('element-plus/es')['ElTooltip'] | ||||
ElUpload: typeof import('element-plus/es')['ElUpload'] | ElUpload: typeof import('element-plus/es')['ElUpload'] | ||||
GithubCorner: typeof import('./../components/GithubCorner/index.vue')['default'] | GithubCorner: typeof import('./../components/GithubCorner/index.vue')['default'] | ||||
Hamburger: typeof import('./../components/Hamburger/index.vue')['default'] | Hamburger: typeof import('./../components/Hamburger/index.vue')['default'] | ||||
IconSelect: typeof import('./../components/IconSelect/index.vue')['default'] | IconSelect: typeof import('./../components/IconSelect/index.vue')['default'] | ||||
IEpCloseBold: typeof import('~icons/ep/close-bold')['default'] | |||||
IEpCollection: typeof import('~icons/ep/collection')['default'] | |||||
IEpDelete: typeof import('~icons/ep/delete')['default'] | IEpDelete: typeof import('~icons/ep/delete')['default'] | ||||
IEpDocumentAdd: typeof import('~icons/ep/document-add')['default'] | IEpDocumentAdd: typeof import('~icons/ep/document-add')['default'] | ||||
IEpDownload: typeof import('~icons/ep/download')['default'] | |||||
IEpEdit: typeof import('~icons/ep/edit')['default'] | IEpEdit: typeof import('~icons/ep/edit')['default'] | ||||
IEpGoods: typeof import('~icons/ep/goods')['default'] | |||||
IEpLoading: typeof import('~icons/ep/loading')['default'] | |||||
IEpLock: typeof import('~icons/ep/lock')['default'] | |||||
IEpMenu: typeof import('~icons/ep/menu')['default'] | |||||
IEpPhone: typeof import('~icons/ep/phone')['default'] | |||||
IEpPlus: typeof import('~icons/ep/plus')['default'] | |||||
IEpRefresh: typeof import('~icons/ep/refresh')['default'] | |||||
IEpSearch: typeof import('~icons/ep/search')['default'] | IEpSearch: typeof import('~icons/ep/search')['default'] | ||||
IEpUser: typeof import('~icons/ep/user')['default'] | |||||
IEpVideoPlay: typeof import('~icons/ep/video-play')['default'] | |||||
LangSelect: typeof import('./../components/LangSelect/index.vue')['default'] | LangSelect: typeof import('./../components/LangSelect/index.vue')['default'] | ||||
MultiUpload: typeof import('./../components/Upload/MultiUpload.vue')['default'] | MultiUpload: typeof import('./../components/Upload/MultiUpload.vue')['default'] | ||||
MyLoading: typeof import('./../components/myLoading.vue')['default'] | MyLoading: typeof import('./../components/myLoading.vue')['default'] | ||||
@@ -60,5 +60,6 @@ declare module '@vue/runtime-core' { | |||||
} | } | ||||
export interface ComponentCustomProperties { | export interface ComponentCustomProperties { | ||||
vInfiniteScroll: typeof import('element-plus/es')['ElInfiniteScroll'] | vInfiniteScroll: typeof import('element-plus/es')['ElInfiniteScroll'] | ||||
vLoading: typeof import('element-plus/es')['ElLoadingDirective'] | |||||
} | } | ||||
} | } |
@@ -1,67 +0,0 @@ | |||||
import axios from 'axios' | |||||
import router from '@/router/index' | |||||
import { ElMessage } from 'element-plus' | |||||
// ElMessage | |||||
import { userInfoModules } from "@/store/modules/userInfo"; | |||||
// import stores from '@/store/index' | |||||
import { store } from '@/store/index'; // 因为不是在setup环境而是js中,必须重新初始化加载store | |||||
const userInfoPinia = userInfoModules(store); //pinia | |||||
// 开发环境需以 "/api" 拼接,其他环境需以 "/C" 拼接 | |||||
const env = process.env.NODE_ENV == 'development' ? "/api" : "/C" | |||||
// console.log(process.env.NODE_ENV, 'env') | |||||
/** | |||||
* @description:发送Axios请求 | |||||
*/ | |||||
const request = axios.create({ | |||||
baseURL: env, | |||||
timeout: 15000 | |||||
}) | |||||
// 请求拦截器 | |||||
request.interceptors.request.use( | |||||
function (config) { | |||||
// 给所有授权的请求提供token | |||||
const AccessToken = localStorage.getItem("AccessToken") | |||||
if (AccessToken) { | |||||
config.headers.token = AccessToken | |||||
} | |||||
return config | |||||
}, | |||||
function (error) { | |||||
// 操作 | |||||
return Promise.reject(error) | |||||
} | |||||
) | |||||
// 响应拦截器 | |||||
request.interceptors.response.use( | |||||
function (response) { | |||||
let code = response.data.code | |||||
// 当token无效(过期或损坏)时 1053为未登录 | |||||
if (code == 1052 || code == 1053) { | |||||
localStorage.removeItem("AccessToken"); | |||||
router.push("/login"); | |||||
ElMessage.error("登录过期,请重新登录!"); | |||||
return | |||||
// 弹出错误 | |||||
} else if (code != 200) { | |||||
if (code == 500) { | |||||
ElMessage.error("系统异常,请稍后再试"); | |||||
// 其他错误 | |||||
} else { | |||||
return Promise.reject(response.data) | |||||
} | |||||
} else { | |||||
// 正常返回 | |||||
return response.data | |||||
} | |||||
}, | |||||
function (error) { | |||||
} | |||||
) | |||||
export default request |
@@ -11,8 +11,8 @@ const appStore = useAppStore(store); //pinia | |||||
const userInfoPinia = userInfoModules(store); //pinia | const userInfoPinia = userInfoModules(store); //pinia | ||||
// const userInfoPinia = userInfoModules(store); //pinia | // const userInfoPinia = userInfoModules(store); //pinia | ||||
// 开发环境需以 "/api" 拼接,其他环境需以 "/C" 拼接 | // 开发环境需以 "/api" 拼接,其他环境需以 "/C" 拼接 | ||||
const env = process.env.NODE_ENV == 'development' ? "/api" : "/C" | |||||
// const env = process.env.NODE_ENV == 'development' ? "" : "" | |||||
// const env = process.env.NODE_ENV == 'development' ? "/api" : "/C" | |||||
const env = process.env.NODE_ENV == 'development' ? "/A" : "/A" | |||||
console.log(env) | console.log(env) | ||||
/** | /** | ||||
@@ -60,7 +60,7 @@ request.interceptors.response.use( | |||||
let code = response.data.code | let code = response.data.code | ||||
// 当token无效(过期或损坏)时 1053为未登录 | // 当token无效(过期或损坏)时 1053为未登录 | ||||
if (code == 1052 || code == 1053) { | if (code == 1052 || code == 1053) { | ||||
localStorage.removeItem("AccessToken"); | |||||
// localStorage.removeItem("AccessToken"); | |||||
router.push("/login"); | router.push("/login"); | ||||
// ElMessage.error("登录过期,请重新登录!"); | // ElMessage.error("登录过期,请重新登录!"); | ||||
// ElMessage.error($t('tips.tokenExpired')); | // ElMessage.error($t('tips.tokenExpired')); | ||||
@@ -757,8 +757,8 @@ const soundStyle = ref(""); //选择的风格 | |||||
// 语言下拉框内容 | // 语言下拉框内容 | ||||
const languageOptions = ref([]); | const languageOptions = ref([]); | ||||
async function voiceTotal() { | async function voiceTotal() { | ||||
const res = await voiceTotalApi(); | |||||
languageOptions.value = res.data; | |||||
// const res = await voiceTotalApi(); | |||||
// languageOptions.value = res.data; | |||||
} | } | ||||
// 声音下拉框内容 | // 声音下拉框内容 | ||||
const soundOptions = ref([]); | const soundOptions = ref([]); | ||||
@@ -0,0 +1,325 @@ | |||||
<!-- 字典数据 --> | |||||
<script setup lang="ts"> | |||||
import { | |||||
getDictPage, | |||||
getDictFormData, | |||||
addDict, | |||||
updateDict, | |||||
deleteDict, | |||||
} from "@/api/dict"; | |||||
import { DictPageVO, DictForm, DictQuery } from "@/api/dict/types"; | |||||
defineOptions({ | |||||
name: "DictData", | |||||
inheritAttrs: false, | |||||
}); | |||||
const props = defineProps({ | |||||
typeCode: { | |||||
type: String, | |||||
default: () => { | |||||
return ""; | |||||
}, | |||||
}, | |||||
typeName: { | |||||
type: String, | |||||
default: () => { | |||||
return ""; | |||||
}, | |||||
}, | |||||
}); | |||||
watch( | |||||
() => props.typeCode, | |||||
(newVal: string) => { | |||||
queryParams.typeCode = newVal; | |||||
formData.typeCode = newVal; | |||||
resetQuery(); | |||||
} | |||||
); | |||||
const queryFormRef = ref(ElForm); | |||||
const dataFormRef = ref(ElForm); | |||||
const loading = ref(false); | |||||
const ids = ref<number[]>([]); | |||||
const total = ref(0); | |||||
const queryParams = reactive<DictQuery>({ | |||||
pageNum: 1, | |||||
pageSize: 10, | |||||
typeCode: props.typeCode, | |||||
}); | |||||
const dictList = ref<DictPageVO[]>(); | |||||
const dialog = reactive<DialogOption>({ | |||||
visible: false, | |||||
}); | |||||
const formData = reactive<DictForm>({ | |||||
status: 1, | |||||
typeCode: props.typeCode, | |||||
sort: 1, | |||||
}); | |||||
const rules = reactive({ | |||||
name: [{ required: true, message: "请输入字典名称", trigger: "blur" }], | |||||
value: [{ required: true, message: "请输入字典值", trigger: "blur" }], | |||||
}); | |||||
/** | |||||
* 查询 | |||||
*/ | |||||
function handleQuery() { | |||||
if (queryParams.typeCode) { | |||||
loading.value = true; | |||||
getDictPage(queryParams) | |||||
.then(({ data }) => { | |||||
dictList.value = data.list; | |||||
total.value = data.total; | |||||
}) | |||||
.finally(() => (loading.value = false)); | |||||
} | |||||
} | |||||
/** | |||||
* 重置查询 | |||||
*/ | |||||
function resetQuery() { | |||||
queryFormRef.value.resetFields(); | |||||
queryParams.pageNum = 1; | |||||
handleQuery(); | |||||
} | |||||
/** | |||||
* 行checkbox change事件 | |||||
* | |||||
* @param selection | |||||
*/ | |||||
function handleSelectionChange(selection: any) { | |||||
ids.value = selection.map((item: any) => item.id); | |||||
} | |||||
/** | |||||
* 打开字典表单弹窗 | |||||
* | |||||
* @param dictId 字典ID | |||||
*/ | |||||
function openDialog(dictId?: number) { | |||||
dialog.visible = true; | |||||
if (dictId) { | |||||
dialog.title = "修改字典"; | |||||
getDictFormData(dictId).then(({ data }) => { | |||||
Object.assign(formData, data); | |||||
}); | |||||
} else { | |||||
dialog.title = "新增字典"; | |||||
} | |||||
} | |||||
/** | |||||
* 字典表单提交 | |||||
*/ | |||||
function handleSubmit() { | |||||
dataFormRef.value.validate((isValid: boolean) => { | |||||
if (isValid) { | |||||
loading.value = false; | |||||
const dictId = formData.id; | |||||
if (dictId) { | |||||
updateDict(dictId, formData) | |||||
.then(() => { | |||||
ElMessage.success("修改成功"); | |||||
closeDialog(); | |||||
resetQuery(); | |||||
}) | |||||
.finally(() => (loading.value = false)); | |||||
} else { | |||||
addDict(formData) | |||||
.then(() => { | |||||
ElMessage.success("新增成功"); | |||||
closeDialog(); | |||||
resetQuery(); | |||||
}) | |||||
.finally(() => (loading.value = false)); | |||||
} | |||||
} | |||||
}); | |||||
} | |||||
/** | |||||
* 关闭弹窗 | |||||
*/ | |||||
function closeDialog() { | |||||
dialog.visible = false; | |||||
resetForm(); | |||||
} | |||||
/** | |||||
* 重置表单 | |||||
*/ | |||||
function resetForm() { | |||||
dataFormRef.value.resetFields(); | |||||
dataFormRef.value.clearValidate(); | |||||
formData.id = undefined; | |||||
formData.status = 1; | |||||
formData.sort = 1; | |||||
formData.typeCode = props.typeCode; | |||||
} | |||||
/** | |||||
* 删除字典 | |||||
*/ | |||||
function handleDelete(dictId?: number) { | |||||
const dictIds = [dictId || ids.value].join(","); | |||||
if (!dictIds) { | |||||
ElMessage.warning("请勾选删除项"); | |||||
return; | |||||
} | |||||
ElMessageBox.confirm("确认删除已选中的数据项?", "警告", { | |||||
confirmButtonText: "确定", | |||||
cancelButtonText: "取消", | |||||
type: "warning", | |||||
}).then(() => { | |||||
deleteDict(dictIds).then(() => { | |||||
ElMessage.success("删除成功"); | |||||
resetQuery(); | |||||
}); | |||||
}); | |||||
} | |||||
onMounted(() => { | |||||
handleQuery(); | |||||
}); | |||||
</script> | |||||
<template> | |||||
<div class="app-container"> | |||||
<div class="search-container"> | |||||
<!-- 搜索表单 --> | |||||
<el-form ref="queryFormRef" :model="queryParams" :inline="true"> | |||||
<el-form-item label="关键字" prop="name"> | |||||
<el-input | |||||
v-model="queryParams.name" | |||||
placeholder="字典名称" | |||||
clearable | |||||
/> | |||||
</el-form-item> | |||||
<el-form-item> | |||||
<el-button type="primary" @click="handleQuery" | |||||
><i-ep-search />搜索</el-button | |||||
> | |||||
<el-button @click="resetQuery"> <i-ep-refresh />重置</el-button> | |||||
</el-form-item> | |||||
</el-form> | |||||
</div> | |||||
<el-card shadow="never"> | |||||
<template #header> | |||||
<el-button | |||||
v-hasPerm="['sys:dict:add']" | |||||
type="success" | |||||
@click="openDialog()" | |||||
><i-ep-plus />新增</el-button | |||||
> | |||||
<el-button | |||||
v-hasPerm="['sys:dict:delete']" | |||||
type="danger" | |||||
:disabled="ids.length === 0" | |||||
@click="handleDelete()" | |||||
><i-ep-delete />删除</el-button | |||||
> | |||||
</template> | |||||
<!-- 数据表格 --> | |||||
<el-table | |||||
v-loading="loading" | |||||
:data="dictList" | |||||
border | |||||
@selection-change="handleSelectionChange" | |||||
> | |||||
<el-table-column type="selection" width="50" /> | |||||
<el-table-column label="字典名称" prop="name" /> | |||||
<el-table-column label="字典值" prop="value" /> | |||||
<el-table-column label="状态" align="center"> | |||||
<template #default="scope"> | |||||
<el-tag v-if="scope.row.status === 1" type="success">启用</el-tag> | |||||
<el-tag v-else type="info">禁用</el-tag> | |||||
</template> | |||||
</el-table-column> | |||||
<el-table-column fixed="right" label="操作" align="center"> | |||||
<template #default="scope"> | |||||
<el-button | |||||
v-hasPerm="['sys:dict:edit']" | |||||
type="primary" | |||||
link | |||||
@click="openDialog(scope.row.id)" | |||||
><i-ep-edit />编辑</el-button | |||||
> | |||||
<el-button | |||||
v-hasPerm="['sys:dict:delete']" | |||||
type="primary" | |||||
link | |||||
@click.stop="handleDelete(scope.row.id)" | |||||
><i-ep-delete />删除</el-button | |||||
> | |||||
</template> | |||||
</el-table-column> | |||||
</el-table> | |||||
<pagination | |||||
v-if="total > 0" | |||||
v-model:total="total" | |||||
v-model:page="queryParams.pageNum" | |||||
v-model:limit="queryParams.pageSize" | |||||
@pagination="handleQuery" | |||||
/> | |||||
</el-card> | |||||
<!-- 表单弹窗 --> | |||||
<el-dialog | |||||
v-model="dialog.visible" | |||||
:title="dialog.title" | |||||
width="500px" | |||||
@close="closeDialog" | |||||
> | |||||
<el-form | |||||
ref="dataFormRef" | |||||
:model="formData" | |||||
:rules="rules" | |||||
label-width="100px" | |||||
> | |||||
<el-form-item label="字典名称">{{ typeName }}</el-form-item> | |||||
<el-form-item label="字典名称" prop="name"> | |||||
<el-input v-model="formData.name" placeholder="请输入字典名称" /> | |||||
</el-form-item> | |||||
<el-form-item label="字典值" prop="value"> | |||||
<el-input v-model="formData.value" placeholder="字典值" /> | |||||
</el-form-item> | |||||
<el-form-item label="排序" prop="sort"> | |||||
<el-input-number | |||||
v-model="formData.sort" | |||||
controls-position="right" | |||||
:min="0" | |||||
/> | |||||
</el-form-item> | |||||
<el-form-item label="状态" prop="status"> | |||||
<el-radio-group v-model="formData.status"> | |||||
<el-radio :label="1">正常</el-radio> | |||||
<el-radio :label="0">停用</el-radio> | |||||
</el-radio-group> | |||||
</el-form-item> | |||||
<el-form-item label="备注" prop="remark"> | |||||
<el-input v-model="formData.remark" type="textarea" /> | |||||
</el-form-item> | |||||
</el-form> | |||||
<template #footer> | |||||
<div class="dialog-footer"> | |||||
<el-button type="primary" @click="handleSubmit">确 定</el-button> | |||||
<el-button @click="closeDialog">取 消</el-button> | |||||
</div> | |||||
</template> | |||||
</el-dialog> | |||||
</div> | |||||
</template> |
@@ -0,0 +1,322 @@ | |||||
<template> | |||||
<div class="app-container"> | |||||
<div class="search-container"> | |||||
<el-form ref="queryFormRef" :model="queryParams" :inline="true"> | |||||
<el-form-item label="关键字" prop="name"> | |||||
<el-input | |||||
v-model="queryParams.keywords" | |||||
placeholder="字典类型名称/编码" | |||||
clearable | |||||
@keyup.enter="handleQuery" | |||||
/> | |||||
</el-form-item> | |||||
<el-form-item> | |||||
<el-button type="primary" @click="handleQuery()" | |||||
><i-ep-search />搜索</el-button | |||||
> | |||||
<el-button @click="resetQuery()"><i-ep-refresh />重置</el-button> | |||||
</el-form-item> | |||||
</el-form> | |||||
</div> | |||||
<el-card shadow="never" class="table-container"> | |||||
<template #header> | |||||
<el-button | |||||
v-hasPerm="['sys:dict_type:add']" | |||||
type="success" | |||||
@click="openDialog()" | |||||
><i-ep-plus />新增</el-button | |||||
> | |||||
<el-button | |||||
type="danger" | |||||
:disabled="ids.length === 0" | |||||
@click="handleDelete()" | |||||
><i-ep-delete />删除</el-button | |||||
> | |||||
</template> | |||||
<el-table | |||||
v-loading="loading" | |||||
highlight-current-row | |||||
:data="dictTypeList" | |||||
border | |||||
@selection-change="handleSelectionChange" | |||||
> | |||||
<el-table-column type="selection" width="55" align="center" /> | |||||
<el-table-column label="字典类型名称" prop="name" width="200" /> | |||||
<el-table-column label="字典类型编码" prop="code" width="200" /> | |||||
<el-table-column label="状态" align="center" width="100"> | |||||
<template #default="scope"> | |||||
<el-tag v-if="scope.row.status === 1" type="success">启用</el-tag> | |||||
<el-tag v-else type="info">禁用</el-tag> | |||||
</template> | |||||
</el-table-column> | |||||
<el-table-column label="备注" prop="remark" align="center" /> | |||||
<el-table-column fixed="right" label="操作" align="center" width="220"> | |||||
<template #default="scope"> | |||||
<el-button | |||||
type="primary" | |||||
link | |||||
size="small" | |||||
@click.stop="openDictDialog(scope.row)" | |||||
><i-ep-Collection />字典数据</el-button | |||||
> | |||||
<el-button | |||||
v-hasPerm="['sys:dict_type:edit']" | |||||
type="primary" | |||||
link | |||||
size="small" | |||||
@click.stop="openDialog(scope.row.id)" | |||||
><i-ep-edit />编辑</el-button | |||||
> | |||||
<el-button | |||||
v-hasPerm="['sys:dict_type:delete']" | |||||
type="primary" | |||||
link | |||||
size="small" | |||||
@click.stop="handleDelete(scope.row.id)" | |||||
><i-ep-delete />删除</el-button | |||||
> | |||||
</template> | |||||
</el-table-column> | |||||
</el-table> | |||||
<pagination | |||||
v-if="total > 0" | |||||
v-model:total="total" | |||||
v-model:page="queryParams.pageNum" | |||||
v-model:limit="queryParams.pageSize" | |||||
@pagination="handleQuery" | |||||
/> | |||||
</el-card> | |||||
<el-dialog | |||||
v-model="dialog.visible" | |||||
:title="dialog.title" | |||||
width="500px" | |||||
@close="closeDialog" | |||||
> | |||||
<el-form | |||||
ref="dataFormRef" | |||||
:model="formData" | |||||
:rules="rules" | |||||
label-width="80px" | |||||
> | |||||
<el-form-item label="字典名称" prop="name"> | |||||
<el-input v-model="formData.name" placeholder="请输入字典名称" /> | |||||
</el-form-item> | |||||
<el-form-item label="字典编码" prop="code"> | |||||
<el-input v-model="formData.code" placeholder="请输入字典编码" /> | |||||
</el-form-item> | |||||
<el-form-item label="状态" prop="status"> | |||||
<el-radio-group v-model="formData.status"> | |||||
<el-radio :label="1">正常</el-radio> | |||||
<el-radio :label="0">停用</el-radio> | |||||
</el-radio-group> | |||||
</el-form-item> | |||||
<el-form-item label="备注" prop="remark"> | |||||
<el-input | |||||
v-model="formData.remark" | |||||
type="textarea" | |||||
placeholder="字典类型备注" | |||||
:autosize="{ minRows: 2, maxRows: 4 }" | |||||
/> | |||||
</el-form-item> | |||||
</el-form> | |||||
<template #footer> | |||||
<div class="dialog-footer"> | |||||
<el-button type="primary" @click="handleSubmit">确 定</el-button> | |||||
<el-button @click="closeDialog">取 消</el-button> | |||||
</div> | |||||
</template> | |||||
</el-dialog> | |||||
<!--字典数据弹窗--> | |||||
<el-dialog | |||||
v-model="dictDataDialog.visible" | |||||
:title="dictDataDialog.title" | |||||
width="1000px" | |||||
@close="closeDictDialog" | |||||
> | |||||
<dict-item | |||||
v-model:typeCode="selectedDictType.typeCode" | |||||
v-model:typeName="selectedDictType.typeName" | |||||
/> | |||||
</el-dialog> | |||||
</div> | |||||
</template> | |||||
<script setup> | |||||
import { | |||||
getDictTypePage, | |||||
getDictTypeForm, | |||||
addDictType, | |||||
updateDictType, | |||||
deleteDictTypes, | |||||
} from "@/api/dict"; | |||||
// import { DictTypePageVO, DictTypeQuery, DictTypeForm } from "@/api/dict/types"; | |||||
defineOptions({ | |||||
name: "DictType", | |||||
inheritAttrs: false, | |||||
}); | |||||
const queryFormRef = ref(""); | |||||
const dataFormRef = ref(""); | |||||
const loading = ref(false); | |||||
const ids = ref([]); | |||||
const total = ref(0); | |||||
const queryParams = reactive({ | |||||
pageNum: 1, | |||||
pageSize: 10, | |||||
}); | |||||
const dictTypeList = ref(); | |||||
const dialog = reactive({ | |||||
visible: false, | |||||
}); | |||||
const formData = reactive({ | |||||
status: 1, | |||||
}); | |||||
const rules = reactive({ | |||||
name: [{ required: true, message: "请输入字典类型名称", trigger: "blur" }], | |||||
code: [{ required: true, message: "请输入字典类型编码", trigger: "blur" }], | |||||
}); | |||||
/** 查询 */ | |||||
function handleQuery() { | |||||
loading.value = true; | |||||
getDictTypePage(queryParams) | |||||
.then(({ data }) => { | |||||
dictTypeList.value = data.list; | |||||
total.value = data.total; | |||||
}) | |||||
.finally(() => { | |||||
loading.value = false; | |||||
}); | |||||
} | |||||
/** | |||||
* 重置查询 | |||||
*/ | |||||
function resetQuery() { | |||||
queryFormRef.value.resetFields(); | |||||
queryParams.pageNum = 1; | |||||
handleQuery(); | |||||
} | |||||
/** 行复选框选中 */ | |||||
function handleSelectionChange(selection) { | |||||
ids.value = selection.map((item) => item.id); | |||||
} | |||||
/** | |||||
* 打开字典类型表单弹窗 | |||||
* | |||||
* @param dicTypeId 字典类型ID | |||||
*/ | |||||
function openDialog(dicTypeId) { | |||||
dialog.visible = true; | |||||
if (dicTypeId) { | |||||
dialog.title = "修改字典类型"; | |||||
getDictTypeForm(dicTypeId).then(({ data }) => { | |||||
Object.assign(formData, data); | |||||
}); | |||||
} else { | |||||
dialog.title = "新增字典类型"; | |||||
} | |||||
} | |||||
/** 字典类型表单提交 */ | |||||
function handleSubmit() { | |||||
dataFormRef.value.validate((isValid) => { | |||||
if (isValid) { | |||||
loading.value = false; | |||||
const dictTypeId = formData.id; | |||||
if (dictTypeId) { | |||||
updateDictType(dictTypeId, formData) | |||||
.then(() => { | |||||
ElMessage.success("修改成功"); | |||||
closeDialog(); | |||||
handleQuery(); | |||||
}) | |||||
.finally(() => (loading.value = false)); | |||||
} else { | |||||
addDictType(formData) | |||||
.then(() => { | |||||
ElMessage.success("新增成功"); | |||||
closeDialog(); | |||||
handleQuery(); | |||||
}) | |||||
.finally(() => (loading.value = false)); | |||||
} | |||||
} | |||||
}); | |||||
} | |||||
/** 关闭字典类型弹窗 */ | |||||
function closeDialog() { | |||||
dialog.visible = false; | |||||
resetForm(); | |||||
} | |||||
/** 重置字典类型表单 */ | |||||
function resetForm() { | |||||
dataFormRef.value.resetFields(); | |||||
dataFormRef.value.clearValidate(); | |||||
formData.id = undefined; | |||||
formData.status = 1; | |||||
} | |||||
/** 删除字典类型 */ | |||||
function handleDelete(dictTypeId) { | |||||
const dictTypeIds = [dictTypeId || ids.value].join(","); | |||||
if (!dictTypeIds) { | |||||
ElMessage.warning("请勾选删除项"); | |||||
return; | |||||
} | |||||
ElMessageBox.confirm("确认删除已选中的数据项?", "警告", { | |||||
confirmButtonText: "确定", | |||||
cancelButtonText: "取消", | |||||
type: "warning", | |||||
}).then(() => { | |||||
deleteDictTypes(dictTypeIds).then(() => { | |||||
ElMessage.success("删除成功"); | |||||
resetQuery(); | |||||
}); | |||||
}); | |||||
} | |||||
const dictDataDialog = reactive({ | |||||
visible: false, | |||||
}); | |||||
const selectedDictType = reactive({ typeCode: "", typeName: "" }); // 当前选中的字典类型 | |||||
/** 打开字典数据弹窗 */ | |||||
function openDictDialog(row) { | |||||
dictDataDialog.visible = true; | |||||
dictDataDialog.title = "【" + row.name + "】字典数据"; | |||||
selectedDictType.typeCode = row.code; | |||||
selectedDictType.typeName = row.name; | |||||
} | |||||
/** 关闭字典数据弹窗 */ | |||||
function closeDictDialog() { | |||||
dictDataDialog.visible = false; | |||||
} | |||||
onMounted(() => { | |||||
handleQuery(); | |||||
}); | |||||
</script> | |||||
<style lang="scss" scoped></style> |
@@ -31,7 +31,7 @@ | |||||
</el-tooltip> | </el-tooltip> | ||||
</div> | </div> | ||||
<el-form-item prop="email"> | |||||
<el-form-item prop="username"> | |||||
<div class="text-white"> | <div class="text-white"> | ||||
<svg-icon icon-class="user" /> | <svg-icon icon-class="user" /> | ||||
</div> | </div> | ||||
@@ -39,8 +39,8 @@ | |||||
class="flex-1" | class="flex-1" | ||||
ref="email" | ref="email" | ||||
size="large" | size="large" | ||||
v-model="loginData.email" | |||||
:placeholder="$t('login.email')" | |||||
v-model="loginData.username" | |||||
:placeholder="$t('login.username')" | |||||
name="email" | name="email" | ||||
/> | /> | ||||
</el-form-item> | </el-form-item> | ||||
@@ -67,14 +67,14 @@ | |||||
</el-form-item> | </el-form-item> | ||||
<!-- 验证码 --> | <!-- 验证码 --> | ||||
<el-form-item prop="verifyCode"> | |||||
<el-form-item prop="captcha"> | |||||
<span class="text-white"> | <span class="text-white"> | ||||
<svg-icon icon-class="verify_code" /> | <svg-icon icon-class="verify_code" /> | ||||
</span> | </span> | ||||
<el-input | <el-input | ||||
v-model="loginData.verifyCode" | |||||
v-model="loginData.captcha" | |||||
auto-complete="off" | auto-complete="off" | ||||
:placeholder="$t('login.verifyCode')" | |||||
:placeholder="$t('login.captcha')" | |||||
class="flex-1" | class="flex-1" | ||||
@keyup.enter="handleLogin" | @keyup.enter="handleLogin" | ||||
/> | /> | ||||
@@ -111,9 +111,6 @@ | |||||
</el-button> | </el-button> | ||||
<div :class="currentLan == 'zh-cn' ? 'bottomBtnCN' : 'bottomBtnEN'"> | <div :class="currentLan == 'zh-cn' ? 'bottomBtnCN' : 'bottomBtnEN'"> | ||||
<div style="margin-bottom: 5px" @click="loginFlag(2)"> | |||||
<span class="join">{{ $t("login.signUp") }}</span> | |||||
</div> | |||||
<div style="margin-bottom: 5px"> | <div style="margin-bottom: 5px"> | ||||
<span class="join" @click="loginFlag(7)">{{ | <span class="join" @click="loginFlag(7)">{{ | ||||
$t("login.SMSLogin") | $t("login.SMSLogin") | ||||
@@ -126,188 +123,8 @@ | |||||
</div> | </div> | ||||
</div> | </div> | ||||
</el-form> | </el-form> | ||||
<!-- 注册账户 isLogin == 2--> | |||||
<el-form | |||||
v-if="isLogin == 2" | |||||
ref="loginFormRef" | |||||
:model="loginData2" | |||||
:rules="loginRules" | |||||
class="login-form" | |||||
> | |||||
<div class="flex text-white items-center"> | |||||
<span class="flex-1 text-center">{{ | |||||
$t("login.title") + " " + $t("login.register") | |||||
}}</span> | |||||
<el-tooltip | |||||
class="box-item" | |||||
effect="dark" | |||||
:content="$t('navbar.LanguageChange')" | |||||
placement="top-start" | |||||
> | |||||
<lang-select class="navItem" style="color: #ffffff" /> | |||||
</el-tooltip> | |||||
</div> | |||||
<el-form-item prop="email"> | |||||
<div class="text-white"> | |||||
<svg-icon icon-class="user" /> | |||||
</div> | |||||
<el-input | |||||
class="flex-1" | |||||
ref="email" | |||||
size="large" | |||||
v-model="loginData2.email" | |||||
:placeholder="$t('login.email')" | |||||
name="email" | |||||
/> | |||||
</el-form-item> | |||||
<el-form-item prop="password"> | |||||
<span class="text-white"> | |||||
<svg-icon icon-class="password" /> | |||||
</span> | |||||
<el-input | |||||
class="flex-1" | |||||
v-model="loginData2.password" | |||||
:placeholder="$t('login.password')" | |||||
:type="passwordVisible === false ? 'password' : 'input'" | |||||
size="large" | |||||
name="password" | |||||
/> | |||||
<span class="mr-2" @click="passwordVisible = !passwordVisible"> | |||||
<svg-icon | |||||
:icon-class="passwordVisible === false ? 'eye' : 'eye-open'" | |||||
class="text-white cursor-pointer" | |||||
/> | |||||
</span> | |||||
</el-form-item> | |||||
<el-form-item prop="confirmPassword"> | |||||
<span class="text-white"> | |||||
<svg-icon icon-class="password" /> | |||||
</span> | |||||
<el-input | |||||
class="flex-1" | |||||
v-model="loginData2.confirmPassword" | |||||
:placeholder="$t('login.confirmPassword')" | |||||
:type="passwordVisible === false ? 'password' : 'input'" | |||||
size="large" | |||||
name="confirmPassword" | |||||
@keyup.enter="handleRegister" | |||||
/> | |||||
<span class="mr-2" @click="passwordVisible = !passwordVisible"> | |||||
<svg-icon | |||||
:icon-class="passwordVisible === false ? 'eye' : 'eye-open'" | |||||
class="text-white cursor-pointer" | |||||
/> | |||||
</span> | |||||
</el-form-item> | |||||
<el-button | |||||
size="default" | |||||
:loading="loading" | |||||
type="primary" | |||||
class="loginBtn" | |||||
@click.prevent="handleRegister" | |||||
> | |||||
<el-icon | |||||
v-if="isRegistering" | |||||
style="margin-right: 10px" | |||||
class="is-loading" | |||||
> | |||||
<svg | |||||
viewBox="0 0 1024 1024" | |||||
xmlns="http://www.w3.org/2000/svg" | |||||
data-v-ea893728="" | |||||
> | |||||
<path | |||||
fill="currentColor" | |||||
d="M512 64a32 32 0 0 1 32 32v192a32 32 0 0 1-64 0V96a32 32 0 0 1 32-32zm0 640a32 32 0 0 1 32 32v192a32 32 0 1 1-64 0V736a32 32 0 0 1 32-32zm448-192a32 32 0 0 1-32 32H736a32 32 0 1 1 0-64h192a32 32 0 0 1 32 32zm-640 0a32 32 0 0 1-32 32H96a32 32 0 0 1 0-64h192a32 32 0 0 1 32 32zM195.2 195.2a32 32 0 0 1 45.248 0L376.32 331.008a32 32 0 0 1-45.248 45.248L195.2 240.448a32 32 0 0 1 0-45.248zm452.544 452.544a32 32 0 0 1 45.248 0L828.8 783.552a32 32 0 0 1-45.248 45.248L647.744 692.992a32 32 0 0 1 0-45.248zM828.8 195.264a32 32 0 0 1 0 45.184L692.992 376.32a32 32 0 0 1-45.248-45.248l135.808-135.808a32 32 0 0 1 45.248 0zm-452.544 452.48a32 32 0 0 1 0 45.248L240.448 828.8a32 32 0 0 1-45.248-45.248l135.808-135.808a32 32 0 0 1 45.248 0z" | |||||
></path> | |||||
</svg> | |||||
</el-icon> | |||||
{{ $t("login.registerBtn") }} | |||||
</el-button> | |||||
<div :class="currentLan == 'zh-cn' ? 'bottomBtnCN' : 'bottomBtnEN'"> | |||||
<div style="margin-bottom: 5px" @click="loginFlag(1)"> | |||||
<span class="join">{{ $t("login.signIn") }}</span> | |||||
</div> | |||||
<div> | |||||
<span class="join" @click="loginFlag(3)">{{ | |||||
$t("login.forgetPwd") | |||||
}}</span> | |||||
</div> | |||||
</div> | |||||
</el-form> | |||||
<!-- 注册账户之后输入短信验证码 isLogin == 6--> | <!-- 注册账户之后输入短信验证码 isLogin == 6--> | ||||
<el-form | |||||
v-if="isLogin == 6" | |||||
ref="loginFormRef" | |||||
:model="loginData6" | |||||
:rules="loginRules" | |||||
class="login-form" | |||||
> | |||||
<div class="flex text-white items-center"> | |||||
<span class="flex-1 text-center">{{ | |||||
$t("login.title") + " " + $t("login.register") | |||||
}}</span> | |||||
<el-tooltip | |||||
class="box-item" | |||||
effect="dark" | |||||
:content="$t('navbar.LanguageChange')" | |||||
placement="top-start" | |||||
> | |||||
<lang-select class="navItem" style="color: #ffffff" /> | |||||
</el-tooltip> | |||||
</div> | |||||
<el-form-item prop="SMSCode"> | |||||
<div class="text-white"> | |||||
<svg-icon icon-class="user" /> | |||||
</div> | |||||
<el-input | |||||
class="flex-1" | |||||
ref="email" | |||||
size="large" | |||||
v-model="loginData6.SMSCode" | |||||
:placeholder="$t('login.SMSCode')" | |||||
name="email" | |||||
/> | |||||
</el-form-item> | |||||
<el-button | |||||
size="default" | |||||
:loading="loading" | |||||
type="primary" | |||||
class="loginBtn" | |||||
@click.prevent="handleRegister" | |||||
> | |||||
<el-icon | |||||
v-if="isRegistering" | |||||
style="margin-right: 10px" | |||||
class="is-loading" | |||||
> | |||||
<svg | |||||
viewBox="0 0 1024 1024" | |||||
xmlns="http://www.w3.org/2000/svg" | |||||
data-v-ea893728="" | |||||
> | |||||
<path | |||||
fill="currentColor" | |||||
d="M512 64a32 32 0 0 1 32 32v192a32 32 0 0 1-64 0V96a32 32 0 0 1 32-32zm0 640a32 32 0 0 1 32 32v192a32 32 0 1 1-64 0V736a32 32 0 0 1 32-32zm448-192a32 32 0 0 1-32 32H736a32 32 0 1 1 0-64h192a32 32 0 0 1 32 32zm-640 0a32 32 0 0 1-32 32H96a32 32 0 0 1 0-64h192a32 32 0 0 1 32 32zM195.2 195.2a32 32 0 0 1 45.248 0L376.32 331.008a32 32 0 0 1-45.248 45.248L195.2 240.448a32 32 0 0 1 0-45.248zm452.544 452.544a32 32 0 0 1 45.248 0L828.8 783.552a32 32 0 0 1-45.248 45.248L647.744 692.992a32 32 0 0 1 0-45.248zM828.8 195.264a32 32 0 0 1 0 45.184L692.992 376.32a32 32 0 0 1-45.248-45.248l135.808-135.808a32 32 0 0 1 45.248 0zm-452.544 452.48a32 32 0 0 1 0 45.248L240.448 828.8a32 32 0 0 1-45.248-45.248l135.808-135.808a32 32 0 0 1 45.248 0z" | |||||
></path> | |||||
</svg> | |||||
</el-icon> | |||||
{{ $t("login.registerBtn") }} | |||||
</el-button> | |||||
<div :class="currentLan == 'zh-cn' ? 'bottomBtnCN' : 'bottomBtnEN'"> | |||||
<div style="margin-bottom: 5px" @click="loginFlag(1)"> | |||||
<span class="join">{{ $t("login.signIn") }}</span> | |||||
</div> | |||||
</div> | |||||
</el-form> | |||||
<!-- 忘记密码 isLogin == 3--> | <!-- 忘记密码 isLogin == 3--> | ||||
<el-form | <el-form | ||||
v-if="isLogin == 3" | v-if="isLogin == 3" | ||||
@@ -691,9 +508,6 @@ | |||||
</el-button> | </el-button> | ||||
<div :class="currentLan == 'zh-cn' ? 'bottomBtnCN' : 'bottomBtnEN'"> | <div :class="currentLan == 'zh-cn' ? 'bottomBtnCN' : 'bottomBtnEN'"> | ||||
<div style="margin-bottom: 5px" @click="loginFlag(2)"> | |||||
<span class="join">{{ $t("login.signUp") }}</span> | |||||
</div> | |||||
<div style="margin-bottom: 5px"> | <div style="margin-bottom: 5px"> | ||||
<span class="join" @click="loginFlag(1)">{{ | <span class="join" @click="loginFlag(1)">{{ | ||||
$t("login.pwsLogin") | $t("login.pwsLogin") | ||||
@@ -786,8 +600,7 @@ | |||||
import LangSelect from "@/components/LangSelect/index.vue"; | import LangSelect from "@/components/LangSelect/index.vue"; | ||||
import SvgIcon from "@/components/SvgIcon/index.vue"; | import SvgIcon from "@/components/SvgIcon/index.vue"; | ||||
import { | import { | ||||
register, | |||||
login, | |||||
loginApi, | |||||
sendRegisterEmail, | sendRegisterEmail, | ||||
getCodeImgUrl, | getCodeImgUrl, | ||||
sendUpdPwdEmailApi, | sendUpdPwdEmailApi, | ||||
@@ -799,6 +612,7 @@ import { | |||||
doFindInviteCode, | doFindInviteCode, | ||||
doUpdateInviteCode, | doUpdateInviteCode, | ||||
} from "@/apis/login"; | } from "@/apis/login"; | ||||
import { getMenuNavApi } from "@/apis/Permission.js"; | |||||
import axios from "axios"; | import axios from "axios"; | ||||
// 状态管理依赖 | // 状态管理依赖 | ||||
@@ -848,9 +662,9 @@ const isLogining = ref(false); | |||||
const isRegistering = ref(false); | const isRegistering = ref(false); | ||||
const loginData = ref({ | const loginData = ref({ | ||||
email: "", | |||||
username: "", | |||||
password: "", | password: "", | ||||
verifyCode: "", | |||||
captcha: "", | |||||
}); | }); | ||||
const loginData2 = ref({ | const loginData2 = ref({ | ||||
@@ -882,6 +696,13 @@ const loginData8 = ref({ | |||||
invitatioCode: "", | invitatioCode: "", | ||||
}); | }); | ||||
const loginRules = ref({ | const loginRules = ref({ | ||||
username: [ | |||||
{ | |||||
required: true, | |||||
trigger: "blur", | |||||
validator: passwordValidator, | |||||
}, | |||||
], | |||||
email: [ | email: [ | ||||
{ | { | ||||
required: true, | required: true, | ||||
@@ -894,13 +715,13 @@ const loginRules = ref({ | |||||
confirmPassword: [ | confirmPassword: [ | ||||
{ required: true, trigger: "blur", validator: confirmPasswordValidator }, | { required: true, trigger: "blur", validator: confirmPasswordValidator }, | ||||
], | ], | ||||
verifyCode: [ | |||||
captcha: [ | |||||
{ | { | ||||
required: true, | required: true, | ||||
trigger: "blur", | trigger: "blur", | ||||
message: | message: | ||||
currentLan.value == "zh-cn" | currentLan.value == "zh-cn" | ||||
? "请输入验证码" | |||||
? "请输入验证码2" | |||||
: "Please input verifyCode", | : "Please input verifyCode", | ||||
}, | }, | ||||
], | ], | ||||
@@ -928,8 +749,8 @@ const loginRules = ref({ | |||||
watch(currentLan, (newValue, oldValue) => { | watch(currentLan, (newValue, oldValue) => { | ||||
const loginRule = loginRules.value; | const loginRule = loginRules.value; | ||||
loginRule.verifyCode[0].message = | |||||
newValue == "zh-cn" ? "请输入验证码" : "Please input verifyCode"; | |||||
loginRule.captcha[0].message = | |||||
newValue == "zh-cn" ? "请输入验证码1" : "Please input verifyCode"; | |||||
setTimeout(() => { | setTimeout(() => { | ||||
loginFormRef.value.resetFields(); | loginFormRef.value.resetFields(); | ||||
getInfo(); | getInfo(); | ||||
@@ -973,7 +794,7 @@ function getInfo() { | |||||
const deCodeUserInfo = decodeURI(data as any); | const deCodeUserInfo = decodeURI(data as any); | ||||
const userInfo = JSON.parse(deCodeUserInfo); | const userInfo = JSON.parse(deCodeUserInfo); | ||||
if (userInfo) { | if (userInfo) { | ||||
loginData.value.email = userInfo.email ? userInfo.email : ""; | |||||
loginData.value.username = userInfo.email ? userInfo.email : ""; | |||||
loginData.value.password = userInfo.password ? userInfo.password : ""; | loginData.value.password = userInfo.password ? userInfo.password : ""; | ||||
} | } | ||||
} | } | ||||
@@ -1091,48 +912,7 @@ function confirmPasswordValidator5(rule: any, value: any, callback: any) { | |||||
} | } | ||||
//#endregion ---------------------------- | //#endregion ---------------------------- | ||||
// 登录行为 | |||||
function handleLogin() { | |||||
loginFormRef.value.validate((val: any) => { | |||||
if (val) { | |||||
const data = { | |||||
phone: loginData.value.email, | |||||
password: loginData.value.password, | |||||
code: loginData.value.verifyCode, | |||||
}; | |||||
isLogining.value = true; | |||||
doLogin(data); | |||||
} else { | |||||
const msg = | |||||
currentLan.value == "zh-cn" | |||||
? "请检查信息格式!" | |||||
: "Please check the format !"; | |||||
ElMessage.error(msg); | |||||
return; | |||||
} | |||||
}); | |||||
} | |||||
// 注册行为 | // 注册行为 | ||||
function handleRegister() { | |||||
loginFormRef.value.validate((val: any) => { | |||||
if (val) { | |||||
const data = { | |||||
phone: loginData2.value.email, | |||||
password: loginData2.value.password, | |||||
}; | |||||
isRegistering.value = true; | |||||
doRegister(data); | |||||
} else { | |||||
const msg = | |||||
currentLan.value == "zh-cn" | |||||
? "请检查信息格式!" | |||||
: "Please check the format !"; | |||||
ElMessage.error(msg); | |||||
return; | |||||
} | |||||
}); | |||||
} | |||||
//#region 忘记密码 表单3 | //#region 忘记密码 表单3 | ||||
function sendEmailforgetPwd() { | function sendEmailforgetPwd() { | ||||
@@ -1329,7 +1109,7 @@ async function checkInviteCode() { | |||||
isLogin.value = 8; | isLogin.value = 8; | ||||
// 有邀请码直接前往我的页面 | // 有邀请码直接前往我的页面 | ||||
} else if (status == 1) { | } else if (status == 1) { | ||||
userInfoPinia.getUserInfo(); //保存邮箱到pinia | |||||
// userInfoPinia.getUserInfo(); //保存邮箱到pinia | |||||
ElMessage.success( | ElMessage.success( | ||||
'currentLan.value == "zh-cn" ? "登录成功!" : "Welcome to Metavatar!"' | 'currentLan.value == "zh-cn" ? "登录成功!" : "Welcome to Metavatar!"' | ||||
); | ); | ||||
@@ -1351,7 +1131,7 @@ async function handleInvitatioCode() { | |||||
}; | }; | ||||
try { | try { | ||||
const res = await doUpdateInviteCode(data); | const res = await doUpdateInviteCode(data); | ||||
userInfoPinia.getUserInfo(); //保存邮箱到pinia | |||||
// userInfoPinia.getUserInfo(); //保存邮箱到pinia | |||||
ElMessage.success( | ElMessage.success( | ||||
'currentLan.value == "zh-cn" ? "登录成功!" : "Welcome to Metavatar!"' | 'currentLan.value == "zh-cn" ? "登录成功!" : "Welcome to Metavatar!"' | ||||
); | ); | ||||
@@ -1370,58 +1150,75 @@ function getCode() { | |||||
axios({ | axios({ | ||||
url: getCodeImgUrl, | url: getCodeImgUrl, | ||||
method: "get", | method: "get", | ||||
}).then(() => { | |||||
}).then((res) => { | |||||
verifyCodeUrl.value = getCodeImgUrl; | verifyCodeUrl.value = getCodeImgUrl; | ||||
showCodeImg.value = true; | showCodeImg.value = true; | ||||
}); | }); | ||||
} | } | ||||
/** | /** | ||||
* @description:注册 | |||||
* @description:登录 | |||||
* @param {Object} data | * @param {Object} data | ||||
* @return: data | * @return: data | ||||
*/ | */ | ||||
async function doRegister(data: object) { | |||||
/** | |||||
* @description:重新发送邮件 | |||||
* @param {string} email | |||||
* @return: data | |||||
*/ | |||||
async function reSendEmail(email: string) { | |||||
const msg = | const msg = | ||||
currentLan.value == "zh-cn" ? "注册成功!" : "Registered successfully"; | |||||
await register(data) | |||||
currentLan.value == "zh-cn" | |||||
? "确认信息已发送至您的邮箱,请注意查收!" | |||||
: "An email has been send to you, Please pay attention to confirm !"; | |||||
await sendRegisterEmail(email) | |||||
.then((res) => { | .then((res) => { | ||||
console.log(res, "res"); | console.log(res, "res"); | ||||
isRegistering.value = false; | |||||
ElMessage.success(msg); | ElMessage.success(msg); | ||||
isLogin.value = 1; | |||||
// 注册成功将账号密码保存到本地 | |||||
saveInfo(data); | |||||
router.go(0); | |||||
}) | }) | ||||
.catch((err) => { | .catch((err) => { | ||||
// 注册失败刷新验证码 | |||||
getCode(); | |||||
isRegistering.value = false; | |||||
console.log(err, "err"); | console.log(err, "err"); | ||||
ElMessage.error(err.message); | ElMessage.error(err.message); | ||||
}); | }); | ||||
} | } | ||||
/** | |||||
* @description:登录 | |||||
* @param {Object} data | |||||
* @return: data | |||||
*/ | |||||
//#region 新登录 | |||||
// 登录行为 | |||||
function handleLogin() { | |||||
loginFormRef.value.validate((val: any) => { | |||||
if (val) { | |||||
const data = { | |||||
username: loginData.value.username, | |||||
password: loginData.value.password, | |||||
captcha: loginData.value.captcha, | |||||
}; | |||||
isLogining.value = true; | |||||
doLogin(data); | |||||
} else { | |||||
const msg = | |||||
currentLan.value == "zh-cn" | |||||
? "请检查信息格式!" | |||||
: "Please check the format !"; | |||||
ElMessage.error(msg); | |||||
return; | |||||
} | |||||
}); | |||||
} | |||||
async function doLogin(data: any) { | async function doLogin(data: any) { | ||||
const msg = | const msg = | ||||
currentLan.value == "zh-cn" ? "登录成功!" : "Welcome to Metavatar!"; | currentLan.value == "zh-cn" ? "登录成功!" : "Welcome to Metavatar!"; | ||||
await login(data) | |||||
await loginApi(data) | |||||
.then(async (res) => { | .then(async (res) => { | ||||
console.log(res, "res"); | console.log(res, "res"); | ||||
localStorage.setItem("AccessToken", res.data.token); | |||||
// localStorage.setItem("AccessToken", res.data.token); | |||||
// 注册成功将账号密码保存到本地 | // 注册成功将账号密码保存到本地 | ||||
saveInfo(data); | saveInfo(data); | ||||
await getMenuNavFunc(); | |||||
isLogining.value = false; | isLogining.value = false; | ||||
// await checkInviteCode(); | // await checkInviteCode(); | ||||
userInfoPinia.getUserInfo(); //保存邮箱到pinia | |||||
// userInfoPinia.getUserInfo(); //保存邮箱到pinia | |||||
ElMessage.success(msg); | ElMessage.success(msg); | ||||
router.push("/createVideo"); | |||||
router.push("/model"); | |||||
}) | }) | ||||
.catch((err) => { | .catch((err) => { | ||||
console.log(err, "err"); | console.log(err, "err"); | ||||
@@ -1434,28 +1231,17 @@ async function doLogin(data: any) { | |||||
} | } | ||||
}); | }); | ||||
} | } | ||||
//#endregion | |||||
/** | |||||
* @description:重新发送邮件 | |||||
* @param {string} email | |||||
* @return: data | |||||
*/ | |||||
async function reSendEmail(email: string) { | |||||
const msg = | |||||
currentLan.value == "zh-cn" | |||||
? "确认信息已发送至您的邮箱,请注意查收!" | |||||
: "An email has been send to you, Please pay attention to confirm !"; | |||||
await sendRegisterEmail(email) | |||||
.then((res) => { | |||||
console.log(res, "res"); | |||||
ElMessage.success(msg); | |||||
}) | |||||
.catch((err) => { | |||||
console.log(err, "err"); | |||||
ElMessage.error(err.message); | |||||
}); | |||||
//#region 获取菜单导航路由 | |||||
async function getMenuNavFunc() { | |||||
try { | |||||
const res = await getMenuNavApi(); | |||||
} catch (error) { | |||||
console.log(error); | |||||
} | |||||
} | } | ||||
//#endregion -------------------------------- | |||||
onMounted(() => { | onMounted(() => { | ||||
getCode(); | getCode(); | ||||
getInfo(); | getInfo(); | ||||
@@ -0,0 +1,171 @@ | |||||
<template> | |||||
<div class="page flex justify-around"> | |||||
<div class="card"> | |||||
<div class="title">密钥管理</div> | |||||
<div class="key"> | |||||
<span class="text">密钥:{{ showCode }}</span> | |||||
<span class="showOrHide" @click="showHideCode">{{ showText }}</span> | |||||
<span v-if="showText == '隐藏'" class="copy" @click="copyKey" | |||||
>复制</span | |||||
> | |||||
</div> | |||||
<div class="keyStatus"> | |||||
<span class="text" | |||||
>密钥状态:{{ keyStatus == 1 ? "正常" : "作废" }}</span | |||||
> | |||||
<span v-if="keyStatus == 1" class="success" @click="changeStatus(2)" | |||||
>恢复</span | |||||
> | |||||
<span v-if="keyStatus == 2" class="fail" @click="changeStatus(1)" | |||||
>作废</span | |||||
> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</template> | |||||
<!-- videoType==1为竖,==2为横 --> | |||||
<script setup> | |||||
//#region 导入 | |||||
import { linkEmits } from "element-plus"; | |||||
import { getCurrentInstance } from "vue"; | |||||
import { useI18n } from "vue-i18n"; | |||||
import { useRoute, useRouter } from "vue-router"; | |||||
const route = useRoute(); | |||||
const router = useRouter(); | |||||
const { locale } = useI18n(); | |||||
const lanChange = ref(locale); | |||||
const AccessToken = localStorage.getItem("AccessToken"); // 判断有没有登录 | |||||
const key = ref("AE0DVHDWMDOURSBCAP"); | |||||
const hideCode = ref(""); | |||||
const showCode = ref(""); | |||||
const showText = ref("查看"); | |||||
const getKey = () => { | |||||
const len = key.value.length; | |||||
let code = ""; | |||||
for (let index = 0; index < len; index++) { | |||||
code += "*"; | |||||
} | |||||
hideCode.value = code; | |||||
showCode.value = code; | |||||
}; | |||||
const showHideCode = () => { | |||||
if (showText.value == "查看") { | |||||
showText.value = "隐藏"; | |||||
showCode.value = key.value; | |||||
} else { | |||||
showText.value = "查看"; | |||||
showCode.value = hideCode.value; | |||||
} | |||||
}; | |||||
const copyKey = () => { | |||||
navigator.clipboard | |||||
.writeText(key.value) | |||||
.then(() => { | |||||
ElMessage.success("复制成功!"); | |||||
}) | |||||
.catch(() => { | |||||
ElMessage.error("复制失败!"); | |||||
}); | |||||
}; | |||||
const keyStatus = ref(""); | |||||
const getStatus = () => { | |||||
// 1:正常;2:作废 | |||||
const status = 1; | |||||
keyStatus.value = status; | |||||
}; | |||||
const changeStatus = (num) => { | |||||
keyStatus.value = num; | |||||
}; | |||||
onMounted(() => { | |||||
getKey(); | |||||
getStatus(); | |||||
}); | |||||
</script> | |||||
<style lang="scss" scoped> | |||||
.page { | |||||
height: calc(100vh - 80px); | |||||
// height: calc(100vh - 80px); | |||||
background-color: #ffffff; | |||||
border-radius: 30px 0 0 0; | |||||
overflow: hidden; | |||||
.card { | |||||
width: 70%; | |||||
height: 70%; | |||||
background-color: #f8f8f8; | |||||
margin-top: 10vh; | |||||
border-radius: 5vh; | |||||
box-shadow: #0000002e 1px 1px 1px 1px; | |||||
.title { | |||||
text-align: center; | |||||
font-size: 4vh; | |||||
padding: 5vh; | |||||
} | |||||
.key { | |||||
text-align: center; | |||||
font-size: 4vh; | |||||
padding: 5vh; | |||||
.copy { | |||||
color: #ffffff; | |||||
margin-left: 2vh; | |||||
cursor: pointer; | |||||
transition: all 0.3s; | |||||
background-color: #3a57b6; | |||||
padding: 0.7vh; | |||||
border-radius: 15px; | |||||
&:hover { | |||||
background-color: #1ceedc; | |||||
} | |||||
} | |||||
.showOrHide { | |||||
color: #20b4a8; | |||||
margin-left: 2vh; | |||||
cursor: pointer; | |||||
transition: all 0.3s; | |||||
&:hover { | |||||
color: #476ad9; | |||||
} | |||||
} | |||||
} | |||||
.keyStatus { | |||||
text-align: center; | |||||
font-size: 4vh; | |||||
padding: 5vh; | |||||
.success { | |||||
color: #ff0000; | |||||
margin-left: 2vh; | |||||
cursor: pointer; | |||||
transition: all 0.3s; | |||||
&:hover { | |||||
color: #36db43; | |||||
} | |||||
} | |||||
.fail { | |||||
color: #36db43; | |||||
margin-left: 2vh; | |||||
cursor: pointer; | |||||
transition: all 0.3s; | |||||
&:hover { | |||||
color: #ff0000; | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
</style> |
@@ -0,0 +1,16 @@ | |||||
<template> | |||||
<div class="page flex justify-around"></div> | |||||
</template> | |||||
<!-- videoType==1为竖,==2为横 --> | |||||
<script setup></script> | |||||
<style lang="scss" scoped> | |||||
.page { | |||||
height: calc(100vh - 80px); | |||||
// height: calc(100vh - 80px); | |||||
background-color: #fff; | |||||
border-radius: 30px 0 0 0; | |||||
overflow: hidden; | |||||
} | |||||
</style> |
@@ -0,0 +1,16 @@ | |||||
<template> | |||||
<div class="page flex justify-around"></div> | |||||
</template> | |||||
<!-- videoType==1为竖,==2为横 --> | |||||
<script setup></script> | |||||
<style lang="scss" scoped> | |||||
.page { | |||||
height: calc(100vh - 80px); | |||||
// height: calc(100vh - 80px); | |||||
background-color: #fff; | |||||
border-radius: 30px 0 0 0; | |||||
overflow: hidden; | |||||
} | |||||
</style> |
@@ -0,0 +1,16 @@ | |||||
<template> | |||||
<div class="page flex justify-around"></div> | |||||
</template> | |||||
<!-- videoType==1为竖,==2为横 --> | |||||
<script setup></script> | |||||
<style lang="scss" scoped> | |||||
.page { | |||||
height: calc(100vh - 80px); | |||||
// height: calc(100vh - 80px); | |||||
background-color: #fff; | |||||
border-radius: 30px 0 0 0; | |||||
overflow: hidden; | |||||
} | |||||
</style> |
@@ -49,12 +49,17 @@ export default defineConfig(({ mode }: ConfigEnv): UserConfig => { | |||||
host: "0.0.0.0", | host: "0.0.0.0", | ||||
port: Number(env.VITE_APP_PORT), | port: Number(env.VITE_APP_PORT), | ||||
open: true, // 运行是否自动打开浏览器 | open: true, // 运行是否自动打开浏览器 | ||||
// "/api": { | |||||
// target: env.VITE_APP_BASE_API, // 线上接口地址 | |||||
// changeOrigin: true, | |||||
// rewrite: (path) => path.replace(/^\/api/, ""), | |||||
// }, | |||||
proxy: { | proxy: { | ||||
// 反向代理解决跨域 | // 反向代理解决跨域 | ||||
"/api": { | |||||
"/A": { | |||||
target: env.VITE_APP_BASE_API, // 线上接口地址 | target: env.VITE_APP_BASE_API, // 线上接口地址 | ||||
changeOrigin: true, | changeOrigin: true, | ||||
rewrite: (path) => path.replace(/^\/api/, ""), | |||||
rewrite: (path) => path.replace(/^\/A/, ""), | |||||
}, | }, | ||||
}, | }, | ||||
}, | }, | ||||