const http = require('http') const BASE = { host: 'localhost', port: 5053, headers: { 'Content-Type': 'application/json; charset=utf-8', 'X-Mp-Timeassistant': 'mp_node_client_enc_test_xxx' } } const post = (path, obj) => new Promise((res, rej) => { const body = Buffer.from(JSON.stringify(obj), 'utf8') const req = http.request({ ...BASE, method: 'POST', path, headers: { ...BASE.headers, 'Content-Length': body.length } }, (r) => { let data = [] r.on('data', (c) => data.push(c)) r.on('end', () => { try { res({ status: r.statusCode, headers: r.headers, body: JSON.parse(Buffer.concat(data).toString('utf8')) }) } catch (e) { rej(e) } }) }) req.on('error', rej) req.write(body); req.end() }) const get = (path) => new Promise((res, rej) => { http.get({ ...BASE, path }, (r) => { let data = [] r.on('data', (c) => data.push(c)) r.on('end', () => { try { res({ status: r.statusCode, body: JSON.parse(Buffer.concat(data).toString('utf8')) }) } catch (e) { rej(e) } }) }).on('error', rej) }) ;(async () => { console.log('=== Step1: POST /cards via UTF-8 JSON (like WeChat mini-program) ===') const body = { title: '瑜伽垫上腰部运动', loopMode: 'loop_n_times', loopCount: 2, steps: [ { name: '热身动作', durationSec: 30, restSec: 10, type: 'action' }, { name: '平板支撑', durationSec: 45, restSec: 15, type: 'action' }, ], } const pr = await post('/api/mp_rep_clock/kits/rep_clock/cards', body) console.log('POST status=', pr.status) const c = pr.body.card console.log('card.id:', c.id) console.log('card.title (JSON.stringify):', JSON.stringify(c.title), ' chars:', Array.from(c.title).map((ch) => ch.charCodeAt(0).toString(16).padStart(4, '0')).join(' ')) console.log('card.loopTimes:', c.loopTimes, ' voice:', c.voice, ' ttsReady:', c.ttsReady) console.log('card.steps:') c.steps.forEach((s, i) => console.log(` [${i}] name=${JSON.stringify(s.name)} durationSec=${s.durationSec} restSec=${s.restSec} type=${s.type}`)) console.log('\n=== Step2: GET /cards ===') const gr = await get('/api/mp_rep_clock/kits/rep_clock/cards') const c0 = gr.body.cards[0] console.log('cards[0].title=', JSON.stringify(c0.title)) console.log('cards[0].ttsReady=', c0.ttsReady, ' loopTimes=', c0.loopTimes, ' voice=', c0.voice) c0.steps.forEach((s, i) => console.log(` [${i}] name=${JSON.stringify(s.name)} restSec=${s.restSec}`)) console.log('\n=== Step3: HEX dump directly from DB to prove storage ===') const Database = require('better-sqlite3') const path = require('path') const db = new Database(path.join(process.cwd(), 'data', 'mp_rep_clock.db')) const row = db.prepare(`SELECT id, hex(title) ht, hex(steps_json) hsj FROM rc_cards WHERE id=? ORDER BY rowid DESC LIMIT 1`).get(c.id) console.log('DB hex(title):', row.ht.substring(0, 200)) const titleFromDb = Buffer.from(row.ht, 'hex').toString('utf8') console.log('DB decoded title:', JSON.stringify(titleFromDb)) const stepsParsed = JSON.parse(Buffer.from(row.hsj, 'hex').toString('utf8')) stepsParsed.forEach((s, i) => console.log(` DB steps[${i}] name=${JSON.stringify(s.name)} restSec=${s.restSec}`)) console.log('\n=== ALL ENCODING CHECKS PASSED if title decoded correctly above ===') })().catch((e) => { console.error('ERR', e); process.exit(1) })