mirror of
https://github.com/MCSManager/MCSManager.git
synced 2024-12-03 07:20:16 +08:00
Merge branch 'next' of github.com:MCSManager/MCSManager into next
This commit is contained in:
commit
4ace238f54
1
frontend/components.d.ts
vendored
1
frontend/components.d.ts
vendored
@ -43,6 +43,7 @@ declare module 'vue' {
|
||||
CardOperator: typeof import('./src/components/CardOperator.vue')['default']
|
||||
CardPanel: typeof import('./src/components/CardPanel.vue')['default']
|
||||
copy: typeof import('./src/components/ActionButton copy.vue')['default']
|
||||
CopyButton: typeof import('./src/components/CopyButton.vue')['default']
|
||||
DataStatistic: typeof import('./src/components/DataStatistic.vue')['default']
|
||||
IconBtn: typeof import('./src/components/IconBtn.vue')['default']
|
||||
InnerCard: typeof import('./src/components/InnerCard.vue')['default']
|
||||
|
@ -97,6 +97,14 @@
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.float-right {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.float-left {
|
||||
float: left;
|
||||
}
|
||||
|
||||
@mixin generate-styles($depth) {
|
||||
.m-#{$depth} {
|
||||
margin: #{$depth}px !important;
|
||||
|
32
frontend/src/components/CopyButton.vue
Normal file
32
frontend/src/components/CopyButton.vue
Normal file
@ -0,0 +1,32 @@
|
||||
<script setup lang="ts">
|
||||
import { t } from "@/lang/i18n";
|
||||
import { CopyOutlined } from "@ant-design/icons-vue";
|
||||
import { message } from "ant-design-vue";
|
||||
|
||||
const props = defineProps<{
|
||||
size?: string;
|
||||
type?: string;
|
||||
value: string;
|
||||
}>();
|
||||
|
||||
const copy = async () => {
|
||||
if (!navigator.clipboard) return message.error(t("您当前的浏览器不支持 Clipboard API"));
|
||||
try {
|
||||
await navigator.clipboard.writeText(props.value);
|
||||
message.success(t("复制成功"));
|
||||
} catch (error) {
|
||||
message.error(t("复制失败:") + error);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-tooltip>
|
||||
<template #title>{{ t("复制") }}</template>
|
||||
<a-button :type="type" :size="size" @click="copy">
|
||||
<template #icon>
|
||||
<CopyOutlined />
|
||||
</template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
</template>
|
@ -2,56 +2,70 @@
|
||||
import { t } from "@/lang/i18n";
|
||||
import { useAppStateStore } from "@/stores/useAppStateStore";
|
||||
import { useAppToolsStore } from "@/stores/useAppToolsStore";
|
||||
import { reactive, toRaw } from "vue";
|
||||
const { state } = useAppStateStore();
|
||||
import { reactive, ref } from "vue";
|
||||
import { setUserApiKey, updatePassword } from "@/services/apis/user";
|
||||
import { message } from "ant-design-vue";
|
||||
import type { FormInstance } from "ant-design-vue";
|
||||
import CopyButton from "@/components/CopyButton.vue";
|
||||
import { sleep } from "@/tools/commom";
|
||||
const { state, updateUserInfo } = useAppStateStore();
|
||||
const { state: tools } = useAppToolsStore();
|
||||
|
||||
// const menus = [
|
||||
// {
|
||||
// title: t("基本信息"),
|
||||
// key: "baseInfo",
|
||||
// icon: ProjectOutlined
|
||||
// },
|
||||
// {
|
||||
// title: t("第三方接口"),
|
||||
// key: "api",
|
||||
// icon: RobotOutlined
|
||||
// },
|
||||
// {
|
||||
// title: t("账号安全"),
|
||||
// key: "password",
|
||||
// icon: RobotOutlined
|
||||
// }
|
||||
// ];
|
||||
const { execute, isLoading: setUserApiKeyLoading } = setUserApiKey();
|
||||
const { execute: executeUpdatePassword, isLoading: updatePasswordLoading } = updatePassword();
|
||||
|
||||
const formState = reactive({
|
||||
resetPassword: false,
|
||||
apikey: "",
|
||||
oldPassword: "",
|
||||
password1: "",
|
||||
password2: ""
|
||||
});
|
||||
|
||||
const handleGenerateApiKey = () => {
|
||||
formState.apikey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
|
||||
const formRef = ref<FormInstance>();
|
||||
|
||||
const handleGenerateApiKey = async (enable: boolean) => {
|
||||
const res = await execute({
|
||||
data: {
|
||||
enable
|
||||
}
|
||||
});
|
||||
|
||||
if (res.value) {
|
||||
updateUserInfo();
|
||||
return message.success(t("更新成功"));
|
||||
}
|
||||
};
|
||||
|
||||
const handleChangePassword = () => {};
|
||||
const onSubmit = () => {
|
||||
console.log("submit!", toRaw(formState));
|
||||
const handleChangePassword = async () => {
|
||||
formRef.value?.validateFields().then(async () => {
|
||||
if (formState.password1 !== formState.password2)
|
||||
return message.error(t("两次输入的密码不一致"));
|
||||
if (formState.password1.length < 6 || formState.password1.length > 36)
|
||||
return message.error(t("密码长度不能小于6位"));
|
||||
try {
|
||||
await executeUpdatePassword({
|
||||
data: {
|
||||
passWord: formState.password1
|
||||
}
|
||||
});
|
||||
updateUserInfo();
|
||||
return message.success(t("更新成功"));
|
||||
} catch (error: any) {
|
||||
return message.error(error.response.data.data);
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-modal
|
||||
v-model:open="tools.showUserInfoDialog"
|
||||
:title="t('用户信息')"
|
||||
centered
|
||||
:title="t('用户信息')"
|
||||
:footer="null"
|
||||
@ok="tools.showUserInfoDialog = false"
|
||||
>
|
||||
<div>
|
||||
<a-form :model="formState" layout="vertical">
|
||||
<a-form ref="formRef" :model="formState" layout="vertical">
|
||||
<a-row>
|
||||
<a-col :span="12">
|
||||
<a-form-item :label="t('用户名')">
|
||||
@ -92,12 +106,6 @@ const onSubmit = () => {
|
||||
重置
|
||||
</a-button>
|
||||
<div v-if="formState.resetPassword">
|
||||
<a-input
|
||||
v-model:value="formState.oldPassword"
|
||||
size="default"
|
||||
class="mb-12"
|
||||
:placeholder="t('请输入旧密码')"
|
||||
/>
|
||||
<a-input
|
||||
v-model:value="formState.password1"
|
||||
size="default"
|
||||
@ -111,7 +119,13 @@ const onSubmit = () => {
|
||||
:placeholder="t('请重复输入新密码')"
|
||||
/>
|
||||
<div>
|
||||
<a-button size="default" @click="handleChangePassword">确定</a-button>
|
||||
<a-button
|
||||
size="default"
|
||||
:loading="updatePasswordLoading"
|
||||
@click="handleChangePassword"
|
||||
>
|
||||
确定
|
||||
</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</a-form-item>
|
||||
@ -124,10 +138,28 @@ const onSubmit = () => {
|
||||
)
|
||||
}}
|
||||
</a-typography-paragraph>
|
||||
<a-typography-paragraph v-if="formState.apikey">
|
||||
<pre>{{ formState.apikey }}</pre>
|
||||
<a-typography-paragraph v-if="state.userInfo?.apiKey">
|
||||
<pre
|
||||
class="flex flex-between">{{ state.userInfo.apiKey }}<CopyButton size="small" type="text" :value="state.userInfo.apiKey" /></pre>
|
||||
</a-typography-paragraph>
|
||||
<a-button size="default" danger @click="handleGenerateApiKey">生成</a-button>
|
||||
<a-typography-paragraph v-else>
|
||||
<pre>{{ t("未启用") }}</pre>
|
||||
</a-typography-paragraph>
|
||||
<a-button
|
||||
class="mr-10"
|
||||
size="default"
|
||||
:loading="setUserApiKeyLoading"
|
||||
@click="handleGenerateApiKey(true)"
|
||||
>
|
||||
{{ t("生成") }}
|
||||
</a-button>
|
||||
<a-popconfirm
|
||||
v-if="state.userInfo?.apiKey"
|
||||
:title="t('你确定要关闭APIKey吗')"
|
||||
@confirm="handleGenerateApiKey(false)"
|
||||
>
|
||||
<a-button size="default" danger> {{ t("关闭") }} </a-button>
|
||||
</a-popconfirm>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</div>
|
||||
|
27
frontend/src/services/apis/user.ts
Normal file
27
frontend/src/services/apis/user.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import { useDefineApi } from "@/stores/useDefineApi";
|
||||
|
||||
// 设置用户APIKey
|
||||
export const setUserApiKey = useDefineApi<
|
||||
{
|
||||
data: {
|
||||
enable: boolean;
|
||||
};
|
||||
},
|
||||
string
|
||||
>({
|
||||
url: "/api/auth/api",
|
||||
method: "PUT"
|
||||
});
|
||||
|
||||
// 更新密码
|
||||
export const updatePassword = useDefineApi<
|
||||
{
|
||||
data: {
|
||||
passWord: string;
|
||||
};
|
||||
},
|
||||
boolean
|
||||
>({
|
||||
url: "/api/auth/update",
|
||||
method: "PUT"
|
||||
});
|
Loading…
Reference in New Issue
Block a user