checkin.ts 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. /**
  2. * 签到功能相关API
  3. */
  4. import { USE_MOCK } from '@/utils/config';
  5. import { mockCheckinRecords, mockCheckinStats, mockTodayCheckin } from '@/mock/checkin';
  6. export enum CheckinType {
  7. INVENTORY_TALLY = 'inventory_tally',
  8. DELIVERY_REPLENISH = 'delivery_replenish'
  9. }
  10. export enum CheckinTypeLabel {
  11. INVENTORY_TALLY = '理货盘点签到',
  12. DELIVERY_REPLENISH = '补货确认签到'
  13. }
  14. export interface LocationInfo {
  15. latitude: number;
  16. longitude: number;
  17. address: string;
  18. accuracy: number;
  19. }
  20. export interface CheckinPhoto {
  21. id: string;
  22. path: string;
  23. watermarkPath?: string;
  24. timestamp: number;
  25. location: LocationInfo;
  26. }
  27. export interface CheckinRecord {
  28. id: string;
  29. type: CheckinType;
  30. typeName: string;
  31. userId: number;
  32. userName: string;
  33. userNo: string;
  34. shopId?: number;
  35. shopName?: string;
  36. deviceId?: number;
  37. deviceName?: string;
  38. location: LocationInfo;
  39. photos: CheckinPhoto[];
  40. remark: string;
  41. status: 'pending' | 'synced' | 'failed';
  42. createdAt: string;
  43. syncedAt?: string;
  44. offlineId?: string;
  45. }
  46. export interface CheckinParams {
  47. type: CheckinType;
  48. shopId?: number;
  49. deviceId?: number;
  50. location: LocationInfo;
  51. photos: CheckinPhoto[];
  52. remark?: string;
  53. offlineId?: string;
  54. }
  55. export interface CheckinQueryParams {
  56. page?: number;
  57. pageSize?: number;
  58. type?: CheckinType;
  59. userId?: number;
  60. shopId?: number;
  61. startDate?: string;
  62. endDate?: string;
  63. status?: string;
  64. }
  65. export interface CheckinListResponse {
  66. list: CheckinRecord[];
  67. total: number;
  68. page: number;
  69. pageSize: number;
  70. }
  71. export interface CheckinStats {
  72. todayCount: number;
  73. weekCount: number;
  74. monthCount: number;
  75. inventoryTallyCount: number;
  76. deliveryReplenishCount: number;
  77. pendingSyncCount: number;
  78. }
  79. export interface TodayCheckin {
  80. hasInventoryTally: boolean;
  81. hasDeliveryReplenish: boolean;
  82. inventoryTallyTime?: string;
  83. deliveryReplenishTime?: string;
  84. }
  85. export async function submitCheckin(params: CheckinParams): Promise<CheckinRecord> {
  86. if (USE_MOCK) {
  87. const record: CheckinRecord = {
  88. id: 'checkin_' + Date.now(),
  89. type: params.type,
  90. typeName: params.type === CheckinType.INVENTORY_TALLY ? '理货盘点签到' : '补货确认签到',
  91. userId: 1,
  92. userName: '测试用户',
  93. userNo: 'EMP001',
  94. shopId: params.shopId,
  95. shopName: '测试门店',
  96. deviceId: params.deviceId,
  97. deviceName: params.deviceId ? '测试设备' : undefined,
  98. location: params.location,
  99. photos: params.photos,
  100. remark: params.remark || '',
  101. status: 'synced',
  102. createdAt: new Date().toISOString(),
  103. syncedAt: new Date().toISOString()
  104. };
  105. return Promise.resolve(record);
  106. }
  107. const { post } = await import('@/utils/request');
  108. return post('/checkin', params);
  109. }
  110. export async function getCheckinList(params: CheckinQueryParams = {}): Promise<CheckinListResponse> {
  111. if (USE_MOCK) {
  112. const { page = 1, pageSize = 10, type, startDate, endDate } = params;
  113. let list = [...mockCheckinRecords];
  114. if (type) {
  115. list = list.filter(item => item.type === type);
  116. }
  117. if (startDate) {
  118. list = list.filter(item => item.createdAt >= startDate);
  119. }
  120. if (endDate) {
  121. list = list.filter(item => item.createdAt <= endDate + ' 23:59:59');
  122. }
  123. const total = list.length;
  124. const startIndex = (page - 1) * pageSize;
  125. return Promise.resolve({
  126. list: list.slice(startIndex, startIndex + pageSize),
  127. total,
  128. page,
  129. pageSize
  130. });
  131. }
  132. const { get } = await import('@/utils/request');
  133. return get('/checkin', params);
  134. }
  135. export async function getCheckinDetail(id: string): Promise<CheckinRecord> {
  136. if (USE_MOCK) {
  137. const record = mockCheckinRecords.find(item => item.id === id);
  138. if (record) {
  139. return Promise.resolve(record);
  140. }
  141. return Promise.reject(new Error('签到记录不存在'));
  142. }
  143. const { get } = await import('@/utils/request');
  144. return get(`/checkin/${id}`);
  145. }
  146. export async function getCheckinStats(): Promise<CheckinStats> {
  147. if (USE_MOCK) {
  148. return Promise.resolve(mockCheckinStats);
  149. }
  150. const { get } = await import('@/utils/request');
  151. return get('/checkin/stats');
  152. }
  153. export async function getTodayCheckin(): Promise<TodayCheckin> {
  154. if (USE_MOCK) {
  155. return Promise.resolve(mockTodayCheckin);
  156. }
  157. const { get } = await import('@/utils/request');
  158. return get('/checkin/today');
  159. }
  160. export async function syncOfflineCheckins(records: CheckinRecord[]): Promise<{ success: number; failed: number }> {
  161. if (USE_MOCK) {
  162. return Promise.resolve({ success: records.length, failed: 0 });
  163. }
  164. const { post } = await import('@/utils/request');
  165. return post('/checkin/sync', { records });
  166. }
  167. export async function exportCheckinRecords(params: CheckinQueryParams): Promise<string> {
  168. if (USE_MOCK) {
  169. return Promise.resolve('https://example.com/export/checkin_records.xlsx');
  170. }
  171. const { get } = await import('@/utils/request');
  172. return get('/checkin/export', params);
  173. }