Initial role user app

This commit is contained in:
湛兮
2026-06-02 14:46:39 +08:00
commit 003dc60111
62 changed files with 7835 additions and 0 deletions
+33
View File
@@ -0,0 +1,33 @@
import { setSessionToken } from "@/lib/session";
import { BackendError, backendRequest } from "@/lib/backend";
import type { LoginResponse } from "@/lib/types";
export async function POST(request: Request) {
try {
const body = await request.json();
const result = await backendRequest<LoginResponse>("/auth/employee/login", {
method: "POST",
body: JSON.stringify({
username: body.username,
password: body.password
}),
token: ""
});
await setSessionToken(result.token);
return Response.json({
success: true,
data: {
user: result.user,
tokenType: result.tokenType,
expiresIn: result.expiresIn
}
});
} catch (error) {
const status = error instanceof BackendError ? error.status : 500;
const message = error instanceof Error ? error.message : "登录失败";
return Response.json({ success: false, data: null, message }, { status });
}
}
+15
View File
@@ -0,0 +1,15 @@
import { NextRequest, NextResponse } from "next/server";
import { clearSessionToken } from "@/lib/session";
export async function POST() {
await clearSessionToken();
return Response.json({ success: true, data: null });
}
export async function GET(request: NextRequest) {
await clearSessionToken();
const next = request.nextUrl.searchParams.get("next") || "/login";
return NextResponse.redirect(new URL(next, request.url));
}
+11
View File
@@ -0,0 +1,11 @@
import { proxyBackendJson } from "@/lib/backend";
import type { AuthUser } from "@/lib/types";
export async function PATCH(request: Request) {
const body = await request.text();
return proxyBackendJson<AuthUser>("/auth/me/password", {
method: "PATCH",
body: body || undefined
});
}
+6
View File
@@ -0,0 +1,6 @@
import { proxyBackendJson } from "@/lib/backend";
import type { AuthUser } from "@/lib/types";
export async function GET() {
return proxyBackendJson<AuthUser>("/auth/me");
}
@@ -0,0 +1,13 @@
import { proxyBackendJson } from "@/lib/backend";
import type { AnnouncementDetail } from "@/lib/types";
type Params = {
params: Promise<{ id: string }>;
};
export async function POST(_request: Request, { params }: Params) {
const { id } = await params;
return proxyBackendJson<AnnouncementDetail>(`/mobile/announcements/${encodeURIComponent(id)}/read`, {
method: "POST"
});
}
@@ -0,0 +1,11 @@
import { proxyBackendJson } from "@/lib/backend";
import type { AnnouncementDetail } from "@/lib/types";
type Params = {
params: Promise<{ id: string }>;
};
export async function GET(_request: Request, { params }: Params) {
const { id } = await params;
return proxyBackendJson<AnnouncementDetail>(`/mobile/announcements/${encodeURIComponent(id)}`);
}
@@ -0,0 +1,6 @@
import { proxyBackendJson } from "@/lib/backend";
export async function GET(request: Request) {
const search = new URL(request.url).search;
return proxyBackendJson<unknown>(`/mobile/announcements${search}`);
}
+7
View File
@@ -0,0 +1,7 @@
import { proxyBackendJson } from "@/lib/backend";
import type { ShiftSummary } from "@/lib/types";
export async function GET(request: Request) {
const search = new URL(request.url).search;
return proxyBackendJson<ShiftSummary[]>(`/mobile/shifts${search}`);
}
+6
View File
@@ -0,0 +1,6 @@
import { proxyBackendJson } from "@/lib/backend";
import type { ShiftSummary } from "@/lib/types";
export async function GET() {
return proxyBackendJson<ShiftSummary | null>("/mobile/shifts/today");
}
@@ -0,0 +1,31 @@
import { backendErrorResponse, BackendError, backendRequest } from "@/lib/backend";
import type { ApiEnvelope, AuthUser, StoreEmployee } from "@/lib/types";
export async function GET() {
try {
const user = await backendRequest<AuthUser>("/auth/me");
if (!user.storeId) {
return Response.json({ success: true, data: [] } satisfies ApiEnvelope<StoreEmployee[]>);
}
const search = new URLSearchParams({
storeId: String(user.storeId),
page: "1",
pageSize: "100"
});
try {
const employees = await backendRequest<unknown>(`/employees?${search.toString()}`);
return Response.json({ success: true, data: employees } satisfies ApiEnvelope<unknown>);
} catch (error) {
if (error instanceof BackendError && [403, 404].includes(error.status)) {
return Response.json({ success: true, data: [] } satisfies ApiEnvelope<StoreEmployee[]>);
}
throw error;
}
} catch (error) {
return backendErrorResponse(error);
}
}
+38
View File
@@ -0,0 +1,38 @@
import { backendErrorResponse, BackendError, backendRequest } from "@/lib/backend";
import type { ApiEnvelope, AuthUser, StoreDetail } from "@/lib/types";
function fallbackStore(user: AuthUser): StoreDetail | null {
if (!user.storeId) return null;
return {
id: user.storeId,
name: user.storeName ?? "当前门店",
address: null,
phone: null,
status: undefined,
employees: []
};
}
export async function GET() {
try {
const user = await backendRequest<AuthUser>("/auth/me");
if (!user.storeId) {
return Response.json({ success: true, data: null } satisfies ApiEnvelope<StoreDetail | null>);
}
try {
const store = await backendRequest<StoreDetail>(`/stores/${user.storeId}`);
return Response.json({ success: true, data: store } satisfies ApiEnvelope<StoreDetail>);
} catch (error) {
if (error instanceof BackendError && [403, 404].includes(error.status)) {
return Response.json({ success: true, data: fallbackStore(user) } satisfies ApiEnvelope<StoreDetail | null>);
}
throw error;
}
} catch (error) {
return backendErrorResponse(error);
}
}
@@ -0,0 +1,16 @@
import { proxyBackendJson } from "@/lib/backend";
import type { TaskDetail } from "@/lib/types";
type Params = {
params: Promise<{ id: string }>;
};
export async function POST(request: Request, { params }: Params) {
const { id } = await params;
const body = await request.text();
return proxyBackendJson<TaskDetail>(`/mobile/tasks/${encodeURIComponent(id)}/comment`, {
method: "POST",
body: body || undefined
});
}
@@ -0,0 +1,13 @@
import { proxyBackendJson } from "@/lib/backend";
import type { TaskDetail } from "@/lib/types";
type Params = {
params: Promise<{ id: string }>;
};
export async function POST(_request: Request, { params }: Params) {
const { id } = await params;
return proxyBackendJson<TaskDetail>(`/mobile/tasks/${encodeURIComponent(id)}/complete`, {
method: "POST"
});
}
+11
View File
@@ -0,0 +1,11 @@
import { proxyBackendJson } from "@/lib/backend";
import type { TaskDetail } from "@/lib/types";
type Params = {
params: Promise<{ id: string }>;
};
export async function GET(_request: Request, { params }: Params) {
const { id } = await params;
return proxyBackendJson<TaskDetail>(`/mobile/tasks/${encodeURIComponent(id)}`);
}
@@ -0,0 +1,13 @@
import { proxyBackendJson } from "@/lib/backend";
import type { TaskDetail } from "@/lib/types";
type Params = {
params: Promise<{ id: string }>;
};
export async function POST(_request: Request, { params }: Params) {
const { id } = await params;
return proxyBackendJson<TaskDetail>(`/mobile/tasks/${encodeURIComponent(id)}/start`, {
method: "POST"
});
}
+6
View File
@@ -0,0 +1,6 @@
import { proxyBackendJson } from "@/lib/backend";
export async function GET(request: Request) {
const search = new URL(request.url).search;
return proxyBackendJson<unknown>(`/mobile/tasks${search}`);
}
+6
View File
@@ -0,0 +1,6 @@
import { proxyBackendJson } from "@/lib/backend";
import type { PermissionPayload } from "@/lib/types";
export async function GET() {
return proxyBackendJson<PermissionPayload>("/permissions/me");
}