diff --git a/admin-console/src/pages/dashboard/index.vue b/admin-console/src/pages/dashboard/index.vue index f1d8606..4783057 100644 --- a/admin-console/src/pages/dashboard/index.vue +++ b/admin-console/src/pages/dashboard/index.vue @@ -64,7 +64,7 @@ {{ item.nickname || item.user_id || '-' }} {{ item.device_id || '-' }} - ✨ 智能模式 + {{ item.mode === 1 ? '✨ 智能' : '🔄 普通' }} {{ Math.floor((item.total_duration_ms || 0) / 60000) }}分 {{ formatDate(item.start_time || item.started_at) }} @@ -128,7 +128,9 @@ export default { methods: { async loadDashboard() { try { - this.stats = await get('/api/v1/admin/dashboard') + const dashboard = await get('/api/v1/admin/dashboard') + this.stats = dashboard + if (dashboard.sub_stats) this.subStats = dashboard.sub_stats } catch (e) { uni.showToast({ title: '加载失败', icon: 'none' }) } @@ -138,10 +140,6 @@ export default { } catch (e) { this.recentTreatments = [] } - try { - const subData = await get('/api/v1/admin/subscriptions', { page: 1, page_size: 1, tab: 'all' }) - if (subData.stats) this.subStats = subData.stats - } catch (e) {} }, formatDate: formatDateUtil, onNav(path) { diff --git a/admin-console/src/pages/device-detail/index.vue b/admin-console/src/pages/device-detail/index.vue index 2a8f013..8f86ade 100644 --- a/admin-console/src/pages/device-detail/index.vue +++ b/admin-console/src/pages/device-detail/index.vue @@ -61,11 +61,11 @@ {{ b.nickname || '-' }} - {{ formatDate(b.bound_at) }} - {{ b.unbound_at ? formatDate(b.unbound_at) : '-' }} + {{ formatDate(b.bind_time) }} + {{ b.unbind_time ? formatDate(b.unbind_time) : '-' }} - - {{ b.status === 1 ? '有效' : '已解绑' }} + + {{ b.bind_status === 1 ? '有效' : '已解绑' }} diff --git a/admin-console/src/pages/user-detail/index.vue b/admin-console/src/pages/user-detail/index.vue index 63f4907..6cc305f 100644 --- a/admin-console/src/pages/user-detail/index.vue +++ b/admin-console/src/pages/user-detail/index.vue @@ -67,7 +67,7 @@ - {{ formatDate(t.started_at) }} + {{ formatDate(t.start_time) }} {{ Math.floor((t.total_duration_ms || 0) / 60000) }}分钟 {{ t.device_id || '-' }} diff --git a/server/src/lib/utils.js b/server/src/lib/utils.js index 420b6b0..2f7c424 100644 --- a/server/src/lib/utils.js +++ b/server/src/lib/utils.js @@ -3,7 +3,9 @@ function toMysqlDate(value) { const d = new Date(value) if (Number.isNaN(d.getTime())) return null const pad = n => String(n).padStart(2, '0') - return d.getFullYear() + '-' + pad(d.getMonth() + 1) + '-' + pad(d.getDate()) + ' ' + pad(d.getHours()) + ':' + pad(d.getMinutes()) + ':' + pad(d.getSeconds()) + const offset = 8 * 60 + const local = new Date(d.getTime() + offset * 60 * 1000) + return local.getUTCFullYear() + '-' + pad(local.getUTCMonth() + 1) + '-' + pad(local.getUTCDate()) + ' ' + pad(local.getUTCHours()) + ':' + pad(local.getUTCMinutes()) + ':' + pad(local.getUTCSeconds()) } function formatDate(date) { diff --git a/server/src/routes/admin.js b/server/src/routes/admin.js index ff4b647..fef9cf1 100644 --- a/server/src/routes/admin.js +++ b/server/src/routes/admin.js @@ -78,8 +78,15 @@ function register(router) { const admin = await requireAdmin(ctx) if (!admin) return fail(1002, '未授权,请重新登录') const p = pageParams(ctx) - const total = await query('SELECT COUNT(*) AS total FROM devices', {}) - const records = await query('SELECT d.*, b.user_id AS bound_user, b.bind_time AS activated_at FROM devices d LEFT JOIN bindings b ON b.device_id = d.device_id AND b.bind_status = 1 ORDER BY d.created_at DESC' + limitClause(p.pageSize, p.offset), {}) + const keyword = (ctx.query.keyword || '').trim() + let where = '' + const params = {} + if (keyword) { + where = ' WHERE d.device_id LIKE :kw OR d.device_name LIKE :kw' + params.kw = '%' + keyword + '%' + } + const total = await query('SELECT COUNT(*) AS total FROM devices d' + where, params) + const records = await query('SELECT d.*, b.user_id AS bound_user, b.bind_time AS activated_at FROM devices d LEFT JOIN bindings b ON b.device_id = d.device_id AND b.bind_status = 1' + where + ' ORDER BY d.created_at DESC' + limitClause(p.pageSize, p.offset), params) return ok({ records, total: total[0].total }) }) @@ -239,7 +246,13 @@ function register(router) { 'SELECT s.*, u.nickname FROM subscriptions s LEFT JOIN users u ON u.user_id = s.user_id' + where + ' ORDER BY s.created_at DESC' + limitClause(p.pageSize, p.offset), params ) - return ok({ records, total: total[0].total }) + const statsRow = await query('SELECT ' + + 'SUM(CASE WHEN plan = \'monthly\' AND status = 1 AND expire_time > NOW() THEN 1 ELSE 0 END) AS monthly_count, ' + + 'SUM(CASE WHEN plan = \'yearly\' AND status = 1 AND expire_time > NOW() THEN 1 ELSE 0 END) AS yearly_count, ' + + 'SUM(CASE WHEN plan = \'trial\' AND status = 1 AND expire_time > NOW() THEN 1 ELSE 0 END) AS trial_count, ' + + 'COALESCE(SUM(CASE WHEN MONTH(start_time) = MONTH(NOW()) AND YEAR(start_time) = YEAR(NOW()) THEN amount ELSE 0 END), 0) AS monthly_revenue ' + + 'FROM subscriptions', {}) + return ok({ records, total: total[0].total, stats: statsRow[0] || {} }) }) router.post('/api/v1/admin/subscriptions', async ctx => {