Skip to content

Commit

Permalink
Feat: Rooms Manager
Browse files Browse the repository at this point in the history
  • Loading branch information
LazyCreeper committed Nov 16, 2023
1 parent 70c9403 commit 7f8e33d
Show file tree
Hide file tree
Showing 6 changed files with 303 additions and 4 deletions.
2 changes: 2 additions & 0 deletions components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ declare module 'vue' {
export interface GlobalComponents {
Bilibili: typeof import('./src/components/icons/Bilibili.vue')['default']
BilibiliParse: typeof import('./src/components/dialogs/bilibiliParse.vue')['default']
CopyButton: typeof import('./src/components/CopyButton.vue')['default']
CustomHeaders: typeof import('./src/components/dialogs/customHeaders.vue')['default']
DarkModeSwitcher: typeof import('./src/components/DarkModeSwitcher.vue')['default']
Edit: typeof import('./src/components/icons/Edit.vue')['default']
Expand All @@ -21,6 +22,7 @@ declare module 'vue' {
ElEmpty: typeof import('element-plus/es')['ElEmpty']
ElForm: typeof import('element-plus/es')['ElForm']
ElFormItem: typeof import('element-plus/es')['ElFormItem']
ElIcon: typeof import('element-plus/es')['ElIcon']
ElInput: typeof import('element-plus/es')['ElInput']
ElMain: typeof import('element-plus/es')['ElMain']
ElOption: typeof import('element-plus/es')['ElOption']
Expand Down
26 changes: 26 additions & 0 deletions src/components/CopyButton.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<script setup lang="ts">
import { DocumentCopy } from "@element-plus/icons-vue";
import { ElMessage } from "element-plus";
const props = defineProps<{
size?: string;
value: string;
}>();
const copy = async () => {
if (!navigator.clipboard) return ElMessage.error("您当前的浏览器不支持 Clipboard API");
try {
await navigator.clipboard.writeText(props.value);
ElMessage.success("复制成功");
} catch (error) {
ElMessage.error("复制失败:" + error);
}
};
</script>

<template>
<el-tooltip>
<template #content>复制</template>
<el-button :icon="DocumentCopy" :size="size" circle @click="copy" />
</el-tooltip>
</template>
53 changes: 53 additions & 0 deletions src/services/apis/admin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,3 +194,56 @@ export const updateSettingApi = useDefineApi<
url: "/api/admin/settings",
method: "POST"
});

// 获取房间列表
export const roomListApi = useDefineApi<
{
headers: {
Authorization: string;
};
params: {
page: number;
max: number;
sort: string;
order: string;
};
},
{
list: RoomList[] | null;
total: number;
}
>({
url: "/api/admin/room/list",
method: "GET"
});

// 封禁房间
export const banRoomApi = useDefineApi<
{
headers: {
Authorization: string;
};
data: {
id: string;
};
},
any
>({
url: "/api/admin/room/ban",
method: "POST"
});

export const unBanRoomApi = useDefineApi<
{
headers: {
Authorization: string;
};
data: {
id: string;
};
},
any
>({
url: "/api/admin/room/unban",
method: "POST"
});
14 changes: 14 additions & 0 deletions src/types/Room.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,17 @@ export interface RoomList {
creatorId: string;
status: number;
}

export enum RoomStatus {
Unknown = 0,
Banned = 1,
Pending = 2,
Active = 3
}

export const roomStatus = {
[RoomStatus.Unknown]: "Unknown",
[RoomStatus.Banned]: "Banned",
[RoomStatus.Pending]: "Pending",
[RoomStatus.Active]: "Active"
};
14 changes: 10 additions & 4 deletions src/views/admin/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { useScreen } from "@/hooks/useScreen";
import { ROLE } from "@/types/User";
import UserManager from "./settings/UserManager.vue";
import RoomsManager from "./settings/RoomsManager.vue";
import SiteSetting from "./settings/SiteSetting.vue";
const { info: userInfo } = userStore();
Expand All @@ -25,17 +26,22 @@ const tabs: Tabs[] = [
icon: "🐵",
component: UserManager
},
{
name: "房间管理",
icon: "🏡",
component: RoomsManager
},
{
name: "站点设置",
icon: "👮‍",
icon: "🌏",
component: SiteSetting
}
];
const activeTab = shallowRef<Tabs>({
name: "站点设置",
icon: "👮‍",
component: SiteSetting
name: "房间管理",
icon: "🏡",
component: RoomsManager
});
const switchTab = (tab: Tabs) => {
Expand Down
198 changes: 198 additions & 0 deletions src/views/admin/settings/RoomsManager.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
<script lang="ts" setup>
import { onMounted, ref } from "vue";
import { ElNotification, ElMessage } from "element-plus";
import { userStore } from "@/stores/user";
import {
roomListApi,
banRoomApi,
unBanRoomApi,
addAdminApi,
delAdminApi
} from "@/services/apis/admin";
import CopyButton from "@/components/CopyButton.vue";
import { RoomStatus, roomStatus } from "@/types/Room";
const props = defineProps<{
title: string;
}>();
const getStatus = (rawStatus: RoomStatus) => roomStatus[rawStatus];
const { token } = userStore();
const totalItems = ref(0);
const currentPage = ref(1);
const pageSize = ref(10);
const order = ref("createdAt");
const sort = ref("desc");
const { state, execute: reqRoomListApi, isLoading: roomListLoading } = roomListApi();
const getRoomListApi = async () => {
try {
await reqRoomListApi({
headers: {
Authorization: token.value
},
params: {
page: currentPage.value,
max: pageSize.value,
sort: sort.value,
order: order.value,
role: "",
search: "all",
keyword: ""
}
});
if (state.value) {
totalItems.value = state.value.total;
}
} catch (err: any) {
console.error(err);
ElNotification({
title: "获取房间列表失败",
type: "error",
message: err.response.data.error || err.message
});
}
};
// 封禁 / 解封 房间
const { execute: ban, isLoading: banLoading } = banRoomApi();
const { execute: unBan, isLoading: unBanLoading } = unBanRoomApi();
const banRoom = async (id: string, is: boolean) => {
try {
const config = {
headers: {
Authorization: token.value
},
data: {
id: id
}
};
is ? await ban(config) : await unBan(config);
ElNotification({
title: `${is ? "封禁" : "解封"}成功`,
type: "success"
});
await getRoomListApi();
} catch (err: any) {
console.error(err);
ElNotification({
title: "错误",
type: "error",
message: err.response.data.error || err.message
});
}
};
// 允许创建
const approveCreate = async (id: string, is: boolean) => {
try {
const config = {
headers: {
Authorization: token.value
},
data: {
id: id
}
};
is ? await addAdminApi().execute(config) : await delAdminApi().execute(config);
ElNotification({
title: "设置成功",
type: "success"
});
await getRoomListApi();
} catch (err: any) {
console.error(err);
ElNotification({
title: "错误",
type: "error",
message: err.response.data.error || err.message
});
}
};
onMounted(async () => {
await getRoomListApi();
});
</script>

<template>
<div class="card">
<div class="card-title">
{{ props.title }}
<el-button>刷新列表</el-button>
</div>
<div class="card-body">
<el-table :data="state?.list" v-loading="roomListLoading" style="width: 100%">
<el-table-column prop="roomName" label="房间名" width="150" />
<el-table-column prop="roomId" label="ID" width="120">
<template #default="scope">
<div class="flex overflow-hidden text-ellipsis max-w-[100px]">
<span class="truncate">{{ scope.row.roomId }}</span>
<CopyButton size="small" :value="scope.row.roomId" />
</div>
</template>
</el-table-column>
<el-table-column prop="creator" label="创建人">
<template #default="scope">
{{ scope.row.creator }}
</template>
</el-table-column>
<el-table-column prop="peopleNum" label="在线人数" width="80">
<template #default="scope">
<el-tag disabled :type="scope.row.peopleNum > 0 ? 'success' : 'danger'">
{{ scope.row.peopleNum }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="needPassword" label="密码保护" width="100">
<template #default="scope">
<el-tag disabled :type="scope.row.needPassword ? 'danger' : 'success'">
{{ scope.row.needPassword ? "有密码" : "无密码" }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="createdAt" label="创建时间">
<template #default="scope">
{{ new Date(scope.row.createdAt).toLocaleString() }}
</template>
</el-table-column>
<el-table-column prop="status" label="状态" width="100">
<template #default="scope">
{{ getStatus(scope.row.status) }}
</template>
</el-table-column>
<el-table-column fixed="right" label="操作">
<template #default="scope">
<el-button
v-if="scope.row.status !== RoomStatus.Banned"
type="danger"
:loading="banLoading"
@click="banRoom(scope.row.roomId, true)"
>
封禁
</el-button>
<el-button
v-else
type="warning"
:loading="unBanLoading"
@click="banRoom(scope.row.roomId, false)"
>
解封
</el-button>
<el-button
v-if="scope.row.status === RoomStatus.Pending"
type="success"
:loading="banLoading"
@click="banRoom(scope.row.roomId, true)"
>
允许创建
</el-button>
</template>
</el-table-column>
</el-table>
</div>
</div>

<userRooms ref="userRoomsDialog" />
</template>

0 comments on commit 7f8e33d

Please sign in to comment.