編輯您的資訊
+更新用戶詳細資訊
+diff --git a/app/Http/Controllers/Admin/IndexController.php b/app/Http/Controllers/Admin/IndexController.php new file mode 100644 index 0000000..34e7f44 --- /dev/null +++ b/app/Http/Controllers/Admin/IndexController.php @@ -0,0 +1,74 @@ +password); + + // 傳送資料到前端 + $data = $user->toArray(); + + if ($isDefaultPassword) { + $data['password'] = $defaultPassword; + } else { + $data['password'] = null; + } + + return view('admin.dashboard.profile', ['data' => (Object) $data]); + } + public function profileUpdate(Request $request) + { + + $user = Auth::user(); + + $user->email = $request->email; + if ($request->password != null) { + $user->password = Hash::make($request->password); + } + $user->phone = $request->phone; + $user->save(); + + return response()->json(['status' => 'success', 'message' => '更新成功', 'data' => $user]); + + } + + public function pageProfile() + { + $user = Auth::user(); + // 從環境變數獲取預設密碼 + $defaultPassword = env('DEFAULT_PASSWORD'); + + // 判斷用戶密碼是否為預設密碼 + $isDefaultPassword = Hash::check($defaultPassword, $user->password); + + // 傳送資料到前端 + $data = $user->toArray(); + + if ($isDefaultPassword) { + $data['password'] = $defaultPassword; + } else { + $data['password'] = null; + } + return view('admin.profile.index', ['data' => (Object) $data]); + } +} diff --git a/app/Http/Controllers/Admin/LoginController.php b/app/Http/Controllers/Admin/LoginController.php deleted file mode 100644 index 754cf2f..0000000 --- a/app/Http/Controllers/Admin/LoginController.php +++ /dev/null @@ -1,11 +0,0 @@ - $data]); + } +} diff --git a/app/Http/Controllers/Admin/RegisterController.php b/app/Http/Controllers/Admin/RegisterController.php new file mode 100644 index 0000000..0e9ff47 --- /dev/null +++ b/app/Http/Controllers/Admin/RegisterController.php @@ -0,0 +1,63 @@ +validate([ + 'name' => 'required', + 'email' => 'required|email|unique:users', + 'password' => 'required|min:6', + 'phone' => 'required', + ]); + + $user = User::create([ + 'name' => $request->name, + 'email' => $request->email, + 'password' => bcrypt($request->password), + 'phone' => $request->phone, + ]); + + return view('admin.dashboard.auth-register'); + } + + public function registerCreate(Request $request) + { + $request->validate([ + 'name' => 'required', + 'email' => 'required|email|unique:users', + 'password' => 'required|min:6', + 'phone' => 'required', + ]); + + $check = User::where('email', $request->email)->first(); + + if ($check) { + return response()->json(['status' => 'error', 'message' => '此帳號已被註冊']); + } + + $user = User::create([ + 'name' => $request->name, + 'email' => $request->email, + 'password' => bcrypt($request->password), + 'phone' => $request->phone, + 'line_id' => null, + 'can_login' => false, + ]); + + return response()->json(['status' => 'success', 'message' => '註冊成功']); + } + +} diff --git a/app/Http/Controllers/Admin/SettingController.php b/app/Http/Controllers/Admin/SettingController.php new file mode 100644 index 0000000..bdcf822 --- /dev/null +++ b/app/Http/Controllers/Admin/SettingController.php @@ -0,0 +1,65 @@ +startOfMonth(); + $end = Carbon::now()->endOfMonth(); + + $result = Promocode::whereBetween('created_at', [$start, $end])->paginate(100); + + return view('admin.setting.promocode', ['data' => $result]); + } + /** + * @param Request $request ->file + * + * @return [type][string ] + */ + public function promoCodeCreate(Request $request) + { + // 驗證文件 + $request->validate([ + 'file' => 'required|mimes:xlsx,xls,csv|max:2048', + ]); + + if ($request->hasFile('file')) { + $file = $request->file('file'); + Log::info('File uploaded: ', [ + 'name' => $file->getClientOriginalName(), + 'size' => $file->getSize(), + 'mime' => $file->getMimeType(), + 'path' => $file->getRealPath(), + ]); + + // 获取整个文件的内容并打印出来 + $data = Excel::toArray([], $file); + // Log::info('Excel file content: ', $data); // 打印整个数据数组 + + // echo '
';
+ // print_r($data);
+ // exit;
+
+ }
+
+ // 讀取並導入 Excel 文件
+ try {
+ Excel::import(new PromoImport, $file);
+ return back()->with('success', '促銷代碼已成功導入!');
+ } catch (\Exception $e) {
+ return back()->with('error', '導入失敗: ' . $e->getMessage());
+ }
+ }
+
+}
diff --git a/app/Http/Controllers/EmailController.php b/app/Http/Controllers/EmailController.php
new file mode 100644
index 0000000..2145e9b
--- /dev/null
+++ b/app/Http/Controllers/EmailController.php
@@ -0,0 +1,263 @@
+all());
+
+ // 獲取當前登入的會員(若存在)
+ $auth = Auth::guard('member')->user();
+
+ // 驗證請求中是否包含 token
+ $validatedData = $request->validate([
+ 'token' => 'required|string',
+ ]);
+
+ // 查詢對應的驗證記錄
+ $check = EmailVerifications::where('token', $validatedData['token'])->first();
+
+ if (!$check) {
+ Log::warning('Invalid token provided for email verification:', ['token' => $validatedData['token']]);
+ return response()->json(['status' => 'error', 'msg' => '無效的驗證連結或連結已過期'], 400);
+ }
+
+ Log::info(message: 'Email verification record found:', context: $check->toArray());
+
+ // 查詢對應的會員
+ $member = Member::where('email', $check->email)->orderBy('created_at', 'asc')->first();
+
+
+
+
+ // 若當前登入用戶存在 line_id,則使用當前用戶更新
+ if ($auth && isset($auth->line_id)) {
+ $line_id = $auth->line_id;
+ } else {
+ $line_id = $member->line_id;
+ }
+
+ if ($auth && isset($auth->avatar)) {
+ $avatar = $auth->avatar;
+ } else {
+ $avatar = $member->avatar;
+ }
+
+
+ // 更新會員的 Email 與驗證時間
+
+ Log::info('Member email verification updated successfully:', $member->toArray());
+
+ // 如果當前登入用戶與驗證的會員不同,登出當前用戶並重新登入
+ if ($auth && $auth->id != $member->id) {
+ // 在登出之前執行需要刪除或處理的操作
+ $needdeletaccount = Auth::guard('member')->user();
+
+ // 確保在登出前刪除帳號資料或執行其他操作
+ if ($needdeletaccount) {
+ $needdeletaccount->delete(); // 這會刪除登入用戶的資料
+ $member->email_verified_at = now();
+ $member->line_id = $line_id;
+ $member->avatar = $avatar;
+ Log::info('Deleted account after logout:', ['user_id' => $needdeletaccount->id]);
+ }
+
+ $member->save();
+
+ // 登出並重新登入
+ Auth::logout();
+ Auth::guard('member')->loginUsingId($member->id);
+ Log::info('Logged out previous user and logged in verified user:', ['user_id' => $member->id]);
+ }
+
+
+ // 刪除驗證記錄以防重複使用
+ $check->delete();
+ Log::info('Verification token record deleted successfully:', ['token' => $validatedData['token']]);
+
+ // return response()->json(['status' => 'success', 'msg' => '電子郵件驗證成功']);
+
+ return redirect()->route('member.index');
+
+
+
+ }
+ public function sendemail(Request $request)
+ {
+ \Log::info('got send mail', ['function' => 'sendemail']);
+
+ // 驗證請求數據
+ $validatedData = $request->validate([
+ 'email' => 'required|email',
+ ]);
+ //判斷是否更新token
+
+ $check = EmailVerifications::where('email', $request->email)->first();
+
+ // 生成隨機 token
+ $token = Str::random(32);
+
+ if (!$check) {
+ $check = new EmailVerifications;
+ }
+
+ $check->email = $request->email;
+ $check->token = $token;
+ $check->save();
+
+ \Log::info('Generated token', ['token' => $token]);
+
+ $subject = "卡菲姬系統-驗證email";
+
+ // 使用 route 生成驗證鏈接
+ $verificationLink = route('email.verify', ['token' => $token]);
+ \Log::info('Generated verification link', ['link' => $verificationLink]);
+
+ try {
+ // 郵件內容
+ $message = "您好,\n\n請點擊以下鏈接以驗證您的電子郵件地址:\n\n" . $verificationLink . "\n\n如果您未請求此操作,請忽略此郵件。\n\n感謝您!";
+
+ \Log::info('Preparing to send mail', ['email' => $validatedData['email'], 'subject' => $subject, 'message' => $message]);
+
+ // 發送電子郵件
+ Mail::to($validatedData['email'])->send(new \App\Mail\CustomMail($subject, $message));
+
+ \Log::info('Mail sent successfully');
+
+ return response()->json(['status' => 'success', 'msg' => '郵件發送成功']);
+ } catch (\Exception $e) {
+ \Log::error('Failed to send mail', ['error' => $e->getMessage()]);
+
+ return response()->json(['status' => 'error', 'msg' => '郵件發送失敗,請稍後再試!', 'error' => $e->getMessage()], 500);
+ }
+ }
+
+ /**
+ * Summary of validemail ajax 驗證email 是否註冊過
+ * @param \Illuminate\Http\Request $request
+ * @return mixed|\Illuminate\Http\JsonResponse
+ */
+ public function validemail(Request $request)
+ {
+ // 構建郵件內容
+
+ // 驗證輸入的數據
+ $validatedData = $request->validate([
+ 'email' => 'required|email',
+ ]);
+
+ // 檢查是否已有其他會員使用相同的 email
+ $user = Member::where('email', $validatedData['email'])->first();
+
+ if ($user) {
+ // 查找是否已有驗證記錄
+ $vaild = EmailVerifications::where('email', $validatedData['email'])->first();
+
+ return response()->json([
+ 'status' => 'error',
+ 'msg' => 'email 以使用 ,是否逕行合併,如果是 請先驗證email',
+ ]);
+ }
+ return response()->json([
+ 'status' => 'success',
+
+ ]);
+
+ }
+ /**
+ * Summary of checkEmail email 寄送 token 點擊後 驗證
+ * @param \Illuminate\Http\Request $request
+ * @return mixed|\Illuminate\Http\JsonResponse|\Illuminate\Http\RedirectResponse
+ */
+ public function checkEmail(Request $request)
+ {
+ Log::info('Email verification request received:', $request->all());
+
+ // 獲取當前登入的會員(若存在)
+ $auth = Auth::guard('member')->user();
+
+ // 驗證請求中是否包含 token
+ $validatedData = $request->validate([
+ 'token' => 'required|string',
+ ]);
+
+ // 查詢對應的驗證記錄
+ $check = EmailVerifications::where('token', $validatedData['token'])->first();
+
+ if (!$check) {
+ Log::warning('Invalid token provided for email verification:', ['token' => $validatedData['token']]);
+ return response()->json(['status' => 'error', 'msg' => '無效的驗證連結或連結已過期'], 400);
+ }
+
+ Log::info(message: 'Email verification record found:', context: $check->toArray());
+
+ // 查詢對應的會員
+ $member = Member::where('email', $check->email)->orderBy('created_at', 'asc')->first();
+
+
+
+
+ // 若當前登入用戶存在 line_id,則使用當前用戶更新
+ if ($auth && isset($auth->line_id)) {
+ $line_id = $auth->line_id;
+ } else {
+ $line_id = $member->line_id;
+ }
+
+ // 更新會員的 Email 與驗證時間
+
+ Log::info('Member email verification updated successfully:', $member->toArray());
+
+ // 如果當前登入用戶與驗證的會員不同,登出當前用戶並重新登入
+ if ($auth && $auth->id != $member->id) {
+ // 在登出之前執行需要刪除或處理的操作
+ $needdeletaccount = Auth::guard('member')->user();
+
+ // 確保在登出前刪除帳號資料或執行其他操作
+ if ($needdeletaccount) {
+ $needdeletaccount->delete(); // 這會刪除登入用戶的資料
+ $member->email_verified_at = now();
+ $member->line_id = $line_id;
+ Log::info('Deleted account after logout:', ['user_id' => $needdeletaccount->id]);
+ }
+
+ $member->save();
+
+ // 登出並重新登入
+ Auth::logout();
+ Auth::guard('member')->loginUsingId($member->id);
+ Log::info('Logged out previous user and logged in verified user:', ['user_id' => $member->id]);
+ }
+
+
+ // 刪除驗證記錄以防重複使用
+ $check->delete();
+ Log::info('Verification token record deleted successfully:', ['token' => $validatedData['token']]);
+
+ // return response()->json(['status' => 'success', 'msg' => '電子郵件驗證成功']);
+
+ return redirect()->route('member.index');
+
+ }
+}
diff --git a/app/Http/Controllers/LoginController.php b/app/Http/Controllers/LoginController.php
new file mode 100644
index 0000000..5cc65fb
--- /dev/null
+++ b/app/Http/Controllers/LoginController.php
@@ -0,0 +1,141 @@
+is('admin/*') ? 'admin' : 'member';
+ session(['redirect_to' => $redirectTo]); // 将值存入 Session
+ return Socialite::driver('line')->redirect();
+ }
+
+ /**
+ * Summary of handleProviderCallback
+ * line 登入後查詢
+ * @return void
+ */
+ public function handleProviderCallback(Request $request)
+ {
+ // 从 Session 获取 $redirectTo
+ $redirectTo = session('redirect_to', 'member');
+
+ $user = Socialite::driver('line')->user();
+ Log::info('line', ['user' => $user]);
+ $lineId = $user->getId();
+ $name = $user->getName();
+ $avatar = $user->getAvatar() ?? '';
+ $email = $user->getEmail() ?? '';
+
+ Log::info('email', [$email]);
+
+ if ($redirectTo == 'admin') {
+ // Admin 登录逻辑
+ $existingUser = $user = User::where('line_id', $lineId)
+ ->orWhere('email', $email)
+ ->first();
+
+ if ($existingUser) {
+ Auth::guard('web')->login($existingUser);
+ } else {
+ $newUser = User::create([
+ 'name' => $name,
+ 'line_id' => $lineId,
+ 'password' => bcrypt(env('DEFAULT_PASSWORD')),
+ 'avatar' => $avatar,
+ 'source' => 'cafeg',
+ 'email' => $email,
+ ]);
+ Auth::guard('web')->login($newUser);
+ }
+
+ $user = Auth::guard('web')->user();
+ return $user->email
+ ? redirect()->route('admin.index')
+ : redirect()->route('admin.profile');
+ } else {
+ // Member 登录逻辑
+ $existingUser = Member::where('line_id', $lineId)
+ ->orWhere('email', $email)
+ ->first();
+ if ($existingUser) {
+ Auth::guard('member')->login($existingUser);
+ } else {
+ $newUser = Member::create([
+ 'name' => $name,
+ 'line_id' => $lineId,
+ 'password' => bcrypt(env('DEFAULT_PASSWORD')),
+ 'avatar' => $avatar,
+ 'source' => 'cafeg',
+ 'email' => $email,
+ ]);
+ Auth::guard('member')->login($newUser);
+ }
+
+ $user = Auth::guard('member')->user();
+ return $user->email
+ ? redirect()->route('member.index')
+ : redirect()->route('member.profile');
+ }
+ }
+
+ public function adminLogout()
+ {
+ Auth::guard('web')->logout();
+ return redirect()->route('admin.login');
+ }
+
+ public function memberLogout()
+ {
+ Auth::guard('member')->logout();
+ return redirect()->route('front.login.view');
+ }
+
+ public function adminNormalLogin(Request $request)
+ {
+
+ $credentials = $request->only('email', 'password');
+
+ if (Auth::guard('web')->attempt($credentials)) {
+ return redirect()->route('admin.index');
+ }
+ return redirect()->route('admin.login');
+ }
+
+ public function memberNormalLogin(Request $request)
+ {
+ $credentials = $request->only('email', 'password');
+
+ if (Auth::guard('member')->attempt($credentials)) {
+ return redirect()->route('member.index');
+ } else {
+
+ return redirect()->route('front.login.view')->with('error', '帳號密碼錯誤');
+ }
+ }
+}
diff --git a/app/Http/Controllers/front/LoginController.php b/app/Http/Controllers/front/LoginController.php
deleted file mode 100644
index 0989c51..0000000
--- a/app/Http/Controllers/front/LoginController.php
+++ /dev/null
@@ -1,77 +0,0 @@
-redirect();
-
- }
-
- /**
- * Summary of handleProviderCallback
- * line 登入後查詢
- * @return void
- */
- public function handleProviderCallback()
- {
- // 获取 LINE 用户信息
- $user = Socialite::driver('line')->user();
-
- // 从返回的信息中获取数据
- $lineId = $user->getId(); // LINE ID
- $name = $user->getName(); // 用户名
- $avatar = $user->getAvatar(); // 用户头像
-
- // 查询数据库中是否已有此用户
- $existingUser = Member::where('line_id', $lineId)->first();
-
- if ($existingUser) {
- // 如果用户存在,使用 guard 'member' 登录
- Auth::guard('member')->login($existingUser);
- } else {
-
- $user = [
- 'name' => $name,
- 'line_id' => $lineId,
- 'password' => bcrypt(env('DEFAULT_PASSWORD')),
- 'avatar' => $avatar,
- 'phone' => '',
- 'source' => 'cafeg',
- ];
-
- // 如果用户不存在,创建新用户并登录
- $newUser = Member::create($user);
-
- Auth::guard('member')->login($newUser);
- }
-
- $user = Auth::guard('member')->user();
-
- if (!$user->email) {
- return redirect()->route('member.profile');
- } else {
-
-// 登录成功后重定向到特定页面
- return redirect()->route('member.index');
- }
- }
-}
diff --git a/app/Http/Controllers/front/MemberController.php b/app/Http/Controllers/front/MemberController.php
index 2f6ef3f..57b397c 100644
--- a/app/Http/Controllers/front/MemberController.php
+++ b/app/Http/Controllers/front/MemberController.php
@@ -1,19 +1,94 @@
user()->id)) {
+ $user_id = Auth::guard('member')->user()->id;
+ $code = Promocode::where('used_count', $user_id)->first();
+
+ return view('front.member.index', ['code' => $code]);
+ } else {
+ Auth::guard('member')->logout();
+ return redirect()->route('front.login.view');
+ }
}
public function profile()
{
return view('front.member.profile');
}
+ /**
+ * Summary of profileUpdate
+ * @param \Illuminate\Http\Request $request
+ * @return \Illuminate\Http\RedirectResponse
+ * @todo 目前沒有錢包與購買方案與report 以後要 一起下壓
+ * @method put
+ */
+ public function profileUpdate(Request $request)
+ {
+ // 驗證輸入的數據
+ $validatedData = $request->validate([
+ 'email' => 'required|email',
+ 'password' => 'nullable|min:6', // password 與 password_confirmation 必須匹配
+ 'phone' => 'nullable|string|max:15',
+ ]);
+
+ $auth = Member::find(Auth::guard('member')->id());
+
+ // 檢查是否已有其他會員使用相同的 email
+ $user = Member::where('email', $validatedData['email'])->first();
+
+ if ($user && $user->id != $auth->id) {
+ // 如果該 Email 已被其他用戶使用,返回錯誤信息
+ return response()->json(['status' => 'error', 'msg' => '該 Email 已被其他帳戶使用'], 422);
+ }
+
+ // 更新當前用戶的資料
+ $auth->email = $validatedData['email'];
+ if ($request->has('password')) {
+ $auth->password = Hash::make($validatedData['password']);
+ }
+ $auth->phone = $validatedData['phone'] ?? $auth->phone;
+
+ // 保存更改
+ $auth->save();
+
+ return response()->json(['status' => 'success', 'msg' => '更新成功']);
+ }
+
+ public function pageProfile(Request $request)
+ {
+
+ return view('front.member.page-profile');
+ }
+
+ public function checkPhone(Request $request)
+ {
+ $validatedData = $request->validate([
+ 'phone' => 'required|string|max:15',
+ ]);
+ \Log::info('checkPhone', []);
+ $user = Member::where('phone', $validatedData['phone'])->first();
+
+ if ($user) {
+ return response()->json(['status' => 'error', 'msg' => '該電話號碼已被其他帳戶使用']);
+ }
+
+ return response()->json(['status' => 'success', 'msg' => '該電話號碼可用']);
+ }
+
}
diff --git a/app/Http/Controllers/front/PromoCodeController.php b/app/Http/Controllers/front/PromoCodeController.php
new file mode 100644
index 0000000..28f6cb7
--- /dev/null
+++ b/app/Http/Controllers/front/PromoCodeController.php
@@ -0,0 +1,81 @@
+user()->id;
+ $count = Promocode::where('used_count', $user_id)->count();
+
+ if (! $count) {
+
+ $row = Promocode::where('used_count', 0)->first();
+ $row->used_count = $user_id;
+ $row->save();
+ return response()->json(['status' => 'success', 'msg' => '已成功取得', 'promocode' => $row->code]);
+ } else {
+ $code = Promocode::where('used_count', $user_id)->first();
+ return response()->json(['status' => 'success', 'msg' => '你已取得過優惠碼', 'promocode' => $code->code]);
+
+ }
+
+ }
+
+ /**
+ * Store a newly created resource in storage.
+ */
+ public function store(Request $request)
+ {
+
+ //
+ }
+
+ /**
+ * Display the specified resource.
+ */
+ public function show(Promocode $promocode)
+ {
+ //
+ }
+
+ /**
+ * Show the form for editing the specified resource.
+ */
+ public function edit(Promocode $promocode)
+ {
+ //
+ }
+
+ /**
+ * Update the specified resource in storage.
+ */
+ public function update(Request $request, Promocode $promocode)
+ {
+ //
+ }
+
+ /**
+ * Remove the specified resource from storage.
+ */
+ public function destroy(Promocode $promocode)
+ {
+ //
+ }
+}
diff --git a/app/Http/Controllers/front/RegisterController.php b/app/Http/Controllers/front/RegisterController.php
new file mode 100644
index 0000000..0d1aca9
--- /dev/null
+++ b/app/Http/Controllers/front/RegisterController.php
@@ -0,0 +1,83 @@
+ $request->name,
+ 'password' => bcrypt($request->password),
+ 'avatar' => $request->avatar ?? '',
+ 'email' => $request->email ?? '',
+ 'source' => 'cafeg',
+ 'phone' => $request->phone ?? '',
+ ]);
+
+ if (isset($newUser->email)) {
+
+ return redirect()->route('member.index')->with('sucess', '完成註冊');
+
+ } else {
+
+ return redirect()->route('member.profile')->with('sucess', '完成註冊,請完善你得資料');
+ }
+
+ }
+
+ /**
+ * Store a newly created resource in storage.
+ */
+ public function store(Request $request)
+ {
+ //
+ }
+
+ /**
+ * Display the specified resource.
+ */
+ public function show(Member $member)
+ {
+ //
+ }
+
+ /**
+ * Show the form for editing the specified resource.
+ */
+ public function edit(Member $member)
+ {
+ //
+ }
+
+ /**
+ * Update the specified resource in storage.
+ */
+ public function update(Request $request, Member $member)
+ {
+ //
+ }
+
+ /**
+ * Remove the specified resource from storage.
+ */
+ public function destroy(Member $member)
+ {
+ //
+ }
+}
diff --git a/app/Http/Middleware/AdminRedirect.php b/app/Http/Middleware/AdminRedirect.php
new file mode 100644
index 0000000..ee3d596
--- /dev/null
+++ b/app/Http/Middleware/AdminRedirect.php
@@ -0,0 +1,34 @@
+path() != 'admin/register') {
+ return redirect()->route('admin.login');
+ }
+ if (Auth::check() && $request->path() == 'admin/login') {
+ return redirect()->route('admin.index');
+ }
+
+ // $user = Auth::user();
+ // if ($user->email == null) {
+ // return redirect()->route('admin.profile');
+ // }
+
+ return $next($request);
+ }
+}
diff --git a/app/Http/Middleware/GuestRedirect.php b/app/Http/Middleware/GuestRedirect.php
new file mode 100644
index 0000000..060e62f
--- /dev/null
+++ b/app/Http/Middleware/GuestRedirect.php
@@ -0,0 +1,29 @@
+check() && $request->path() == '/') {
+
+ return redirect()->route('front.login.view');
+
+ } else if ($request->path() == '/' && Auth::guard('member')->check()) {
+ return redirect()->route('member.index');
+
+ }
+
+ return $next($request);
+ }
+}
diff --git a/app/Http/Middleware/MemberRedirect.php b/app/Http/Middleware/MemberRedirect.php
new file mode 100644
index 0000000..5ef5045
--- /dev/null
+++ b/app/Http/Middleware/MemberRedirect.php
@@ -0,0 +1,31 @@
+check()) {
+
+ $loginUrlPath = parse_url(route('front.login.view'), PHP_URL_PATH);
+ if ($request->is('login')) {
+ return redirect()->route('member.index');
+ }
+
+ }
+
+ return $next($request);
+ }
+}
diff --git a/app/Http/Middleware/memberAuth.php b/app/Http/Middleware/memberAuth.php
index 8135e75..49ea1d0 100644
--- a/app/Http/Middleware/memberAuth.php
+++ b/app/Http/Middleware/memberAuth.php
@@ -1,5 +1,4 @@
check()) {
-
- $loginUrlPath = parse_url(route('front.login.view'), PHP_URL_PATH);
- // if ($request->path() === ltrim($loginUrlPath, '/')) {
- // return redirect()->route('member.index');
-
- // }
+ // 使用 'member' 守衛進行身份驗證
+ if (!Auth::guard('member')->check()) {
+ // 未登入,記錄日誌並重導向
+ \Log::warning('Unauthorized access attempt.', ['url' => $request->url()]);
+ return redirect()->route('front.login.view');
}
+ // 驗證成功,繼續處理請求
return $next($request);
}
}
diff --git a/app/Imports/PromoImport.php b/app/Imports/PromoImport.php
new file mode 100644
index 0000000..38e3230
--- /dev/null
+++ b/app/Imports/PromoImport.php
@@ -0,0 +1,36 @@
+ $row->toArray()[3]]);
+
+ if ($row->toArray()[3] != '提货码') // 跳過第一行
+ {
+ Promocode::create([
+ 'code' => $row->toArray()[3], // 使用 "提货码" 列
+ 'discount' => 100, // 假設折扣為固定值 100
+ 'type' => 'percent', // 默認為百分比
+ 'usage_limit' => 1, // 默認每個代碼只能使用一次
+ 'valid_from' => date('Y-m-d'), // 當前日期
+ 'valid_to' => date('Y-m-d', strtotime('1 day')), // 默認有效期至第二天
+ 'is_active' => 1, // 默認啟用
+ ]);
+ }
+
+ }
+
+ }
+}
diff --git a/app/Mail/CustomMail.php b/app/Mail/CustomMail.php
new file mode 100644
index 0000000..d07980b
--- /dev/null
+++ b/app/Mail/CustomMail.php
@@ -0,0 +1,36 @@
+subject = $subject;
+ $this->emailMessage = $emailMessage;
+ }
+
+ public function build()
+ {
+ Log::info('mail send log test:', [
+ 'subject' => $this->subject,
+ 'emailMessage' => $this->emailMessage,
+ ]);
+
+ return $this->subject($this->subject)
+ ->view('emails.custom')
+ ->with([
+ 'subject' => $this->subject,
+ 'emailMessage' => $this->emailMessage,
+ ]);
+ }
+}
diff --git a/app/Models/EmailVerifications.php b/app/Models/EmailVerifications.php
new file mode 100644
index 0000000..03f93c6
--- /dev/null
+++ b/app/Models/EmailVerifications.php
@@ -0,0 +1,12 @@
+ '一般會員',
+ 1 => '白銀會員',
+ 2 => '黃金會員',
+ 9 => '管理員',
+ ];
+
+ // 訪問器:自動轉換 Level
+ public function getLevelNameAttribute()
+ {
+ return self::$levelName[$this->level] ?? '未知會員';
+ }
+
/**
* 隱藏的屬性。
*
diff --git a/app/Models/Promocode.php b/app/Models/Promocode.php
new file mode 100644
index 0000000..35ec6b0
--- /dev/null
+++ b/app/Models/Promocode.php
@@ -0,0 +1,21 @@
+
*/
protected $hidden = [
- 'password',
'remember_token',
];
diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php
index 02a4756..a9468da 100644
--- a/app/Providers/AppServiceProvider.php
+++ b/app/Providers/AppServiceProvider.php
@@ -2,6 +2,7 @@
namespace App\Providers;
+use Illuminate\Pagination\Paginator;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\ServiceProvider;
@@ -31,5 +32,11 @@ public function boot(): void
$app['request'], $config['client_id'], $config['client_secret'], $config['redirect']
);
});
+
+ // 设置默认分页视图为 Materialize 样式
+ Paginator::defaultView('vendor.pagination.materialize');
+
+ // 可选:设置简单分页的默认视图
+ Paginator::defaultSimpleView('vendor.pagination.materialize');
}
}
diff --git a/app/Providers/MenuProvider.php b/app/Providers/MenuProvider.php
index 694a96e..2d60819 100644
--- a/app/Providers/MenuProvider.php
+++ b/app/Providers/MenuProvider.php
@@ -1,5 +1,4 @@
share('menuData', [
$verticalMenuData,
- $horizontalMenuData,
+ $memberMenuData,
]);
}
}
diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php
deleted file mode 100644
index e1b8c94..0000000
--- a/app/Providers/RouteServiceProvider.php
+++ /dev/null
@@ -1,41 +0,0 @@
-by($request->user()?->id ?: $request->ip());
- });
-
- $this->routes(function () {
- Route::middleware('api')
- ->prefix('api')
- ->group(base_path('routes/api.php'));
-
- Route::middleware('web')
- ->namespace('App\Http\Controllers')
- ->group(base_path('routes/web.php'));
- });
- }
-}
diff --git a/bootstrap/app.php b/bootstrap/app.php
index 9266892..93fd463 100644
--- a/bootstrap/app.php
+++ b/bootstrap/app.php
@@ -23,6 +23,7 @@
]);
})
+
->withExceptions(function (Exceptions $exceptions) {
//
})->create();
diff --git a/bootstrap/providers.php b/bootstrap/providers.php
index ed31fb3..d5be48c 100644
--- a/bootstrap/providers.php
+++ b/bootstrap/providers.php
@@ -3,4 +3,5 @@
return [
App\Providers\AppServiceProvider::class,
App\Providers\MenuProvider::class,
+
];
diff --git a/composer.json b/composer.json
index 86a4de1..177e2b2 100644
--- a/composer.json
+++ b/composer.json
@@ -11,6 +11,7 @@
"laravel/sanctum": "^4.0",
"laravel/socialite": "^5.16",
"laravel/tinker": "^2.9",
+ "maatwebsite/excel": "^3.1",
"socialiteproviders/line": "^4.1"
},
"require-dev": {
diff --git a/composer.lock b/composer.lock
index c51f29a..638b92b 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "6124ac50e296caf206e7d2ec2e56ae8e",
+ "content-hash": "a479f93c0f786bef7c2eb2887cbe259b",
"packages": [
{
"name": "brick/math",
@@ -135,6 +135,87 @@
],
"time": "2024-02-09T16:56:22+00:00"
},
+ {
+ "name": "composer/semver",
+ "version": "3.4.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/composer/semver.git",
+ "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/composer/semver/zipball/4313d26ada5e0c4edfbd1dc481a92ff7bff91f12",
+ "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.3.2 || ^7.0 || ^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^1.11",
+ "symfony/phpunit-bridge": "^3 || ^7"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Composer\\Semver\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nils Adermann",
+ "email": "naderman@naderman.de",
+ "homepage": "http://www.naderman.de"
+ },
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "http://seld.be"
+ },
+ {
+ "name": "Rob Bast",
+ "email": "rob.bast@gmail.com",
+ "homepage": "http://robbast.nl"
+ }
+ ],
+ "description": "Semver library that offers utilities, version constraint parsing and validation.",
+ "keywords": [
+ "semantic",
+ "semver",
+ "validation",
+ "versioning"
+ ],
+ "support": {
+ "irc": "ircs://irc.libera.chat:6697/composer",
+ "issues": "https://github.com/composer/semver/issues",
+ "source": "https://github.com/composer/semver/tree/3.4.3"
+ },
+ "funding": [
+ {
+ "url": "https://packagist.com",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/composer",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/composer/composer",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-09-19T14:15:21+00:00"
+ },
{
"name": "dflydev/dot-access-data",
"version": "v3.0.3",
@@ -510,6 +591,67 @@
],
"time": "2024-12-27T00:36:43+00:00"
},
+ {
+ "name": "ezyang/htmlpurifier",
+ "version": "v4.18.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/ezyang/htmlpurifier.git",
+ "reference": "cb56001e54359df7ae76dc522d08845dc741621b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/cb56001e54359df7ae76dc522d08845dc741621b",
+ "reference": "cb56001e54359df7ae76dc522d08845dc741621b",
+ "shasum": ""
+ },
+ "require": {
+ "php": "~5.6.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0"
+ },
+ "require-dev": {
+ "cerdic/css-tidy": "^1.7 || ^2.0",
+ "simpletest/simpletest": "dev-master"
+ },
+ "suggest": {
+ "cerdic/css-tidy": "If you want to use the filter 'Filter.ExtractStyleBlocks'.",
+ "ext-bcmath": "Used for unit conversion and imagecrash protection",
+ "ext-iconv": "Converts text to and from non-UTF-8 encodings",
+ "ext-tidy": "Used for pretty-printing HTML"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "library/HTMLPurifier.composer.php"
+ ],
+ "psr-0": {
+ "HTMLPurifier": "library/"
+ },
+ "exclude-from-classmap": [
+ "/library/HTMLPurifier/Language/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "LGPL-2.1-or-later"
+ ],
+ "authors": [
+ {
+ "name": "Edward Z. Yang",
+ "email": "admin@htmlpurifier.org",
+ "homepage": "http://ezyang.com"
+ }
+ ],
+ "description": "Standards compliant HTML filter written in PHP",
+ "homepage": "http://htmlpurifier.org/",
+ "keywords": [
+ "html"
+ ],
+ "support": {
+ "issues": "https://github.com/ezyang/htmlpurifier/issues",
+ "source": "https://github.com/ezyang/htmlpurifier/tree/v4.18.0"
+ },
+ "time": "2024-11-01T03:51:45+00:00"
+ },
{
"name": "fahlisaputra/laravel-minify",
"version": "v1.1.5",
@@ -2346,6 +2488,271 @@
],
"time": "2024-12-08T08:18:47+00:00"
},
+ {
+ "name": "maatwebsite/excel",
+ "version": "3.1.62",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/SpartnerNL/Laravel-Excel.git",
+ "reference": "decfb9140161fcc117571e47e35ddf27983189ce"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/SpartnerNL/Laravel-Excel/zipball/decfb9140161fcc117571e47e35ddf27983189ce",
+ "reference": "decfb9140161fcc117571e47e35ddf27983189ce",
+ "shasum": ""
+ },
+ "require": {
+ "composer/semver": "^3.3",
+ "ext-json": "*",
+ "illuminate/support": "5.8.*||^6.0||^7.0||^8.0||^9.0||^10.0||^11.0",
+ "php": "^7.0||^8.0",
+ "phpoffice/phpspreadsheet": "^1.29.7",
+ "psr/simple-cache": "^1.0||^2.0||^3.0"
+ },
+ "require-dev": {
+ "laravel/scout": "^7.0||^8.0||^9.0||^10.0",
+ "orchestra/testbench": "^6.0||^7.0||^8.0||^9.0",
+ "predis/predis": "^1.1"
+ },
+ "type": "library",
+ "extra": {
+ "laravel": {
+ "aliases": {
+ "Excel": "Maatwebsite\\Excel\\Facades\\Excel"
+ },
+ "providers": [
+ "Maatwebsite\\Excel\\ExcelServiceProvider"
+ ]
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Maatwebsite\\Excel\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Patrick Brouwers",
+ "email": "patrick@spartner.nl"
+ }
+ ],
+ "description": "Supercharged Excel exports and imports in Laravel",
+ "keywords": [
+ "PHPExcel",
+ "batch",
+ "csv",
+ "excel",
+ "export",
+ "import",
+ "laravel",
+ "php",
+ "phpspreadsheet"
+ ],
+ "support": {
+ "issues": "https://github.com/SpartnerNL/Laravel-Excel/issues",
+ "source": "https://github.com/SpartnerNL/Laravel-Excel/tree/3.1.62"
+ },
+ "funding": [
+ {
+ "url": "https://laravel-excel.com/commercial-support",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/patrickbrouwers",
+ "type": "github"
+ }
+ ],
+ "time": "2025-01-04T12:14:36+00:00"
+ },
+ {
+ "name": "maennchen/zipstream-php",
+ "version": "3.1.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/maennchen/ZipStream-PHP.git",
+ "reference": "6187e9cc4493da94b9b63eb2315821552015fca9"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/6187e9cc4493da94b9b63eb2315821552015fca9",
+ "reference": "6187e9cc4493da94b9b63eb2315821552015fca9",
+ "shasum": ""
+ },
+ "require": {
+ "ext-mbstring": "*",
+ "ext-zlib": "*",
+ "php-64bit": "^8.1"
+ },
+ "require-dev": {
+ "ext-zip": "*",
+ "friendsofphp/php-cs-fixer": "^3.16",
+ "guzzlehttp/guzzle": "^7.5",
+ "mikey179/vfsstream": "^1.6",
+ "php-coveralls/php-coveralls": "^2.5",
+ "phpunit/phpunit": "^10.0",
+ "vimeo/psalm": "^5.0"
+ },
+ "suggest": {
+ "guzzlehttp/psr7": "^2.4",
+ "psr/http-message": "^2.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "ZipStream\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Paul Duncan",
+ "email": "pabs@pablotron.org"
+ },
+ {
+ "name": "Jonatan Männchen",
+ "email": "jonatan@maennchen.ch"
+ },
+ {
+ "name": "Jesse Donat",
+ "email": "donatj@gmail.com"
+ },
+ {
+ "name": "András Kolesár",
+ "email": "kolesar@kolesar.hu"
+ }
+ ],
+ "description": "ZipStream is a library for dynamically streaming dynamic zip files from PHP without writing to the disk at all on the server.",
+ "keywords": [
+ "stream",
+ "zip"
+ ],
+ "support": {
+ "issues": "https://github.com/maennchen/ZipStream-PHP/issues",
+ "source": "https://github.com/maennchen/ZipStream-PHP/tree/3.1.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/maennchen",
+ "type": "github"
+ }
+ ],
+ "time": "2024-10-10T12:33:01+00:00"
+ },
+ {
+ "name": "markbaker/complex",
+ "version": "3.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/MarkBaker/PHPComplex.git",
+ "reference": "95c56caa1cf5c766ad6d65b6344b807c1e8405b9"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/MarkBaker/PHPComplex/zipball/95c56caa1cf5c766ad6d65b6344b807c1e8405b9",
+ "reference": "95c56caa1cf5c766ad6d65b6344b807c1e8405b9",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2 || ^8.0"
+ },
+ "require-dev": {
+ "dealerdirect/phpcodesniffer-composer-installer": "dev-master",
+ "phpcompatibility/php-compatibility": "^9.3",
+ "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0",
+ "squizlabs/php_codesniffer": "^3.7"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Complex\\": "classes/src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Mark Baker",
+ "email": "mark@lange.demon.co.uk"
+ }
+ ],
+ "description": "PHP Class for working with complex numbers",
+ "homepage": "https://github.com/MarkBaker/PHPComplex",
+ "keywords": [
+ "complex",
+ "mathematics"
+ ],
+ "support": {
+ "issues": "https://github.com/MarkBaker/PHPComplex/issues",
+ "source": "https://github.com/MarkBaker/PHPComplex/tree/3.0.2"
+ },
+ "time": "2022-12-06T16:21:08+00:00"
+ },
+ {
+ "name": "markbaker/matrix",
+ "version": "3.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/MarkBaker/PHPMatrix.git",
+ "reference": "728434227fe21be27ff6d86621a1b13107a2562c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/MarkBaker/PHPMatrix/zipball/728434227fe21be27ff6d86621a1b13107a2562c",
+ "reference": "728434227fe21be27ff6d86621a1b13107a2562c",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1 || ^8.0"
+ },
+ "require-dev": {
+ "dealerdirect/phpcodesniffer-composer-installer": "dev-master",
+ "phpcompatibility/php-compatibility": "^9.3",
+ "phpdocumentor/phpdocumentor": "2.*",
+ "phploc/phploc": "^4.0",
+ "phpmd/phpmd": "2.*",
+ "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0",
+ "sebastian/phpcpd": "^4.0",
+ "squizlabs/php_codesniffer": "^3.7"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Matrix\\": "classes/src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Mark Baker",
+ "email": "mark@demon-angel.eu"
+ }
+ ],
+ "description": "PHP Class for working with matrices",
+ "homepage": "https://github.com/MarkBaker/PHPMatrix",
+ "keywords": [
+ "mathematics",
+ "matrix",
+ "vector"
+ ],
+ "support": {
+ "issues": "https://github.com/MarkBaker/PHPMatrix/issues",
+ "source": "https://github.com/MarkBaker/PHPMatrix/tree/3.0.1"
+ },
+ "time": "2022-12-02T22:17:43+00:00"
+ },
{
"name": "monolog/monolog",
"version": "3.8.1",
@@ -2965,6 +3372,111 @@
},
"time": "2020-10-15T08:29:30+00:00"
},
+ {
+ "name": "phpoffice/phpspreadsheet",
+ "version": "1.29.7",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/PHPOffice/PhpSpreadsheet.git",
+ "reference": "02c8625411dcb96e1f63d58c47460284e15b2e80"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/02c8625411dcb96e1f63d58c47460284e15b2e80",
+ "reference": "02c8625411dcb96e1f63d58c47460284e15b2e80",
+ "shasum": ""
+ },
+ "require": {
+ "ext-ctype": "*",
+ "ext-dom": "*",
+ "ext-fileinfo": "*",
+ "ext-gd": "*",
+ "ext-iconv": "*",
+ "ext-libxml": "*",
+ "ext-mbstring": "*",
+ "ext-simplexml": "*",
+ "ext-xml": "*",
+ "ext-xmlreader": "*",
+ "ext-xmlwriter": "*",
+ "ext-zip": "*",
+ "ext-zlib": "*",
+ "ezyang/htmlpurifier": "^4.15",
+ "maennchen/zipstream-php": "^2.1 || ^3.0",
+ "markbaker/complex": "^3.0",
+ "markbaker/matrix": "^3.0",
+ "php": "^7.4 || ^8.0",
+ "psr/http-client": "^1.0",
+ "psr/http-factory": "^1.0",
+ "psr/simple-cache": "^1.0 || ^2.0 || ^3.0"
+ },
+ "require-dev": {
+ "dealerdirect/phpcodesniffer-composer-installer": "dev-main",
+ "dompdf/dompdf": "^1.0 || ^2.0 || ^3.0",
+ "friendsofphp/php-cs-fixer": "^3.2",
+ "mitoteam/jpgraph": "^10.3",
+ "mpdf/mpdf": "^8.1.1",
+ "phpcompatibility/php-compatibility": "^9.3",
+ "phpstan/phpstan": "^1.1",
+ "phpstan/phpstan-phpunit": "^1.0",
+ "phpunit/phpunit": "^8.5 || ^9.0",
+ "squizlabs/php_codesniffer": "^3.7",
+ "tecnickcom/tcpdf": "^6.5"
+ },
+ "suggest": {
+ "dompdf/dompdf": "Option for rendering PDF with PDF Writer",
+ "ext-intl": "PHP Internationalization Functions",
+ "mitoteam/jpgraph": "Option for rendering charts, or including charts with PDF or HTML Writers",
+ "mpdf/mpdf": "Option for rendering PDF with PDF Writer",
+ "tecnickcom/tcpdf": "Option for rendering PDF with PDF Writer"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "PhpOffice\\PhpSpreadsheet\\": "src/PhpSpreadsheet"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Maarten Balliauw",
+ "homepage": "https://blog.maartenballiauw.be"
+ },
+ {
+ "name": "Mark Baker",
+ "homepage": "https://markbakeruk.net"
+ },
+ {
+ "name": "Franck Lefevre",
+ "homepage": "https://rootslabs.net"
+ },
+ {
+ "name": "Erik Tilt"
+ },
+ {
+ "name": "Adrien Crivelli"
+ }
+ ],
+ "description": "PHPSpreadsheet - Read, Create and Write Spreadsheet documents in PHP - Spreadsheet engine",
+ "homepage": "https://github.com/PHPOffice/PhpSpreadsheet",
+ "keywords": [
+ "OpenXML",
+ "excel",
+ "gnumeric",
+ "ods",
+ "php",
+ "spreadsheet",
+ "xls",
+ "xlsx"
+ ],
+ "support": {
+ "issues": "https://github.com/PHPOffice/PhpSpreadsheet/issues",
+ "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.29.7"
+ },
+ "time": "2024-12-27T05:10:37+00:00"
+ },
{
"name": "phpoption/phpoption",
"version": "1.9.3",
diff --git a/config/app.php b/config/app.php
index f467267..4d26007 100644
--- a/config/app.php
+++ b/config/app.php
@@ -11,7 +11,7 @@
| framework needs to place the application's name in a notification or
| other UI elements where an application name needs to be displayed.
|
- */
+ */
'name' => env('APP_NAME', 'Laravel'),
@@ -24,7 +24,7 @@
| running in. This may determine how you prefer to configure various
| services the application utilizes. Set this in your ".env" file.
|
- */
+ */
'env' => env('APP_ENV', 'production'),
@@ -37,7 +37,7 @@
| stack traces will be shown on every error that occurs within your
| application. If disabled, a simple generic error page is shown.
|
- */
+ */
'debug' => (bool) env('APP_DEBUG', false),
@@ -50,7 +50,7 @@
| the Artisan command line tool. You should set this to the root of
| the application so that it's available within Artisan commands.
|
- */
+ */
'url' => env('APP_URL', 'http://localhost'),
@@ -63,9 +63,9 @@
| will be used by the PHP date and date-time functions. The timezone
| is set to "UTC" by default as it is suitable for most use cases.
|
- */
+ */
- 'timezone' => env('APP_TIMEZONE', 'UTC'),
+ 'timezone' => env('APP_TIMEZONE', 'asia/Taipei'),
/*
|--------------------------------------------------------------------------
@@ -76,7 +76,7 @@
| by Laravel's translation / localization methods. This option can be
| set to any locale for which you plan to have translation strings.
|
- */
+ */
'locale' => env('APP_LOCALE', 'en'),
@@ -93,14 +93,14 @@
| to a random, 32 character string to ensure that all encrypted values
| are secure. You should do this prior to deploying the application.
|
- */
+ */
'cipher' => 'AES-256-CBC',
'key' => env('APP_KEY'),
'previous_keys' => [
- ...array_filter(
+ ...array_filter(
explode(',', env('APP_PREVIOUS_KEYS', ''))
),
],
@@ -116,7 +116,7 @@
|
| Supported drivers: "file", "cache"
|
- */
+ */
'maintenance' => [
'driver' => env('APP_MAINTENANCE_DRIVER', 'file'),
diff --git a/database/migrations/0001_01_01_000000_create_users_table.php b/database/migrations/0001_01_01_000000_create_users_table.php
index 3562faa..ae40745 100644
--- a/database/migrations/0001_01_01_000000_create_users_table.php
+++ b/database/migrations/0001_01_01_000000_create_users_table.php
@@ -14,12 +14,14 @@ public function up(): void
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
- $table->string('email')->unique();
+ $table->string('email')->nullable()->unique();
$table->timestamp('email_verified_at')->nullable();
- $table->string('app_id')->comment('line user_id');
+ $table->string('line_id')->nullable()->comment('line user_id');
$table->string('phone')->nullable()->comment('手機電話');
- $table->string('role')->comment('admin,agent');
+ // $table->string('role')->comment('admin,agent');
$table->string('password');
+ $table->string('avatar')->nullable(); // 頭像
+ $table->boolean('can_login')->default(true); // 是否可以登入
$table->rememberToken();
$table->softDeletes();
$table->timestamps();
@@ -32,12 +34,20 @@ public function up(): void
});
Schema::create('sessions', function (Blueprint $table) {
- $table->string('id')->primary();
- $table->foreignId('user_id')->nullable()->index();
- $table->string('ip_address', 45)->nullable();
- $table->text('user_agent')->nullable();
- $table->longText('payload');
- $table->integer('last_activity')->index();
+ $table->id();
+ $table->string('name')->default('客戶')->nullable(); // 使用者名稱
+ $table->string('email')->nullable()->unique(); // 電子郵件
+ $table->string('password'); // 密碼
+ $table->string('avatar')->nullable(); // 頭像
+ $table->string('phone')->nullable(); // 電話
+ $table->string('line_id')->nullable()->unique(); // Line ID
+ $table->string('facebook_id')->nullable()->unique(); // Facebook ID
+ $table->string('google_id')->nullable()->unique(); // Google ID
+ $table->integer('level')->default(1)->comment('會員等級 一般,1.系統管理員,2工程師'); // 會員等級
+ $table->string('reset_token')->nullable(); // 密碼重置 Token
+ $table->timestamp('email_verified_at')->nullable(); // 電子郵件驗證時間
+ $table->rememberToken(); // 記住登入 Token
+ $table->timestamps(); // 建立與更新時間
});
}
diff --git a/database/migrations/2025_01_08_025433_create_member_table.php b/database/migrations/2025_01_08_025433_create_member_table.php
index 04d4d3d..e38199e 100644
--- a/database/migrations/2025_01_08_025433_create_member_table.php
+++ b/database/migrations/2025_01_08_025433_create_member_table.php
@@ -15,20 +15,21 @@ public function up()
{
Schema::create('members', function (Blueprint $table) {
$table->id();
- $table->string('name')->default('客戶')->nullable(); // 使用者名稱
- $table->string('email')->nullable()->unique(); // 電子郵件
- $table->string('password'); // 密碼
- $table->string('avatar')->nullable(); // 頭像
- $table->string('phone')->nullable(); // 電話
- $table->string('source')->comment('來源'); // 來源
- $table->string('line_id')->nullable()->unique(); // Line ID
- $table->string('facebook_id')->nullable()->unique(); // Facebook ID
- $table->string('google_id')->nullable()->unique(); // Google ID
+ $table->string('name')->default('客戶')->nullable(); // 使用者名稱
+ $table->string('email')->nullable()->unique(); // 電子郵件
+ $table->string('password'); // 密碼
+ $table->string('avatar')->nullable(); // 頭像
+ $table->string('phone')->nullable(); // 電話
+ $table->string('source')->comment('來源'); // 來源
+ $table->string('line_id')->nullable()->unique(); // Line ID
+ $table->string('facebook_id')->nullable()->unique(); // Facebook ID
+ $table->string('google_id')->nullable()->unique(); // Google ID
$table->integer('level')->default(0)->comment('會員等級 0 一般,1.銀會員,2金會員,9.測試人員'); // 會員等級
- $table->string('reset_token')->nullable(); // 密碼重置 Token
- $table->timestamp('email_verified_at')->nullable(); // 電子郵件驗證時間
- $table->rememberToken(); // 記住登入 Token
- $table->timestamps(); // 建立與更新時間
+ $table->string('reset_token')->nullable(); // 密碼重置 Token
+ $table->softDeletes(); //軟刪除
+ $table->timestamp('email_verified_at')->nullable(); // 電子郵件驗證時間
+ $table->rememberToken(); // 記住登入 Token
+ $table->timestamps(); // 建立與更新時間
});
}
diff --git a/database/migrations/2025_01_08_025554_create_order_table.php b/database/migrations/2025_01_08_025554_create_order_table.php
index c8b84f9..57aceaf 100644
--- a/database/migrations/2025_01_08_025554_create_order_table.php
+++ b/database/migrations/2025_01_08_025554_create_order_table.php
@@ -16,10 +16,10 @@ public function up(): void
$table->string('order_no')->comment('訂單編號');
$table->string('member_id')->comment('會員編號');
$table->string('name')->comment('姓名');
- $table->integer('goods_code', 8)->comment('提貨編號');
+ $table->integer('goods_code')->nullable()->comment('提貨編號');
$table->string('goods')->comment('商品');
$table->string('amount')->comment('金額');
- $table->string('status')->comment('狀態0:未付款,1:已付款,2:已出貨,3:已完成,4:已取消');
+ $table->string('status')->comment('狀態0:未付款,1:已付款,2:已兌換 ,3:優惠碼兌換,4:已完成,5:已取消');
$table->string('note')->comment('備註');
$table->string('price')->comment('單一價格');
$table->timestamps();
diff --git a/database/migrations/2025_01_13_154705_create_promocodes_table.php b/database/migrations/2025_01_13_154705_create_promocodes_table.php
new file mode 100644
index 0000000..1ffdc0e
--- /dev/null
+++ b/database/migrations/2025_01_13_154705_create_promocodes_table.php
@@ -0,0 +1,35 @@
+id(); // 自增主鍵
+ $table->string('code', 8)->unique()->comment('優惠碼');
+ $table->decimal('discount', 8, 2)->default(100)->comment('折扣金額或百分比');
+ $table->enum('type', ['amount', 'percent'])->default('percent')->comment('優惠類型: 金額或百分比');
+ $table->integer('usage_limit')->default(1)->comment('使用次數限制');
+ $table->integer('used_count')->default(0)->comment('已使用次數');
+ $table->date('valid_from')->nullable()->comment('有效期開始');
+ $table->date('valid_to')->nullable()->comment('有效期結束');
+ $table->boolean('is_active')->default(true)->comment('是否啟用');
+ $table->timestamps(); // 自動生成 created_at 和 updated_at
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::dropIfExists('promocodes');
+ }
+};
diff --git a/database/migrations/2025_01_17_102838_create_email_verifications_table.php b/database/migrations/2025_01_17_102838_create_email_verifications_table.php
new file mode 100644
index 0000000..0a161d2
--- /dev/null
+++ b/database/migrations/2025_01_17_102838_create_email_verifications_table.php
@@ -0,0 +1,29 @@
+id();
+ $table->string('email')->unique();
+ $table->string('token');
+ $table->timestamps();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::dropIfExists('email_verifications');
+ }
+};
diff --git a/database/seeders/PromocodeSeeder.php b/database/seeders/PromocodeSeeder.php
new file mode 100644
index 0000000..a53e6c8
--- /dev/null
+++ b/database/seeders/PromocodeSeeder.php
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+ 卡菲姬後台註冊
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{--
+
+ Buy Now
+
+ --}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/views/admin/dashboard/index.blade.php b/resources/views/admin/dashboard/index.blade.php
new file mode 100644
index 0000000..92fe55e
--- /dev/null
+++ b/resources/views/admin/dashboard/index.blade.php
@@ -0,0 +1,27 @@
+@extends('layouts.admin_app')
+@section('header')
+@endsection
+@section('content')
+
+
+
+
+
+
+
+
+
+
+ @endsection
+ @section('scripts')
+ @endsection
diff --git a/resources/views/admin/dashboard/profile.blade.php b/resources/views/admin/dashboard/profile.blade.php
new file mode 100644
index 0000000..b2f672c
--- /dev/null
+++ b/resources/views/admin/dashboard/profile.blade.php
@@ -0,0 +1,435 @@
+
+
+
+
+
+
+
+
+ 卡菲姬後台登入
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 卡菲姬個人資料
+ Hi, {{$data->name }} 管理者 歡迎你 ! ,請花幾分鐘完善資料
+
+
+
+
+
+ 編輯您的資訊
+ 更新用戶詳細資訊
+
+
+
+
+
+
+
+ {{--
+ 新的裝置?
+
+ 創建新的帳號
+
+
+
+
+ 或
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{--
+ Buy Now
+ --}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{{-- --}}
+{{-- --}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/resources/views/admin/login.blade.php b/resources/views/admin/login.blade.php
index ff478d9..6fe89bd 100644
--- a/resources/views/admin/login.blade.php
+++ b/resources/views/admin/login.blade.php
@@ -3,46 +3,62 @@
-
-
+
+
- Login Basic - Pages |
- Materialize -
- Materialize - Bootstrap 5 HTML Laravel Admin Template
-
-
-
-
-
-
-
-
+ 卡菲姬後台登入
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{{-- --}}
+{{-- --}}
+
+
+
-
+
+
-
+
+
+
+
+
+
+
+
diff --git a/resources/views/admin/member/index.blade.php b/resources/views/admin/member/index.blade.php
new file mode 100644
index 0000000..e020cbb
--- /dev/null
+++ b/resources/views/admin/member/index.blade.php
@@ -0,0 +1,194 @@
+@extends('layouts.admin_app')
+@section('header')
+@endsection
+@section('content')
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 會員共計
+
+ 21,459
+ (+29%)
+
+ Total Users
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 普通會員
+
+ 4,567
+ (+18%)
+
+ Last week analytics
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 白銀會員
+
+ 19,860
+ (-14%)
+
+ Last week analytics
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 白金會員
+
+ 237
+ (+42%)
+
+ Last week analytics
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Filters
+
+
+
+
+
+
+
+
+
+
+ 會員id
+ 會員名稱
+ 手機號碼
+ 會員等級
+ 兌換碼
+ 操 作
+
+
+
+ @foreach($data as $item)
+
+ {{$item->id}}
+
+
+
+
+
+
+
+
+
+ {{$item->name}}
+ {{$item->email}}
+
+
+
+
+ {{$item->phone}}
+
+
+
+ @if($item->level == 0)
+
+ @elseif($item->level == 1)
+
+ @elseif($item->level == 2)
+
+
+ @endif
+
+ {{$item->Level_Name}}
+
+
+
+
+ 未實作
+
+
+ @endforeach
+
+
+
+
+
+ {{$data->links()}}
+
+
+
+
+
+
+@endsection
+@section('scripts')
+@endsection
diff --git a/resources/views/admin/profile/index.blade.php b/resources/views/admin/profile/index.blade.php
index df93b3e..22b7c6d 100644
--- a/resources/views/admin/profile/index.blade.php
+++ b/resources/views/admin/profile/index.blade.php
@@ -1,160 +1,343 @@
-@extends('layouts.app')
+@extends('layouts.admin_app')
@section('header')
@endsection
@section('content')
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Selina Kyle
-
-
-
- admin
-
-
-
-
-
-
-
-
-
- 1,230
Task Done
-
-
-
-
-
-
- 568
Project Done
-
-
-
-
- Details
-
-
-
-
-
-
-
-
- Username: @catwomen1940
-
-
-
-
-
-
-
-
-
- Billing Email: irena.dubrovna@wayne.com
-
-
-
-
-
-
-
-
-
- Status: Active
-
-
-
-
-
-
-
-
-
- Role: admin
-
-
-
-
-
-
-
-
-
- Tax ID: Tax-8894
-
-
-
-
-
-
-
-
-
- Contact: (829) 537-0057
-
-
-
-
-
-
-
-
-
- Language: English
-
-
-
-
-
-
-
-
-
- Country: United States
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 卡菲姬個人資料
+ Hi, {{$data->name }} 管理者 歡迎你 ! ,請花幾分鐘完善資料
+
+
+
+
+
+ 編輯您的資訊
+ 更新用戶詳細資訊
+
+
+
-@endsection
-@section('scripts')
+
+
+ {{--
+ 新的裝置?
+
+ 創建新的帳號
+
+
+
+
+ 或
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{--
+ Buy Now
+ --}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{{-- --}}
+{{-- --}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+