diff --git a/backend/main.py b/backend/main.py index 4fa4148..9ac83ce 100644 --- a/backend/main.py +++ b/backend/main.py @@ -1420,11 +1420,15 @@ def get_notifications(user=Depends(get_current_user)): if not user["id"]: return [] conn = get_db() + # Only show notifications created after user registration + user_created = conn.execute("SELECT created_at FROM users WHERE id = ?", (user["id"],)).fetchone() + created_at = user_created["created_at"] if user_created else "2000-01-01" rows = conn.execute( "SELECT id, title, body, is_read, created_at FROM notifications " "WHERE (target_user_id = ? OR (target_user_id IS NULL AND (target_role = ? OR target_role = 'all'))) " + "AND created_at >= ? " "ORDER BY is_read ASC, id DESC LIMIT 200", - (user["id"], user["role"]) + (user["id"], user["role"], created_at) ).fetchall() conn.close() return [dict(r) for r in rows] diff --git a/frontend/src/views/MyDiary.vue b/frontend/src/views/MyDiary.vue index bd00166..a9632eb 100644 --- a/frontend/src/views/MyDiary.vue +++ b/frontend/src/views/MyDiary.vue @@ -241,18 +241,57 @@ -
+

💼 商业认证

-

申请商业认证后可使用商业核算功能。

-
- - + + +
+
+
已认证商业用户
- -
-
-

💼 商业认证

-
✅ 已认证商业用户
+ + + + + + + + +
@@ -300,13 +339,20 @@ const displayName = ref('') const oldPassword = ref('') const newPassword = ref('') const confirmPassword = ref('') +const businessName = ref('') const businessReason = ref('') +const bizApp = ref({ status: null }) onMounted(async () => { await diaryStore.loadDiary() displayName.value = auth.user.display_name || '' await loadBrandSettings() returnRecipeId.value = localStorage.getItem('oil_return_recipe_id') || null + // Load business application status + try { + const bizRes = await api('/api/my-business-application') + if (bizRes.ok) bizApp.value = await bizRes.json() + } catch {} // 从商业核算跳转过来,滚到商业认证区域 if (route.query.section === 'biz-cert') { await nextTick() @@ -623,13 +669,30 @@ async function changePassword() { } async function applyBusiness() { + if (!businessName.value.trim()) { + ui.showToast('请填写商户名称') + return + } try { - await api('/api/business-apply', { + const res = await api('/api/business-apply', { method: 'POST', - body: JSON.stringify({ reason: businessReason.value }), + body: JSON.stringify({ + business_name: businessName.value.trim(), + document: businessReason.value.trim(), + }), }) - businessReason.value = '' - ui.showToast('申请已提交,请等待审核') + if (res.ok) { + businessName.value = '' + businessReason.value = '' + bizApp.value = { status: 'pending', business_name: businessName.value } + ui.showToast('申请已提交,请等待管理员审核') + // Reload status + const bizRes = await api('/api/my-business-application') + if (bizRes.ok) bizApp.value = await bizRes.json() + } else { + const err = await res.json().catch(() => ({})) + ui.showToast(err.detail || '提交失败') + } } catch { ui.showToast('提交失败') } @@ -1084,6 +1147,20 @@ async function applyBusiness() { text-align: center; } +.biz-status { + padding: 16px; + border-radius: 12px; + text-align: center; + margin-bottom: 12px; +} +.biz-status-icon { font-size: 32px; margin-bottom: 8px; } +.biz-status-text { font-size: 15px; font-weight: 600; margin-bottom: 4px; } +.biz-status-detail { font-size: 12px; color: #999; } +.biz-approved { background: #e8f5e9; color: #2e7d5a; } +.biz-pending { background: #fff8e1; color: #e65100; } +.biz-rejected { background: #fce4ec; color: #c62828; } +.biz-reject-reason { font-size: 13px; margin-top: 8px; padding: 8px 12px; background: rgba(0,0,0,0.05); border-radius: 8px; } + /* Buttons */ .btn-primary { background: linear-gradient(135deg, #7ec6a4 0%, #4a9d7e 100%); diff --git a/frontend/src/views/UserManagement.vue b/frontend/src/views/UserManagement.vue index 0709927..e299dbd 100644 --- a/frontend/src/views/UserManagement.vue +++ b/frontend/src/views/UserManagement.vue @@ -27,8 +27,8 @@
- {{ app.user_name || app.display_name }} - {{ app.reason }} + {{ app.display_name || app.username }} + 商户名:{{ app.business_name }}
@@ -101,7 +101,7 @@ import { ref, computed, onMounted } from 'vue' import { useAuthStore } from '../stores/auth' import { useUiStore } from '../stores/ui' import { api } from '../composables/useApi' -import { showConfirm } from '../composables/useDialog' +import { showConfirm, showPrompt } from '../composables/useDialog' const auth = useAuthStore() const ui = useUiStore() @@ -248,8 +248,13 @@ async function approveBusiness(app) { async function rejectBusiness(app) { const id = app._id || app.id + const reason = await showPrompt('请输入拒绝原因(选填):') + if (reason === null) return try { - const res = await api(`/api/business-applications/${id}/reject`, { method: 'POST' }) + const res = await api(`/api/business-applications/${id}/reject`, { + method: 'POST', + body: JSON.stringify({ reason: reason || '' }), + }) if (res.ok) { businessApps.value = businessApps.value.filter(item => (item._id || item.id) !== id) ui.showToast('已拒绝')