| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788 |
- import { Component, OnInit, Input, Output, EventEmitter, OnDestroy } from '@angular/core';
- import { CommonModule } from '@angular/common';
- import { Router, ActivatedRoute, RouterModule } from '@angular/router';
- import { IonicModule } from '@ionic/angular';
- import { WxworkSDK, WxworkCorp, WxworkAuth } from 'fmode-ng/core';
- import { FmodeParse, FmodeObject } from 'fmode-ng/parse';
- import { ProfileService } from '../../../../app/services/profile.service';
- import { ProjectBottomCardComponent } from '../../components/project-bottom-card/project-bottom-card.component';
- import { ProjectFilesModalComponent } from '../../components/project-files-modal/project-files-modal.component';
- import { ProjectMembersModalComponent } from '../../components/project-members-modal/project-members-modal.component';
- import { ProjectIssuesModalComponent } from '../../components/project-issues-modal/project-issues-modal.component';
- import { ProjectIssueService } from '../../services/project-issue.service';
- import { FormsModule } from '@angular/forms';
- import { CustomerSelectorComponent } from '../../components/contact-selector/contact-selector.component';
- import { OrderApprovalPanelComponent } from '../../../../app/shared/components/order-approval-panel/order-approval-panel.component';
- import { GroupChatSummaryComponent } from '../../components/group-chat-summary/group-chat-summary.component';
- const Parse = FmodeParse.with('nova');
- /**
- * 憿寧𤌍霂行��詨�蝏�辣
- *
- * �蠘�嚗? * 1. 撅閧內�偦𧫴畾萄紡�迎�霈W������&霈日�瘙���漱隞䀹�銵䎚��睸�𤾸�獢��
- * 2. �寞旿閫坿𠧧�批����
- * 3. 摮鞱楝�勗��a𧫴畾萄�摰? * 4. �舀�@Input�諹楝�勗��唬舅蝘齿㺭�桀�頧賣䲮撘? *
- * 頝舐眏嚗?wxwork/:cid/project/:projectId
- */
- @Component({
- selector: 'app-project-detail',
- standalone: true,
- imports: [
- CommonModule,
- IonicModule,
- RouterModule,
- ProjectBottomCardComponent,
- ProjectFilesModalComponent,
- ProjectMembersModalComponent,
- ProjectIssuesModalComponent,
- CustomerSelectorComponent,
- OrderApprovalPanelComponent,
- GroupChatSummaryComponent
- ],
- templateUrl: './project-detail.component.html',
- styleUrls: ['./project-detail.component.scss']
- })
- export class ProjectDetailComponent implements OnInit, OnDestroy {
- // 颲枏���㺭嚗�𣈲���隞嗅��剁�
- @Input() project: FmodeObject | null = null;
- @Input() groupChat: FmodeObject | null = null;
- @Input() currentUser: FmodeObject | null = null;
- // �桅�蝏蠘恣
- issueCount: number = 0;
- // 頝舐眏��㺭
- cid: string = '';
- projectId: string = '';
- groupId: string = '';
- profileId: string = '';
- chatId: string = ''; // 隞𦒘�敺株��交𧒄�?chat_id
- // 隡�凝SDK
- wxwork: WxworkSDK | null = null;
- wecorp: WxworkCorp | null = null;
- wxAuth: WxworkAuth | null = null; // WxworkAuth 摰硺�
- // �㰘蝸�嗆�? loading: boolean = true;
- error: string | null = null;
- // 憿寧𤌍�唳旿
- contact: FmodeObject | null = null;
- assignee: FmodeObject | null = null;
- // 敶枏��嗆挾
- currentStage: string = 'order'; // order | requirements | delivery | aftercare
- stages = [
- { id: 'order', name: '霈W����', icon: 'document-text-outline', number: 1 },
- { id: 'requirements', name: '蝖株恕��瘙?, icon: 'checkmark-circle-outline', number: 2 },
- { id: 'delivery', name: '鈭支��扯�', icon: 'rocket-outline', number: 3 },
- { id: 'aftercare', name: '�桀�敶埝﹝', icon: 'archive-outline', number: 4 }
- ];
- // ���
- canEdit: boolean = false;
- canViewCustomerPhone: boolean = false;
- role: string = '';
- // 璅⊥����嗆�? showFilesModal: boolean = false;
- showMembersModal: boolean = false;
- showIssuesModal: boolean = false;
- // �啣�嚗𡁜恥�瑁祕��儒�誯𢒰�輻𠶖�? showContactPanel: boolean = false;
- // �桀㭘�嗆�? surveyStatus: {
- filled: boolean;
- text: string;
- icon: string;
- surveyLog?: FmodeObject;
- contact?: FmodeObject;
- } = {
- filled: false,
- text: '�煾��䔮�?,
- icon: 'document-text-outline'
- };
- // �睃�嚗𡁻★�桀抅�砌縑�? showProjectInfoCollapsed: boolean = true;
- // 鈭衤辣�穃𨯬�典��? private stageCompletedListener: any = null;
- constructor(
- private router: Router,
- private route: ActivatedRoute,
- private profileService: ProfileService,
- private issueService: ProjectIssueService
- ) {}
- async ngOnInit() {
- // �瑕�頝舐眏��㺭
- this.cid = this.route.snapshot.paramMap.get('cid') || '';
- this.projectId = this.route.snapshot.paramMap.get('projectId') || '';
- this.groupId = this.route.snapshot.queryParamMap.get('groupId') || '';
- this.profileId = this.route.snapshot.queryParamMap.get('profileId') || '';
- this.chatId = this.route.snapshot.queryParamMap.get('chatId') || '';
- // �穃𨯬頝舐眏�睃�
- this.route.firstChild?.url.subscribe((segments) => {
- if (segments.length > 0) {
- this.currentStage = segments[0].path;
- console.log('�� 敶枏��嗆挾撌脫凒�?', this.currentStage);
- }
- });
- // �嘥��碶�敺格����銝漤獈憛鮋△�W�頧踝�
- await this.initWxworkAuth();
- await this.loadData();
- // �嘥��硋極雿𨀣��嗆挾嚗�𥅾蝻箏仃�蹱覔�桀歇摰峕�霈啣��冽鱏嚗? this.ensureWorkflowStage();
- // �穃𨯬��𧫴畾萄��𣂷�隞塚��芸𢆡�刻��唬�銝��航�
- this.stageCompletedListener = async (e: any) => {
- const stageId = e?.detail?.stage as string;
- if (!stageId) return;
- console.log('�?�交𤣰�圈𧫴畾萄��𣂷�隞?', stageId);
- await this.advanceToNextStage(stageId);
- };
- document.addEventListener('stage:completed', this.stageCompletedListener);
- }
- /**
- * 蝏�辣��瘥�𧒄皜��鈭衤辣�穃𨯬�? */
- ngOnDestroy() {
- if (this.stageCompletedListener) {
- document.removeEventListener('stage:completed', this.stageCompletedListener);
- console.log('�完 撌脫���𧫴畾萄��𣂷�隞嗥��砍膥');
- }
- }
- /**
- * �嘥��碶�敺格����銝漤獈憛鮋△�g�
- */
- async initWxworkAuth() {
- try {
- let cid = this.cid || localStorage.getItem("company") || "";
-
- // 憒��瘝⊥�cid嚗諹扇敶閗郎�𠹺�銝齿��粹�霂? if (!cid) {
- console.warn('�𩤃� �芣𪄳�軏ompany ID (cid)嚗䔶�敺桀��賢�銝滚虾�?);
- return;
- }
-
- this.wxAuth = new WxworkAuth({ cid: cid });
- this.wxwork = new WxworkSDK({ cid: cid, appId: 'crm' });
- this.wecorp = new WxworkCorp(cid);
-
- console.log('�?隡�凝SDK�嘥��𡝗����cid:', cid);
- } catch (error) {
- console.error('�?隡�凝SDK�嘥��硋仃韐?', error);
- // 銝漤獈憛鮋△�W�頧? }
- }
- /**
- * �睃�/撅訫� 憿寧𤌍�箸𧋦靽⊥�
- */
- toggleProjectInfo(): void {
- this.showProjectInfoCollapsed = !this.showProjectInfoCollapsed;
- }
- /**
- * 頝唾蓮�唳�摰𡁻𧫴畾? */
- goToStage(stageId: 'order'|'requirements'|'delivery'|'aftercare') {
- // 摮鞱楝�梧�敶枏�銝?/.../project-detail/:projectId/:stage
- this.currentStage = stageId;
- // 雿輻鍂銝羓漣�詨笆頝臬�嚗𣬚&靽嘥銁隞颱�撋��頝舐眏銝钅��賣迤蝖桀��? this.router.navigate(['../', stageId], { relativeTo: this.route });
- }
- /**
- * 隞𡒊�摰𡁻𧫴畾菜綫餈𥕦�銝衤�銝芷𧫴畾? */
- async advanceToNextStage(current: string) {
- const order = ['order','requirements','delivery','aftercare'];
- const idx = order.indexOf(current);
-
- console.log('�� �刻��嗆挾:', { current, idx, currentStage: this.currentStage });
-
- if (idx === -1) {
- console.warn('�𩤃� �芣𪄳�啣��漤𧫴畾?', current);
- return;
- }
-
- if (idx >= order.length - 1) {
- console.log('�?撌脣�颲暹��𡡞𧫴畾?);
- window?.fmode?.alert('���厰𧫴畾萄歇摰峕�嚗?);
- return;
- }
-
- const next = order[idx + 1];
- console.log('�∴� 頝唾蓮�唬�銝��嗆挾:', next);
- // ����吔���扇敶枏��嗆挾摰峕�撟嗉挽蝵桐�銝��嗆挾銝箏��? await this.persistStageProgress(current, next);
- // 撖潸⏛�唬�銝��嗆挾嚗���孵�撌乩�瘚���脣ế摰𡄯�隞���W�摰對�
- this.goToStage(next as any);
-
- const nextStageName = this.stages.find(s => s.id === next)?.name || next;
- window?.fmode?.alert(`撌脰䌊�刻歲頧砍�銝衤��嗆挾: ${nextStageName}`);
- }
- /**
- * 蝖桐�摮睃銁撌乩�瘚���漤𧫴畾萸���蝻箏仃�蹱覔�桀��鞱扇敶閗恣蝞? */
- ensureWorkflowStage() {
- if (!this.project) return;
- const order = ['order','requirements','delivery','aftercare'];
- const data = this.project.get('data') || {};
- const statuses = data.stageStatuses || {};
- let current = this.project.get('currentStage');
- if (!current) {
- // �曉�蝚砌�銝芣𧊋摰峕���𧫴畾? current = order.find(s => statuses[s] !== 'completed') || 'aftercare';
- this.project.set('currentStage', current);
- }
- }
- /**
- * ����㚚𧫴畾菜綫餈𨥈���扇敶枏�摰峕���挽蝵桐�銝��嗆挾嚗? */
- private async persistStageProgress(current: string, next: string) {
- if (!this.project) {
- console.warn('�𩤃� 憿寧𤌍撖寡情銝滚��剁��䭾�����?);
- return;
- }
-
- console.log('�𠒣 撘�憪𧢲�銋���嗆挾:', { current, next });
-
- const data = this.project.get('data') || {};
- data.stageStatuses = data.stageStatuses || {};
- data.stageStatuses[current] = 'completed';
- this.project.set('data', data);
- this.project.set('currentStage', next);
-
- console.log('�𠒣 霈曄蔭�嗆挾�嗆�?', {
- currentStage: next,
- stageStatuses: data.stageStatuses
- });
-
- try {
- await this.project.save();
- console.log('�?�嗆挾�嗆���銋���𣂼�');
- } catch (e) {
- console.warn('�𩤃� �嗆挾�嗆���銋��憭梯揖嚗�蕭�乩誑靽肽�瘚���舐誧蝏哨�:', e);
- }
- }
- /**
- * �㰘蝸�唳旿
- */
- async loadData() {
- try {
- this.loading = true;
- // 2. �瑕�敶枏��冽�嚗������典��滚𦛚�瑕�嚗? if (!this.currentUser?.id && this.wxAuth) {
- try {
- this.currentUser = await this.wxAuth.currentProfile();
- } catch (error) {
- console.warn('�𩤃� �瑕�敶枏��冽�Profile憭梯揖:', error);
- }
- }
- // 霈曄蔭���
- this.role = this.currentUser?.get('roleName') || '';
- this.canEdit = ['摰X�', '蝏��', '蝏�鵭', '蝞∠��?, '霈曇恣撣?, '摰X�銝餌恣'].includes(this.role);
- this.canViewCustomerPhone = ['摰X�', '蝏�鵭', '蝞∠��?].includes(this.role);
- const companyId = this.currentUser?.get('company')?.id || localStorage?.getItem("company");
- // 3. �㰘蝸憿寧𤌍
- if (!this.project) {
- if (this.projectId) {
- // �朞� projectId �㰘蝸嚗���𤾸蝱餈𥕦�嚗? const query = new Parse.Query('Project');
- query.include('contact', 'assignee','department','department.leader');
- this.project = await query.get(this.projectId);
- } else if (this.chatId) {
- // �朞� chat_id �交𪄳憿寧𤌍嚗��隡�凝蝢方�餈𥕦�嚗? if (companyId) {
- // ��䰻�?GroupChat
- const gcQuery = new Parse.Query('GroupChat');
- gcQuery.equalTo('chat_id', this.chatId);
- gcQuery.equalTo('company', companyId);
- let groupChat = await gcQuery.first();
- if (groupChat) {
- this.groupChat = groupChat;
- const projectPointer = groupChat.get('project');
- if (projectPointer) {
- const pQuery = new Parse.Query('Project');
- pQuery.include('contact', 'assignee','department','department.leader');
- this.project = await pQuery.get(projectPointer.id);
- }
- }
- if (!this.project) {
- throw new Error('霂亦黎�𠰴��芸��娪★�殷�霂瑕��典��啣�撱粹★�?);
- }
- }
- }
- }
-
- if(!this.groupChat?.id){
- const gcQuery2 = new Parse.Query('GroupChat');
- gcQuery2.equalTo('project', this.projectId);
- gcQuery2.equalTo('company', companyId);
- this.groupChat = await gcQuery2.first();
- }
- this.wxwork?.syncGroupChat(this.groupChat?.toJSON())
- if (!this.project) {
- throw new Error('�䭾��㰘蝸憿寧𤌍靽⊥�');
- }
- this.contact = this.project.get('contact');
- this.assignee = this.project.get('assignee');
- // �㰘蝸�桀㭘�嗆�? await this.loadSurveyStatus();
- // �湔鰵�桅�霈⊥㺭
- try {
- if (this.project?.id) {
- this.issueService.seed(this.project.id!);
- const counts = this.issueService.getCounts(this.project.id!);
- this.issueCount = counts.total;
- }
- } catch (e) {
- console.warn('蝏蠘恣�桅��圈�憭梯揖:', e);
- }
- // 4. �㰘蝸蝢方�嚗���𨀣瓷�劐��乩��斉roupId嚗? if (!this.groupChat && this.groupId) {
- try {
- const gcQuery = new Parse.Query('GroupChat');
- this.groupChat = await gcQuery.get(this.groupId);
- } catch (err) {
- console.warn('�㰘蝸蝢方�憭梯揖:', err);
- }
- }
- // 5. �寞旿憿寧𤌍敶枏��嗆挾霈曄蔭暺䁅恕頝舐眏
- const projectStage = this.project.get('currentStage');
- const stageMap: any = {
- '霈W����': 'order',
- '蝖株恕��瘙?: 'requirements',
- '�寞�蝖株恕': 'requirements',
- '�寞�瘛勗�': 'requirements',
- '鈭支��扯�': 'delivery',
- '撱箸芋': 'delivery',
- '頧航�': 'delivery',
- '皜脫�': 'delivery',
- '�擧�': 'delivery',
- '撠暹狡蝏梶�': 'aftercare',
- '摰X�霂�遠': 'aftercare',
- '�閗�憭��': 'aftercare'
- };
- const targetStage = stageMap[projectStage] || 'order';
- // 憒��敶枏�瘝⊥�摮鞱楝�梧�頝唾蓮�啣笆摨娪𧫴畾? if (!this.route.firstChild) {
- this.router.navigate([targetStage], { relativeTo: this.route, replaceUrl: true });
- }
- } catch (err: any) {
- console.error('�㰘蝸憭梯揖:', err);
- this.error = err.message || '�㰘蝸憭梯揖';
- } finally {
- this.loading = false;
- }
- }
- /**
- * ��揢�嗆挾
- */
- switchStage(stageId: string) {
- this.currentStage = stageId;
- this.router.navigate([stageId], { relativeTo: this.route });
- }
- /**
- * �瑕��嗆挾�嗆�? */
- getStageStatus(stageId: string): 'completed' | 'active' | 'pending' {
- // 憸𡏭𠧧�曄內隞���?撌乩�瘚�𠶖�?嚗䔶��𦯀葩�嗆�閫�楝�勗蔣�? const data = this.project?.get('data') || {};
- const statuses = data.stageStatuses || {};
- const workflowCurrent = this.project?.get('currentStage') || 'order';
- console.log('�綫 霈∠��嗆挾�嗆�?', {
- stageId,
- workflowCurrent,
- statuses,
- result: statuses[stageId] === 'completed' ? 'completed' : (workflowCurrent === stageId ? 'active' : 'pending')
- });
- if (statuses[stageId] === 'completed') return 'completed';
- if (workflowCurrent === stageId) return 'active';
- return 'pending';
- }
- /**
- * 餈𥪜�
- */
- goBack() {
- let ua = navigator.userAgent.toLowerCase();
- let isWeixin = ua.indexOf("micromessenger") != -1;
- if(isWeixin){
- this.router.navigate(['/wxwork', this.cid, 'project-loader']);
- }else{
- history.back();
- }
- }
- /**
- * �湔鰵憿寧𤌍�嗆挾
- */
- async updateProjectStage(stage: string) {
- if (!this.project || !this.canEdit) return;
- try {
- this.project.set('currentStage', stage);
- await this.project.save();
- // 瘛餃��嗆挾��蟮
- const data = this.project.get('data') || {};
- const stageHistory = data.stageHistory || [];
- stageHistory.push({
- stage,
- startTime: new Date(),
- status: 'current',
- operator: {
- id: this.currentUser!.id,
- name: this.currentUser!.get('name'),
- role: this.role
- }
- });
- this.project.set('data', { ...data, stageHistory });
- await this.project.save();
- } catch (err) {
- console.error('�湔鰵�嗆挾憭梯揖:', err);
- window?.fmode?.alert('�湔鰵憭梯揖');
- }
- }
- /**
- * �煾���敺格��? */
- async sendWxMessage(message: string) {
- if (!this.groupChat || !this.wecorp) return;
- try {
- const chatId = this.groupChat.get('chat_id');
- await this.wecorp.appchat.sendText(chatId, message);
- } catch (err) {
- console.error('�煾����臬仃韐?', err);
- }
- }
- /**
- * �㗇𥋘摰X�嚗��蝢方��𣂼�銝剝�㗇𥋘憭㚚��𠉛頂鈭綽�
- */
- async selectCustomer() {
- console.log(this.canEdit, this.groupChat)
- if (!this.groupChat) return;
- try {
- const memberList = this.groupChat.get('member_list') || [];
- const externalMembers = memberList.filter((m: any) => m.type === 2);
- if (externalMembers.length === 0) {
- window?.fmode?.alert('敶枏�蝢方�銝剜瓷�匧��刻�蝟颱犖');
- return;
- }
- console.log(externalMembers)
- // 蝞��訫��堆��㗇𥋘蝚砌�銝芸��刻�蝟颱犖
- // TODO: 摰䂿緵�㗇𥋘�沃I
- const selectedMember = externalMembers[0];
- await this.setCustomerFromMember(selectedMember);
- } catch (err) {
- console.error('�㗇𥋘摰X�憭梯揖:', err);
- window?.fmode?.alert('�㗇𥋘摰X�憭梯揖');
- }
- }
- /**
- * 隞𡒊黎�𣂼�霈曄蔭摰X�
- */
- async setCustomerFromMember(member: any) {
- if (!this.wecorp) return;
- try {
- const companyId = this.currentUser?.get('company')?.id || localStorage.getItem("company");
- if (!companyId) throw new Error('�䭾��瑕�隡��靽⊥�');
- // 1. �亥砭�臬炏撌脣��?ContactInfo
- const query = new Parse.Query('ContactInfo');
- query.equalTo('external_userid', member.userid);
- query.equalTo('company', companyId);
- let contactInfo = await query.first();
- // 2. 憒��銝滚��剁��朞�隡�凝API�瑕�撟嗅�撱? if (!contactInfo) {
- contactInfo = new Parse.Object("ContactInfo");
- }
- const externalContactData = await this.wecorp.externalContact.get(member.userid);
- console.log("externalContactData",externalContactData)
- const ContactInfo = Parse.Object.extend('ContactInfo');
- contactInfo.set('name', externalContactData.name);
- contactInfo.set('external_userid', member.userid);
- const company = new Parse.Object('Company');
- company.id = companyId;
- const companyPointer = company.toPointer();
- contactInfo.set('company', companyPointer);
- contactInfo.set('data', externalContactData);
- await contactInfo.save();
- // 3. 霈曄蔭銝粹★�桀恥�? if (this.project) {
- this.project.set('contact', contactInfo.toPointer());
- await this.project.save();
- this.contact = contactInfo;
- window?.fmode?.alert('摰X�霈曄蔭�𣂼�');
- }
- } catch (err) {
- console.error('霈曄蔭摰X�憭梯揖:', err);
- throw err;
- }
- }
- /**
- * �曄內��辣璅⊥���
- */
- showFiles() {
- this.showFilesModal = true;
- }
- /**
- * �曄內�𣂼�璅⊥���
- */
- showMembers() {
- this.showMembersModal = true;
- }
- /** �曄內�桅�璅⊥��� */
- showIssues() {
- this.showIssuesModal = true;
- }
- /**
- * �喲𡡒��辣璅⊥���
- */
- closeFilesModal() {
- this.showFilesModal = false;
- }
- /**
- * �喲𡡒�𣂼�璅⊥���
- */
- closeMembersModal() {
- this.showMembersModal = false;
- }
- /** �曄內摰X�霂行��X踎 */
- openContactPanel() {
- if (this.contact) {
- this.showContactPanel = true;
- }
- }
- /** �喲𡡒摰X�霂行��X踎 */
- closeContactPanel() {
- this.showContactPanel = false;
- }
- /** �喲𡡒�桅�璅⊥��� */
- closeIssuesModal() {
- this.showIssuesModal = false;
- if (this.project?.id) {
- const counts = this.issueService.getCounts(this.project.id!);
- this.issueCount = counts.total;
- }
- }
- /** 摰X��㗇𥋘鈭衤辣�噼�嚗�𦻖�嗅�蝏�辣颲枏枂嚗?*/
- onContactSelected(evt: { contact: FmodeObject; isNewCustomer: boolean; action: 'selected' | 'created' | 'updated' }) {
- this.contact = evt.contact;
- // �齿鰵�㰘蝸�桀㭘�嗆�? this.loadSurveyStatus();
- }
- /**
- * �㰘蝸�桀㭘�嗆�? */
- async loadSurveyStatus() {
- if (!this.project?.id) return;
- try {
- const query = new Parse.Query('SurveyLog');
- query.equalTo('project', this.project.toPointer());
- query.equalTo('type', 'survey-project');
- query.equalTo('isCompleted', true);
- query.include("contact")
- const surveyLog = await query.first();
- if (surveyLog) {
- this.surveyStatus = {
- filled: true,
- text: '�亦��桀㭘',
- icon: 'checkmark-circle',
- surveyLog,
- contact:surveyLog?.get("contact")
- };
- console.log('�?�桀㭘撌脣‵�?);
- } else {
- this.surveyStatus = {
- filled: false,
- text: '�煾��䔮�?,
- icon: 'document-text-outline'
- };
- console.log('�?�桀㭘�芸‵�?);
- }
- } catch (err) {
- console.error('�?�亥砭�桀㭘�嗆��仃韐?', err);
- }
- }
- /**
- * �煾��䔮�? */
- async sendSurvey() {
- if (!this.groupChat || !this.wxwork) {
- window?.fmode?.alert('�䭾��煾��䔮�?�芣𪄳�啁黎�𦠜�隡�凝SDK�芸�憪见�');
- return;
- }
- try {
- const chatId = this.groupChat.get('chat_id');
- const surveyUrl = `${document.baseURI}/wxwork/${this.cid}/survey/project/${this.project?.id}`;
- await this.wxwork.ww.openExistedChatWithMsg({
- chatId: chatId,
- msg: {
- msgtype: 'link',
- link: {
- title: '�𠰴振鋆���𨅯㦛�滚𦛚��瘙���亥”�?,
- desc: '銝箄悟�祆活�滚𦛚�渲斐������瘙?霂瑁�3-5���憛怠�蝞��剝䔮�?�蠘陝�舀�!',
- url: surveyUrl,
- imgUrl: `${document.baseURI}/assets/logo.jpg`
- }
- }
- });
- window?.fmode?.alert('�桀㭘撌脣����蝢方�!');
- } catch (err) {
- console.error('�?�煾��䔮�瑕仃韐?', err);
- window?.fmode?.alert('�煾��仃韐?霂琿�霂?);
- }
- }
- /**
- * �亦��桀㭘蝏𤘪�
- */
- async viewSurvey() {
- if (!this.surveyStatus.surveyLog) return;
- // 頝唾蓮�圈䔮�琿△�X䰻�讠��? this.router.navigate(['/wxwork', this.cid, 'survey', 'project', this.project?.id]);
- }
- /**
- * 憭���桀㭘�孵稬
- */
- async handleSurveyClick(event: Event) {
- event.stopPropagation();
- if (this.surveyStatus.filled) {
- // 撌脣‵�?�亦�蝏𤘪�
- await this.viewSurvey();
- } else {
- // �芸‵�?�煾��䔮�? await this.sendSurvey();
- }
- }
- /**
- * �臬炏�曄內摰⊥鸌�X踎
- * �∩辣嚗𡁜��滨鍂�瑟糓蝏�鵭 + 憿寧𤌍憭��霈W�����嗆挾 + 摰⊥鸌�嗆��蛹敺�恣�? * �𩤃� 銝湔𧒄�曉����嚗𡁜�霈豢��㕑��脫䰻�见恣�寥𢒰�選�瘚贝��剁�
- */
- get showApprovalPanel(): boolean {
- if (!this.project || !this.currentUser) {
- console.log('�� 摰⊥鸌�X踎璉��? 蝻箏�憿寧𤌍�𣇉鍂�瑟㺭�?);
- return false;
- }
-
- const userRole = this.currentUser.get('roleName') || '';
- // �𩤃� 銝湔𧒄瘜券�閫坿𠧧璉��伐���捂���㕑��脰挪�? // const isTeamLeader = userRole === '霈曇恣蝏�鵭' || userRole === 'team-leader';
- const isTeamLeader = true; // 銝湔𧒄�曉����
-
- const currentStage = this.project.get('currentStage') || '';
- const isOrderStage = currentStage === '霈W����' || currentStage === 'order';
-
- const data = this.project.get('data') || {};
- const approvalStatus = data.approvalStatus;
- const isPending = approvalStatus === 'pending';
-
- console.log('�� 摰⊥鸌�X踎璉��?[銝湔𧒄�曉����]:', {
- userRole,
- isTeamLeader,
- currentStage,
- isOrderStage,
- approvalStatus,
- isPending,
- result: isTeamLeader && isOrderStage && isPending
- });
-
- return isTeamLeader && isOrderStage && isPending;
- }
- /**
- * 憭��摰⊥鸌摰峕�鈭衤辣
- */
- async onApprovalCompleted(event: { action: 'approved' | 'rejected'; reason?: string; comment?: string }) {
- if (!this.project) return;
- try {
- const data = this.project.get('data') || {};
- const approvalHistory = data.approvalHistory || [];
- const latestRecord = approvalHistory[approvalHistory.length - 1];
- if (latestRecord) {
- latestRecord.status = event.action;
- latestRecord.approver = {
- id: this.currentUser?.id,
- name: this.currentUser?.get('name'),
- role: this.currentUser?.get('roleName')
- };
- latestRecord.approvalTime = new Date();
- latestRecord.comment = event.comment;
- latestRecord.reason = event.reason;
- }
- if (event.action === 'approved') {
- // �朞�摰⊥鸌嚗𡁏綫餈𥕦�蝖株恕��瘙�𧫴畾? data.approvalStatus = 'approved';
- this.project.set('currentStage', '蝖株恕��瘙?);
- this.project.set('data', data);
- await this.project.save();
-
- alert('�?摰⊥鸌�朞�嚗屸★�桀歇餈𥕦�蝖株恕��瘙�𧫴畾?);
-
- // �瑟鰵憿菟𢒰�唳旿
- await this.loadData();
- } else {
- // 撽喳�嚗帋���銁霈W�����嗆挾嚗諹扇敶閖底�𧼮��? data.approvalStatus = 'rejected';
- data.lastRejectionReason = event.reason || '�芣�靘𥕦��?;
- this.project.set('data', data);
- await this.project.save();
-
- alert('�?撌脤底�噼恥�𤏪�摰X�撠�𤣰�圈�𡁶䰻');
-
- // �瑟鰵憿菟𢒰�唳旿
- await this.loadData();
- }
- } catch (err) {
- console.error('憭��摰⊥鸌憭梯揖:', err);
- alert('摰⊥鸌�滢�憭梯揖嚗諹窈�滩�');
- }
- }
- }
- // duplicate inline CustomerSelectorComponent removed (we keep single declaration above)
|