activity-api.js 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. /**
  2. * 活动管理API接口系统
  3. * 支持活动的增删改查、海报管理、时间地点管理
  4. */
  5. class ActivityApiService {
  6. constructor() {
  7. this.listeners = []; // 数据变化监听器
  8. this.initActivityData();
  9. }
  10. // 初始化活动数据
  11. initActivityData() {
  12. const activities = this.getAllActivities();
  13. if (activities.length === 0) {
  14. const sampleActivities = [
  15. {
  16. id: 'activity_001',
  17. name: '北京春季音乐节',
  18. description: '2024年北京春季音乐节,汇聚国内外知名音乐人',
  19. poster: '/images/activity1.jpg',
  20. startDate: '2024-03-15',
  21. endDate: '2024-03-17',
  22. city: '北京',
  23. venue: '北京国家体育场(鸟巢)',
  24. address: '北京市朝阳区国家体育场南路1号',
  25. coordinates: {
  26. lng: 116.404,
  27. lat: 39.915
  28. },
  29. status: 'active', // active, inactive, draft
  30. createTime: '2024-01-15 10:00:00',
  31. updateTime: '2024-01-15 10:00:00',
  32. tags: ['音乐节', '春季', '户外'],
  33. organizer: '北京文化传媒有限公司',
  34. contact: {
  35. phone: '400-123-4567',
  36. email: 'contact@musicfestival.com'
  37. }
  38. },
  39. {
  40. id: 'activity_002',
  41. name: '上海国际车展',
  42. description: '2024年上海国际汽车工业展览会',
  43. poster: '/images/activity2.jpg',
  44. startDate: '2024-04-20',
  45. endDate: '2024-04-28',
  46. city: '上海',
  47. venue: '上海国家会展中心',
  48. address: '上海市青浦区崧泽大道333号',
  49. coordinates: {
  50. lng: 121.473,
  51. lat: 31.230
  52. },
  53. status: 'active',
  54. createTime: '2024-01-20 14:00:00',
  55. updateTime: '2024-01-20 14:00:00',
  56. tags: ['车展', '国际', '工业'],
  57. organizer: '上海国际展览有限公司',
  58. contact: {
  59. phone: '400-234-5678',
  60. email: 'info@autoshow.com'
  61. }
  62. }
  63. ];
  64. this.saveActivities(sampleActivities);
  65. }
  66. }
  67. // 获取所有活动
  68. getAllActivities() {
  69. try {
  70. return wx.getStorageSync('activities') || [];
  71. } catch (error) {
  72. console.error('获取活动数据失败:', error);
  73. return [];
  74. }
  75. }
  76. // 保存活动数据
  77. saveActivities(activities) {
  78. try {
  79. wx.setStorageSync('activities', activities);
  80. this.notifyListeners(activities);
  81. return true;
  82. } catch (error) {
  83. console.error('保存活动数据失败:', error);
  84. return false;
  85. }
  86. }
  87. // 根据ID获取活动
  88. getActivityById(activityId) {
  89. const activities = this.getAllActivities();
  90. return activities.find(activity => activity.id === activityId);
  91. }
  92. // 创建活动
  93. createActivity(activityData) {
  94. const activities = this.getAllActivities();
  95. const newActivity = {
  96. ...activityData,
  97. id: this.generateActivityId(),
  98. createTime: new Date().toISOString().replace('T', ' ').substring(0, 19),
  99. updateTime: new Date().toISOString().replace('T', ' ').substring(0, 19),
  100. status: activityData.status || 'active'
  101. };
  102. activities.push(newActivity);
  103. this.saveActivities(activities);
  104. return newActivity;
  105. }
  106. // 更新活动
  107. updateActivity(activityId, updateData) {
  108. const activities = this.getAllActivities();
  109. const activityIndex = activities.findIndex(activity => activity.id === activityId);
  110. if (activityIndex === -1) {
  111. throw new Error('活动不存在');
  112. }
  113. activities[activityIndex] = {
  114. ...activities[activityIndex],
  115. ...updateData,
  116. updateTime: new Date().toISOString().replace('T', ' ').substring(0, 19)
  117. };
  118. this.saveActivities(activities);
  119. return activities[activityIndex];
  120. }
  121. // 删除活动
  122. deleteActivity(activityId) {
  123. const activities = this.getAllActivities();
  124. const filteredActivities = activities.filter(activity => activity.id !== activityId);
  125. if (filteredActivities.length === activities.length) {
  126. throw new Error('活动不存在');
  127. }
  128. this.saveActivities(filteredActivities);
  129. return true;
  130. }
  131. // 搜索活动
  132. searchActivities(searchParams) {
  133. const activities = this.getAllActivities();
  134. let filteredActivities = [...activities];
  135. // 按活动名称搜索
  136. if (searchParams.name) {
  137. filteredActivities = filteredActivities.filter(activity =>
  138. activity.name.toLowerCase().includes(searchParams.name.toLowerCase())
  139. );
  140. }
  141. // 按城市搜索
  142. if (searchParams.city) {
  143. filteredActivities = filteredActivities.filter(activity =>
  144. activity.city.includes(searchParams.city)
  145. );
  146. }
  147. // 按场馆搜索
  148. if (searchParams.venue) {
  149. filteredActivities = filteredActivities.filter(activity =>
  150. activity.venue.toLowerCase().includes(searchParams.venue.toLowerCase())
  151. );
  152. }
  153. // 按状态搜索
  154. if (searchParams.status) {
  155. filteredActivities = filteredActivities.filter(activity =>
  156. activity.status === searchParams.status
  157. );
  158. }
  159. // 按日期范围搜索
  160. if (searchParams.startDate && searchParams.endDate) {
  161. filteredActivities = filteredActivities.filter(activity => {
  162. const activityStartDate = new Date(activity.startDate);
  163. const searchStartDate = new Date(searchParams.startDate);
  164. const searchEndDate = new Date(searchParams.endDate);
  165. return activityStartDate >= searchStartDate && activityStartDate <= searchEndDate;
  166. });
  167. }
  168. // 排序
  169. const sortBy = searchParams.sortBy || 'createTime';
  170. const sortOrder = searchParams.sortOrder || 'desc';
  171. filteredActivities.sort((a, b) => {
  172. let aValue = a[sortBy];
  173. let bValue = b[sortBy];
  174. if (sortBy === 'createTime' || sortBy === 'updateTime' || sortBy === 'startDate') {
  175. aValue = new Date(aValue);
  176. bValue = new Date(bValue);
  177. }
  178. if (sortOrder === 'asc') {
  179. return aValue > bValue ? 1 : -1;
  180. } else {
  181. return aValue < bValue ? 1 : -1;
  182. }
  183. });
  184. return {
  185. activities: filteredActivities,
  186. total: filteredActivities.length,
  187. page: searchParams.page || 1,
  188. pageSize: searchParams.pageSize || 20
  189. };
  190. }
  191. // 获取活动统计信息
  192. getActivityStatistics() {
  193. const activities = this.getAllActivities();
  194. const stats = {
  195. total: activities.length,
  196. byStatus: {},
  197. byCity: {},
  198. byMonth: {},
  199. upcoming: 0
  200. };
  201. const now = new Date();
  202. activities.forEach(activity => {
  203. // 按状态统计
  204. stats.byStatus[activity.status] = (stats.byStatus[activity.status] || 0) + 1;
  205. // 按城市统计
  206. stats.byCity[activity.city] = (stats.byCity[activity.city] || 0) + 1;
  207. // 按月份统计
  208. const month = activity.startDate.substring(0, 7); // YYYY-MM
  209. stats.byMonth[month] = (stats.byMonth[month] || 0) + 1;
  210. // 即将开始的活动
  211. const activityDate = new Date(activity.startDate);
  212. if (activityDate > now) {
  213. stats.upcoming++;
  214. }
  215. });
  216. return stats;
  217. }
  218. // 批量更新活动状态
  219. batchUpdateActivityStatus(activityIds, status) {
  220. const activities = this.getAllActivities();
  221. const updatedActivities = activities.map(activity => {
  222. if (activityIds.includes(activity.id)) {
  223. return {
  224. ...activity,
  225. status,
  226. updateTime: new Date().toISOString().replace('T', ' ').substring(0, 19)
  227. };
  228. }
  229. return activity;
  230. });
  231. this.saveActivities(updatedActivities);
  232. return true;
  233. }
  234. // 导出活动数据
  235. exportActivities(searchParams = {}) {
  236. const result = this.searchActivities(searchParams);
  237. return {
  238. activities: result.activities,
  239. exportTime: new Date().toISOString(),
  240. total: result.total,
  241. searchParams
  242. };
  243. }
  244. // 生成活动ID
  245. generateActivityId() {
  246. const timestamp = Date.now();
  247. const random = Math.floor(Math.random() * 1000).toString().padStart(3, '0');
  248. return `activity_${timestamp}_${random}`;
  249. }
  250. // 监听器管理
  251. addListener(callback) {
  252. this.listeners.push(callback);
  253. }
  254. removeListener(callback) {
  255. const index = this.listeners.indexOf(callback);
  256. if (index > -1) {
  257. this.listeners.splice(index, 1);
  258. }
  259. }
  260. notifyListeners(activities) {
  261. this.listeners.forEach(callback => {
  262. try {
  263. callback(activities);
  264. } catch (error) {
  265. console.error('活动数据监听器回调执行失败:', error);
  266. }
  267. });
  268. }
  269. // 同步活动数据
  270. syncActivityData() {
  271. const activities = this.getAllActivities();
  272. this.notifyListeners(activities);
  273. return activities;
  274. }
  275. }
  276. // 创建单例实例
  277. const activityApiService = new ActivityApiService();
  278. export default activityApiService;