Feat: guest user join room

This commit is contained in:
Lazy 2024-04-18 22:35:33 +08:00
parent 83979276fd
commit 063db6c7de
10 changed files with 153 additions and 33 deletions

View File

@ -41,6 +41,19 @@ const menuLinks = computed(() => {
to: "/auth/register"
});
if (!isLogin.value && settings?.guestEnable) {
basicLinks.push({
name: "加入房间",
to: "/joinRoom"
});
route.path.startsWith("/cinema") &&
basicLinks.push({
name: "影厅",
to: "/cinema/" + route.params.roomId
});
}
if (isLogin.value) {
const loginLinks = route.path.startsWith("/cinema")
? [

View File

@ -3,12 +3,14 @@ import { onMounted, ref } from "vue";
import { ElNotification } from "element-plus";
import { roomStatus, type RoomList } from "@/types/Room";
import JoinRoom from "@/views/JoinRoom.vue";
import { indexStore } from "@/stores";
import { userStore } from "@/stores/user";
import { Search } from "@element-plus/icons-vue";
import { useTimeAgo } from "@vueuse/core";
import { useRouter } from "vue-router";
import { useRoomApi } from "@/hooks/useRoom";
import { getObjValue } from "@/utils";
import { guestJoinRoomApi } from "@/services/apis/room";
const router = useRouter();
const props = defineProps<{
@ -17,6 +19,7 @@ const props = defineProps<{
userId?: string;
}>();
const { settings } = indexStore();
const { isLogin, info } = userStore();
const thisRoomList = ref<RoomList[]>([]);
const formData = ref<{
@ -45,7 +48,8 @@ const {
getHotRoomList,
hotRoomList,
joinRoom
joinRoom,
guestJoinRoom
} = useRoomApi(formData.value.roomId);
const getRoomList = async (showMsg = false) => {
@ -63,7 +67,7 @@ const getRoomList = async (showMsg = false) => {
const JoinRoomDialog = ref(false);
const joinThisRoom = async (item: RoomList) => {
if (!isLogin.value) {
if (!settings?.guestEnable && isLogin.value) {
ElNotification({
title: "错误",
message: "请先登录",
@ -79,9 +83,13 @@ const joinThisRoom = async (item: RoomList) => {
}
formData.value.roomId = item.roomId;
info.value?.username === item.creator || !item.needPassword
? await joinRoom(formData.value)
: (JoinRoomDialog.value = true);
return isLogin.value
? info.value?.username === item.creator || !item.needPassword
? await joinRoom(formData.value)
: (JoinRoomDialog.value = true)
: settings?.guestEnable && !item.needPassword
? await guestJoinRoom(formData.value)
: (JoinRoomDialog.value = true);
};
onMounted(() => {

View File

@ -5,7 +5,14 @@ import { roomStore } from "@/stores/room";
import router from "@/router";
import { myRoomListApi } from "@/services/apis/user";
import { userRoomListApi } from "@/services/apis/admin";
import { joinRoomApi, checkRoomApi, roomListApi, hotRoom, myInfoApi } from "@/services/apis/room";
import {
joinRoomApi,
checkRoomApi,
roomListApi,
hotRoom,
myInfoApi,
guestJoinRoomApi
} from "@/services/apis/room";
import { strLengthLimit } from "@/utils";
import { storeToRefs } from "pinia";
import { RoomMemberPermission, RoomAdminPermission } from "@/types/Room";
@ -92,6 +99,54 @@ export const useRoomApi = (roomId: string) => {
}
};
// 加入房间(访客)
const { state: guestJoinRoomInfo, execute: reqGuestJoinRoomApi } = guestJoinRoomApi();
const guestJoinRoom = async (formData: { roomId: string; password: string }) => {
if (!formData.roomId) {
ElNotification({
title: "错误",
message: "请填写表单完整",
type: "error"
});
return;
}
for (const key in formData) {
strLengthLimit(key, 32);
}
try {
await reqGuestJoinRoomApi({
data: formData
});
if (!guestJoinRoomInfo.value)
return ElNotification({
title: "错误",
message: "服务器并未返回token",
type: "error"
});
localStorage.setItem(
`room-${guestJoinRoomInfo.value.roomId}-token`,
guestJoinRoomInfo.value?.token
);
if (formData.password)
localStorage.setItem(`room-${guestJoinRoomInfo.value.roomId}-pwd`, formData.password);
await getMyInfo(guestJoinRoomInfo.value.token);
ElNotification({
title: "加入成功",
type: "success"
});
router.replace(`/cinema/${guestJoinRoomInfo.value.roomId}`);
} catch (err: any) {
console.error(err);
ElNotification({
title: "错误",
message: err.response.data.error || err.message,
type: "error"
});
}
};
// 房间列表
const totalItems = ref(0);
const currentPage = ref(1);
@ -297,7 +352,10 @@ export const useRoomApi = (roomId: string) => {
hotRoomList,
getMyInfo,
myInfo
myInfo,
guestJoinRoom,
guestJoinRoomInfo
};
};

View File

@ -1,7 +1,9 @@
import { createRouter, createWebHistory } from "vue-router";
import { start, close } from "@/utils/nprogress";
import { ROLE } from "@/types/User";
import { userStore } from "@/stores/user";
// import { indexStore } from "@/stores";
const Base_Title = "SyncTV";
@ -100,8 +102,10 @@ const router = createRouter({
}
});
router.beforeEach((to: any, from: any, next) => {
router.beforeEach(async (to: any, from: any, next) => {
start();
const { indexStore } = await import("@/stores");
const { settings } = indexStore();
const { info } = userStore();
const permission = info.value?.role ?? -1;
if (to.meta.permission <= permission) {
@ -109,12 +113,19 @@ router.beforeEach((to: any, from: any, next) => {
next();
} else {
if (permission === ROLE.Visitor) {
router.replace({
name: "login",
query: {
redirect: to.fullPath
}
});
if (
(settings?.guestEnable && to.path.startsWith("/cinema")) ||
to.path.startsWith("/joinRoom")
) {
next();
} else {
router.replace({
name: "login",
query: {
redirect: to.fullPath
}
});
}
} else {
next("/403");
}

View File

@ -1,5 +1,5 @@
import { useDefineApi } from "@/stores/useDefineApi";
import type { RegForm, EmailRegForm } from "@/types";
import type { RegForm, EmailRegForm, PublicSettings } from "@/types";
// 注册
export const RegisterApi = useDefineApi<
@ -88,15 +88,7 @@ export const oAuth2Callback = useDefineApi<
});
// 获取站点配置信息
export const getPublicSettings = useDefineApi<
any,
{
emailEnable: boolean;
emailDisableUserSignup: boolean;
emailWhitelistEnabled: boolean;
emailWhitelist: string[];
}
>({
export const getPublicSettings = useDefineApi<any, PublicSettings>({
url: "/api/public/settings",
method: "GET"
});

View File

@ -84,6 +84,25 @@ export const joinRoomApi = useDefineApi<
method: "POST"
});
// 加入房间(访客)
export const guestJoinRoomApi = useDefineApi<
// request
{
data: {
roomId: string;
password: string;
};
},
// response
{
roomId: string;
token: string;
}
>({
url: "/api/room/guest",
method: "POST"
});
// 删除房间
export const delRoomApi = useDefineApi<
{

View File

@ -2,16 +2,12 @@ import { ref } from "vue";
import { ElNotification } from "element-plus";
import { getPublicSettings } from "@/services/apis/auth";
import { defineStore } from "pinia";
import type { PublicSettings } from "@/types";
export const indexStore = defineStore("indexStore", () => {
const { execute, state } = getPublicSettings();
const settings = ref<{
emailEnable: boolean;
emailDisableUserSignup: boolean;
emailWhitelistEnabled: boolean;
emailWhitelist: string[];
}>();
const settings = ref<PublicSettings>();
const getSiteOptions = async () => {
try {

View File

@ -6,3 +6,11 @@ export interface RegForm {
export interface EmailRegForm extends RegForm {
captcha: string;
}
export interface PublicSettings {
emailEnable: boolean;
emailDisableUserSignup: boolean;
emailWhitelistEnabled: boolean;
emailWhitelist: string[];
guestEnable: boolean;
}

View File

@ -3,6 +3,11 @@ import { ref, computed, onMounted } from "vue";
import { useRoute } from "vue-router";
import { useRouteParams, useRouteQuery } from "@vueuse/router";
import { useRoomApi } from "@/hooks/useRoom";
import { indexStore } from "@/stores";
import { userStore } from "@/stores/user";
const { settings } = indexStore();
const { isLogin } = userStore();
const route = useRoute();
const roomID = useRouteParams("roomId");
const pwd = useRouteQuery("pwd");
@ -28,7 +33,7 @@ const formData = ref<{
});
if (props.item) formData.value = props.item;
const { checkRoom, joinRoom } = useRoomApi(formData.value.roomId);
const { checkRoom, joinRoom, guestJoinRoom } = useRoomApi(formData.value.roomId);
onMounted(() => {
if (formData.value.roomId) checkRoom(pwd.value as string);
@ -55,7 +60,15 @@ onMounted(() => {
autocomplete="new-password"
/>
<br />
<button class="btn m-[10px]" @click="joinRoom(formData)">加入</button>
<button
v-if="settings?.guestEnable && !isLogin"
class="btn btn-success my-[10px]"
@click="guestJoinRoom(formData)"
>
以访客身份加入
</button>
<button v-else class="btn my-[10px]" @click="joinRoom(formData)">加入</button>
<div class="text-sm">
<b>注意</b>所有输入框最大只可输入32个字符
<br />

View File

@ -3,6 +3,7 @@ import { ref, onUnmounted } from "vue";
import { ElNotification } from "element-plus";
import type { RoomList } from "@/types/Room";
import JoinRoom from "./JoinRoom.vue";
import { indexStore } from "@/stores";
import { userStore } from "@/stores/user";
import { useTimeAgo } from "@vueuse/core";
import { useRouter } from "vue-router";
@ -21,9 +22,10 @@ const formData = ref<{
const { totalItems, currentPage, pageSize, keyword, search, getRoomList, roomList, joinRoom } =
useRoomApi(formData.value.roomId);
const { settings } = indexStore();
const JoinRoomDialog = ref(false);
const openJoinRoomDialog = async (item: RoomList) => {
if (!isLogin.value) {
if (!settings?.guestEnable && isLogin.value) {
ElNotification({
title: "错误",
message: "请先登录",