# 使用说明 * 喝酒了么 - 后端接口 API * 小程序:喝酒了么(uni-app 微信小程序) * 基础URL: /api/v1 * * 主要功能模块: * 1. 用户模块 - 微信登录、用户信息管理 * 2. 打卡记录模块 - 饮酒记录创建、查询、日历数据 * 3. 照片上传模块 - 单张/批量照片上传 * 4. 统计模块 - 用户统计、月度统计、酒类分布 * 5. 成就模块 - 成就列表和进度 * 6. 社交模块 - 朋友圈动态、点赞 **版本:** v1.0.8 ## 安装 ``` 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 POST `/api/have_a_drink/v1/auth/wechat/login` #### 请求参数 |名称|类型|校验规则|说明| |:-|:-|:-|:-| |code|`string`|required| 登录时获取的 code, 可通过 wx.login 获取| |nickName|`string`|| 用户昵称| |avatarUrl|`string`|| 头像URL| #### 返回值 |名称|类型|说明| |:-|:-:|:-| |token|`string`| JWT Token
| |user|`User`| 用户信息
| |isNew|`boolean`| 是否新用户
| |session_key|`string`| 会话密钥
| |open_id|`string`| 用户唯一标识
| |union_id|`string`| 用户在开放平台的唯一标识符,若当前小程序已绑定到微信开放平台账号下会返回,详见 UnionID 机制说明。
| |errcode|`number`| 错误码
| |errmsg|`string`| 错误信息
| |refresh_token|`string`| 刷新token
| **User** |名称|类型|说明| |:-|:-|:-| |id|`string\|number`| 用户ID| |nickname|`string`| 用户昵称| |avatar|`string`| 头像URL| |joinedAt|`string`| 加入时间| |preferences|`UserPreferences`| 用户偏好| **UserPreferences** |名称|类型|说明| |:-|:-|:-| |favoriteCategories|`Array`| 偏好酒类ID列表| |frequency|`Frequency`| 饮酒频率| ```javascript const req = new WechatLoginReq() client.WechatLogin(req).then(...).catch(...) ``` ### 获取微信手机号 POST `/api/have_a_drink/v1/auth/wechat/get_phone_number` #### 请求参数 |名称|类型|校验规则|说明| |:-|:-|:-|:-| |code|`string`|required| 手机号获取凭证| #### 返回值 |名称|类型|说明| |:-|:-:|:-| |errcode|`number`| 错误码
| |errmsg|`string`| 错误信息
| |token|`string`| token:api使用
| |expires_in|`number`| token 超时时间,单位(秒)
| |refresh_token|`string`| refresh_token:刷新token
| ```javascript const req = new WechatGetPhoneNumberReq() client.WechatGetPhoneNumber(req).then(...).catch(...) ``` ### 刷新 token 接口 POST `/api/have_a_drink/v1/auth/refresh_token` #### 请求参数 |名称|类型|校验规则|说明| |:-|:-|:-|:-| |refresh_token|`string`|required| 签发 token 时生成的 refresh_token| #### 返回值 |名称|类型|说明| |:-|:-:|:-| |token|`string`| 生成的新token
| |expire_in|`number`| token 超时时间,单位(秒)
| |refresh_token|`string`| refresh_token:刷新token
| ```javascript const req = new RefreshTokenReq() client.RefreshToken(req).then(...).catch(...) ``` ### 获取成就列表 GET `/api/have_a_drink/v1/achievements/list` #### 请求参数 |名称|类型|校验规则|说明| |:-|:-|:-|:-| #### 返回值 |名称|类型|说明| |:-|:-:|:-| |data|`AchievementsData`| 成就列表数据
| **AchievementsData** |名称|类型|说明| |:-|:-|:-| |achievements|`Array`| 成就列表| **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(...) ``` ### 获取朋友圈动态 GET `/api/have_a_drink/v1/communication/feed` #### 请求参数 |名称|类型|校验规则|说明| |:-|:-|:-|:-| |lastId|`string\|number`|| 游标分页,上一页最后一条ID| #### 返回值 |名称|类型|说明| |:-|:-:|:-| |data|`FeedPageData`| 朋友圈动态分页数据
| **FeedPageData** |名称|类型|说明| |:-|:-|:-| |list|`Array`| 动态列表| **FeedItem** |名称|类型|说明| |:-|:-|:-| |id|`string\|number`| 记录ID| |user|`FeedUser`| 用户信息| |date|`string`| 日期| |mode|`Mode`| 打卡模式| |drinks|`Array`| 酒水列表| |food|`FoodInfo`| 配餐信息| |feeling|`Feeling`| 感受| |photos|`Array`| 照片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`| 标准杯数(前端计算,后端应校验)| |customAmount|`number`| 自定义饮酒数量| |customUnit|`Unit`| 自定义饮酒单位| **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| **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(...) ``` ### 上传照片 POST `/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(...) ``` ### 批量上传照片 POST `/api/have_a_drink/v1/photo/upload/photos` #### 请求参数 |名称|类型|校验规则|说明| |:-|:-|:-|:-| |urls|`Array`|required,max=9| 图片URL数组(最多9张)| |recordId|`string\|number`|required| 关联记录ID| #### 返回值 |名称|类型|说明| |:-|:-:|:-| ```javascript const req = new UploadPhotosReq() client.UploadPhotos(req).then(...).catch(...) ``` ### 创建打卡记录 POST `/api/have_a_drink/v1/record/records` #### 请求参数 |名称|类型|校验规则|说明| |:-|:-|:-|:-| |date|`string`|required| 日期 YYYY-MM-DD| |mode|`Mode`|今日喝了: Mode.Drank = "drank"
今日未喝: Mode.Abstain = "abstain"| 打卡模式| |drinks|`Array`|| 酒水列表(mode=abstain时为空数组)| |food|`FoodInfo`|| 配餐信息| |feeling|`Feeling`|微醺: Feeling.Tipsy = "tipsy"
到位: Feeling.Buzzed = "buzzed"
醉了: Feeling.Drunk = "drunk"
断片: Feeling.Blackout = "blackout"| 感受ID| |photos|`Array`|max=9| 照片URL数组(最多9张)| |visibility|`Visibility`|公开: Visibility.Public = "public"
仅好友: Visibility.Friends = "friends"
仅自己: Visibility.Private = "private"| 可见范围| |quote|`string`|| 酒言酒语| **DrinkItem** |名称|类型|校验规则|说明| |:-|:-|:-|:-| |category|`Category`|| 酒类分类ID| |brand|`string`|required| 品牌名称| |product|`string`|| 产品名| |amount|`number`|required,gt=0| 饮用量数值| |unit|`Unit`|required| 单位| |degree|`number`|required,gte=0,lte=100| 酒精度数(%)| |standardCups|`number`|| 标准杯数(前端计算,后端应校验)| |customAmount|`number`|| 自定义饮酒数量| |customUnit|`Unit`|| 自定义饮酒单位| **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| **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`|无配餐| #### 返回值 |名称|类型|说明| |:-|:-:|:-| |data|`Record`| 创建的记录详情
| **Record** |名称|类型|说明| |:-|:-|:-| |id|`string\|number`| 记录ID| |date|`string`| 日期| |mode|`Mode`| 打卡模式| |drinks|`Array`| 酒水列表| |food|`FoodInfo`| 配餐信息| |feeling|`Feeling`| 感受| |photos|`Array`| 照片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`| 标准杯数(前端计算,后端应校验)| |customAmount|`number`| 自定义饮酒数量| |customUnit|`Unit`| 自定义饮酒单位| **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(...) ``` ### 获取记录列表 GET `/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"
今日未喝: Mode.Abstain = "abstain"| 打卡模式筛选| #### 返回值 |名称|类型|说明| |:-|:-:|:-| |list|`Array`| 分页数据
| **Record** |名称|类型|说明| |:-|:-|:-| |id|`string\|number`| 记录ID| |date|`string`| 日期| |mode|`Mode`| 打卡模式| |drinks|`Array`| 酒水列表| |food|`FoodInfo`| 配餐信息| |feeling|`Feeling`| 感受| |photos|`Array`| 照片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`| 标准杯数(前端计算,后端应校验)| |customAmount|`number`| 自定义饮酒数量| |customUnit|`Unit`| 自定义饮酒单位| **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(...) ``` ### 获取单条记录详情 GET `/api/have_a_drink/v1/record/records/detail` #### 请求参数 |名称|类型|校验规则|说明| |:-|:-|:-|:-| |id|`string\|number`|required| 记录ID| #### 返回值 |名称|类型|说明| |:-|:-:|:-| |data|`Record`| 记录详情
| **Record** |名称|类型|说明| |:-|:-|:-| |id|`string\|number`| 记录ID| |date|`string`| 日期| |mode|`Mode`| 打卡模式| |drinks|`Array`| 酒水列表| |food|`FoodInfo`| 配餐信息| |feeling|`Feeling`| 感受| |photos|`Array`| 照片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`| 标准杯数(前端计算,后端应校验)| |customAmount|`number`| 自定义饮酒数量| |customUnit|`Unit`| 自定义饮酒单位| **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(...) ``` ### 删除记录 DELETE `/api/have_a_drink/v1/record/records` #### 请求参数 |名称|类型|校验规则|说明| |:-|:-|:-|:-| |id|`string\|number`|required| 记录ID| #### 返回值 |名称|类型|说明| |:-|:-:|:-| ```javascript const req = new DeleteRecordReq() client.DeleteRecord(req).then(...).catch(...) ``` ### 获取日历打卡数据 GET `/api/have_a_drink/v1/record/records/calendar` #### 请求参数 |名称|类型|校验规则|说明| |:-|:-|:-|:-| |year|`number`|required| 年份| |month|`number`|required,gte=1,lte=12| 月份(1-12)| #### 返回值 |名称|类型|说明| |:-|:-:|:-| |year|`number`| 年份
| |month|`number`| 月份
| |days|`Array`| 每天的打卡数据,null表示当天无记录
| **CalendarDayData** |名称|类型|说明| |:-|:-|:-| |date|`string`| 日期YYYY-MM-DD| |hasRecord|`boolean`| 是否有记录| |mode|`Mode`| 打卡模式| |standardCupsTotal|`number`| 标准杯总数| |id|`string\|number`| 记录ID| |drinks|`Array`| 酒水列表| |food|`FoodInfo`| 配餐信息| |feeling|`Feeling`| 感受| |photos|`Array`| 照片URL数组| |visibility|`Visibility`| 可见范围| |quote|`string`| 酒言酒语| |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`| 标准杯数(前端计算,后端应校验)| |customAmount|`number`| 自定义饮酒数量| |customUnit|`Unit`| 自定义饮酒单位| **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 GetCalendarReq() client.GetCalendar(req).then(...).catch(...) ``` ### 获取用户统计概览 GET `/api/have_a_drink/v1/statistics/overview` #### 请求参数 |名称|类型|校验规则|说明| |:-|:-|:-|:-| #### 返回值 |名称|类型|说明| |:-|:-:|:-| |data|`StatsOverview`| 统计概览数据
| **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(...) ``` ### 获取月度统计 GET `/api/have_a_drink/v1/statistics/monthly` #### 请求参数 |名称|类型|校验规则|说明| |:-|:-|:-|:-| |year|`number`|| 年份,默认当前年| |month|`number`|| 月份,默认当前月| #### 返回值 |名称|类型|说明| |:-|:-:|:-| |data|`MonthlyStats`| 月度统计数据
| **MonthlyStats** |名称|类型|说明| |:-|:-|:-| |year|`number`| 年份| |month|`number`| 月份| |drinkDays|`number`| 饮酒天数| |abstainDays|`number`| 戒酒天数| |totalCups|`number`| 总标准杯数| |avgCupsPerDay|`number`| 日均标准杯数| |categoryBreakdown|`Array`| 酒类分布| |feelingBreakdown|`Array`| 感受分布| |foodBreakdown|`Array`| 配餐分布| **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(...) ``` ### 获取酒类分布统计 GET `/api/have_a_drink/v1/statistics/categories` #### 请求参数 |名称|类型|校验规则|说明| |:-|:-|:-|:-| #### 返回值 |名称|类型|说明| |:-|:-:|:-| |data|`CategoryStatsData`| 酒类分布统计数据
| **CategoryStatsData** |名称|类型|说明| |:-|:-|:-| |categories|`Array`| 酒类分布列表| **CategoryStats** |名称|类型|说明| |:-|:-|:-| |id|`Category`| 酒类分类ID| |name|`string`| 酒类名称| |recordCount|`number`| 记录次数| |totalCups|`number`| 总标准杯数| |percentage|`number`| 占比(百分比)| ```javascript const req = new GetCategoryStatsReq() client.GetCategoryStats(req).then(...).catch(...) ``` ### 获取用户信息 GET `/api/have_a_drink/v1/user/user/profile` #### 请求参数 |名称|类型|校验规则|说明| |:-|:-|:-|:-| #### 返回值 |名称|类型|说明| |:-|:-:|:-| |id|`string\|number`| 用户ID
| |nickname|`string`| 用户昵称
| |avatar|`string`| 头像URL
| |joinedAt|`string`| 加入时间
| |preferences|`UserPreferences`| 用户偏好
| **UserPreferences** |名称|类型|说明| |:-|:-|:-| |favoriteCategories|`Array`| 偏好酒类ID列表| |frequency|`Frequency`| 饮酒频率| **Frequency** |名称|值|类型|说明| |:-|:-:|:-|:-| |Rarely|"rarely"|`Frequency`|很少| |Sometimes|"sometimes"|`Frequency`|有时| |Often|"often"|`Frequency`|经常| ```javascript const req = new GetUserProfileReq() client.GetUserProfile(req).then(...).catch(...) ``` ### 更新用户偏好 PUT `/api/have_a_drink/v1/user/user/preferences` #### 请求参数 |名称|类型|校验规则|说明| |:-|:-|:-|:-| |favoriteCategories|`Array`|| 偏好酒类ID列表| |frequency|`Frequency`|很少: Frequency.Rarely = "rarely"
有时: Frequency.Sometimes = "sometimes"
经常: Frequency.Often = "often"| 饮酒频率| #### 返回值 |名称|类型|说明| |:-|:-:|:-| |favoriteCategories|`Array`| 偏好酒类ID列表
| |frequency|`Frequency`| 饮酒频率
很少: Frequency.Rarely = "rarely"
有时: Frequency.Sometimes = "sometimes"
经常: Frequency.Often = "often"| ```javascript const req = new UpdatePreferencesReq() client.UpdatePreferences(req).then(...).catch(...) ``` ### 上传文件 POST `/api/have_a_drink/v1/upload/image` #### 请求参数 |名称|类型|校验规则|说明| |:-|:-|:-|:-| |image|`any`|required| 图片| #### 返回值 |名称|类型|说明| |:-|:-:|:-| |id|`string\|number`| 图片 id
| |url|`string`| 图片 url
| ```javascript const req = new UploadImageReq() client.UploadImage(req).then(...).catch(...) ``` ### 动态信息流 GET `/api/have_a_drink/v1/moments/feeds` #### 请求参数 |名称|类型|校验规则|说明| |:-|:-|:-|:-| |lastId|`string\|number`|| 最后一条动态ID,用于分页| |pageSize|`number`|| 每页数量| #### 返回值 |名称|类型|说明| |:-|:-:|:-| |list|`Array`| 动态列表
| |hasMore|`boolean`| 是否还有更多动态
| **Feed** |名称|类型|说明| |:-|:-|:-| |id|`string\|number`| 动态ID| |userId|`string\|number`| 用户ID| |nickname|`string`| 昵称| |avatar|`string`| 头像| |time|`string`| 发布时间| |text|`string`| 动态文本| |drinks|`Array`| 酒水标签| |feeling|`Feeling`| 自我感觉| |images|`Array`| 图片列表| |likes|`number`| 点赞数| |liked|`boolean`| 是否点赞| |comments|`number`| 评论数| **DrinkTag** |名称|类型|说明| |:-|:-|:-| |category|`Category`| 酒类分类| |name|`string`| 酒类名称| |amount|`number`| 酒类数量| **Feeling** |名称|值|类型|说明| |:-|:-:|:-|:-| |Tipsy|"tipsy"|`Feeling`|微醺| |Buzzed|"buzzed"|`Feeling`|到位| |Drunk|"drunk"|`Feeling`|醉了| |Blackout|"blackout"|`Feeling`|断片| ```javascript const req = new GetFeedsReq() client.GetFeeds(req).then(...).catch(...) ``` ### 发布动态 POST `/api/have_a_drink/v1/moments/feeds` #### 请求参数 |名称|类型|校验规则|说明| |:-|:-|:-|:-| |text|`string`|| 动态文本| |images|`Array`|| 图片列表| |recordId|`string\|number`|| 关联的记录ID| |visibility|`Visibility`|公开: Visibility.Public = "public"
仅好友: Visibility.Friends = "friends"
仅自己: Visibility.Private = "private"| 可见性| #### 返回值 |名称|类型|说明| |:-|:-:|:-| |success|`boolean`| 是否成功
| |feedId|`string\|number`| 动态ID
| ```javascript const req = new PublishFeedReq() client.PublishFeed(req).then(...).catch(...) ``` ### 点赞 POST `/api/have_a_drink/v1/moments/feeds/like` #### 请求参数 |名称|类型|校验规则|说明| |:-|:-|:-|:-| |id|`string\|number`|| 动态ID| #### 返回值 |名称|类型|说明| |:-|:-:|:-| |ok|`boolean`| 是否成功
| ```javascript const req = new LikeFeedReq() client.LikeFeed(req).then(...).catch(...) ``` ### 取消点赞 POST `/api/have_a_drink/v1/moments/feeds/unlike` #### 请求参数 |名称|类型|校验规则|说明| |:-|:-|:-|:-| |id|`string\|number`|| 动态ID| #### 返回值 |名称|类型|说明| |:-|:-:|:-| |ok|`boolean`| 是否成功
| ```javascript const req = new UnlikeFeedReq() client.UnlikeFeed(req).then(...).catch(...) ``` ### 获取评论 GET `/api/have_a_drink/v1/moments/feeds/comments` #### 请求参数 |名称|类型|校验规则|说明| |:-|:-|:-|:-| |id|`string\|number`|| 动态ID| #### 返回值 |名称|类型|说明| |:-|:-:|:-| |list|`Array`| 评论列表
| **Comment** |名称|类型|说明| |:-|:-|:-| |id|`string\|number`| 评论ID| |userId|`string\|number`| 用户ID| |nickname|`string`| 昵称| |avatar|`string`| 头像| |content|`string`| 评论内容| |time|`string`| 评论时间| ```javascript const req = new GetFeedCommentsReq() client.GetFeedComments(req).then(...).catch(...) ``` ### 发表评论 POST `/api/have_a_drink/v1/moments/feeds/comments` #### 请求参数 |名称|类型|校验规则|说明| |:-|:-|:-|:-| |id|`string\|number`|| 动态ID| |content|`string`|| 评论内容| #### 返回值 |名称|类型|说明| |:-|:-:|:-| |id|`string\|number`| 评论ID
| |userId|`string\|number`| 用户ID
| |nickname|`string`| 昵称
| |avatar|`string`| 头像
| |content|`string`| 评论内容
| |time|`string`| 评论时间
| ```javascript const req = new AddCommentFullReq() client.AddComment(req).then(...).catch(...) ``` ### 酒友管理 GET `/api/have_a_drink/v1/friends/friends` #### 请求参数 |名称|类型|校验规则|说明| |:-|:-|:-|:-| |keyword|`string`|| 搜索关键词| #### 返回值 |名称|类型|说明| |:-|:-:|:-| |list|`Array`| 分页数据
| **Friend** |名称|类型|说明| |:-|:-|:-| |id|`string\|number`| 酒友ID| |nickname|`string`| 昵称| |avatar|`string`| 头像| |lastDrink|`string\|number`| 最近一次喝的酒| |lastDrinkTime|`string`| 最近一次喝的酒时间| |online|`boolean`| 是否在线| ```javascript const req = new GetFriendsReq() client.GetFriends(req).then(...).catch(...) ``` ### 好友请求管理 GET `/api/have_a_drink/v1/friends/friend-requests` #### 请求参数 |名称|类型|校验规则|说明| |:-|:-|:-|:-| #### 返回值 |名称|类型|说明| |:-|:-:|:-| |list|`Array`| 分页数据
| **FriendRequest** |名称|类型|说明| |:-|:-|:-| |id|`string\|number`| 好友请求ID| |userId|`string\|number`| 酒友ID| |nickname|`string`| 昵称| |avatar|`string`| 头像| |message|`string`| 消息| |time|`string`| 创建时间| ```javascript const req = new GetFriendRequestsReq() client.GetFriendRequests(req).then(...).catch(...) ``` ### 发送好友请求 POST `/api/have_a_drink/v1/friends/friend-requests` #### 请求参数 |名称|类型|校验规则|说明| |:-|:-|:-|:-| |userId|`string\|number`|| 酒友ID| |message|`string`|| 消息| #### 返回值 |名称|类型|说明| |:-|:-:|:-| ```javascript const req = new SendFriendRequestReq() client.SendFriendRequest(req).then(...).catch(...) ``` ### 接受好友请求 POST `/api/have_a_drink/v1/friends/friend-requests/accept` #### 请求参数 |名称|类型|校验规则|说明| |:-|:-|:-|:-| |id|`string\|number`|| 好友请求ID| #### 返回值 |名称|类型|说明| |:-|:-:|:-| ```javascript const req = new AcceptFriendRequestReq() client.AcceptFriendRequest(req).then(...).catch(...) ``` ### 删除酒友 DELETE `/api/have_a_drink/v1/friends/friends` #### 请求参数 |名称|类型|校验规则|说明| |:-|:-|:-|:-| |userId|`string\|number`|| 酒友ID| #### 返回值 |名称|类型|说明| |:-|:-:|:-| ```javascript const req = new RemoveFriendReq() client.RemoveFriend(req).then(...).catch(...) ``` ### 约酒活动 GET `/api/have_a_drink/v1/events/events` #### 请求参数 |名称|类型|校验规则|说明| |:-|:-|:-|:-| |status|`EventStatus`|开放报名: EventStatus.Open = 1
待开始: EventStatus.Upcoming = 2
进行中: EventStatus.Ongoing = 3
已结束: EventStatus.Ended = 4| 状态筛选| #### 返回值 |名称|类型|说明| |:-|:-:|:-| |list|`Array`| 分页数据
| **Event** |名称|类型|说明| |:-|:-|:-| |id|`string\|number`| 酒局ID| |title|`string`| 酒局标题| |organizer|`User`| 酒局组织者| |time|`string`| 酒局时间| |location|`string`| 酒局地点| |maxPeople|`number`| 最大人数| |joined|`number`| 已报名人数| |participants|`Array`| 已报名用户| |status|`EventStatus`| 酒局状态| |note|`string`| 酒局备注| |isJoined|`boolean`| 是否已报名| |isOrganizer|`boolean`| 是否为组织者| **User** |名称|类型|说明| |:-|:-|:-| |id|`string\|number`| 用户ID| |nickname|`string`| 用户昵称| |avatar|`string`| 头像URL| |joinedAt|`string`| 加入时间| |preferences|`UserPreferences`| 用户偏好| **UserPreferences** |名称|类型|说明| |:-|:-|:-| |favoriteCategories|`Array`| 偏好酒类ID列表| |frequency|`Frequency`| 饮酒频率| **Frequency** |名称|值|类型|说明| |:-|:-:|:-|:-| |Rarely|"rarely"|`Frequency`|很少| |Sometimes|"sometimes"|`Frequency`|有时| |Often|"often"|`Frequency`|经常| **EventStatus** |名称|值|类型|说明| |:-|:-:|:-|:-| |Open|1|`EventStatus`|开放报名| |Upcoming|2|`EventStatus`|待开始| |Ongoing|3|`EventStatus`|进行中| |Ended|4|`EventStatus`|已结束| ```javascript const req = new GetEventsReq() client.GetEvents(req).then(...).catch(...) ``` ### 获取酒局详情 GET `/api/have_a_drink/v1/events/events/detail` #### 请求参数 |名称|类型|校验规则|说明| |:-|:-|:-|:-| |id|`string\|number`|| 酒局ID| #### 返回值 |名称|类型|说明| |:-|:-:|:-| |id|`string\|number`| 酒局ID
| |title|`string`| 酒局标题
| |organizer|`User`| 酒局组织者
| |time|`string`| 酒局时间
| |location|`string`| 酒局地点
| |maxPeople|`number`| 最大人数
| |joined|`number`| 已报名人数
| |participants|`Array`| 已报名用户
| |status|`EventStatus`| 酒局状态
开放报名: EventStatus.Open = 1
待开始: EventStatus.Upcoming = 2
进行中: EventStatus.Ongoing = 3
已结束: EventStatus.Ended = 4| |note|`string`| 酒局备注
| |isJoined|`boolean`| 是否已报名
| |isOrganizer|`boolean`| 是否为组织者
| **User** |名称|类型|说明| |:-|:-|:-| |id|`string\|number`| 用户ID| |nickname|`string`| 用户昵称| |avatar|`string`| 头像URL| |joinedAt|`string`| 加入时间| |preferences|`UserPreferences`| 用户偏好| **UserPreferences** |名称|类型|说明| |:-|:-|:-| |favoriteCategories|`Array`| 偏好酒类ID列表| |frequency|`Frequency`| 饮酒频率| ```javascript const req = new GetEventDetailReq() client.GetEventDetail(req).then(...).catch(...) ``` ### 发起酒局 POST `/api/have_a_drink/v1/events/events` #### 请求参数 |名称|类型|校验规则|说明| |:-|:-|:-|:-| |title|`string`|| 酒局标题| |time|`string`|| 酒局时间| |location|`string`|| 酒局地点| |maxPeople|`number`|| 最大人数| |geo|`GeoPoint`|| 坐标信息| |note|`string`|| 酒局备注| **GeoPoint** |名称|类型|校验规则|说明| |:-|:-|:-|:-| |latitude|`number`|| 纬度| |longitude|`number`|| 经度| #### 返回值 |名称|类型|说明| |:-|:-:|:-| |eventId|`string\|number`| 酒局ID
| ```javascript const req = new CreateEventReq() client.CreateEvent(req).then(...).catch(...) ``` ### 报名酒局 POST `/api/have_a_drink/v1/events/events/join` #### 请求参数 |名称|类型|校验规则|说明| |:-|:-|:-|:-| |id|`string\|number`|| 酒局ID| #### 返回值 |名称|类型|说明| |:-|:-:|:-| |ok|`boolean`| 是否成功
| ```javascript const req = new JoinEventReq() client.JoinEvent(req).then(...).catch(...) ``` ### 取消报名酒局 POST `/api/have_a_drink/v1/events/events/quit` #### 请求参数 |名称|类型|校验规则|说明| |:-|:-|:-|:-| |id|`string\|number`|| 酒局ID| #### 返回值 |名称|类型|说明| |:-|:-:|:-| |ok|`boolean`| 是否成功
| ```javascript const req = new QuitEventReq() client.QuitEvent(req).then(...).catch(...) ``` ### 签到酒局 POST `/api/have_a_drink/v1/events/events/checkin` #### 请求参数 |名称|类型|校验规则|说明| |:-|:-|:-|:-| |id|`string\|number`|| 酒局ID| #### 返回值 |名称|类型|说明| |:-|:-:|:-| |ok|`boolean`| 是否成功
| ```javascript const req = new CheckInEventReq() client.CheckInEvent(req).then(...).catch(...) ``` ### 获取会话列表 GET `/api/have_a_drink/v1/chat/conversations` #### 请求参数 |名称|类型|校验规则|说明| |:-|:-|:-|:-| #### 返回值 |名称|类型|说明| |:-|:-:|:-| |list|`Array`| 会话列表
| **Conversation** |名称|类型|说明| |:-|:-|:-| |id|`string`| 会话ID| |friendId|`string\|number`| 对方用户ID| |nickname|`string`| 对方昵称| |avatar|`string`| 对方头像URL(可为空)| |lastMessage|`string`| 最后一条消息摘要| |lastTime|`string`| 最后消息时间(ISO 8601)| |unread|`number`| 未读消息数| |online|`boolean`| 对方是否在线| ```javascript const req = new GetConversationsReq() client.GetConversations(req).then(...).catch(...) ``` ### 获取历史消息 GET `/api/have_a_drink/v1/chat/messages` #### 请求参数 |名称|类型|校验规则|说明| |:-|:-|:-|:-| |conversationId|`string`|required| 会话ID| |lastID|`string\|number`|| 游标分页| |pageSize|`number`|gt=0,lte=100| 每页数量,默认20| #### 返回值 |名称|类型|说明| |:-|:-:|:-| |list|`Array`| 消息列表
| |hasMore|`boolean`| 是否还有更多消息
| **Message** |名称|类型|说明| |:-|:-|:-| |id|`string\|number`| 消息ID| |conversationId|`string`| 会话ID| |senderId|`string\|number`| 发送者ID| |receiverId|`string\|number`| 接收者ID| |type|`MessageType`| 消息类型| |content|`string`| 消息内容| |timestamp|`number`| 发送时间(毫秒时间戳)| |status|`MessageStatus`| 消息状态| **MessageType** |名称|值|类型|说明| |:-|:-:|:-|:-| |Text|"text"|`MessageType`|文本消息| |Image|"image"|`MessageType`|图片消息| **MessageStatus** |名称|值|类型|说明| |:-|:-:|:-|:-| |Sending|"sending"|`MessageStatus`|发送中| |Sent|"sent"|`MessageStatus`|已发送| |Delivered|"delivered"|`MessageStatus`|已送达| |Read|"read"|`MessageStatus`|已读| ```javascript const req = new GetMessagesReq() client.GetMessages(req).then(...).catch(...) ``` ### 标记会话已读 POST `/api/have_a_drink/v1/chat/conversations/read` #### 请求参数 |名称|类型|校验规则|说明| |:-|:-|:-|:-| |id|`string`|required| 会话ID(路径参数)| #### 返回值 |名称|类型|说明| |:-|:-:|:-| |success|`boolean`| 是否成功
| ```javascript const req = new MarkReadReq() client.MarkRead(req).then(...).catch(...) ``` ### 获取未读消息总数 GET `/api/have_a_drink/v1/chat/unread-count` #### 请求参数 |名称|类型|校验规则|说明| |:-|:-|:-|:-| #### 返回值 |名称|类型|说明| |:-|:-:|:-| |total|`number`| 未读总数
| ```javascript const req = new GetUnreadCountReq() client.GetUnreadCount(req).then(...).catch(...) ``` ### 注意:连接建立后,服务端会先验证 token,然后推送 connected 事件 WS `/api/have_a_drink/v1/chat/chat` #### 请求参数 |名称|类型|校验规则|说明| |:-|:-|:-|:-| |mesgType|`ClientMesgType`|发送消息: ClientMesgType.Chat = "chat"
输入状态: ClientMesgType.Typing = "typing"
已读回执: ClientMesgType.Read = "read"
心跳: ClientMesgType.Ping = "ping"| 消息类型| |data|`ClientMessage`|| 消息数据| #### 返回值 |名称|类型|说明| |:-|:-:|:-| |mesgType|`ServerMesgType`| 消息类型
推送新消息: ServerMesgType.Chat = "chat"
对方输入状态: ServerMesgType.Typing = "typing"
对方已读回执: ServerMesgType.Read = "read"
消息送达确认: ServerMesgType.Ack = "ack"
心跳响应: ServerMesgType.Pong = "pong"
连接成功: ServerMesgType.Connected = "connected"
被踢下线: ServerMesgType.Kicked = "kicked"| |data|`ServerMessage`| 消息数据
| ```javascript const req = new ChatWebSocket() client.ChatWebSocket(req).then(...).catch(...) ```