chore(release): 冻结 v1.1.0 版本
- 同步版本号:VERSION / backend pom / admin-web / miniapp 均升至 1.1.0 - 合并本轮代码审查修复(详见 docs/CODE-REVIEW-2026-09-24.md): - 后端:微信登录真实实现 RealWechatLoginProvider、实名核验真实实现 RealIdentityVerificationProvider(本地强校验 + 可配置第三方 + fail-closed/fail-fast) - 照片直传落库端点 POST /me/photos/confirm(fileKey 归属校验 + 对象存在性校验后 savePhoto) - 刷新 Token Redis TTL 修正(getExpirationMs()*2 的 4h → refreshExpirationMs 的 14 天) - 管理端 token 改为 HttpOnly Cookie + silent-refresh,移除 localStorage 明文存储与 30+ 处手工注入 - 小程序:红娘接单鉴权头错位修复、serviceType 中文映射、生产域名可配置 - 隔离本地产物(.workbuddy/、*.bundle、*.dump、secrets、application-dev.yml 等已被 .gitignore 覆盖) 未验证项(打标签 ≠ 生产发布): - 后端编译 / 单测未在本环境执行(Maven 慢、Docker DNS 受限) - 管理端 登录→刷新→登出 端到端、小程序真机走查待人工验收 - 生产部署需注入 WECHAT_APP_ID / WECHAT_APP_SECRET、VERIFICATION_API_URL / VERIFICATION_API_KEY 与小程序生产域名
This commit is contained in:
@@ -80,6 +80,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getAccessToken } from '@/utils/token'
|
||||
/**
|
||||
* U32 活动签到工作台(Phase 15)
|
||||
*
|
||||
@@ -111,7 +112,7 @@ const TYPE_TEXT: Record<string, string> = {
|
||||
}
|
||||
const typeText = (t: string) => TYPE_TEXT[t] || t || '未分类'
|
||||
|
||||
const authHeader = () => ({ Authorization: `Bearer ${localStorage.getItem('accessToken') || ''}` })
|
||||
const authHeader = () => ({ Authorization: `Bearer ${getAccessToken() || ''}` })
|
||||
|
||||
const formatTime = (v: any) => {
|
||||
if (!v) return '-'
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getAccessToken } from '@/utils/token'
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { get } from '@/api/client'
|
||||
|
||||
@@ -55,7 +56,7 @@ const mutualList = ref<any[]>([])
|
||||
async function loadData() {
|
||||
loading.value = true
|
||||
try {
|
||||
const token = localStorage.getItem('accessToken')
|
||||
const token = getAccessToken()
|
||||
const res: any = await get('/activities/operator/activity-interest-summary', {}, { Authorization: `Bearer ${token}` })
|
||||
const rows = res.data || []
|
||||
tableData.value = searchActivityId.value
|
||||
@@ -72,7 +73,7 @@ async function viewMutuals(activityId: string) {
|
||||
drawerVisible.value = true
|
||||
currentActivity.value = tableData.value.find(row => row.activityId === activityId)
|
||||
try {
|
||||
const token = localStorage.getItem('accessToken')
|
||||
const token = getAccessToken()
|
||||
const mutualRes: any = await get(`/activities/operator/${activityId}/mutuals`, {}, { Authorization: `Bearer ${token}` })
|
||||
mutualList.value = mutualRes.data || []
|
||||
} catch (e) {
|
||||
|
||||
@@ -168,6 +168,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getAccessToken } from '@/utils/token'
|
||||
/**
|
||||
* 活动管理(V1.1 Phase 14)
|
||||
*
|
||||
@@ -259,7 +260,7 @@ function emptyForm() {
|
||||
}
|
||||
|
||||
function authHeader() {
|
||||
return { Authorization: `Bearer ${localStorage.getItem('accessToken')}` }
|
||||
return { Authorization: `Bearer ${getAccessToken()}` }
|
||||
}
|
||||
|
||||
async function loadData() {
|
||||
|
||||
@@ -213,6 +213,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getAccessToken } from '@/utils/token'
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { get } from '@/api/client'
|
||||
import { token } from '@/theme/tokens'
|
||||
@@ -302,7 +303,7 @@ async function loadFunnel() {
|
||||
try {
|
||||
// 注意:这里曾是 `const token = ...`,与顶部从 @/theme/tokens 导入的**颜色助手**
|
||||
// `token` 同名(函数内遮蔽)。现已改名 authToken,避免后续在函数内误用颜色助手。
|
||||
const authToken = localStorage.getItem('accessToken')
|
||||
const authToken = getAccessToken()
|
||||
if (dateRange.value[0] && dateRange.value[1]) {
|
||||
const [userRes, matchRes, safetyRes, v11Res]: any[] = await Promise.all([
|
||||
get('/operator/analytics/user-funnel', {
|
||||
@@ -328,7 +329,7 @@ async function loadFunnel() {
|
||||
|
||||
async function loadDailySummary() {
|
||||
try {
|
||||
const authToken = localStorage.getItem('accessToken')
|
||||
const authToken = getAccessToken()
|
||||
const res: any = await get('/operator/analytics/daily-summary', { days: 30 }, { Authorization: `Bearer ${authToken}` })
|
||||
dailySummary.value = res.data || []
|
||||
} catch (e) { console.error(e) }
|
||||
|
||||
@@ -84,6 +84,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getAccessToken } from '@/utils/token'
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { get, post } from '@/api/client'
|
||||
import { token as tokenColor } from '@/theme/tokens'
|
||||
@@ -109,7 +110,7 @@ const STATUS_MAP: Record<string, { text: string; type: string }> = {
|
||||
async function loadData() {
|
||||
loading.value = true
|
||||
try {
|
||||
const token = localStorage.getItem('accessToken')
|
||||
const token = getAccessToken()
|
||||
const res: any = await get('/operator/appeals/pending', {}, { Authorization: `Bearer ${token}` })
|
||||
tableData.value = res.data || []
|
||||
loadStats()
|
||||
@@ -119,7 +120,7 @@ async function loadData() {
|
||||
|
||||
async function loadStats() {
|
||||
try {
|
||||
const token = localStorage.getItem('accessToken')
|
||||
const token = getAccessToken()
|
||||
const res: any = await get('/operator/appeals/stats', {}, { Authorization: `Bearer ${token}` })
|
||||
const data = res.data || {}
|
||||
stats.value = [
|
||||
@@ -138,7 +139,7 @@ async function openDetail(id: string) {
|
||||
decision.value = 'approve'
|
||||
decisionNote.value = ''
|
||||
try {
|
||||
const token = localStorage.getItem('accessToken')
|
||||
const token = getAccessToken()
|
||||
const res: any = await get(`/operator/appeals/${id}`, {}, { Authorization: `Bearer ${token}` })
|
||||
detail.value = res.data
|
||||
} catch (e) { console.error(e) }
|
||||
@@ -148,7 +149,7 @@ async function handleProcess() {
|
||||
if (!decision.value) return
|
||||
processing.value = true
|
||||
try {
|
||||
const token = localStorage.getItem('accessToken')
|
||||
const token = getAccessToken()
|
||||
await post(`/operator/appeals/${currentId.value}/process`,
|
||||
{ decision: decision.value, decisionNote: decisionNote.value },
|
||||
{ Authorization: `Bearer ${token}` })
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getAccessToken } from '@/utils/token'
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { get } from '@/api/client'
|
||||
|
||||
@@ -70,7 +71,7 @@ const ACTION_TEXT: Record<string, string> = {
|
||||
async function loadData() {
|
||||
loading.value = true
|
||||
try {
|
||||
const token = localStorage.getItem('accessToken')
|
||||
const token = getAccessToken()
|
||||
const res: any = await get('/operator/audit/logs', {
|
||||
resourceType: resourceFilter.value || undefined,
|
||||
page: page.value,
|
||||
|
||||
@@ -62,6 +62,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getAccessToken } from '@/utils/token'
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { get, post, put } from '@/api/client'
|
||||
|
||||
@@ -79,7 +80,7 @@ const orgMap = ref<Record<string, string>>({})
|
||||
async function loadData() {
|
||||
loading.value = true
|
||||
try {
|
||||
const token = localStorage.getItem('accessToken')
|
||||
const token = getAccessToken()
|
||||
const res: any = await get('/operator/operators', { page: page.value, pageSize: pageSize.value }, { Authorization: `Bearer ${token}` })
|
||||
tableData.value = res.data?.list || []
|
||||
total.value = res.data?.total || 0
|
||||
@@ -89,7 +90,7 @@ async function loadData() {
|
||||
|
||||
async function loadOrgs() {
|
||||
try {
|
||||
const token = localStorage.getItem('accessToken')
|
||||
const token = getAccessToken()
|
||||
const res: any = await get('/operator/operators/organizations', {}, { Authorization: `Bearer ${token}` })
|
||||
orgList.value = res.data || []
|
||||
orgList.value.forEach(o => { orgMap.value[o.id] = o.name })
|
||||
@@ -105,7 +106,7 @@ async function save() {
|
||||
if (!form.value.username || !form.value.password) return
|
||||
saving.value = true
|
||||
try {
|
||||
const token = localStorage.getItem('accessToken')
|
||||
const token = getAccessToken()
|
||||
await post('/operator/operators', form.value, { Authorization: `Bearer ${token}` })
|
||||
formVisible.value = false
|
||||
loadData()
|
||||
@@ -115,7 +116,7 @@ async function save() {
|
||||
|
||||
async function toggleStatus(row: any) {
|
||||
try {
|
||||
const token = localStorage.getItem('accessToken')
|
||||
const token = getAccessToken()
|
||||
const action = row.status === 'normal' ? 'disable' : 'enable'
|
||||
await put(`/operator/operators/${row.id}/${action}`, {}, { Authorization: `Bearer ${token}` })
|
||||
loadData()
|
||||
@@ -126,7 +127,7 @@ async function resetPwd(id: string) {
|
||||
const pwd = prompt('请输入新密码(至少8位)')
|
||||
if (!pwd || pwd.length < 8) return
|
||||
try {
|
||||
const token = localStorage.getItem('accessToken')
|
||||
const token = getAccessToken()
|
||||
await put(`/operator/operators/${id}/reset-password`, { newPassword: pwd }, { Authorization: `Bearer ${token}` })
|
||||
} catch (e) { console.error(e) }
|
||||
}
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getAccessToken } from '@/utils/token'
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { get, post, put } from '@/api/client'
|
||||
|
||||
@@ -78,7 +79,7 @@ const ORG_TYPE_TEXT: Record<string, string> = {
|
||||
async function loadData() {
|
||||
loading.value = true
|
||||
try {
|
||||
const token = localStorage.getItem('accessToken')
|
||||
const token = getAccessToken()
|
||||
const res: any = await get('/operator/organizations', {}, { Authorization: `Bearer ${token}` })
|
||||
tableData.value = res.data || []
|
||||
} catch (e) { console.error(e) }
|
||||
@@ -101,7 +102,7 @@ async function save() {
|
||||
if (!form.value.name) return
|
||||
saving.value = true
|
||||
try {
|
||||
const token = localStorage.getItem('accessToken')
|
||||
const token = getAccessToken()
|
||||
if (editId.value) {
|
||||
await put(`/operator/organizations/${editId.value}`, form.value, {
|
||||
Authorization: `Bearer ${token}`
|
||||
@@ -119,7 +120,7 @@ async function save() {
|
||||
|
||||
async function toggleStatus(row: any) {
|
||||
try {
|
||||
const token = localStorage.getItem('accessToken')
|
||||
const token = getAccessToken()
|
||||
const action = row.status === 'normal' ? 'disable' : 'enable'
|
||||
await put(`/operator/organizations/${row.id}/${action}`, {}, {
|
||||
Authorization: `Bearer ${token}`
|
||||
|
||||
@@ -98,6 +98,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getAccessToken } from '@/utils/token'
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { get, post } from '@/api/client'
|
||||
import { token as tokenColor } from '@/theme/tokens'
|
||||
@@ -124,7 +125,7 @@ const STATUS_MAP: Record<string, { text: string; type: string }> = {
|
||||
async function loadData() {
|
||||
loading.value = true
|
||||
try {
|
||||
const token = localStorage.getItem('accessToken')
|
||||
const token = getAccessToken()
|
||||
const res: any = await get(`/operator/risk/reports/${statusFilter.value}`, {}, { Authorization: `Bearer ${token}` })
|
||||
tableData.value = res.data || []
|
||||
loadStats()
|
||||
@@ -134,7 +135,7 @@ async function loadData() {
|
||||
|
||||
async function loadStats() {
|
||||
try {
|
||||
const token = localStorage.getItem('accessToken')
|
||||
const token = getAccessToken()
|
||||
const res: any = await get('/operator/risk/reports/stats', {}, { Authorization: `Bearer ${token}` })
|
||||
const data = res.data || {}
|
||||
stats.value = [
|
||||
@@ -152,7 +153,7 @@ async function openDetail(reportId: string) {
|
||||
processResult.value = 'no_action'
|
||||
processNote.value = ''
|
||||
try {
|
||||
const token = localStorage.getItem('accessToken')
|
||||
const token = getAccessToken()
|
||||
const res: any = await get(`/operator/risk/reports/${reportId}`, {}, { Authorization: `Bearer ${token}` })
|
||||
detail.value = res.data
|
||||
} catch (e) { console.error(e) }
|
||||
@@ -162,7 +163,7 @@ async function handleProcess() {
|
||||
if (!processResult.value) return
|
||||
processing.value = true
|
||||
try {
|
||||
const token = localStorage.getItem('accessToken')
|
||||
const token = getAccessToken()
|
||||
await post(`/operator/risk/reports/${currentReportId.value}/process`,
|
||||
{ processResult: processResult.value, processNote: processNote.value },
|
||||
{ Authorization: `Bearer ${token}` })
|
||||
|
||||
Reference in New Issue
Block a user