Files
hejiu/node_modules/HaveADrink/README.md
T
cg 860136bceb feat(theme): 实现日夜主题自动切换功能
- 添加日夜主题CSS变量定义,支持琥珀夜光和暖白琥珀两种风格
- 实现主题切换逻辑,根据时间自动切换白天(light)和夜间(dark)主题
- 在App.vue中集成主题初始化和token恢复功能
- 更新全局样式类应用主题颜色变量,包括卡片、文本、边框等
- 创建主题混入(mixin)供各页面使用,确保主题同步更新
- 实现导航栏和TabBar主题动态切换,提升用户体验
- 添加API服务层封装HaveADrink SDK,统一处理认证和请求
- 优化DrinkCard组件显示饮酒感受信息,丰富打卡记录展示
- 更新项目依赖配置,集成新的API客户端库
2026-07-16 22:47:38 +08:00

1116 lines
23 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 使用说明
* 喝酒了么 - 后端接口 API
* 小程序:喝酒了么(uni-app 微信小程序)
* 基础URL: /api/v1
*
* 主要功能模块:
* 1. 用户模块 - 微信登录、用户信息管理
* 2. 打卡记录模块 - 饮酒记录创建、查询、日历数据
* 3. 照片上传模块 - 单张/批量照片上传
* 4. 统计模块 - 用户统计、月度统计、酒类分布
* 5. 成就模块 - 成就列表和进度
* 6. 社交模块 - 朋友圈动态、点赞
**版本:** v1.0.2
## 安装
```
npm install --registry="https://npm.wash-painting.cn" HaveADrink
```
## 用法
用户需实现普通 http 请求函数和文件上传函数,返回值均为 json 对象
**示例**
```javascript
// reslove 和 reject 必须返回 json 对象
const http_request_function = (url, method, headers, body) => {
return new Promise((reslove, reject)=>{});
}
const upload_function = (url, method, headers, data) => {
return new Promise((reslove, reject)=>{});
}
const client = new HaveADrink(host, http_request_function, upload_function);
```
## 接口文档
### 微信登录, 获取openid、unionid、token
<font color="green">POST</font> `/api/have_a_drink/v1/auth/wechat/login`
#### 请求参数
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
|code|`string`|required| 登录时获取的 code, 可通过 wx.login 获取|
|nickName|`string`|| 用户昵称|
|avatarUrl|`string`|| 头像URL|
#### 返回值
|名称|类型|说明|
|:-|:-:|:-|
|token|`string`| JWT Token<br>|
|user|`User`| 用户信息<br>|
|isNew|`boolean`| 是否新用户<br>|
|session_key|`string`| 会话密钥<br>|
|open_id|`string`| 用户唯一标识<br>|
|union_id|`string`| 用户在开放平台的唯一标识符,若当前小程序已绑定到微信开放平台账号下会返回,详见 UnionID 机制说明。<br>|
|errcode|`number`| 错误码<br>|
|errmsg|`string`| 错误信息<br>|
|refresh_token|`string`| 刷新token<br>|
**User**
|名称|类型|说明|
|:-|:-|:-|
|id|`string\|number`| 用户ID|
|nickname|`string`| 用户昵称|
|avatar|`string`| 头像URL|
|joinedAt|`string`| 加入时间|
|preferences|`UserPreferences`| 用户偏好|
**UserPreferences**
|名称|类型|说明|
|:-|:-|:-|
|favoriteCategories|`Array<Category>`| 偏好酒类ID列表|
|frequency|`Frequency`| 饮酒频率|
```javascript
const req = new WechatLoginReq()
client.WechatLogin(req).then(...).catch(...)
```
### 获取微信手机号
<font color="green">POST</font> `/api/have_a_drink/v1/auth/wechat/get_phone_number`
#### 请求参数
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
|code|`string`|required| 手机号获取凭证|
#### 返回值
|名称|类型|说明|
|:-|:-:|:-|
|errcode|`number`| 错误码<br>|
|errmsg|`string`| 错误信息<br>|
|token|`string`| token:api使用<br>|
|expires_in|`number`| token 超时时间,单位(秒)<br>|
|refresh_token|`string`| refresh_token:刷新token<br>|
```javascript
const req = new WechatGetPhoneNumberReq()
client.WechatGetPhoneNumber(req).then(...).catch(...)
```
### 刷新 token 接口
<font color="green">POST</font> `/api/have_a_drink/v1/auth/refresh_token`
#### 请求参数
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
|refresh_token|`string`|required| 签发 token 时生成的 refresh_token|
#### 返回值
|名称|类型|说明|
|:-|:-:|:-|
|token|`string`| 生成的新token<br>|
|expire_in|`number`| token 超时时间,单位(秒)<br>|
|refresh_token|`string`| refresh_token:刷新token<br>|
```javascript
const req = new RefreshTokenReq()
client.RefreshToken(req).then(...).catch(...)
```
### 获取成就列表
<font color="green">GET</font> `/api/have_a_drink/v1/achievements/list`
#### 请求参数
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
#### 返回值
|名称|类型|说明|
|:-|:-:|:-|
|data|`AchievementsData`| 成就列表数据<br>|
**AchievementsData**
|名称|类型|说明|
|:-|:-|:-|
|achievements|`Array<Achievement>`| 成就列表|
**Achievement**
|名称|类型|说明|
|:-|:-|:-|
|id|`string`| 成就ID|
|name|`string`| 成就名称|
|desc|`string`| 成就描述|
|icon|`string`| 成就图标|
|unlocked|`boolean`| 是否已解锁|
|unlockedAt|`string`| 解锁时间|
|condition|`AchievementCondition`| 成就条件|
|progress|`number`| 进度(0-1|
**AchievementCondition**
|名称|类型|说明|
|:-|:-|:-|
|type|`AchievementConditionType`| 条件类型|
|value|`number`| 目标值|
**AchievementConditionType**
|名称|值|类型|说明|
|:-|:-:|:-|:-|
|TotalRecords|"total_records"|`AchievementConditionType`|总记录数|
|TotalStandardCups|"total_standard_cups"|`AchievementConditionType`|累计标准杯|
|StreakDays|"streak_days"|`AchievementConditionType`|连续打卡天数|
|CategoryRecords|"category_records"|`AchievementConditionType`|某酒类打卡次数|
|CategoryVariety|"category_variety"|`AchievementConditionType`|尝试酒类品种数|
```javascript
const req = new GetAchievementsReq()
client.GetAchievements(req).then(...).catch(...)
```
### 获取朋友圈动态
<font color="green">GET</font> `/api/have_a_drink/v1/communication/feed`
#### 请求参数
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
|lastId|`string\|number`|| 游标分页,上一页最后一条ID|
#### 返回值
|名称|类型|说明|
|:-|:-:|:-|
|data|`FeedPageData`| 朋友圈动态分页数据<br>|
**FeedPageData**
|名称|类型|说明|
|:-|:-|:-|
|list|`Array<FeedItem>`| 动态列表|
**FeedItem**
|名称|类型|说明|
|:-|:-|:-|
|id|`string\|number`| 记录ID|
|user|`FeedUser`| 用户信息|
|date|`string`| 日期|
|mode|`Mode`| 打卡模式|
|drinks|`Array<DrinkItem>`| 酒水列表|
|food|`FoodInfo`| 配餐信息|
|feeling|`Feeling`| 感受|
|photos|`Array<string>`| 照片URL数组|
|standardCupsTotal|`number`| 标准杯总数|
|quote|`string`| 酒言酒语|
|likeCount|`number`| 点赞数|
|commentCount|`number`| 评论数|
|liked|`boolean`| 当前用户是否已点赞|
|createdAt|`string`| 创建时间|
**FeedUser**
|名称|类型|说明|
|:-|:-|:-|
|id|`string\|number`| 用户ID|
|nickname|`string`| 用户昵称|
|avatar|`string`| 头像URL|
**DrinkItem**
|名称|类型|说明|
|:-|:-|:-|
|category|`Category`| 酒类分类ID|
|brand|`string`| 品牌名称|
|product|`string`| 产品名|
|amount|`number`| 饮用量数值|
|unit|`Unit`| 单位|
|degree|`number`| 酒精度数(%)|
|standardCups|`number`| 标准杯数(前端计算,后端应校验)|
**Category**
|名称|值|类型|说明|
|:-|:-:|:-|:-|
|Baijiu|"baijiu"|`Category`|白酒|
|Beer|"beer"|`Category`|啤酒|
|Wine|"wine"|`Category`|红酒|
|Whisky|"whisky"|`Category`|洋酒|
|Huangjiu|"huangjiu"|`Category`|黄酒|
|Sake|"sake"|`Category`|清酒|
|Fruit|"fruit"|`Category`|果酒|
|Cocktail|"cocktail"|`Category`|调酒|
|Other|"other"|`Category`|其他|
**Unit**
|名称|值|类型|说明|
|:-|:-:|:-|:-|
|Ml|"ml"|`Unit`|毫升|
|Liang|"liang"|`Unit`|两|
|Bottle|"bottle"|`Unit`|瓶|
|Cup|"cup"|`Unit`|杯|
|Can|"can"|`Unit`|听|
|Shot|"shot"|`Unit`|shot|
**FoodInfo**
|名称|类型|说明|
|:-|:-|:-|
|category|`FoodCategory`| 配餐分类ID|
|name|`string`| 具体菜名|
**FoodCategory**
|名称|值|类型|说明|
|:-|:-:|:-|:-|
|Hotpot|"hotpot"|`FoodCategory`|火锅|
|Bbq|"bbq"|`FoodCategory`|烧烤|
|Stirfry|"stirfry"|`FoodCategory`|炒菜|
|Seafood|"seafood"|`FoodCategory`|海鲜|
|Japanese|"japanese"|`FoodCategory`|日料|
|Western|"western"|`FoodCategory`|西餐|
|Snack|"snack"|`FoodCategory`|小吃卤味|
|Junk|"junk"|`FoodCategory`|零食|
|None|"none"|`FoodCategory`|无配餐|
```javascript
const req = new GetFeedReq()
client.GetFeed(req).then(...).catch(...)
```
### 点赞
<font color="green">POST</font> `/api/have_a_drink/v1/communication/records/like`
#### 请求参数
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
|id|`string\|number`|required| 记录ID|
#### 返回值
|名称|类型|说明|
|:-|:-:|:-|
```javascript
const req = new LikeRecordReq()
client.LikeRecord(req).then(...).catch(...)
```
### 取消点赞
<font color="green">POST</font> `/api/have_a_drink/v1/communication/records/unlike`
#### 请求参数
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
|id|`string\|number`|required| 记录ID|
#### 返回值
|名称|类型|说明|
|:-|:-:|:-|
```javascript
const req = new LikeRecordReq()
client.UnlikeRecord(req).then(...).catch(...)
```
### 上传照片
<font color="green">POST</font> `/api/have_a_drink/v1/photo/upload/photo`
#### 请求参数
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
|url|`string`|required| 图片Url|
|recordId|`string\|number`|required| 关联记录ID|
#### 返回值
|名称|类型|说明|
|:-|:-:|:-|
```javascript
const req = new UploadPhotoReq()
client.UploadPhoto(req).then(...).catch(...)
```
### 批量上传照片
<font color="green">POST</font> `/api/have_a_drink/v1/photo/upload/photos`
#### 请求参数
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
|urls|`Array<string>`|required,max=9| 图片URL数组(最多9张)|
|recordId|`string\|number`|required| 关联记录ID|
#### 返回值
|名称|类型|说明|
|:-|:-:|:-|
```javascript
const req = new UploadPhotosReq()
client.UploadPhotos(req).then(...).catch(...)
```
### 创建打卡记录
<font color="green">POST</font> `/api/have_a_drink/v1/record/records`
#### 请求参数
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
|date|`string`|required| 日期 YYYY-MM-DD|
|mode|`Mode`|今日喝了: Mode.Drank = "drank"<br>今日未喝: Mode.Abstain = "abstain"| 打卡模式|
|drinks|`Array<DrinkItem>`|| 酒水列表(mode=abstain时为空数组)|
|food|`FoodInfo`|| 配餐信息|
|feeling|`Feeling`|微醺: Feeling.Tipsy = "tipsy"<br>到位: Feeling.Buzzed = "buzzed"<br>醉了: Feeling.Drunk = "drunk"<br>断片: Feeling.Blackout = "blackout"| 感受ID|
|photos|`Array<string>`|max=9| 照片URL数组(最多9张)|
|visibility|`Visibility`|公开: Visibility.Public = "public"<br>仅好友: Visibility.Friends = "friends"<br>仅自己: Visibility.Private = "private"| 可见范围|
|quote|`string`|| 酒言酒语|
**DrinkItem**
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
|category|`Category`|required| 酒类分类ID|
|brand|`string`|required| 品牌名称|
|product|`string`|| 产品名|
|amount|`number`|required,gt=0| 饮用量数值|
|unit|`Unit`|required| 单位|
|degree|`number`|required,gte=0,lte=100| 酒精度数(%)|
|standardCups|`number`|| 标准杯数(前端计算,后端应校验)|
**Category**
|名称|值|类型|说明|
|:-|:-|:-|:-|
|Baijiu|"baijiu"|`Category`|白酒|
|Beer|"beer"|`Category`|啤酒|
|Wine|"wine"|`Category`|红酒|
|Whisky|"whisky"|`Category`|洋酒|
|Huangjiu|"huangjiu"|`Category`|黄酒|
|Sake|"sake"|`Category`|清酒|
|Fruit|"fruit"|`Category`|果酒|
|Cocktail|"cocktail"|`Category`|调酒|
|Other|"other"|`Category`|其他|
**Unit**
|名称|值|类型|说明|
|:-|:-|:-|:-|
|Ml|"ml"|`Unit`|毫升|
|Liang|"liang"|`Unit`|两|
|Bottle|"bottle"|`Unit`|瓶|
|Cup|"cup"|`Unit`|杯|
|Can|"can"|`Unit`|听|
|Shot|"shot"|`Unit`|shot|
**FoodInfo**
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
|category|`FoodCategory`|required| 配餐分类ID|
|name|`string`|| 具体菜名|
**FoodCategory**
|名称|值|类型|说明|
|:-|:-|:-|:-|
|Hotpot|"hotpot"|`FoodCategory`|火锅|
|Bbq|"bbq"|`FoodCategory`|烧烤|
|Stirfry|"stirfry"|`FoodCategory`|炒菜|
|Seafood|"seafood"|`FoodCategory`|海鲜|
|Japanese|"japanese"|`FoodCategory`|日料|
|Western|"western"|`FoodCategory`|西餐|
|Snack|"snack"|`FoodCategory`|小吃卤味|
|Junk|"junk"|`FoodCategory`|零食|
|None|"none"|`FoodCategory`|无配餐|
#### 返回值
|名称|类型|说明|
|:-|:-:|:-|
|data|`Record`| 创建的记录详情<br>|
**Record**
|名称|类型|说明|
|:-|:-|:-|
|id|`string\|number`| 记录ID|
|date|`string`| 日期|
|mode|`Mode`| 打卡模式|
|drinks|`Array<DrinkItem>`| 酒水列表|
|food|`FoodInfo`| 配餐信息|
|feeling|`Feeling`| 感受|
|photos|`Array<string>`| 照片URL数组|
|visibility|`Visibility`| 可见范围|
|quote|`string`| 酒言酒语|
|standardCupsTotal|`number`| 标准杯总数|
|createdAt|`string`| 创建时间|
**Mode**
|名称|值|类型|说明|
|:-|:-:|:-|:-|
|Drank|"drank"|`Mode`|今日喝了|
|Abstain|"abstain"|`Mode`|今日未喝|
**DrinkItem**
|名称|类型|说明|
|:-|:-|:-|
|category|`Category`| 酒类分类ID|
|brand|`string`| 品牌名称|
|product|`string`| 产品名|
|amount|`number`| 饮用量数值|
|unit|`Unit`| 单位|
|degree|`number`| 酒精度数(%)|
|standardCups|`number`| 标准杯数(前端计算,后端应校验)|
**FoodInfo**
|名称|类型|说明|
|:-|:-|:-|
|category|`FoodCategory`| 配餐分类ID|
|name|`string`| 具体菜名|
**Feeling**
|名称|值|类型|说明|
|:-|:-:|:-|:-|
|Tipsy|"tipsy"|`Feeling`|微醺|
|Buzzed|"buzzed"|`Feeling`|到位|
|Drunk|"drunk"|`Feeling`|醉了|
|Blackout|"blackout"|`Feeling`|断片|
**Visibility**
|名称|值|类型|说明|
|:-|:-:|:-|:-|
|Public|"public"|`Visibility`|公开|
|Friends|"friends"|`Visibility`|仅好友|
|Private|"private"|`Visibility`|仅自己|
```javascript
const req = new CreateRecordReq()
client.CreateRecord(req).then(...).catch(...)
```
### 获取记录列表
<font color="green">GET</font> `/api/have_a_drink/v1/record/records`
#### 请求参数
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
|page|`number`|required,min=1| 页码|
|pageSize|`number`|required,min=1,max=100| 每页数量,默认1-100|
|month|`string`|| 月份筛选 YYYY-MM|
|mode|`Mode`|今日喝了: Mode.Drank = "drank"<br>今日未喝: Mode.Abstain = "abstain"| 打卡模式筛选|
#### 返回值
|名称|类型|说明|
|:-|:-:|:-|
|list|`Array<Record>`| 分页数据<br>|
**Record**
|名称|类型|说明|
|:-|:-|:-|
|id|`string\|number`| 记录ID|
|date|`string`| 日期|
|mode|`Mode`| 打卡模式|
|drinks|`Array<DrinkItem>`| 酒水列表|
|food|`FoodInfo`| 配餐信息|
|feeling|`Feeling`| 感受|
|photos|`Array<string>`| 照片URL数组|
|visibility|`Visibility`| 可见范围|
|quote|`string`| 酒言酒语|
|standardCupsTotal|`number`| 标准杯总数|
|createdAt|`string`| 创建时间|
**Mode**
|名称|值|类型|说明|
|:-|:-:|:-|:-|
|Drank|"drank"|`Mode`|今日喝了|
|Abstain|"abstain"|`Mode`|今日未喝|
**DrinkItem**
|名称|类型|说明|
|:-|:-|:-|
|category|`Category`| 酒类分类ID|
|brand|`string`| 品牌名称|
|product|`string`| 产品名|
|amount|`number`| 饮用量数值|
|unit|`Unit`| 单位|
|degree|`number`| 酒精度数(%)|
|standardCups|`number`| 标准杯数(前端计算,后端应校验)|
**FoodInfo**
|名称|类型|说明|
|:-|:-|:-|
|category|`FoodCategory`| 配餐分类ID|
|name|`string`| 具体菜名|
**Feeling**
|名称|值|类型|说明|
|:-|:-:|:-|:-|
|Tipsy|"tipsy"|`Feeling`|微醺|
|Buzzed|"buzzed"|`Feeling`|到位|
|Drunk|"drunk"|`Feeling`|醉了|
|Blackout|"blackout"|`Feeling`|断片|
**Visibility**
|名称|值|类型|说明|
|:-|:-:|:-|:-|
|Public|"public"|`Visibility`|公开|
|Friends|"friends"|`Visibility`|仅好友|
|Private|"private"|`Visibility`|仅自己|
```javascript
const req = new GetRecordsReq()
client.GetRecords(req).then(...).catch(...)
```
### 获取单条记录详情
<font color="green">GET</font> `/api/have_a_drink/v1/record/records/detail`
#### 请求参数
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
|id|`string\|number`|required| 记录ID|
#### 返回值
|名称|类型|说明|
|:-|:-:|:-|
|data|`Record`| 记录详情<br>|
**Record**
|名称|类型|说明|
|:-|:-|:-|
|id|`string\|number`| 记录ID|
|date|`string`| 日期|
|mode|`Mode`| 打卡模式|
|drinks|`Array<DrinkItem>`| 酒水列表|
|food|`FoodInfo`| 配餐信息|
|feeling|`Feeling`| 感受|
|photos|`Array<string>`| 照片URL数组|
|visibility|`Visibility`| 可见范围|
|quote|`string`| 酒言酒语|
|standardCupsTotal|`number`| 标准杯总数|
|createdAt|`string`| 创建时间|
**Mode**
|名称|值|类型|说明|
|:-|:-:|:-|:-|
|Drank|"drank"|`Mode`|今日喝了|
|Abstain|"abstain"|`Mode`|今日未喝|
**DrinkItem**
|名称|类型|说明|
|:-|:-|:-|
|category|`Category`| 酒类分类ID|
|brand|`string`| 品牌名称|
|product|`string`| 产品名|
|amount|`number`| 饮用量数值|
|unit|`Unit`| 单位|
|degree|`number`| 酒精度数(%)|
|standardCups|`number`| 标准杯数(前端计算,后端应校验)|
**FoodInfo**
|名称|类型|说明|
|:-|:-|:-|
|category|`FoodCategory`| 配餐分类ID|
|name|`string`| 具体菜名|
**Feeling**
|名称|值|类型|说明|
|:-|:-:|:-|:-|
|Tipsy|"tipsy"|`Feeling`|微醺|
|Buzzed|"buzzed"|`Feeling`|到位|
|Drunk|"drunk"|`Feeling`|醉了|
|Blackout|"blackout"|`Feeling`|断片|
**Visibility**
|名称|值|类型|说明|
|:-|:-:|:-|:-|
|Public|"public"|`Visibility`|公开|
|Friends|"friends"|`Visibility`|仅好友|
|Private|"private"|`Visibility`|仅自己|
```javascript
const req = new GetRecordDetailReq()
client.GetRecordDetail(req).then(...).catch(...)
```
### 删除记录
<font color="green">DELETE</font> `/api/have_a_drink/v1/record/records`
#### 请求参数
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
|id|`string\|number`|required| 记录ID|
#### 返回值
|名称|类型|说明|
|:-|:-:|:-|
```javascript
const req = new DeleteRecordReq()
client.DeleteRecord(req).then(...).catch(...)
```
### 获取日历打卡数据
<font color="green">GET</font> `/api/have_a_drink/v1/record/records/calendar`
#### 请求参数
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
|year|`number`|required| 年份|
|month|`number`|required,gte=1,lte=12| 月份(1-12)|
#### 返回值
|名称|类型|说明|
|:-|:-:|:-|
|data|`CalendarData`| 日历数据<br>|
**CalendarData**
|名称|类型|说明|
|:-|:-|:-|
|year|`number`| 年份|
|month|`number`| 月份|
|days|`Array<CalendarDayData>`| 每天的打卡数据,null表示当天无记录|
**CalendarDayData**
|名称|类型|说明|
|:-|:-|:-|
|date|`string`| 日期YYYY-MM-DD|
|hasRecord|`boolean`| 是否有记录|
|mode|`Mode`| 打卡模式|
|standardCupsTotal|`number`| 标准杯总数|
```javascript
const req = new GetCalendarReq()
client.GetCalendar(req).then(...).catch(...)
```
### 获取用户统计概览
<font color="green">GET</font> `/api/have_a_drink/v1/statistics/overview`
#### 请求参数
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
#### 返回值
|名称|类型|说明|
|:-|:-:|:-|
|data|`StatsOverview`| 统计概览数据<br>|
**StatsOverview**
|名称|类型|说明|
|:-|:-|:-|
|weekDrinkCount|`number`| 本周饮酒天数|
|weekCups|`number`| 本周标准杯总数|
|monthDrinkCount|`number`| 本月饮酒天数|
|monthCups|`number`| 本月标准杯总数|
|streak|`number`| 当前连续打卡天数|
|streakType|`Mode`| 连续类型|
|totalDays|`number`| 总饮酒天数(去重)|
|totalRecords|`number`| 总记录数|
|totalCups|`number`| 历史累计标准杯|
|favCategory|`Category`| 最爱酒类ID|
|categoryVariety|`number`| 尝试过的酒类品种数|
**Mode**
|名称|值|类型|说明|
|:-|:-:|:-|:-|
|Drank|"drank"|`Mode`|今日喝了|
|Abstain|"abstain"|`Mode`|今日未喝|
**Category**
|名称|值|类型|说明|
|:-|:-:|:-|:-|
|Baijiu|"baijiu"|`Category`|白酒|
|Beer|"beer"|`Category`|啤酒|
|Wine|"wine"|`Category`|红酒|
|Whisky|"whisky"|`Category`|洋酒|
|Huangjiu|"huangjiu"|`Category`|黄酒|
|Sake|"sake"|`Category`|清酒|
|Fruit|"fruit"|`Category`|果酒|
|Cocktail|"cocktail"|`Category`|调酒|
|Other|"other"|`Category`|其他|
```javascript
const req = new GetStatsOverviewReq()
client.GetStatsOverview(req).then(...).catch(...)
```
### 获取月度统计
<font color="green">GET</font> `/api/have_a_drink/v1/statistics/monthly`
#### 请求参数
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
|year|`number`|| 年份,默认当前年|
|month|`number`|| 月份,默认当前月|
#### 返回值
|名称|类型|说明|
|:-|:-:|:-|
|data|`MonthlyStats`| 月度统计数据<br>|
**MonthlyStats**
|名称|类型|说明|
|:-|:-|:-|
|year|`number`| 年份|
|month|`number`| 月份|
|drinkDays|`number`| 饮酒天数|
|abstainDays|`number`| 戒酒天数|
|totalCups|`number`| 总标准杯数|
|avgCupsPerDay|`number`| 日均标准杯数|
|categoryBreakdown|`Array<CategoryBreakdown>`| 酒类分布|
|feelingBreakdown|`Array<FeelingBreakdown>`| 感受分布|
|foodBreakdown|`Array<FoodBreakdown>`| 配餐分布|
**CategoryBreakdown**
|名称|类型|说明|
|:-|:-|:-|
|category|`Category`| 酒类分类|
|count|`number`| 次数|
|cups|`number`| 标准杯数|
**FeelingBreakdown**
|名称|类型|说明|
|:-|:-|:-|
|feeling|`Feeling`| 感受类型|
|count|`number`| 次数|
**FoodBreakdown**
|名称|类型|说明|
|:-|:-|:-|
|category|`FoodCategory`| 配餐分类|
|count|`number`| 次数|
```javascript
const req = new GetMonthlyStatsReq()
client.GetMonthlyStats(req).then(...).catch(...)
```
### 获取酒类分布统计
<font color="green">GET</font> `/api/have_a_drink/v1/statistics/categories`
#### 请求参数
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
#### 返回值
|名称|类型|说明|
|:-|:-:|:-|
|data|`CategoryStatsData`| 酒类分布统计数据<br>|
**CategoryStatsData**
|名称|类型|说明|
|:-|:-|:-|
|categories|`Array<CategoryStats>`| 酒类分布列表|
**CategoryStats**
|名称|类型|说明|
|:-|:-|:-|
|id|`Category`| 酒类分类ID|
|name|`string`| 酒类名称|
|recordCount|`number`| 记录次数|
|totalCups|`number`| 总标准杯数|
|percentage|`number`| 占比(百分比)|
```javascript
const req = new GetCategoryStatsReq()
client.GetCategoryStats(req).then(...).catch(...)
```
### 获取用户信息
<font color="green">GET</font> `/api/have_a_drink/v1/user/user/profile`
#### 请求参数
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
#### 返回值
|名称|类型|说明|
|:-|:-:|:-|
|id|`string\|number`| 用户ID<br>|
|nickname|`string`| 用户昵称<br>|
|avatar|`string`| 头像URL<br>|
|joinedAt|`string`| 加入时间<br>|
|preferences|`UserPreferences`| 用户偏好<br>|
**UserPreferences**
|名称|类型|说明|
|:-|:-|:-|
|favoriteCategories|`Array<Category>`| 偏好酒类ID列表|
|frequency|`Frequency`| 饮酒频率|
**Frequency**
|名称|值|类型|说明|
|:-|:-:|:-|:-|
|Rarely|"rarely"|`Frequency`|很少|
|Sometimes|"sometimes"|`Frequency`|有时|
|Often|"often"|`Frequency`|经常|
```javascript
const req = new GetUserProfileReq()
client.GetUserProfile(req).then(...).catch(...)
```
### 更新用户偏好
<font color="green">PUT</font> `/api/have_a_drink/v1/user/user/preferences`
#### 请求参数
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
|favoriteCategories|`Array<Category>`|| 偏好酒类ID列表|
|frequency|`Frequency`|很少: Frequency.Rarely = "rarely"<br>有时: Frequency.Sometimes = "sometimes"<br>经常: Frequency.Often = "often"| 饮酒频率|
#### 返回值
|名称|类型|说明|
|:-|:-:|:-|
|favoriteCategories|`Array<Category>`| 偏好酒类ID列表<br>|
|frequency|`Frequency`| 饮酒频率<br>很少: Frequency.Rarely = "rarely"<br>有时: Frequency.Sometimes = "sometimes"<br>经常: Frequency.Often = "often"|
```javascript
const req = new UpdatePreferencesReq()
client.UpdatePreferences(req).then(...).catch(...)
```
### 上传文件
<font color="green">POST</font> `/api/have_a_drink/v1/upload/image`
#### 请求参数
|名称|类型|校验规则|说明|
|:-|:-|:-|:-|
|image|`any`|required| 图片|
#### 返回值
|名称|类型|说明|
|:-|:-:|:-|
|id|`string\|number`| 图片 id<br>|
|url|`string`| 图片 url<br>|
```javascript
const req = new UploadImageReq()
client.UploadImage(req).then(...).catch(...)
```