diff --git a/src/api/manage/auditLog.ts b/src/api/manage/auditLog.ts
index 9697610..9e20322 100644
--- a/src/api/manage/auditLog.ts
+++ b/src/api/manage/auditLog.ts
@@ -10,15 +10,17 @@ export interface AuditLogItem {
actorUserId: number
/** 操作人名 */
name?: string
- /** 请求方法 */
+ /** 操作描述(中文,如"创建天卡订单(设备端)") */
+ head?: string
+ /** 请求方法枚举(如 DAYCARD_ORDER_CREATE) */
method?: string
/** 接口路径 */
api?: string
/** 请求参数 */
param?: string
- /** 中文描述 */
+ /** 中文描述(旧字段,多为空) */
paramDesc?: string
- /** 操作结果 */
+ /** 操作结果(完整返回字符串,含 code=/msg=) */
result?: string
/** 变更前 */
before?: string
@@ -41,6 +43,8 @@ export interface AuditLogListParams extends ManagePageParams {
actorUserId?: number
api?: string
method?: string
+ head?: string
+ ip?: string
ticketNo?: string
}
diff --git a/src/api/manage/device.ts b/src/api/manage/device.ts
index 2790580..5c9a47d 100644
--- a/src/api/manage/device.ts
+++ b/src/api/manage/device.ts
@@ -46,6 +46,7 @@ export interface DeviceListParams extends ManagePageParams {
status?: string
deviceName?: string
mac?: string
+ deviceSn?: string
/** 设备来源:DIRECT / PARTNER */
source?: string
/** 合作伙伴UUID(source=PARTNER 时筛选) */
diff --git a/src/api/manage/jstCallLog.ts b/src/api/manage/jstCallLog.ts
index 8ef4433..55d8b73 100644
--- a/src/api/manage/jstCallLog.ts
+++ b/src/api/manage/jstCallLog.ts
@@ -6,7 +6,7 @@ import type { ManageListResponse, ManagePageParams } from './types'
*/
export interface JstCallLogItem {
id: number
- /** 请求URL */
+ /** 请求URL(可能带反引号和query参数) */
apiPath: string
/** 请求方法 */
requestMethod?: string
@@ -20,6 +20,12 @@ export interface JstCallLogItem {
success: number
/** 耗时(ms) */
duration?: number
+ /** 关联数据ID */
+ dataId?: number
+ /** 请求头(JSON字符串) */
+ requestHeaders?: string
+ /** 客户端IP */
+ clientIp?: string
/** 错误信息 */
errorMessage?: string
/** 关联设备MAC */
@@ -28,8 +34,14 @@ export interface JstCallLogItem {
deviceSn?: string
/** 关联设备UID */
deviceUid?: string
- /** 设备所属门店 */
+ /** 门店组织ID */
+ storeOrgId?: number
+ /** 设备所属门店名称 */
storeOrgName?: string
+ /** 门店编码 */
+ storeOrgCode?: string
+ /** 门店类型 */
+ storeOrgType?: string
createTime: string
}
@@ -42,6 +54,8 @@ export interface JstCallLogListParams extends ManagePageParams {
endTime?: string
apiPath?: string
requestBody?: string
+ /** 结果筛选:1=成功,0=失败 */
+ success?: number
}
/** 橘视厅调用日志列表 */
diff --git a/src/api/manage/payConfig.ts b/src/api/manage/payConfig.ts
index 3fa6a0e..5bc71b1 100644
--- a/src/api/manage/payConfig.ts
+++ b/src/api/manage/payConfig.ts
@@ -16,7 +16,8 @@ export interface PayConfigInfo {
mchId: string
apiV3Key: string
certSerialNo: string
- privateKeyPath: string
+ /** 商户 API 私钥(apiclient_key.pem 的 PEM 内容) */
+ privateKey: string
notifyUrl: string
status: string
remark: string
@@ -49,7 +50,8 @@ export interface PayConfigSaveData {
mchId: string
apiV3Key: string
certSerialNo?: string
- privateKeyPath?: string
+ /** 商户 API 私钥(apiclient_key.pem 的 PEM 内容) */
+ privateKey?: string
notifyUrl: string
status?: string
remark?: string
diff --git a/src/views/modules/manage/audit-log.vue b/src/views/modules/manage/audit-log.vue
index 90e66cf..5fe94cb 100644
--- a/src/views/modules/manage/audit-log.vue
+++ b/src/views/modules/manage/audit-log.vue
@@ -2,16 +2,22 @@
-
+
-
+
-
+
-
+
+
+
+
+
+
+
查询
@@ -19,28 +25,27 @@
-
-
- {{ scope.row.name || scope.row.actorUserId || '-' }}
-
-
-
-
- {{ scope.row.paramDesc || '-' }}
-
-
+
+
- 成功
- {{ scope.row.result }}
- -
+ {{ scope.row.head || '-' }}
-
- {{ scope.row.ip || '-' }}
+
+
+
+
+ {{ scope.row.name }}
+ 用户#{{ scope.row.actorUserId }}
+ 系统
+
-
- {{ scope.row.ticketNo || '-' }}
+
+
+ {{ resultTag(scope.row).label }}
+
+
@@ -60,27 +65,37 @@
-
+
- {{ detailData.name || detailData.actorUserId || '-' }}
+ {{ detailData.head || '-' }}
{{ detailData.method || '-' }}
{{ detailData.api || '-' }}
- {{ detailData.paramDesc || '-' }}
- {{ detailData.result || '-' }}
- {{ detailData.ticketNo || '-' }}
+
+ {{ detailData.name }}
+ 用户#{{ detailData.actorUserId }}
+ 系统
+
+
+ {{ resultTag(detailData).label }}
+ {{ resultSummary(detailData.result) }}
+
{{ detailData.ip || '-' }}
- {{ detailData.deviceInfo || '-' }}
+ {{ detailData.deviceInfo || '-' }}
+ {{ detailData.ticketNo || '-' }}
{{ detailData.reason || '-' }}
+ {{ detailData.createdAt || '-' }}
- {{ detailData.param || '-' }}
+ {{ detailData.param || '-' }}
+
+
+ {{ detailData.result || '-' }}
- {{ detailData.before || '-' }}
+ {{ detailData.before || '-' }}
- {{ detailData.after || '-' }}
+ {{ detailData.after || '-' }}
- {{ detailData.createdAt || '-' }}
关闭
@@ -94,30 +109,70 @@ import { reactive, ref, onMounted } from 'vue'
import { getAuditLogList, type AuditLogItem } from '@/api/manage/auditLog'
interface DataForm {
- name: string
api: string
method: string
- ticketNo: string
+ head: string
+ ip: string
+ resultStatus: string
}
-const dataForm = reactive({ name: '', api: '', method: '', ticketNo: '' })
+const dataForm = reactive({ api: '', method: '', head: '', ip: '', resultStatus: '' })
const dataList = ref([])
const pageIndex = ref(1)
const pageSize = ref(10)
const totalPage = ref(0)
const dataListLoading = ref(false)
+/** 解析 result 字符串,返回标签类型与文案 */
+function resultTag (row: Partial | undefined): { type: 'success' | 'danger' | 'warning' | 'info', label: string } {
+ if (!row) return { type: 'info', label: '-' }
+ const r = row.result || ''
+ if (!r) return { type: 'info', label: '-' }
+ // 异常
+ if (r.startsWith('exception') || /Exception/i.test(r)) return { type: 'danger', label: '异常' }
+ // 解析 code=N
+ const m = r.match(/code=(\d+)/)
+ if (m) {
+ const code = Number(m[1])
+ if (code === 0) return { type: 'success', label: '成功' }
+ return { type: 'danger', label: `失败(${code})` }
+ }
+ // 兜底:msg=success
+ if (/msg=success/i.test(r)) return { type: 'success', label: '成功' }
+ if (/msg=/i.test(r) && !/msg=success/i.test(r)) return { type: 'danger', label: '失败' }
+ return { type: 'warning', label: '未知' }
+}
+
+/** 返回结果摘要(取 msg 部分) */
+function resultSummary (result?: string): string {
+ if (!result) return ''
+ const m = result.match(/msg=([^,}]+)/)
+ return m ? `msg: ${m[1]}` : ''
+}
+
async function getDataList (): Promise {
dataListLoading.value = true
try {
- const res = await getAuditLogList({
+ const params: any = {
page: pageIndex.value,
limit: pageSize.value,
api: dataForm.api || undefined,
method: dataForm.method || undefined,
- ticketNo: dataForm.ticketNo || undefined
- })
+ head: dataForm.head || undefined,
+ ip: dataForm.ip || undefined
+ }
+ // 结果状态由前端筛选(后端无此参数)
+ const res = await getAuditLogList(params)
if (res && res.code === 0) {
- dataList.value = res.data?.page?.list || []
+ let list = res.data?.page?.list || []
+ if (dataForm.resultStatus) {
+ const wantSuccess = dataForm.resultStatus === 'SUCCESS'
+ list = list.filter((item: AuditLogItem) => {
+ const tag = resultTag(item)
+ const isSuccess = tag.type === 'success'
+ return wantSuccess ? isSuccess : !isSuccess
+ })
+ }
+ dataList.value = list
totalPage.value = res.data?.page?.totalCount || 0
} else {
dataList.value = []
@@ -156,4 +211,15 @@ onMounted(() => {
.mod-audit-log {
padding: 10px;
}
+.log-pre {
+ white-space: pre-wrap;
+ word-break: break-all;
+ max-height: 220px;
+ overflow: auto;
+ margin: 0;
+ background: #f5f7fa;
+ padding: 8px;
+ border-radius: 4px;
+ font-size: 12px;
+}
diff --git a/src/views/modules/manage/device.vue b/src/views/modules/manage/device.vue
index 2abbdea..242ff4b 100644
--- a/src/views/modules/manage/device.vue
+++ b/src/views/modules/manage/device.vue
@@ -499,10 +499,9 @@ async function showBenefits (row: DeviceInfo): Promise {
}
try {
const res = await getDeviceBenefits(row.id)
- if (res && res.code === 0 && res.data) {
- benefitsData.value = { ...res.data, deviceName: row.deviceName, deviceId: row.id, mac: row.mac }
- } else if (res && res.code === 200 && res.data) {
- benefitsData.value = { ...res.data, deviceName: row.deviceName, deviceId: row.id, mac: row.mac }
+ const benefits = res?.data
+ if (benefits) {
+ benefitsData.value = { ...benefits, deviceName: row.deviceName, deviceId: row.id, mac: row.mac }
} else {
ElMessage.error(res?.msg || '查询权益失败')
}
diff --git a/src/views/modules/manage/jst-call-log.vue b/src/views/modules/manage/jst-call-log.vue
index 5862261..53dfa82 100644
--- a/src/views/modules/manage/jst-call-log.vue
+++ b/src/views/modules/manage/jst-call-log.vue
@@ -7,6 +7,12 @@
+
+
+
+
+
+
@@ -19,26 +25,35 @@
-
-
-
-
+
+
+
+ {{ apiShort(scope.row.apiPath) }}
+
+
+
+
成功
失败
-
- {{ scope.row.responseCode || '-' }}
+
+
+ {{ scope.row.responseCode }}
+ {{ scope.row.responseCode }}
+ -
+
-
-
+
+
+ {{ scope.row.duration ?? '-' }} ms
+
+
+
{{ scope.row.mac || '-' }}
-
- {{ scope.row.deviceSn || '-' }}
-
-
+
{{ scope.row.storeOrgName || '-' }}
@@ -60,26 +75,34 @@
-
+
- {{ detailData.apiPath }}
- {{ detailData.requestMethod || '-' }}
+
+ {{ cleanUrl(detailData.apiPath) }}
+
+ {{ detailData.requestMethod || '-' }}
成功
失败
+ HTTP {{ detailData.responseCode || '-' }}
- {{ detailData.responseCode || '-' }}
{{ detailData.duration ?? '-' }} ms
{{ detailData.mac || '-' }}
{{ detailData.deviceSn || '-' }}
{{ detailData.deviceUid || '-' }}
{{ detailData.storeOrgName || '-' }}
- {{ detailData.errorMessage }}
+ {{ detailData.clientIp }}
+
+ {{ detailData.errorMessage }}
+
+
+ {{ formatJson(detailData.requestHeaders) }}
+
- {{ detailData.requestBody || '-' }}
+ {{ formatJson(detailData.requestBody) }}
- {{ detailData.responseBody || '-' }}
+ {{ formatJson(detailData.responseBody) }}
{{ detailData.createTime || '-' }}
@@ -97,16 +120,54 @@ import { getJstCallLogList, type JstCallLogItem } from '@/api/manage/jstCallLog'
interface DataForm {
mac: string
apiPath: string
+ success: number | ''
beginTime: string
endTime: string
}
-const dataForm = reactive({ mac: '', apiPath: '', beginTime: '', endTime: '' })
+const dataForm = reactive({ mac: '', apiPath: '', success: '', beginTime: '', endTime: '' })
const dataList = ref([])
const pageIndex = ref(1)
const pageSize = ref(10)
const totalPage = ref(0)
const dataListLoading = ref(false)
+/** 清理 URL 首尾的反引号和空格 */
+function cleanUrl (url?: string): string {
+ if (!url) return '-'
+ return url.trim().replace(/^`|`$/g, '')
+}
+
+/** 列表展示用:仅取 host + path,去掉 query 串 */
+function apiShort (url?: string): string {
+ const clean = cleanUrl(url)
+ if (clean === '-') return clean
+ // 去掉 query
+ const qIdx = clean.indexOf('?')
+ const noQuery = qIdx > -1 ? clean.substring(0, qIdx) : clean
+ // 提取 host + path
+ const m = noQuery.match(/^https?:\/\/[^/]+(.*)$/i)
+ if (m && m[1]) return m[1]
+ return noQuery
+}
+
+/** 耗时颜色:<300ms 绿,<1000ms 普通,>=1000ms 红 */
+function durationClass (duration?: number): string {
+ if (duration == null) return ''
+ if (duration < 300) return 'dur-fast'
+ if (duration >= 1000) return 'dur-slow'
+ return ''
+}
+
+/** 尝试格式化 JSON 字符串,失败则原样返回 */
+function formatJson (str?: string): string {
+ if (!str) return '-'
+ try {
+ return JSON.stringify(JSON.parse(str), null, 2)
+ } catch {
+ return str
+ }
+}
+
async function getDataList (): Promise {
dataListLoading.value = true
try {
@@ -115,6 +176,7 @@ async function getDataList (): Promise {
limit: pageSize.value,
mac: dataForm.mac || undefined,
apiPath: dataForm.apiPath || undefined,
+ success: dataForm.success === '' ? undefined : (dataForm.success as number),
beginTime: dataForm.beginTime || undefined,
endTime: dataForm.endTime || undefined
})
@@ -158,4 +220,21 @@ onMounted(() => {
.mod-jst-call-log {
padding: 10px;
}
+.log-pre {
+ white-space: pre-wrap;
+ word-break: break-all;
+ max-height: 240px;
+ overflow: auto;
+ margin: 0;
+ background: #f5f7fa;
+ padding: 8px;
+ border-radius: 4px;
+ font-size: 12px;
+}
+.dur-fast {
+ color: #67c23a;
+}
+.dur-slow {
+ color: #f56c6c;
+}
diff --git a/src/views/modules/manage/partner-device.vue b/src/views/modules/manage/partner-device.vue
index d990c6f..c86b267 100644
--- a/src/views/modules/manage/partner-device.vue
+++ b/src/views/modules/manage/partner-device.vue
@@ -2,15 +2,15 @@
-
+
-
+
-
+
查询
@@ -18,25 +18,37 @@
-
-
+
+
+
+ 第三方
+ 自营
+ {{ scope.row.source || '-' }}
+
+
+
+
+ {{ scope.row.wifiMac || '-' }}
+
+
+ {{ scope.row.deviceSn || '-' }}
+
+
+ {{ scope.row.deviceUid || '-' }}
+
+
{{ partnerNameOf(scope.row.partnerId) }}
-
-
-
-
-
+
- 启用
- 禁用
+ 已激活
+ 未激活
{{ scope.row.status }}
-
- {{ scope.row.storeName || '-' }}
+
+ {{ scope.row.lastHeartbeat || '-' }}
-
({ partnerId: null, deviceName: '', mac: '' })
+const dataForm = reactive({ partnerId: null, mac: '', deviceSn: '' })
const dataList = ref([])
const pageIndex = ref(1)
const pageSize = ref(10)
@@ -94,8 +106,8 @@ async function getDataList (): Promise {
limit: pageSize.value,
source: 'PARTNER',
partnerId: dataForm.partnerId ?? undefined,
- deviceName: dataForm.deviceName || undefined,
- mac: dataForm.mac || undefined
+ mac: dataForm.mac || undefined,
+ deviceSn: dataForm.deviceSn || undefined
})
if (res && res.code === 0) {
dataList.value = res.data?.page?.list || []
diff --git a/src/views/modules/manage/pay-config.vue b/src/views/modules/manage/pay-config.vue
index 5ca01b7..53bf60e 100644
--- a/src/views/modules/manage/pay-config.vue
+++ b/src/views/modules/manage/pay-config.vue
@@ -86,8 +86,26 @@
-
-
+
+
+
+
+
+ 上传 .pem 文件
+
+ 仅读取本地文件内容,不会上传到服务器
+
+
+
@@ -109,7 +127,7 @@