This commit is contained in:
2026-01-12 17:51:42 +08:00
parent 38668d82c4
commit f1634872de
10 changed files with 460 additions and 283 deletions
+5
View File
@@ -185,6 +185,11 @@ func ApiUser(r *gin.RouterGroup) {
} }
}) })
//修改用户头像
r.POST("/updateAvatar", func(ctx *gin.Context) {
})
//更新用户info //更新用户info
r.POST("/updateInfo", func(ctx *gin.Context) { r.POST("/updateInfo", func(ctx *gin.Context) {
isAuth, user, data := AuthenticationAuthority(ctx) isAuth, user, data := AuthenticationAuthority(ctx)
@@ -206,18 +206,18 @@ onMounted(() => {
</div> </div>
</div> </div>
<div class="dropdown-menu dropdown-menu-end dropdown-menu-arrow"> <div class="dropdown-menu dropdown-menu-end dropdown-menu-arrow">
<router-link to="" class="dropdown-item">{{ <!-- <router-link to="" class="dropdown-item">{{
t("message.user_home") t("message.user_home")
}}</router-link> }}</router-link> -->
<router-link to="/settings/account" class="dropdown-item">{{ <router-link to="/settings/account" class="dropdown-item">{{
t("message.user_settings") t("message.user_settings")
}}</router-link> }}</router-link>
<router-link to="" class="dropdown-item">{{ <!-- <router-link to="" class="dropdown-item">{{
t("message.preferences") t("message.preferences")
}}</router-link> }}</router-link> -->
<div class="dropdown-divider"></div> <div class="dropdown-divider"></div>
<!-- 如何用户是系统管理员这里显示跳转管理的url --> <!-- 如何用户是系统管理员这里显示跳转管理的url -->
<router-link to="/admin" class="dropdown-item"> <!-- <router-link to="/admin" class="dropdown-item">
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
width="24" width="24"
@@ -237,7 +237,7 @@ onMounted(() => {
<path d="M9 12a3 3 0 1 0 6 0a3 3 0 0 0 -6 0" /> <path d="M9 12a3 3 0 1 0 6 0a3 3 0 0 0 -6 0" />
</svg> </svg>
{{ t("message.administrator") }}</router-link {{ t("message.administrator") }}</router-link
> > -->
<div @click="logOut" class="dropdown-item"> <div @click="logOut" class="dropdown-item">
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
@@ -11,14 +11,31 @@ const { t } = useI18n();
<div class="list-group list-group-transparent"> <div class="list-group list-group-transparent">
<router-link <router-link
to="/settings/account" to="/settings/account"
class="list-group-item list-group-item-action d-flex align-items-center active" active-class="active"
class="list-group-item list-group-item-action d-flex align-items-center"
> >
{{t('settings.account_settings')}}</router-link {{t('settings.basic_information')}}</router-link
> >
</div> </div>
<h4 class="subheader mt-4">{{t('settings.admin')}}</h4> <div class="list-group list-group-transparent">
<router-link
to="/settings/contact"
active-class="active"
class="list-group-item list-group-item-action d-flex align-items-center"
>
{{t('settings.contact_information')}}</router-link
>
</div>
<div class="list-group list-group-transparent">
<router-link
to="/settings/security"
active-class="active"
class="list-group-item list-group-item-action d-flex align-items-center"
>
{{t('settings.security_settings')}}</router-link
>
</div>
<!-- <h4 class="subheader mt-4">{{t('settings.admin')}}</h4>
<div class="list-group list-group-transparent"> <div class="list-group list-group-transparent">
<router-link <router-link
to="/settings/account" to="/settings/account"
@@ -26,7 +43,7 @@ const { t } = useI18n();
> >
{{t('settings.website_settings')}}</router-link {{t('settings.website_settings')}}</router-link
> >
</div> </div> -->
</div> </div>
</div> </div>
</template> </template>
+4
View File
@@ -105,6 +105,10 @@
"confirm_password_incorrect": "Confirm password is incorrect" "confirm_password_incorrect": "Confirm password is incorrect"
}, },
"settings": { "settings": {
"cancel": "Cancel",
"basic_information":"Basic Information",
"contact_information":"Contact Information",
"security_settings":"Security Settings",
"account_settings": "Account Settings", "account_settings": "Account Settings",
"my_account": "My Account", "my_account": "My Account",
"profile_information": "Profile Information", "profile_information": "Profile Information",
+4
View File
@@ -105,6 +105,10 @@
"confirm_password_incorrect":"确认密码不正确" "confirm_password_incorrect":"确认密码不正确"
}, },
"settings": { "settings": {
"cancel": "取消",
"basic_information":"基本信息",
"contact_information":"联系信息",
"security_settings":"安全设置",
"account_settings": "个人设置", "account_settings": "个人设置",
"my_account": "我的账户", "my_account": "我的账户",
"profile_information": "个人信息", "profile_information": "个人信息",
@@ -21,6 +21,9 @@ export const my_network_func = {
re_data["error"] = error; re_data["error"] = error;
callback(re_data); callback(re_data);
}); });
},
postflise(path,flise,json,callback){
}, },
postJson(path, json, callback) { postJson(path, json, callback) {
//把cookie插入json //把cookie插入json
+16 -5
View File
@@ -13,6 +13,21 @@ const router = createRouter({
name: "home", name: "home",
component: HomeView, component: HomeView,
}, },
{
path: "/settings/account",
name: "settings account",
component: () => import("../views/settings/account.vue"),
},
{
path: "/settings/contact",
name: "settings contact",
component: () => import("../views/settings/contact.vue"),
},
{
path: "/settings/security",
name: "settings security",
component: () => import("../views/settings/security.vue"),
},
{ {
path: "/about", path: "/about",
name: "about", name: "about",
@@ -46,11 +61,7 @@ const router = createRouter({
name: "admin", name: "admin",
component: () => import("../views/adminView.vue"), component: () => import("../views/adminView.vue"),
}, },
{
path: "/settings/account",
name: "settings account",
component: () => import("../views/settings/account.vue"),
},
{ {
path: "/schedule", path: "/schedule",
name: "schedule", name: "schedule",
@@ -7,7 +7,7 @@ import imageCropper from "@/components/imageCropper.vue";
import { useUserStore } from "@/stores/user"; import { useUserStore } from "@/stores/user";
import { my_network_func } from "@/my_network_func"; import { my_network_func } from "@/my_network_func";
import MyOffcanvas from "@/components/MyOffcanvas.vue"; import MyOffcanvas from "@/components/MyOffcanvas.vue";
import { myfuncs } from "@/myfunc";
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
const mos = ref(); const mos = ref();
@@ -19,24 +19,13 @@ const birthday = ref();
const username = ref(); const username = ref();
const userremark = ref(); const userremark = ref();
const emailInput = ref();
const userStore = useUserStore(); const userStore = useUserStore();
const oldPassInput = ref();
const newPassInput = ref();
const cnfPassInput = ref();
const isShowPassword = ref(false);
const is_avatar_change = ref(false); const is_avatar_change = ref(false);
const avatar_temp_url = ref(""); const avatar_temp_url = ref("");
function togglePasswordVisibility() {
isShowPassword.value = !isShowPassword.value;
}
function updataInfo() { function updataInfo() {
let isDataErr = false; let isDataErr = false;
let birthdayValue = birthday.value.datepicker.value; let birthdayValue = birthday.value.datepicker.value;
@@ -66,10 +55,13 @@ function updataInfo() {
//console.log("用户信息有误,无法保存"); //console.log("用户信息有误,无法保存");
return; return;
} }
// console.log("保存用户信息");
// console.log("用户名:", usernameValue); //检查头像是否需要更新
// console.log("备注:", userremarkValue); if(is_avatar_change)
// console.log("生日:", birthdayValue); {
}
my_network_func.postJson( my_network_func.postJson(
"/users/updateInfo", "/users/updateInfo",
{ {
@@ -100,158 +92,19 @@ function updataInfo() {
); );
} }
function changeEmail() {
if (emailInput.value.value == "") {
emailInput.value.classList.add("is-invalid");
mos.value?.showAlert("warning", t("message.please_enter_your_email"), 3000);
return;
} else {
emailInput.value.classList.remove("is-invalid");
}
//判断是否是合法邮箱
if (myfuncs.isValidEmail(emailInput.value.value) == false) {
emailInput.value.classList.add("is-invalid");
mos.value?.showAlert("danger", t("message.this_not_email"), 3000);
return;
} else {
emailInput.value.classList.remove("is-invalid");
}
my_network_func.postJson(
"/users/changeEmail",
{
newemail: emailInput.value.value,
},
(r) => {
switch (r.statusCode) {
case 200:
switch (r.data.err_code) {
case 0:
mos.value?.showAlert("success", t("message.change_ok"), 5000);
// 更新用户信息到store
userStore.getUserInfoFromCookie();
break;
case -43:
emailInput.value.classList.add("is-invalid");
mos.value?.showAlert("danger", t("message.this_not_email"), 3000);
break;
default:
mos.value?.showAlert("danger", t("message.server_error"), 5000);
break;
}
break;
default:
mos.value?.showAlert("danger", t("message.network_err"), 5000);
break;
}
}
);
}
function changePassword() {
let isDataErr = false;
let oldPass = oldPassInput.value.value;
let newPass = newPassInput.value.value;
let cnfPass = cnfPassInput.value.value;
oldPassInput.value.classList.remove("is-invalid");
newPassInput.value.classList.remove("is-invalid");
cnfPassInput.value.classList.remove("is-invalid");
if (!oldPass) {
isDataErr = true;
oldPassInput.value.classList.add("is-invalid");
}
if (!newPass) {
isDataErr = true;
newPassInput.value.classList.add("is-invalid");
}
if (!cnfPass) {
isDataErr = true;
cnfPassInput.value.classList.add("is-invalid");
}
if (newPass !== cnfPass) {
isDataErr = true;
newPassInput.value.classList.add("is-invalid");
cnfPassInput.value.classList.add("is-invalid");
mos.value?.showAlert(
"warning",
t("message.confirm_password_incorrect"),
3000
);
}
if (isDataErr) {
return;
}
my_network_func.postJson(
"/users/changePassword",
{
oldpass: oldPass,
newpass: newPass,
},
(r) => {
switch (r.statusCode) {
case 200:
switch (r.data.err_code) {
case 0:
// 清空输入框
oldPassInput.value.value = "";
newPassInput.value.value = "";
cnfPassInput.value.value = "";
mos.value?.showAlert(
"success",
t("message.change_ok"),
2000,
() => {
userStore.logout();
router.push("/");
}
);
break;
case -42:
oldPassInput.value.classList.add("is-invalid");
mos.value?.showAlert(
"danger",
t("message.old_pass_incorrect"),
3000
);
break;
default:
mos.value?.showAlert("danger", t("message.server_error"), 5000);
break;
}
break;
default:
mos.value?.showAlert("danger", t("message.network_err"), 5000);
break;
}
}
);
}
function changeAvatar() {
mos.value?.showAlert(
"info",
t("message.functionality_not_yet_developed"),
5000
);
}
function rev_avatar_url(url) { function rev_avatar_url(url) {
is_avatar_change.value=true is_avatar_change.value = true;
avatar_temp_url.value=url avatar_temp_url.value = url;
//console.log(url) //console.log(url)
} }
function cancel_change_avatar(){
is_avatar_change.value=false
}
function functionupdataTitle() { function functionupdataTitle() {
document.title = "Operations." + t("settings.account_settings"); document.title = "Operations." + t("settings.basic_information");
} }
// 监听语言变化,更新标题 // 监听语言变化,更新标题
@@ -274,7 +127,7 @@ onMounted(() => {
<div class="page-wrapper"> <div class="page-wrapper">
<div class="page-header d-print-none"> <div class="page-header d-print-none">
<div class="container-xl"> <div class="container-xl">
<h2 class="page-title">{{ t("settings.account_settings") }}</h2> <h2 class="page-title">{{ t("settings.my_account") }}</h2>
</div> </div>
</div> </div>
@@ -285,14 +138,18 @@ onMounted(() => {
<settingNavigation /> <settingNavigation />
<div class="col-12 col-md-9 d-flex flex-column"> <div class="col-12 col-md-9 d-flex flex-column">
<div class="card-body"> <div class="card-body">
<h2 class="mb-4">{{ t("settings.my_account") }}</h2> <!-- <h2 class="mb-4">{{ t("settings.my_account") }}</h2> -->
<h3 class="card-title"> <!-- <h3 class="card-title">
{{ t("settings.profile_information") }} {{ t("settings.profile_information") }}
</h3> </h3> -->
<div class="row align-items-center"> <div class="row align-items-center">
<div class="col-auto"> <div class="col-auto">
<img <img
:src="is_avatar_change?avatar_temp_url:userStore.getUserAvatarPath()" :src="
is_avatar_change
? avatar_temp_url
: userStore.getUserAvatarPath()
"
alt="" alt=""
class="avatar avatar-xl" class="avatar avatar-xl"
/> />
@@ -300,9 +157,10 @@ onMounted(() => {
<!-- <imageCropper /> --> <!-- <imageCropper /> -->
<div class="col-auto " > <div class="col-auto " >
<imageCropper @crop="rev_avatar_url"></imageCropper> <imageCropper @crop="rev_avatar_url"></imageCropper>
<!-- <button class="btn" @click="changeAvatar">
{{ t("settings.change_avatar") }} <button v-show="is_avatar_change" class="btn btn-outline-secondary " @click="cancel_change_avatar">
</button> --> {{ t("settings.cancel") }}
</button>
</div> </div>
</div> </div>
<h3 class="card-title mt-4">-</h3> <h3 class="card-title mt-4">-</h3>
@@ -342,96 +200,6 @@ onMounted(() => {
</button> </button>
</div> </div>
</div> </div>
<h3 class="card-title mt-4">{{ t("settings.email") }}</h3>
<div>
<div class="row g-2">
<div class="col-auto">
<input
ref="emailInput"
type="text"
class="form-control w-auto"
:value="userStore.user.Email"
:placeholder="t('message.your_email_address')"
/>
</div>
<div class="col-auto">
<button class="btn" @click="changeEmail">
{{ t("settings.change_email") }}
</button>
</div>
</div>
</div>
<h3 class="card-title mt-4">
{{ t("settings.password") }}
<!-- Download SVG icon from http://tabler-icons.io/i/eye -->
<svg
v-if="!isShowPassword"
@click="togglePasswordVisibility"
xmlns="http://www.w3.org/2000/svg"
class="icon"
width="24"
height="24"
viewBox="0 0 24 24"
stroke-width="2"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M10 12a2 2 0 1 0 4 0a2 2 0 0 0 -4 0" />
<path
d="M21 12c-2.4 4 -5.4 6 -9 6c-3.6 0 -6.6 -2 -9 -6c2.4 -4 5.4 -6 9 -6c3.6 0 6.6 2 9 6"
/>
</svg>
<svg
v-if="isShowPassword"
@click="togglePasswordVisibility"
xmlns="http://www.w3.org/2000/svg"
class="icon"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M10.585 10.587a2 2 0 0 0 2.829 2.828" />
<path
d="M16.681 16.673a8.717 8.717 0 0 1 -4.681 1.327c-3.6 0 -6.6 -2 -9 -6c1.272 -2.12 2.712 -3.678 4.32 -4.674m2.86 -1.146a9.055 9.055 0 0 1 1.82 -.18c3.6 0 6.6 2 9 6c-.666 1.11 -1.379 2.067 -2.138 2.87"
/>
<path d="M3 3l18 18" />
</svg>
</h3>
<input
ref="oldPassInput"
:type="isShowPassword ? 'text' : 'password'"
class="form-control w-auto mb-1"
:placeholder="t('message.type_old_pass')"
/>
<input
ref="newPassInput"
:type="isShowPassword ? 'text' : 'password'"
class="form-control w-auto mb-1"
:placeholder="t('message.type_new_pass')"
/>
<input
ref="cnfPassInput"
:type="isShowPassword ? 'text' : 'password'"
class="form-control w-auto mb-1"
:placeholder="t('message.type_cof_pass')"
/>
<div>
<button class="btn" @click="changePassword">
{{ t("settings.set_new_password") }}
</button>
</div>
</div> </div>
</div> </div>
</div> </div>
@@ -0,0 +1,135 @@
<script setup>
import { onMounted, watch, ref } from "vue";
import settingNavigation from "@/components/settingNavigation.vue";
import { useI18n } from "vue-i18n";
import { useUserStore } from "@/stores/user";
import { my_network_func } from "@/my_network_func";
import MyOffcanvas from "@/components/MyOffcanvas.vue";
import { myfuncs } from "@/myfunc";
import { useRouter } from "vue-router";
const mos = ref();
const { t, locale } = useI18n();
const router = useRouter();
const emailInput = ref();
const userStore = useUserStore();
function changeEmail() {
if (emailInput.value.value == "") {
emailInput.value.classList.add("is-invalid");
mos.value?.showAlert("warning", t("message.please_enter_your_email"), 3000);
return;
} else {
emailInput.value.classList.remove("is-invalid");
}
//判断是否是合法邮箱
if (myfuncs.isValidEmail(emailInput.value.value) == false) {
emailInput.value.classList.add("is-invalid");
mos.value?.showAlert("danger", t("message.this_not_email"), 3000);
return;
} else {
emailInput.value.classList.remove("is-invalid");
}
my_network_func.postJson(
"/users/changeEmail",
{
newemail: emailInput.value.value,
},
(r) => {
switch (r.statusCode) {
case 200:
switch (r.data.err_code) {
case 0:
mos.value?.showAlert("success", t("message.change_ok"), 5000);
// 更新用户信息到store
userStore.getUserInfoFromCookie();
break;
case -43:
emailInput.value.classList.add("is-invalid");
mos.value?.showAlert("danger", t("message.this_not_email"), 3000);
break;
default:
mos.value?.showAlert("danger", t("message.server_error"), 5000);
break;
}
break;
default:
mos.value?.showAlert("danger", t("message.network_err"), 5000);
break;
}
}
);
}
function functionupdataTitle() {
document.title = "Operations." + t("settings.contact_information");
}
// 监听语言变化,更新标题
watch(locale, () => {
functionupdataTitle();
});
onMounted(() => {
//console.log("account mounted");
//username.value.value="Kevin";
functionupdataTitle();
if (!userStore.isLoggedIn) {
router.push("/login");
}
});
</script>
<template>
<div class="page-wrapper">
<div class="page-header d-print-none">
<div class="container-xl">
<h2 class="page-title">{{ t("settings.my_account") }}</h2>
</div>
</div>
<div class="page-body">
<div class="container-xl">
<div class="card">
<div class="row g-0">
<settingNavigation />
<div class="col-12 col-md-9 d-flex flex-column">
<div class="card-body">
<h3 class="card-title mt-4">{{ t("settings.email") }}</h3>
<div>
<div class="row g-2">
<div class="col-auto">
<input
ref="emailInput"
type="text"
class="form-control w-auto"
:value="userStore.user.Email"
:placeholder="t('message.your_email_address')"
/>
</div>
<div class="col-auto">
<button class="btn" @click="changeEmail">
{{ t("settings.change_email") }}
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<MyOffcanvas ref="mos" />
</template>
@@ -0,0 +1,230 @@
<script setup>
import { onMounted, watch, ref } from "vue";
import settingNavigation from "@/components/settingNavigation.vue";
import { useI18n } from "vue-i18n";
import { useUserStore } from "@/stores/user";
import { my_network_func } from "@/my_network_func";
import MyOffcanvas from "@/components/MyOffcanvas.vue";
import { useRouter } from "vue-router";
const mos = ref();
const { t, locale } = useI18n();
const router = useRouter();
const userStore = useUserStore();
const oldPassInput = ref();
const newPassInput = ref();
const cnfPassInput = ref();
const isShowPassword = ref(false);
function togglePasswordVisibility() {
isShowPassword.value = !isShowPassword.value;
}
function changePassword() {
let isDataErr = false;
let oldPass = oldPassInput.value.value;
let newPass = newPassInput.value.value;
let cnfPass = cnfPassInput.value.value;
oldPassInput.value.classList.remove("is-invalid");
newPassInput.value.classList.remove("is-invalid");
cnfPassInput.value.classList.remove("is-invalid");
if (!oldPass) {
isDataErr = true;
oldPassInput.value.classList.add("is-invalid");
}
if (!newPass) {
isDataErr = true;
newPassInput.value.classList.add("is-invalid");
}
if (!cnfPass) {
isDataErr = true;
cnfPassInput.value.classList.add("is-invalid");
}
if (newPass !== cnfPass) {
isDataErr = true;
newPassInput.value.classList.add("is-invalid");
cnfPassInput.value.classList.add("is-invalid");
mos.value?.showAlert(
"warning",
t("message.confirm_password_incorrect"),
3000
);
}
if (isDataErr) {
return;
}
my_network_func.postJson(
"/users/changePassword",
{
oldpass: oldPass,
newpass: newPass,
},
(r) => {
switch (r.statusCode) {
case 200:
switch (r.data.err_code) {
case 0:
// 清空输入框
oldPassInput.value.value = "";
newPassInput.value.value = "";
cnfPassInput.value.value = "";
mos.value?.showAlert(
"success",
t("message.change_ok"),
2000,
() => {
userStore.logout();
router.push("/");
}
);
break;
case -42:
oldPassInput.value.classList.add("is-invalid");
mos.value?.showAlert(
"danger",
t("message.old_pass_incorrect"),
3000
);
break;
default:
mos.value?.showAlert("danger", t("message.server_error"), 5000);
break;
}
break;
default:
mos.value?.showAlert("danger", t("message.network_err"), 5000);
break;
}
}
);
}
function functionupdataTitle() {
document.title = "Operations." + t("settings.security_settings");
}
// 监听语言变化,更新标题
watch(locale, () => {
functionupdataTitle();
});
onMounted(() => {
//console.log("account mounted");
//username.value.value="Kevin";
functionupdataTitle();
if (!userStore.isLoggedIn) {
router.push("/login");
}
});
</script>
<template>
<div class="page-wrapper">
<div class="page-header d-print-none">
<div class="container-xl">
<h2 class="page-title">{{ t("settings.my_account") }}</h2>
</div>
</div>
<div class="page-body">
<div class="container-xl">
<div class="card">
<div class="row g-0">
<settingNavigation />
<div class="col-12 col-md-9 d-flex flex-column">
<div class="card-body">
<h3 class="card-title mt-4">
{{ t("settings.password") }}
<!-- Download SVG icon from http://tabler-icons.io/i/eye -->
<svg
v-if="!isShowPassword"
@click="togglePasswordVisibility"
xmlns="http://www.w3.org/2000/svg"
class="icon"
width="24"
height="24"
viewBox="0 0 24 24"
stroke-width="2"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M10 12a2 2 0 1 0 4 0a2 2 0 0 0 -4 0" />
<path
d="M21 12c-2.4 4 -5.4 6 -9 6c-3.6 0 -6.6 -2 -9 -6c2.4 -4 5.4 -6 9 -6c3.6 0 6.6 2 9 6"
/>
</svg>
<svg
v-if="isShowPassword"
@click="togglePasswordVisibility"
xmlns="http://www.w3.org/2000/svg"
class="icon"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M10.585 10.587a2 2 0 0 0 2.829 2.828" />
<path
d="M16.681 16.673a8.717 8.717 0 0 1 -4.681 1.327c-3.6 0 -6.6 -2 -9 -6c1.272 -2.12 2.712 -3.678 4.32 -4.674m2.86 -1.146a9.055 9.055 0 0 1 1.82 -.18c3.6 0 6.6 2 9 6c-.666 1.11 -1.379 2.067 -2.138 2.87"
/>
<path d="M3 3l18 18" />
</svg>
</h3>
<input
ref="oldPassInput"
:type="isShowPassword ? 'text' : 'password'"
class="form-control w-auto mb-1"
:placeholder="t('message.type_old_pass')"
/>
<input
ref="newPassInput"
:type="isShowPassword ? 'text' : 'password'"
class="form-control w-auto mb-1"
:placeholder="t('message.type_new_pass')"
/>
<input
ref="cnfPassInput"
:type="isShowPassword ? 'text' : 'password'"
class="form-control w-auto mb-1"
:placeholder="t('message.type_cof_pass')"
/>
<div>
<button class="btn" @click="changePassword">
{{ t("settings.set_new_password") }}
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<MyOffcanvas ref="mos" />
</template>