增加异步日志和库存展示
This commit is contained in:
+94
-11
@@ -107,6 +107,7 @@ type PrizeInfo = {
|
||||
left_num?: number
|
||||
status?: number
|
||||
percent?: string
|
||||
is_show_num?: number
|
||||
img?: string
|
||||
}
|
||||
|
||||
@@ -208,9 +209,77 @@ function priceOf(row?: PrizeInfo): number {
|
||||
return row.new_score || row.score || 0
|
||||
}
|
||||
|
||||
function leftOf(row?: PrizeInfo): number {
|
||||
if (!row) return 0
|
||||
return row.left_num || 0
|
||||
type InventoryInfo = {
|
||||
left?: number
|
||||
total?: number
|
||||
percent?: string
|
||||
estimated: boolean
|
||||
}
|
||||
|
||||
function inventoryOf(row?: PrizeInfo): InventoryInfo {
|
||||
if (!row) return { estimated: false }
|
||||
const total = Number(row.num || 0)
|
||||
const percent = normalizePercent(row.percent)
|
||||
const rawLeft = Number(row.left_num || 0)
|
||||
if (rawLeft > 0 || percent === '0%') {
|
||||
return {
|
||||
left: rawLeft,
|
||||
total: total > 0 ? total : undefined,
|
||||
percent,
|
||||
estimated: false,
|
||||
}
|
||||
}
|
||||
if (total > 0 && percent) {
|
||||
const percentValue = Number(percent.replace('%', ''))
|
||||
if (Number.isFinite(percentValue)) {
|
||||
return {
|
||||
left: Math.floor((total * percentValue) / 100),
|
||||
total,
|
||||
percent,
|
||||
estimated: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
total: total > 0 ? total : undefined,
|
||||
percent,
|
||||
estimated: false,
|
||||
}
|
||||
}
|
||||
|
||||
function normalizePercent(value?: string): string | undefined {
|
||||
const text = String(value || '').trim()
|
||||
if (!text) return undefined
|
||||
const numeric = Number(text.replace('%', ''))
|
||||
if (!Number.isFinite(numeric)) return text
|
||||
return `${numeric}%`
|
||||
}
|
||||
|
||||
function inventoryText(row?: PrizeInfo): string {
|
||||
const info = inventoryOf(row)
|
||||
const left = info.left === undefined ? '-' : `${info.estimated ? '约 ' : ''}${info.left}`
|
||||
const total = info.total === undefined ? '-' : String(info.total)
|
||||
return `剩余 ${left} / 总量 ${total}${info.percent ? ` · ${info.percent}` : ''}`
|
||||
}
|
||||
|
||||
function summarizeInventory(items: PrizeInfo[]): string {
|
||||
let left = 0
|
||||
let total = 0
|
||||
let leftKnown = 0
|
||||
let totalKnown = 0
|
||||
items.forEach((item) => {
|
||||
const info = inventoryOf(item)
|
||||
if (info.left !== undefined) {
|
||||
left += info.left
|
||||
leftKnown += 1
|
||||
}
|
||||
if (info.total !== undefined) {
|
||||
total += info.total
|
||||
totalKnown += 1
|
||||
}
|
||||
})
|
||||
if (leftKnown === 0 && totalKnown === 0) return '库存未公开'
|
||||
return `剩余 ${leftKnown ? left : '-'} / 总量 ${totalKnown ? total : '-'}`
|
||||
}
|
||||
|
||||
function statusTag(status?: number, error?: string): ReactNode {
|
||||
@@ -550,6 +619,7 @@ export default function Dashboard() {
|
||||
String(priceOf(item)).includes(keyword),
|
||||
)
|
||||
}, [prizes, productSearch])
|
||||
const inventorySummary = useMemo(() => summarizeInventory(filteredPrizes), [filteredPrizes])
|
||||
|
||||
const config = () => ({
|
||||
...pickConfig(form.getFieldsValue(true)),
|
||||
@@ -911,10 +981,9 @@ export default function Dashboard() {
|
||||
|
||||
const prizeColumns: ColumnsType<PrizeInfo> = useMemo(
|
||||
() => [
|
||||
{ title: 'num', dataIndex: 'id', width: 92 },
|
||||
{ title: 'name', dataIndex: 'name', minWidth: 220, ellipsis: true },
|
||||
{ title: '剩余', width: 84, render: (_, row) => leftOf(row) || '-' },
|
||||
{ title: '总量', dataIndex: 'num', width: 84 },
|
||||
{ title: 'PID', dataIndex: 'id', width: 92 },
|
||||
{ title: '名称', dataIndex: 'name', minWidth: 220, ellipsis: true },
|
||||
{ title: '库存', minWidth: 190, render: (_, row) => inventoryText(row) },
|
||||
{ title: '价格', width: 84, render: (_, row) => priceOf(row) || '-' },
|
||||
],
|
||||
[],
|
||||
@@ -1065,6 +1134,7 @@ export default function Dashboard() {
|
||||
|
||||
<div className="inventory-line">
|
||||
<span>商品缓存 {filteredPrizes.length} 个</span>
|
||||
<span>{inventorySummary}</span>
|
||||
<span>{productListUpdatedAt ? `更新 ${productListUpdatedAt}` : '未缓存'}</span>
|
||||
</div>
|
||||
|
||||
@@ -1091,9 +1161,9 @@ export default function Dashboard() {
|
||||
</div>
|
||||
<div className="product-meta">
|
||||
<strong>{item.name}</strong>
|
||||
<div>
|
||||
<div className="product-tags">
|
||||
<Tag color="gold">{priceOf(item)} 积分</Tag>
|
||||
<Tag color="green">库存 {leftOf(item) || '-'}</Tag>
|
||||
<InventoryTags prize={item} compact />
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
@@ -1425,18 +1495,31 @@ export default function Dashboard() {
|
||||
)
|
||||
}
|
||||
|
||||
function InventoryTags({ prize, compact = false }: { prize?: PrizeInfo; compact?: boolean }) {
|
||||
const info = inventoryOf(prize)
|
||||
const left = info.left === undefined ? '-' : `${info.estimated ? '约 ' : ''}${info.left}`
|
||||
const total = info.total === undefined ? '-' : String(info.total)
|
||||
return (
|
||||
<span className={`inventory-tags${compact ? ' compact' : ''}`}>
|
||||
<Tag color={info.left === 0 ? 'red' : 'green'}>剩余 {left}</Tag>
|
||||
<Tag>总量 {total}</Tag>
|
||||
{info.percent ? <Tag color="blue">{info.percent}</Tag> : null}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
function CurrentProduct({ prize }: { prize?: PrizeInfo }) {
|
||||
const name = prize?.name || '未从 CK 列表选择'
|
||||
return (
|
||||
<div className="current-product">
|
||||
<span>当前商品</span>
|
||||
<strong>{name}</strong>
|
||||
<div>
|
||||
<div className="current-product-tags">
|
||||
{prize ? (
|
||||
<>
|
||||
<Tag color="gold">{priceOf(prize)} 积分</Tag>
|
||||
<Tag color="green">库存 {leftOf(prize) || '-'}</Tag>
|
||||
<Tag>PID {prize.id}</Tag>
|
||||
<InventoryTags prize={prize} />
|
||||
</>
|
||||
) : (
|
||||
<Tag>CK 商品源</Tag>
|
||||
|
||||
@@ -73,8 +73,32 @@ body {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.current-product-tags,
|
||||
.product-tags,
|
||||
.inventory-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.inventory-tags {
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
.inventory-tags.compact {
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.inventory-tags .ant-tag,
|
||||
.product-tags .ant-tag,
|
||||
.current-product-tags .ant-tag {
|
||||
margin-inline-end: 0;
|
||||
}
|
||||
|
||||
.inventory-line {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
|
||||
+101
-2
@@ -7,6 +7,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/wailsapp/wails/v2/pkg/runtime"
|
||||
@@ -20,6 +21,7 @@ const (
|
||||
eventMonitorResult = "gui:monitor-result"
|
||||
eventMonitorState = "gui:monitor-state"
|
||||
maxLogEntries = 500
|
||||
logQueueSize = 2048
|
||||
)
|
||||
|
||||
type App struct {
|
||||
@@ -28,6 +30,12 @@ type App struct {
|
||||
logMu sync.Mutex
|
||||
logs []LogEntry
|
||||
|
||||
logCh chan LogEntry
|
||||
logStop chan struct{}
|
||||
logWorkerOnce sync.Once
|
||||
logStopOnce sync.Once
|
||||
droppedLogs atomic.Int64
|
||||
|
||||
runMu sync.Mutex
|
||||
monitorCancel context.CancelFunc
|
||||
monitorRunning bool
|
||||
@@ -111,16 +119,21 @@ type cookieLine struct {
|
||||
}
|
||||
|
||||
func NewApp() *App {
|
||||
return &App{}
|
||||
return &App{
|
||||
logCh: make(chan LogEntry, logQueueSize),
|
||||
logStop: make(chan struct{}),
|
||||
}
|
||||
}
|
||||
|
||||
func (a *App) Startup(ctx context.Context) {
|
||||
a.ctx = ctx
|
||||
a.startLogWorker()
|
||||
a.addLog("info", "GUI 已启动")
|
||||
}
|
||||
|
||||
func (a *App) Shutdown(ctx context.Context) {
|
||||
a.StopMonitor()
|
||||
a.stopLogWorker()
|
||||
}
|
||||
|
||||
func (a *App) DefaultConfig() Config {
|
||||
@@ -192,7 +205,8 @@ func (a *App) ListPrizes(cfg Config) (PrizeListResult, error) {
|
||||
a.addLog("error", "查询奖品失败: %v", err)
|
||||
return PrizeListResult{}, err
|
||||
}
|
||||
a.addLog("info", "查询奖品完成: uid=%d sid=%d count=%d", accounts[0].UID, cfg.SID, len(resp.Prizes))
|
||||
left, total, leftKnown, totalKnown := prizeInventorySummary(resp.Prizes)
|
||||
a.addLog("info", "查询商品完成: uid=%d sid=%d status=%d count=%d 剩余=%d/%d项 总量=%d/%d项 msg=%s", accounts[0].UID, cfg.SID, resp.Status, len(resp.Prizes), left, leftKnown, total, totalKnown, resp.Msg)
|
||||
return PrizeListResult{
|
||||
UID: accounts[0].UID,
|
||||
Status: resp.Status,
|
||||
@@ -423,6 +437,77 @@ func (a *App) addLog(level, format string, args ...any) {
|
||||
Level: level,
|
||||
Message: fmt.Sprintf(format, args...),
|
||||
}
|
||||
if a.logCh == nil {
|
||||
a.writeLogEntry(entry)
|
||||
return
|
||||
}
|
||||
select {
|
||||
case a.logCh <- entry:
|
||||
default:
|
||||
a.droppedLogs.Add(1)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *App) startLogWorker() {
|
||||
if a.logCh == nil {
|
||||
a.logCh = make(chan LogEntry, logQueueSize)
|
||||
}
|
||||
if a.logStop == nil {
|
||||
a.logStop = make(chan struct{})
|
||||
}
|
||||
a.logWorkerOnce.Do(func() {
|
||||
go a.logWorker()
|
||||
})
|
||||
}
|
||||
|
||||
func (a *App) stopLogWorker() {
|
||||
if a.logStop == nil {
|
||||
return
|
||||
}
|
||||
a.logStopOnce.Do(func() {
|
||||
close(a.logStop)
|
||||
})
|
||||
}
|
||||
|
||||
func (a *App) logWorker() {
|
||||
for {
|
||||
select {
|
||||
case entry := <-a.logCh:
|
||||
a.flushDroppedLogs()
|
||||
a.writeLogEntry(entry)
|
||||
case <-a.logStop:
|
||||
a.drainLogQueue()
|
||||
a.flushDroppedLogs()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (a *App) drainLogQueue() {
|
||||
for {
|
||||
select {
|
||||
case entry := <-a.logCh:
|
||||
a.flushDroppedLogs()
|
||||
a.writeLogEntry(entry)
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (a *App) flushDroppedLogs() {
|
||||
dropped := a.droppedLogs.Swap(0)
|
||||
if dropped <= 0 {
|
||||
return
|
||||
}
|
||||
a.writeLogEntry(LogEntry{
|
||||
Time: time.Now().Format("15:04:05.000"),
|
||||
Level: "warn",
|
||||
Message: fmt.Sprintf("日志队列繁忙,已异步丢弃 %d 条日志", dropped),
|
||||
})
|
||||
}
|
||||
|
||||
func (a *App) writeLogEntry(entry LogEntry) {
|
||||
a.logMu.Lock()
|
||||
a.logs = append(a.logs, entry)
|
||||
if len(a.logs) > maxLogEntries {
|
||||
@@ -643,3 +728,17 @@ func errorString(err error) string {
|
||||
}
|
||||
return err.Error()
|
||||
}
|
||||
|
||||
func prizeInventorySummary(prizes []huya.PrizeInfo) (left, total int64, leftKnown, totalKnown int) {
|
||||
for _, prize := range prizes {
|
||||
if prize.Num > 0 {
|
||||
total += prize.Num
|
||||
totalKnown++
|
||||
}
|
||||
if itemLeft, ok := prize.InventoryLeft(); ok {
|
||||
left += itemLeft
|
||||
leftKnown++
|
||||
}
|
||||
}
|
||||
return left, total, leftKnown, totalKnown
|
||||
}
|
||||
|
||||
@@ -77,3 +77,24 @@ func TestParseStartTimeAcceptsClockOnly(t *testing.T) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestAddLogDoesNotBlockWhenQueueIsFull(t *testing.T) {
|
||||
app := &App{
|
||||
logCh: make(chan LogEntry),
|
||||
logStop: make(chan struct{}),
|
||||
}
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
app.addLog("debug", "test")
|
||||
close(done)
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-done:
|
||||
case <-time.After(100 * time.Millisecond):
|
||||
t.Fatal("addLog blocked when log queue was full")
|
||||
}
|
||||
if dropped := app.droppedLogs.Load(); dropped != 1 {
|
||||
t.Fatalf("droppedLogs = %d, want 1", dropped)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -261,18 +261,26 @@ func (p PrizeInfo) Price() int64 {
|
||||
}
|
||||
|
||||
func (p PrizeInfo) EstimatedLeft() int64 {
|
||||
left, ok := p.InventoryLeft()
|
||||
if ok {
|
||||
return left
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (p PrizeInfo) InventoryLeft() (int64, bool) {
|
||||
if p.LeftNum > 0 {
|
||||
return p.LeftNum
|
||||
return p.LeftNum, true
|
||||
}
|
||||
text := strings.TrimSuffix(strings.TrimSpace(p.Percent), "%")
|
||||
if text == "" || p.Num <= 0 {
|
||||
return 0
|
||||
return 0, false
|
||||
}
|
||||
percent, err := strconv.ParseFloat(text, 64)
|
||||
if err != nil {
|
||||
return 0
|
||||
return 0, false
|
||||
}
|
||||
return int64(math.Floor(float64(p.Num)*percent/100.0 + 1e-9))
|
||||
return int64(math.Floor(float64(p.Num)*percent/100.0 + 1e-9)), true
|
||||
}
|
||||
|
||||
type PrizeTag struct {
|
||||
@@ -579,3 +587,35 @@ func (r *ScoreExchangePrizeResp) ReadFrom(rd *taf.Reader) error {
|
||||
func (r ScoreExchangePrizeResp) Success() bool {
|
||||
return r.Status == 200 && (r.Msg == "" || strings.Contains(r.Msg, "成功"))
|
||||
}
|
||||
|
||||
func prizeListInventorySummary(prizes []PrizeInfo) (left, total int64, leftKnown, totalKnown int) {
|
||||
for _, prize := range prizes {
|
||||
if prize.Num > 0 {
|
||||
total += prize.Num
|
||||
totalKnown++
|
||||
}
|
||||
if itemLeft, ok := prize.InventoryLeft(); ok {
|
||||
left += itemLeft
|
||||
leftKnown++
|
||||
}
|
||||
}
|
||||
return left, total, leftKnown, totalKnown
|
||||
}
|
||||
|
||||
func exchangeResponseMessage(resp *ScoreExchangePrizeResp) string {
|
||||
if resp == nil {
|
||||
return ""
|
||||
}
|
||||
for _, text := range []string{
|
||||
resp.Msg,
|
||||
resp.ActPreCondition.Tip,
|
||||
resp.ActPreCondition.ButtonDesc,
|
||||
resp.ExchangeInfo.Desc,
|
||||
resp.OrderID,
|
||||
} {
|
||||
if strings.TrimSpace(text) != "" {
|
||||
return strings.TrimSpace(text)
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ func (c *HTTPClient) CallRPC(ctx context.Context, service, method string, reqStr
|
||||
httpReq = httpReq.WithContext(ctx)
|
||||
}
|
||||
|
||||
c.logf("[HTTP] POST %s.%s body=%dB", service, method, len(body))
|
||||
c.logf("[HTTP] 请求 %s.%s", service, method)
|
||||
httpResp, err := client.Do(httpReq)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -141,6 +141,9 @@ func (c *HTTPClient) QueryUserScore(ctx context.Context, uid int64, cookie strin
|
||||
req := &GetUserScoreReq{User: c.buildUser(uid, cookie, ActivityWebUA), SID: sid}
|
||||
var resp GetUserScoreResp
|
||||
_, err := c.CallRPC(ctx, ServantWebActUI, FuncGetUserScore, req, &resp, CallOptions{UID: uid, Cookie: cookie, RequestID: 2})
|
||||
if err == nil {
|
||||
c.logf("[HTTP] 积分已解码 uid=%d sid=%d status=%d 可用=%d msg=%s", uid, sid, resp.Status, resp.AvailableScore(), resp.Msg)
|
||||
}
|
||||
return &resp, err
|
||||
}
|
||||
|
||||
@@ -148,6 +151,10 @@ func (c *HTTPClient) GetActPrizeList(ctx context.Context, uid int64, cookie stri
|
||||
req := &GetActPrizeListReq{User: c.buildUser(uid, cookie, ActivityWebUA), SID: sid}
|
||||
var resp GetActPrizeListResp
|
||||
_, err := c.CallRPC(ctx, ServantWebActUI, FuncPrizeList, req, &resp, CallOptions{UID: uid, Cookie: cookie, RequestID: 1})
|
||||
if err == nil {
|
||||
left, total, leftKnown, totalKnown := prizeListInventorySummary(resp.Prizes)
|
||||
c.logf("[HTTP] 商品列表已解码 uid=%d sid=%d status=%d count=%d 剩余=%d/%d项 总量=%d/%d项 msg=%s", uid, sid, resp.Status, len(resp.Prizes), left, leftKnown, total, totalKnown, resp.Msg)
|
||||
}
|
||||
return &resp, err
|
||||
}
|
||||
|
||||
@@ -157,6 +164,9 @@ func (c *HTTPClient) GetUserPrizeRecords(ctx context.Context, uid int64, cookie
|
||||
req := &GetUserPrizeRecordsReq{User: user, SID: sid}
|
||||
var resp GetUserPrizeRecordsResp
|
||||
_, err := c.CallRPC(ctx, ServantWebActUI, FuncPrizeRecords, req, &resp, CallOptions{UID: uid, Cookie: cookie, RequestID: 6})
|
||||
if err == nil {
|
||||
c.logf("[HTTP] 兑换记录已解码 uid=%d sid=%d status=%d count=%d msg=%s", uid, sid, resp.Status, len(resp.Records), resp.Msg)
|
||||
}
|
||||
return &resp, err
|
||||
}
|
||||
|
||||
@@ -170,5 +180,8 @@ func (c *HTTPClient) ScoreExchangePrize(ctx context.Context, uid int64, cookie s
|
||||
}
|
||||
var resp ScoreExchangePrizeResp
|
||||
_, err := c.CallRPC(ctx, ServantWebActUI, FuncExchangePrize, req, &resp, CallOptions{UID: uid, Cookie: cookie, RequestID: 1})
|
||||
if err == nil {
|
||||
c.logf("[HTTP] 兑换结果已解码 uid=%d sid=%d pid=%d status=%d order=%s msg=%s", uid, sid, pid, resp.Status, resp.OrderID, exchangeResponseMessage(&resp))
|
||||
}
|
||||
return &resp, err
|
||||
}
|
||||
|
||||
@@ -238,7 +238,7 @@ func (s *WSSSession) readLoop() {
|
||||
case WSSCmdHeartBeatAck, WSSCmdHeartBeatRsp:
|
||||
// 心跳响应无需处理。
|
||||
case WSSCmdRegisterGroupRsp, WSSCmdVerifyCookieRsp, WSSCmdUpdateUserInfoRsp, WSSCmdUpdateUserExpsRsp:
|
||||
s.client.logf("[WSS] 收到控制响应 cmd=%d data=%dB", cmd.CmdType, len(cmd.Data))
|
||||
// 控制类响应频率高且没有业务字段,避免刷屏。
|
||||
default:
|
||||
s.client.logf("[WSS] 收到 cmd=%d data=%dB requestID=%d", cmd.CmdType, len(cmd.Data), cmd.RequestID)
|
||||
}
|
||||
@@ -456,7 +456,7 @@ func (s *WSSSession) callWUPWithRequestIDAndTrace(ctx context.Context, service,
|
||||
s.pendingMu.Lock()
|
||||
s.pending[requestID] = ch
|
||||
s.pendingMu.Unlock()
|
||||
s.client.logf("[WSS] WUP %s.%s requestID=%d body=%dB", service, method, requestID, len(data))
|
||||
s.client.logf("[WSS] 请求 %s.%s requestID=%d", service, method, requestID)
|
||||
if err := s.writePayload(ctx, payload); err != nil {
|
||||
s.removePending(requestID)
|
||||
return nil, err
|
||||
@@ -509,6 +509,9 @@ func (c *WSSClient) QueryUserScore(ctx context.Context, uid int64, cookie string
|
||||
req := &GetUserScoreReq{User: c.buildUser(uid, cookie), SID: sid}
|
||||
var resp GetUserScoreResp
|
||||
_, err = session.callRPC(ctx, ServantWebActUI, FuncGetUserScore, req, &resp)
|
||||
if err == nil {
|
||||
c.logf("[WSS] 积分已解码 uid=%d sid=%d status=%d 可用=%d msg=%s", uid, sid, resp.Status, resp.AvailableScore(), resp.Msg)
|
||||
}
|
||||
return &resp, err
|
||||
}
|
||||
|
||||
@@ -520,6 +523,10 @@ func (c *WSSClient) GetActPrizeList(ctx context.Context, uid int64, cookie strin
|
||||
req := &GetActPrizeListReq{User: c.buildUser(uid, cookie), SID: sid}
|
||||
var resp GetActPrizeListResp
|
||||
_, err = session.callRPC(ctx, ServantWebActUI, FuncPrizeList, req, &resp)
|
||||
if err == nil {
|
||||
left, total, leftKnown, totalKnown := prizeListInventorySummary(resp.Prizes)
|
||||
c.logf("[WSS] 商品列表已解码 uid=%d sid=%d status=%d count=%d 剩余=%d/%d项 总量=%d/%d项 msg=%s", uid, sid, resp.Status, len(resp.Prizes), left, leftKnown, total, totalKnown, resp.Msg)
|
||||
}
|
||||
return &resp, err
|
||||
}
|
||||
|
||||
@@ -531,6 +538,9 @@ func (c *WSSClient) GetUserPrizeRecords(ctx context.Context, uid int64, cookie s
|
||||
req := &GetUserPrizeRecordsReq{User: c.buildUser(uid, cookie), SID: sid}
|
||||
var resp GetUserPrizeRecordsResp
|
||||
_, err = session.callRPC(ctx, ServantWebActUI, FuncPrizeRecords, req, &resp)
|
||||
if err == nil {
|
||||
c.logf("[WSS] 兑换记录已解码 uid=%d sid=%d status=%d count=%d msg=%s", uid, sid, resp.Status, len(resp.Records), resp.Msg)
|
||||
}
|
||||
return &resp, err
|
||||
}
|
||||
|
||||
@@ -548,6 +558,9 @@ func (c *WSSClient) ScoreExchangePrize(ctx context.Context, uid int64, cookie st
|
||||
}
|
||||
var resp ScoreExchangePrizeResp
|
||||
_, err = session.callRPC(ctx, ServantWebActUI, FuncExchangePrize, req, &resp)
|
||||
if err == nil {
|
||||
c.logf("[WSS] 兑换结果已解码 uid=%d sid=%d pid=%d status=%d order=%s msg=%s", uid, sid, pid, resp.Status, resp.OrderID, exchangeResponseMessage(&resp))
|
||||
}
|
||||
return &resp, err
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user