|
@@ -62,6 +62,28 @@ export class PageDynamic implements AfterViewInit {
|
|
|
};
|
|
|
selectedAward: CloudObject | null = null;
|
|
|
showAwardDetail = false;
|
|
|
+
|
|
|
+ //众包任务相关属性
|
|
|
+ crowdTasks: CloudObject[] = [];
|
|
|
+ filteredCrowdTasks: CloudObject[] = [];
|
|
|
+
|
|
|
+ taskStatuses = ['待领取', '进行中', '已完成'] as const;
|
|
|
+ taskTypes = [
|
|
|
+ { id: '1', name: '设计', icon: 'fa-paint-brush' },
|
|
|
+ { id: '2', name: '开发', icon: 'fa-code' },
|
|
|
+ { id: '3', name: '文案', icon: 'fa-pen' },
|
|
|
+ { id: '4', name: '调研', icon: 'fa-search' },
|
|
|
+ { id: '5', name: '翻译', icon: 'fa-language' }
|
|
|
+];
|
|
|
+ taskFilter = {
|
|
|
+ status: '' as '' | '待领取' | '进行中' | '已完成',
|
|
|
+ typeId: '',
|
|
|
+ minReward: 0,
|
|
|
+ maxReward: 10000
|
|
|
+ };
|
|
|
+ selectedTask: CloudObject | null = null;
|
|
|
+ showTaskDetail = false;
|
|
|
+ acceptingTask = false;
|
|
|
|
|
|
// 生成年份数组方法
|
|
|
generateYears(start: number, end: number): number[] {
|
|
@@ -102,6 +124,10 @@ export class PageDynamic implements AfterViewInit {
|
|
|
// 初始化模拟数据
|
|
|
this.createMockAwards();
|
|
|
await this.loadAwardData();
|
|
|
+
|
|
|
+ // 加载众包任务数据
|
|
|
+ await this.loadCrowdTasks();
|
|
|
+ await this.loadTaskTypes();
|
|
|
}
|
|
|
|
|
|
// 加载奖项数据
|
|
@@ -560,7 +586,234 @@ getAchievementIcon(category: string): string {
|
|
|
return icons[category] || 'star';
|
|
|
}
|
|
|
|
|
|
+// 加载众包任务
|
|
|
+ async loadCrowdTasks() {
|
|
|
+ try {
|
|
|
+ const query = new CloudQuery("CrowdTask");
|
|
|
+ query.include("type");
|
|
|
+ query.include("location");
|
|
|
+ query.include("publisher");
|
|
|
+ this.crowdTasks = await query.find();
|
|
|
+ this.filteredCrowdTasks = [...this.crowdTasks];
|
|
|
+ } catch (e) {
|
|
|
+ console.error('加载众包任务失败:', e);
|
|
|
+ // 创建模拟数据
|
|
|
+ this.createMockTasks();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 加载任务类型
|
|
|
+ async loadTaskTypes() {
|
|
|
+ // 直接使用本地定义的 taskTypes,不再从云端加载
|
|
|
+ // 如果需要,可以保留从云端加载的逻辑,但需要调整类型
|
|
|
+ console.log('使用本地任务类型定义');
|
|
|
+
|
|
|
+ // 如果需要从云端加载,可以这样调整:
|
|
|
+ /*
|
|
|
+ try {
|
|
|
+ const query = new CloudQuery("TaskType");
|
|
|
+ const types = await query.find();
|
|
|
+
|
|
|
+ // 转换类型以匹配本地定义
|
|
|
+ this.taskTypes = types.map(t => ({
|
|
|
+ id: t.id!,
|
|
|
+ name: t.get('name') as string,
|
|
|
+ icon: t.get('icon') as string
|
|
|
+ }));
|
|
|
+ } catch (e) {
|
|
|
+ console.error('加载任务类型失败,使用本地定义', e);
|
|
|
+ // 保留本地定义
|
|
|
+ }
|
|
|
+ */
|
|
|
+}
|
|
|
+
|
|
|
+ // 创建模拟类型
|
|
|
+ createMockType(id: string, name: string, icon: string): CloudObject {
|
|
|
+ const type = new CloudObject("TaskType");
|
|
|
+ type.set({ name, icon });
|
|
|
+ type.id = id;
|
|
|
+ return type;
|
|
|
+ }
|
|
|
|
|
|
+ // 创建模拟任务
|
|
|
+ createMockTasks() {
|
|
|
+ const tasks = [
|
|
|
+ {
|
|
|
+ id: '1',
|
|
|
+ title: '江西旅游宣传册设计',
|
|
|
+ description: '设计一本24页的江西旅游宣传册,包含庐山、景德镇等景点',
|
|
|
+ reward: 5000,
|
|
|
+ deadline: new Date('2023-12-31'),
|
|
|
+ status: '待领取' as const,
|
|
|
+ publisher: { objectId: 'user1' },
|
|
|
+ type: { objectId: '1' },
|
|
|
+ location: { objectId: 'loc1' }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: '2',
|
|
|
+ title: '文化协会官网开发',
|
|
|
+ description: '开发响应式网站,包含会员管理、活动发布等功能',
|
|
|
+ reward: 15000,
|
|
|
+ deadline: new Date('2023-11-30'),
|
|
|
+ status: '进行中' as const,
|
|
|
+ publisher: { objectId: 'user2' },
|
|
|
+ type: { objectId: '2' },
|
|
|
+ location: { objectId: 'loc2' }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: '3',
|
|
|
+ title: '非遗文化研究报告',
|
|
|
+ description: '撰写关于江西非遗文化保护与传承的10万字研究报告',
|
|
|
+ reward: 8000,
|
|
|
+ deadline: new Date('2024-01-15'),
|
|
|
+ status: '待领取' as const,
|
|
|
+ publisher: { objectId: 'user3' },
|
|
|
+ type: { objectId: '4' },
|
|
|
+ location: { objectId: 'loc1' }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: '4',
|
|
|
+ title: '瓷器产品文案翻译',
|
|
|
+ description: '将30件景德镇瓷器产品说明翻译成英文',
|
|
|
+ reward: 3000,
|
|
|
+ deadline: new Date('2023-10-31'),
|
|
|
+ status: '已完成' as const,
|
|
|
+ publisher: { objectId: 'user4' },
|
|
|
+ type: { objectId: '5' },
|
|
|
+ location: { objectId: 'loc3' }
|
|
|
+ }
|
|
|
+ ];
|
|
|
+
|
|
|
+ this.crowdTasks = tasks.map(task => {
|
|
|
+ const obj = new CloudObject("CrowdTask");
|
|
|
+ obj.set(task);
|
|
|
+ obj.id = task.id;
|
|
|
+ return obj;
|
|
|
+ });
|
|
|
+
|
|
|
+ this.filteredCrowdTasks = [...this.crowdTasks];
|
|
|
+ // 手动触发变更检测
|
|
|
+ this.cdr.detectChanges();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 筛选任务
|
|
|
+ filterTasks() {
|
|
|
+ this.filteredCrowdTasks = this.crowdTasks.filter(task => {
|
|
|
+ const taskStatus = task.get('status');
|
|
|
+ const taskTypeId = task.get('type')?.objectId;
|
|
|
+ const reward = task.get('reward') || 0;
|
|
|
+
|
|
|
+ // 状态筛选
|
|
|
+ if (this.taskFilter.status && taskStatus !== this.taskFilter.status) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 类型筛选
|
|
|
+ if (this.taskFilter.typeId && taskTypeId !== this.taskFilter.typeId) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 奖励范围筛选
|
|
|
+ if (reward < this.taskFilter.minReward || reward > this.taskFilter.maxReward) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 重置筛选
|
|
|
+ resetTaskFilter() {
|
|
|
+ this.taskFilter = {
|
|
|
+ status: '',
|
|
|
+ typeId: '',
|
|
|
+ minReward: 0,
|
|
|
+ maxReward: 10000
|
|
|
+ };
|
|
|
+ this.filterTasks();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查看任务详情
|
|
|
+ viewTaskDetail(task: CloudObject) {
|
|
|
+ this.selectedTask = task;
|
|
|
+ this.showTaskDetail = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取类型图标
|
|
|
+ getTaskTypeIcon(task: CloudObject): string {
|
|
|
+ const typeId = task.get('type')?.objectId;
|
|
|
+ const type = this.taskTypes.find(t => t.id === typeId);
|
|
|
+ return type?.icon || 'fa-tasks';
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取类型名称
|
|
|
+ getTaskTypeName(task: CloudObject): string {
|
|
|
+ const typeId = task.get('type')?.objectId;
|
|
|
+ const type = this.taskTypes.find(t => t.id === typeId);
|
|
|
+ return type?.name || '未知类型';
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取空间名称
|
|
|
+ getLocationName(task: CloudObject): string {
|
|
|
+ const location = task.get('location');
|
|
|
+ return location?.get('name') || '未知空间';
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取发布者名称
|
|
|
+ getPublisherName(task: CloudObject): string {
|
|
|
+ const publisher = task.get('publisher');
|
|
|
+ return publisher?.get('username') || '未知发布者';
|
|
|
+ }
|
|
|
+
|
|
|
+ // 接取任务
|
|
|
+ async acceptTask(task: CloudObject) {
|
|
|
+ if (!this.currentUser) {
|
|
|
+ alert('请先登录!');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (task.get('status') !== '待领取') {
|
|
|
+ alert('该任务无法接取');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.acceptingTask = true;
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 模拟接单过程
|
|
|
+ await new Promise(resolve => setTimeout(resolve, 1500));
|
|
|
+
|
|
|
+ // 实际应用中应更新任务状态和执行者
|
|
|
+ // const updatedTask = new CloudObject("CrowdTask");
|
|
|
+ // updatedTask.id = task.id;
|
|
|
+ // updatedTask.set({
|
|
|
+ // status: '进行中',
|
|
|
+ // worker: this.currentUser.toPointer()
|
|
|
+ // });
|
|
|
+ // await updatedTask.save();
|
|
|
+
|
|
|
+ // 更新本地状态
|
|
|
+ task.set({ status: '进行中' });
|
|
|
+ task.set({ worker: this.currentUser?.toPointer() });
|
|
|
+
|
|
|
+
|
|
|
+ // 触发陶轮旋转动画
|
|
|
+ const taskElement = document.querySelector(`#task-${task.id}`);
|
|
|
+ if (taskElement) {
|
|
|
+ taskElement.classList.add('accepting');
|
|
|
+ setTimeout(() => {
|
|
|
+ taskElement.classList.remove('accepting');
|
|
|
+ }, 2000);
|
|
|
+ }
|
|
|
+
|
|
|
+ alert('接单成功!');
|
|
|
+ } catch (e) {
|
|
|
+ console.error('接单失败:', e);
|
|
|
+ alert('接单失败,请重试');
|
|
|
+ } finally {
|
|
|
+ this.acceptingTask = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
|
|
|
|