Files
jiu/client/lib/repositories/shop_repository.dart
T
wangjia a05f9bd4ec
Deploy / deploy (push) Failing after 8s
feat(shop): 门店 logo 上传 + 侧边栏品牌替换
- shops 表新增 logo_url 字段,AutoMigrate 自动建列
- 后端新增 POST /api/v1/shop/logo 接口(管理员),图片裁剪为 256×256 JPEG 存储
- UpdateInfo 支持传入 logo_url
- 侧边栏「岩美」替换为门店真实名称 + 自定义 logo
- 无 logo 时显示店名首字文字头像(深蓝底白字)
- 设置页「酒行信息」展示 logo 预览,编辑弹窗新增「更换 Logo」上传按钮
- 修复库存导入计数逻辑:total/imported/updated/errors 四项分别统计
- 库存导入去重改为双路索引(编号 + 名称|系列|规格),避免 key 不一致误判新增
- settings 页导入结果统一显示「重复 X 条」,兼容 skipped 和 updated 两个字段

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 20:03:43 +08:00

50 lines
1.5 KiB
Dart

import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import '../core/api/api_client.dart';
import '../core/exceptions.dart';
import '../models/shop.dart';
class ShopRepository {
final ApiClient _client;
const ShopRepository(this._client);
Future<ShopInfo> getInfo() async {
try {
final resp = await _client.get('/shop/info');
return ShopInfo.fromJson(resp.data as Map<String, dynamic>);
} on DioException catch (e) {
throw AppException(
e.response?.data?['error'] as String? ?? '获取酒行信息失败',
statusCode: e.response?.statusCode,
);
}
}
Future<ShopInfo> updateInfo(Map<String, dynamic> body) async {
try {
final resp = await _client.put('/shop/info', data: body);
return ShopInfo.fromJson(resp.data as Map<String, dynamic>);
} on DioException catch (e) {
throw AppException(
e.response?.data?['error'] as String? ?? '更新失败',
statusCode: e.response?.statusCode,
);
}
}
Future<String> uploadLogo(Uint8List bytes, String filename) async {
try {
final formData = FormData.fromMap({
'file': MultipartFile.fromBytes(bytes, filename: filename),
});
final resp = await _client.post('/shop/logo', data: formData);
return (resp.data as Map<String, dynamic>)['logo_url'] as String? ?? '';
} on DioException catch (e) {
throw AppException(
e.response?.data?['error'] as String? ?? 'Logo 上传失败',
statusCode: e.response?.statusCode,
);
}
}
}