|
|
@@ -14,6 +14,16 @@ interface SurveyChart {
|
|
|
questions: { id: string; title: string; type: string; options: { text: string; value: string; count: number }[]; otherCount: number }[];
|
|
|
}
|
|
|
|
|
|
+interface PlatformMemberPage {
|
|
|
+ companyObjectId: string;
|
|
|
+ compId: number;
|
|
|
+ creatorUsername: string;
|
|
|
+ page: number;
|
|
|
+ pageSize: number;
|
|
|
+ total: number;
|
|
|
+ results: Record<string, unknown>[];
|
|
|
+}
|
|
|
+
|
|
|
@Component({
|
|
|
selector: 'app-admin-resource',
|
|
|
standalone: true,
|
|
|
@@ -149,18 +159,24 @@ export class AdminResourceComponent implements OnInit {
|
|
|
readonly filterSystemLogEndDate = signal('');
|
|
|
readonly updatingMisType = signal(false);
|
|
|
readonly updatingPageStyle = signal(false);
|
|
|
+ readonly updatingPlatformCompany = signal(false);
|
|
|
+ readonly platformMembers = signal<PlatformMemberPage | null>(null);
|
|
|
+ readonly platformMembersLoading = signal(false);
|
|
|
+ readonly platformMembersError = signal('');
|
|
|
+ readonly platformMemberUsername = signal('');
|
|
|
+ readonly platformCreatorUsername = signal('');
|
|
|
readonly selectedIds = signal<string[]>([]);
|
|
|
readonly bulkError = signal('');
|
|
|
readonly bulkMessage = signal('');
|
|
|
readonly icons = { ChevronLeft, ChevronRight, Eye, KeyRound, LoaderCircle, Pencil, Plus, RefreshCw, Search, Trash2, X };
|
|
|
readonly columns = computed(() => {
|
|
|
const fields = this.schema()?.fields ?? [];
|
|
|
- const preferred = ['objectId', 'name', 'title', 'typeName', 'pageNodeName', 'tlpName', 'pName', 'pTitle', 'questionTitle', 'tName', 'newsName', 'nodeName', 'value', 'remark', 'qtitle', 'sName', 'storeName', 'styleName', 'count', 'content', 'str1', 'categoryname', 'dicname', 'cateName', 'gradeName', 'cClassName', 'testPoint', 'kName', 'tname', 'username', 'userName', 'realName', 'cname', 'type1', 'type2', 'detail', 'cdate', 'sRemrk', 'askId', 'zoneId', 'typeId', 'shape', 'qtype', 'required', 'ztype', 'priority', 'zstatus', 'storeState', 'storeCommendState', 'storeStyleId', 'sDefault', 'sIndex', 'str4', 'sdate', 'edate', 'fileUrl', 'type', 'state', 'eliteLevel', 'orderId', 'mobile', 'sourceKey', 'status', 'createdAt', 'updatedAt'];
|
|
|
+ const preferred = ['objectId', 'name', 'title', 'typeName', 'pageNodeName', 'compName', 'tlpName', 'pName', 'pTitle', 'questionTitle', 'tName', 'newsName', 'nodeName', 'value', 'remark', 'qtitle', 'sName', 'storeName', 'styleName', 'count', 'content', 'str1', 'categoryname', 'dicname', 'cateName', 'gradeName', 'cClassName', 'testPoint', 'kName', 'tname', 'username', 'userName', 'realName', 'cname', 'type1', 'type2', 'detail', 'cdate', 'sRemrk', 'askId', 'zoneId', 'typeId', 'shape', 'qtype', 'required', 'ztype', 'priority', 'zstatus', 'storeState', 'storeCommendState', 'storeStyleId', 'sDefault', 'sIndex', 'str4', 'sdate', 'edate', 'fileUrl', 'type', 'state', 'eliteLevel', 'orderId', 'mobile', 'sourceKey', 'status', 'createdAt', 'updatedAt'];
|
|
|
const rank = (name: string): number => { const index = preferred.indexOf(name); return index < 0 ? preferred.length : index; };
|
|
|
return fields.map((field, index) => ({ field, index })).sort((a, b) => rank(a.field.name) - rank(b.field.name) || a.index - b.index).map(({ field }) => field).slice(0, 7);
|
|
|
});
|
|
|
readonly pageCount = computed(() => Math.max(1, Math.ceil((this.page()?.total ?? 0) / (this.page()?.pageSize || 20))));
|
|
|
- readonly bulkEnabled = computed(() => ['_User', 'CommonModel', 'Node', 'Special', 'Guestbook', 'GuestBar', 'Datadiccategory', 'Datadic', 'GradeCate', 'Grade', 'Currency', 'SysHoliday', 'Search', 'AdZone', 'AdInfo', 'FontPicShape', 'FontPicShapeType', 'DesignAsk', 'DesignQuestion', 'DesignAnswer', 'ServiceSeat', 'Temp', 'StoreApplication', 'StoreStyle', 'UserLevel', 'Baike', 'CRMSAttr', 'ShopFareTlp', 'MisType', 'PageStyle'].includes(this.className()));
|
|
|
+ readonly bulkEnabled = computed(() => ['_User', 'CommonModel', 'Node', 'Special', 'Guestbook', 'GuestBar', 'Datadiccategory', 'Datadic', 'GradeCate', 'Grade', 'Currency', 'SysHoliday', 'Search', 'AdZone', 'AdInfo', 'FontPicShape', 'FontPicShapeType', 'DesignAsk', 'DesignQuestion', 'DesignAnswer', 'ServiceSeat', 'Temp', 'StoreApplication', 'StoreStyle', 'UserLevel', 'Baike', 'CRMSAttr', 'ShopFareTlp', 'MisType', 'PageStyle', 'PlatComp'].includes(this.className()));
|
|
|
readonly allPageSelected = computed(() => {
|
|
|
const ids = (this.page()?.results || []).map((row) => String(row['objectId'] || '')).filter(Boolean);
|
|
|
return Boolean(ids.length) && ids.every((id) => this.selectedIds().includes(id));
|
|
|
@@ -197,7 +213,7 @@ export class AdminResourceComponent implements OnInit {
|
|
|
if (this.className() === 'FontPicShape' && reloadSchema) await this.loadFontShapeTypes();
|
|
|
if (['DesignQuestion', 'DesignAnswer'].includes(this.className()) && reloadSchema) { await this.loadSurveys(); if (!this.filterSurveyId() && this.surveys().length) this.filterSurveyId.set(this.surveyIdOf(this.surveys()[0])); }
|
|
|
if (this.className() === 'StoreApplication' && reloadSchema) await this.loadStoreStyles();
|
|
|
- const pageOperation = this.className() === 'Grade' && this.filterGradeCategoryId() > 0 ? 'gradeOptions' : this.className() === 'Search' ? 'searchNavigations' : this.className() === 'AdZone' ? 'adZones' : this.className() === 'AdInfo' ? 'adInfos' : this.className() === 'FontPicShape' ? 'fontShapes' : this.className() === 'FontPicShapeType' ? 'fontShapeTypes' : this.className() === 'DesignAsk' ? 'surveys' : this.className() === 'DesignQuestion' ? 'surveyQuestions' : this.className() === 'DesignAnswer' ? 'surveyResults' : this.className() === 'ServiceSeat' ? 'serviceSeats' : this.className() === 'Temp' ? 'serviceCodes' : this.className() === 'StoreApplication' ? 'storeApplications' : this.className() === 'StoreStyle' ? 'storeStyles' : this.className() === 'ContentTagKey' ? 'contentTagKeys' : this.className() === 'UserLevel' ? 'userLevels' : this.className() === 'UserMoneyLog' ? 'userMoneyLogs' : this.className() === 'Baike' ? 'baikeEntries' : this.className() === 'CRMSAttr' ? 'crmClientTypes' : this.className() === 'ShopFareTlp' ? 'shopFareTemplates' : this.className() === 'SysLog' ? 'systemLogs' : this.className() === 'MisType' ? 'misTypes' : this.className() === 'PageStyle' ? 'pageStyles' : 'list';
|
|
|
+ const pageOperation = this.className() === 'Grade' && this.filterGradeCategoryId() > 0 ? 'gradeOptions' : this.className() === 'Search' ? 'searchNavigations' : this.className() === 'AdZone' ? 'adZones' : this.className() === 'AdInfo' ? 'adInfos' : this.className() === 'FontPicShape' ? 'fontShapes' : this.className() === 'FontPicShapeType' ? 'fontShapeTypes' : this.className() === 'DesignAsk' ? 'surveys' : this.className() === 'DesignQuestion' ? 'surveyQuestions' : this.className() === 'DesignAnswer' ? 'surveyResults' : this.className() === 'ServiceSeat' ? 'serviceSeats' : this.className() === 'Temp' ? 'serviceCodes' : this.className() === 'StoreApplication' ? 'storeApplications' : this.className() === 'StoreStyle' ? 'storeStyles' : this.className() === 'ContentTagKey' ? 'contentTagKeys' : this.className() === 'UserLevel' ? 'userLevels' : this.className() === 'UserMoneyLog' ? 'userMoneyLogs' : this.className() === 'Baike' ? 'baikeEntries' : this.className() === 'CRMSAttr' ? 'crmClientTypes' : this.className() === 'ShopFareTlp' ? 'shopFareTemplates' : this.className() === 'SysLog' ? 'systemLogs' : this.className() === 'MisType' ? 'misTypes' : this.className() === 'PageStyle' ? 'pageStyles' : this.className() === 'PlatComp' ? 'platformCompanies' : 'list';
|
|
|
const pagePayload: Record<string, unknown> = { className: this.className(), page: pageNumber, pageSize: 20, search: this.search().trim() };
|
|
|
if (pageOperation === 'gradeOptions') { pagePayload['categoryId'] = this.filterGradeCategoryId(); pagePayload['parentId'] = this.filterGradeParentId(); }
|
|
|
if (pageOperation === 'searchNavigations') { pagePayload['type'] = this.filterSearchNavigationType(); pagePayload['state'] = this.filterSearchNavigationState(); pagePayload['elite'] = this.filterSearchNavigationElite(); }
|
|
|
@@ -217,21 +233,22 @@ export class AdminResourceComponent implements OnInit {
|
|
|
finally { this.loading.set(false); }
|
|
|
}
|
|
|
|
|
|
- openCreate(): void { this.draftId.set(''); this.draft.set({}); this.fieldErrors.set({}); this.fieldInputs.set({}); this.resetPasswordFields(); this.resetCreateUserFields(); this.resetUserActions(); this.resetContentActions(); this.resetNodeActions(); this.resetSpecialActions(); this.resetGuestbookActions(); this.resetGuestCategoryActions(); this.resetBarActions(); this.resetExamClassActions(); this.resetExamPointActions(); this.resetKnowledgeActions(); this.resetTeacherActions(); this.resetDictionaryActions(); this.resetGradeActions(); this.resetAdActions(); this.resetFontShapeActions(); this.resetSurveyActions(); this.resetServiceActions(); this.resetStoreActions(); this.resetTagKeyActions(); this.editorOpen.set(true); }
|
|
|
+ openCreate(): void { this.draftId.set(''); this.draft.set({}); this.fieldErrors.set({}); this.fieldInputs.set({}); this.resetPasswordFields(); this.resetCreateUserFields(); this.resetUserActions(); this.resetContentActions(); this.resetNodeActions(); this.resetSpecialActions(); this.resetGuestbookActions(); this.resetGuestCategoryActions(); this.resetBarActions(); this.resetExamClassActions(); this.resetExamPointActions(); this.resetKnowledgeActions(); this.resetTeacherActions(); this.resetDictionaryActions(); this.resetGradeActions(); this.resetAdActions(); this.resetFontShapeActions(); this.resetSurveyActions(); this.resetServiceActions(); this.resetStoreActions(); this.resetTagKeyActions(); this.resetPlatformCompanyActions(); this.editorOpen.set(true); }
|
|
|
async openEdit(row: Record<string, unknown>): Promise<void> {
|
|
|
const objectId = String(row['objectId'] ?? '');
|
|
|
this.error.set('');
|
|
|
try {
|
|
|
const detailOperation = this.className() === 'ContentTagKey' ? 'getContentTagKeys' : this.className() === 'UserMoneyLog' ? 'getUserMoneyLog' : 'get';
|
|
|
const detail = await this.functions.admin<Record<string, unknown>>(detailOperation, { className: this.className(), objectId });
|
|
|
- this.draftId.set(objectId); this.draft.set(detail); this.fieldErrors.set({}); this.fieldInputs.set({}); this.resetPasswordFields(); this.resetCreateUserFields(); this.resetUserActions(detail); this.resetContentActions(detail); this.resetNodeActions(detail); this.resetSpecialActions(detail); this.resetGuestbookActions(detail); this.resetGuestCategoryActions(detail); this.resetBarActions(detail); this.resetExamClassActions(detail); this.resetExamPointActions(detail); this.resetKnowledgeActions(detail); this.resetTeacherActions(detail); this.resetDictionaryActions(detail); this.resetGradeActions(detail); this.resetAdActions(detail); this.resetFontShapeActions(detail); this.resetSurveyActions(); this.resetServiceActions(detail); this.resetStoreActions(detail); this.resetTagKeyActions(detail); this.editorOpen.set(true);
|
|
|
+ this.draftId.set(objectId); this.draft.set(detail); this.fieldErrors.set({}); this.fieldInputs.set({}); this.resetPasswordFields(); this.resetCreateUserFields(); this.resetUserActions(detail); this.resetContentActions(detail); this.resetNodeActions(detail); this.resetSpecialActions(detail); this.resetGuestbookActions(detail); this.resetGuestCategoryActions(detail); this.resetBarActions(detail); this.resetExamClassActions(detail); this.resetExamPointActions(detail); this.resetKnowledgeActions(detail); this.resetTeacherActions(detail); this.resetDictionaryActions(detail); this.resetGradeActions(detail); this.resetAdActions(detail); this.resetFontShapeActions(detail); this.resetSurveyActions(); this.resetServiceActions(detail); this.resetStoreActions(detail); this.resetTagKeyActions(detail); this.resetPlatformCompanyActions(detail); this.editorOpen.set(true);
|
|
|
if (this.className() === '_User') await this.loadUserGroups();
|
|
|
if (this.className() === 'AdInfo' && !this.adZones().length) await this.loadAdZones();
|
|
|
if (this.className() === 'AdZone') await this.loadAdPreview();
|
|
|
if (this.className() === 'FontPicShape' && !this.fontShapeTypes().length) await this.loadFontShapeTypes();
|
|
|
+ if (this.className() === 'PlatComp') await this.loadPlatformMembers();
|
|
|
} catch (error) { this.error.set(error instanceof Error ? error.message : '详情加载失败'); }
|
|
|
}
|
|
|
- closeEditor(): void { this.editorOpen.set(false); this.draft.set({}); this.draftId.set(''); this.fieldErrors.set({}); this.fieldInputs.set({}); this.resetPasswordFields(); this.resetCreateUserFields(); this.resetUserActions(); this.resetContentActions(); this.resetNodeActions(); this.resetSpecialActions(); this.resetGuestbookActions(); this.resetGuestCategoryActions(); this.resetBarActions(); this.resetExamClassActions(); this.resetExamPointActions(); this.resetKnowledgeActions(); this.resetTeacherActions(); this.resetDictionaryActions(); this.resetGradeActions(); this.resetAdActions(); this.resetFontShapeActions(); this.resetSurveyActions(); this.resetServiceActions(); this.resetStoreActions(); this.resetTagKeyActions(); }
|
|
|
+ closeEditor(): void { this.editorOpen.set(false); this.draft.set({}); this.draftId.set(''); this.fieldErrors.set({}); this.fieldInputs.set({}); this.resetPasswordFields(); this.resetCreateUserFields(); this.resetUserActions(); this.resetContentActions(); this.resetNodeActions(); this.resetSpecialActions(); this.resetGuestbookActions(); this.resetGuestCategoryActions(); this.resetBarActions(); this.resetExamClassActions(); this.resetExamPointActions(); this.resetKnowledgeActions(); this.resetTeacherActions(); this.resetDictionaryActions(); this.resetGradeActions(); this.resetAdActions(); this.resetFontShapeActions(); this.resetSurveyActions(); this.resetServiceActions(); this.resetStoreActions(); this.resetTagKeyActions(); this.resetPlatformCompanyActions(); }
|
|
|
setField(field: AdminFieldSchema, raw: unknown): void {
|
|
|
let value = raw;
|
|
|
if (field.type === 'Number') value = raw === '' ? null : Number(raw);
|
|
|
@@ -295,7 +312,8 @@ export class AdminResourceComponent implements OnInit {
|
|
|
: this.className() === 'CRMSAttr' ? 'saveCrmClientType'
|
|
|
: this.className() === 'ShopFareTlp' ? 'saveShopFareTemplate'
|
|
|
: this.className() === 'MisType' ? 'saveMisType'
|
|
|
- : this.className() === 'PageStyle' ? 'savePageStyle' : 'save';
|
|
|
+ : this.className() === 'PageStyle' ? 'savePageStyle'
|
|
|
+ : this.className() === 'PlatComp' ? 'savePlatformCompany' : 'save';
|
|
|
const payload: Record<string, unknown> = { className: this.className(), objectId: this.draftId() || undefined, fields: this.draft() };
|
|
|
if (this.className() === 'Node') payload['parentId'] = this.targetNodeParentId();
|
|
|
if (this.className() === 'Special') payload['pid'] = this.targetSpecialParentId();
|
|
|
@@ -311,6 +329,7 @@ export class AdminResourceComponent implements OnInit {
|
|
|
if (this.className() === 'ServiceSeat') payload['username'] = this.targetServiceSeatUsername();
|
|
|
if (this.className() === 'StoreApplication') { payload['username'] = this.targetStoreUsername(); payload['styleId'] = this.targetStoreStyleId(); }
|
|
|
if (this.className() === 'ContentTagKey') payload['content'] = this.tagKeyContent();
|
|
|
+ if (this.className() === 'PlatComp') payload['creatorUsername'] = this.platformCreatorUsername();
|
|
|
await this.functions.admin(operation, payload);
|
|
|
this.closeEditor(); await this.load();
|
|
|
} catch (error) { this.error.set(error instanceof Error ? error.message : '保存失败'); }
|
|
|
@@ -781,6 +800,38 @@ export class AdminResourceComponent implements OnInit {
|
|
|
catch (error) { this.bulkError.set(error instanceof Error ? error.message : '黄页样式删除失败'); }
|
|
|
finally { this.updatingPageStyle.set(false); }
|
|
|
}
|
|
|
+ async loadPlatformMembers(): Promise<void> {
|
|
|
+ const companyObjectId = this.draftId(); this.platformMembersError.set(''); this.platformMembers.set(null);
|
|
|
+ if (this.className() !== 'PlatComp' || !companyObjectId) return;
|
|
|
+ this.platformMembersLoading.set(true);
|
|
|
+ try { const result = await this.functions.admin<PlatformMemberPage>('platformCompanyMembers', { companyObjectId, page: 1, pageSize: 100, search: '' }); this.platformMembers.set(result); if (result.creatorUsername) this.platformCreatorUsername.set(result.creatorUsername); }
|
|
|
+ catch (error) { this.platformMembersError.set(error instanceof Error ? error.message : '企业成员加载失败'); }
|
|
|
+ finally { this.platformMembersLoading.set(false); }
|
|
|
+ }
|
|
|
+ async addPlatformMember(): Promise<void> {
|
|
|
+ const username = this.platformMemberUsername().trim(); this.platformMembersError.set('');
|
|
|
+ if (this.className() !== 'PlatComp' || !this.draftId() || !username) { this.platformMembersError.set('请输入要加入的成员账号'); return; }
|
|
|
+ this.updatingPlatformCompany.set(true);
|
|
|
+ try { await this.functions.admin('platformCompanyMemberBatch', { companyObjectId: this.draftId(), action: 'add', usernames: [username] }); this.platformMemberUsername.set(''); await this.loadPlatformMembers(); }
|
|
|
+ catch (error) { this.platformMembersError.set(error instanceof Error ? error.message : '企业成员添加失败'); }
|
|
|
+ finally { this.updatingPlatformCompany.set(false); }
|
|
|
+ }
|
|
|
+ async removePlatformMember(member: Record<string, unknown>): Promise<void> {
|
|
|
+ const objectId = String(member['objectId'] || ''); if (!objectId || !confirm(`确认将 ${String(member['username'] || objectId)} 移出该企业?`)) return;
|
|
|
+ this.platformMembersError.set(''); this.updatingPlatformCompany.set(true);
|
|
|
+ try { await this.functions.admin('platformCompanyMemberBatch', { companyObjectId: this.draftId(), action: 'remove', objectIds: [objectId] }); await this.loadPlatformMembers(); }
|
|
|
+ catch (error) { this.platformMembersError.set(error instanceof Error ? error.message : '企业成员移除失败'); }
|
|
|
+ finally { this.updatingPlatformCompany.set(false); }
|
|
|
+ }
|
|
|
+ async applyBulkPlatformCompanyDelete(): Promise<void> {
|
|
|
+ const objectIds = this.selectedIds(); this.bulkError.set(''); this.bulkMessage.set('');
|
|
|
+ if (this.className() !== 'PlatComp' || !objectIds.length) { this.bulkError.set('请先选择协同办公企业'); return; }
|
|
|
+ if (!confirm(`确认删除选中的 ${objectIds.length} 个协同办公企业?仍有成员或角色时会拒绝。`)) return;
|
|
|
+ this.updatingPlatformCompany.set(true);
|
|
|
+ try { const result = await this.functions.admin<{ updated: number }>('platformCompanyBatch', { className: 'PlatComp', action: 'delete', objectIds }); await this.load(); this.bulkMessage.set(`已删除 ${result.updated} 个协同办公企业`); }
|
|
|
+ catch (error) { this.bulkError.set(error instanceof Error ? error.message : '协同办公企业删除失败'); }
|
|
|
+ finally { this.updatingPlatformCompany.set(false); }
|
|
|
+ }
|
|
|
async applyBulkBaikeAction(action: 'audit' | 'unaudit' | 'elite' | 'unelite'): Promise<void> {
|
|
|
const objectIds = this.selectedIds(); this.bulkError.set(''); this.bulkMessage.set('');
|
|
|
if (this.className() !== 'Baike' || !objectIds.length) { this.bulkError.set('请先选择百科词条'); return; }
|
|
|
@@ -807,6 +858,7 @@ export class AdminResourceComponent implements OnInit {
|
|
|
else if (this.className() === 'ShopFareTlp') await this.functions.admin('shopFareTemplateBatch', { className: 'ShopFareTlp', action: 'delete', objectIds: [objectId] });
|
|
|
else if (this.className() === 'MisType') await this.functions.admin('misTypeBatch', { className: 'MisType', action: 'delete', objectIds: [objectId] });
|
|
|
else if (this.className() === 'PageStyle') await this.functions.admin('pageStyleBatch', { className: 'PageStyle', action: 'delete', objectIds: [objectId] });
|
|
|
+ else if (this.className() === 'PlatComp') await this.functions.admin('platformCompanyBatch', { className: 'PlatComp', action: 'delete', objectIds: [objectId] });
|
|
|
else await this.functions.admin('delete', { className: this.className(), objectId });
|
|
|
await this.load();
|
|
|
}
|
|
|
@@ -888,4 +940,5 @@ export class AdminResourceComponent implements OnInit {
|
|
|
private resetServiceActions(detail: Record<string, unknown> = {}): void { this.targetServiceSeatUsername.set(String(detail['sRemrk'] || '')); }
|
|
|
private resetStoreActions(detail: Record<string, unknown> = {}): void { this.targetStoreUsername.set(String(detail['userName'] || '')); this.targetStoreStyleId.set(Number(detail['storeStyleId']) || 0); }
|
|
|
private resetTagKeyActions(detail: Record<string, unknown> = {}): void { this.tagKeyContent.set(String(detail['content'] || '')); }
|
|
|
+ private resetPlatformCompanyActions(detail: Record<string, unknown> = {}): void { this.platformMembers.set(null); this.platformMembersLoading.set(false); this.platformMembersError.set(''); this.platformMemberUsername.set(''); this.platformCreatorUsername.set(String(detail['creatorUsername'] || '')); }
|
|
|
}
|