|
@@ -125,18 +125,20 @@ export class AdminResourceComponent implements OnInit {
|
|
|
readonly surveyChartLoading = signal(false);
|
|
readonly surveyChartLoading = signal(false);
|
|
|
readonly surveyChartError = signal('');
|
|
readonly surveyChartError = signal('');
|
|
|
readonly updatingSurvey = signal(false);
|
|
readonly updatingSurvey = signal(false);
|
|
|
|
|
+ readonly targetServiceSeatUsername = signal('');
|
|
|
|
|
+ readonly updatingService = signal(false);
|
|
|
readonly selectedIds = signal<string[]>([]);
|
|
readonly selectedIds = signal<string[]>([]);
|
|
|
readonly bulkError = signal('');
|
|
readonly bulkError = signal('');
|
|
|
readonly bulkMessage = signal('');
|
|
readonly bulkMessage = signal('');
|
|
|
readonly icons = { ChevronLeft, ChevronRight, Eye, KeyRound, LoaderCircle, Pencil, Plus, RefreshCw, Search, Trash2, X };
|
|
readonly icons = { ChevronLeft, ChevronRight, Eye, KeyRound, LoaderCircle, Pencil, Plus, RefreshCw, Search, Trash2, X };
|
|
|
readonly columns = computed(() => {
|
|
readonly columns = computed(() => {
|
|
|
const fields = this.schema()?.fields ?? [];
|
|
const fields = this.schema()?.fields ?? [];
|
|
|
- const preferred = ['objectId', 'name', 'title', 'qtitle', 'categoryname', 'dicname', 'cateName', 'gradeName', 'cClassName', 'testPoint', 'kName', 'tname', 'username', 'realName', 'askId', 'zoneId', 'typeId', 'shape', 'qtype', 'required', 'ztype', 'priority', 'zstatus', 'sdate', 'edate', 'fileUrl', 'type', 'state', 'eliteLevel', 'orderId', 'mobile', 'sourceKey', 'status', 'createdAt', 'updatedAt'];
|
|
|
|
|
|
|
+ const preferred = ['objectId', 'name', 'title', 'qtitle', 'sName', 'str1', 'categoryname', 'dicname', 'cateName', 'gradeName', 'cClassName', 'testPoint', 'kName', 'tname', 'username', 'realName', 'sRemrk', 'askId', 'zoneId', 'typeId', 'shape', 'qtype', 'required', 'ztype', 'priority', 'zstatus', '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; };
|
|
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);
|
|
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 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'].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'].includes(this.className()));
|
|
|
readonly allPageSelected = computed(() => {
|
|
readonly allPageSelected = computed(() => {
|
|
|
const ids = (this.page()?.results || []).map((row) => String(row['objectId'] || '')).filter(Boolean);
|
|
const ids = (this.page()?.results || []).map((row) => String(row['objectId'] || '')).filter(Boolean);
|
|
|
return Boolean(ids.length) && ids.every((id) => this.selectedIds().includes(id));
|
|
return Boolean(ids.length) && ids.every((id) => this.selectedIds().includes(id));
|
|
@@ -154,6 +156,7 @@ export class AdminResourceComponent implements OnInit {
|
|
|
this.filterAdZoneType.set(''); this.filterAdStatus.set(-100); this.filterAdInfoZoneId.set(''); this.resetAdActions();
|
|
this.filterAdZoneType.set(''); this.filterAdStatus.set(-100); this.filterAdInfoZoneId.set(''); this.resetAdActions();
|
|
|
this.filterFontShapeTypeId.set(0); this.resetFontShapeActions();
|
|
this.filterFontShapeTypeId.set(0); this.resetFontShapeActions();
|
|
|
this.filterSurveyStatus.set(-100); this.filterSurveyId.set(0); this.resetSurveyActions();
|
|
this.filterSurveyStatus.set(-100); this.filterSurveyId.set(0); this.resetSurveyActions();
|
|
|
|
|
+ this.resetServiceActions();
|
|
|
void this.load(1, true);
|
|
void this.load(1, true);
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
@@ -166,7 +169,7 @@ export class AdminResourceComponent implements OnInit {
|
|
|
if (this.className() === 'AdInfo' && reloadSchema) await this.loadAdZones();
|
|
if (this.className() === 'AdInfo' && reloadSchema) await this.loadAdZones();
|
|
|
if (this.className() === 'FontPicShape' && reloadSchema) await this.loadFontShapeTypes();
|
|
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 (['DesignQuestion', 'DesignAnswer'].includes(this.className()) && reloadSchema) { await this.loadSurveys(); if (!this.filterSurveyId() && this.surveys().length) this.filterSurveyId.set(this.surveyIdOf(this.surveys()[0])); }
|
|
|
- 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' : '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' : 'list';
|
|
|
const pagePayload: Record<string, unknown> = { className: this.className(), page: pageNumber, pageSize: 20, search: this.search().trim() };
|
|
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 === 'gradeOptions') { pagePayload['categoryId'] = this.filterGradeCategoryId(); pagePayload['parentId'] = this.filterGradeParentId(); }
|
|
|
if (pageOperation === 'searchNavigations') { pagePayload['type'] = this.filterSearchNavigationType(); pagePayload['state'] = this.filterSearchNavigationState(); pagePayload['elite'] = this.filterSearchNavigationElite(); }
|
|
if (pageOperation === 'searchNavigations') { pagePayload['type'] = this.filterSearchNavigationType(); pagePayload['state'] = this.filterSearchNavigationState(); pagePayload['elite'] = this.filterSearchNavigationElite(); }
|
|
@@ -182,20 +185,20 @@ export class AdminResourceComponent implements OnInit {
|
|
|
finally { this.loading.set(false); }
|
|
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.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.editorOpen.set(true); }
|
|
|
async openEdit(row: Record<string, unknown>): Promise<void> {
|
|
async openEdit(row: Record<string, unknown>): Promise<void> {
|
|
|
const objectId = String(row['objectId'] ?? '');
|
|
const objectId = String(row['objectId'] ?? '');
|
|
|
this.error.set('');
|
|
this.error.set('');
|
|
|
try {
|
|
try {
|
|
|
const detail = await this.functions.admin<Record<string, unknown>>('get', { className: this.className(), objectId });
|
|
const detail = await this.functions.admin<Record<string, unknown>>('get', { 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.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.editorOpen.set(true);
|
|
|
if (this.className() === '_User') await this.loadUserGroups();
|
|
if (this.className() === '_User') await this.loadUserGroups();
|
|
|
if (this.className() === 'AdInfo' && !this.adZones().length) await this.loadAdZones();
|
|
if (this.className() === 'AdInfo' && !this.adZones().length) await this.loadAdZones();
|
|
|
if (this.className() === 'AdZone') await this.loadAdPreview();
|
|
if (this.className() === 'AdZone') await this.loadAdPreview();
|
|
|
if (this.className() === 'FontPicShape' && !this.fontShapeTypes().length) await this.loadFontShapeTypes();
|
|
if (this.className() === 'FontPicShape' && !this.fontShapeTypes().length) await this.loadFontShapeTypes();
|
|
|
} catch (error) { this.error.set(error instanceof Error ? error.message : '详情加载失败'); }
|
|
} 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(); }
|
|
|
|
|
|
|
+ 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(); }
|
|
|
setField(field: AdminFieldSchema, raw: unknown): void {
|
|
setField(field: AdminFieldSchema, raw: unknown): void {
|
|
|
let value = raw;
|
|
let value = raw;
|
|
|
if (field.type === 'Number') value = raw === '' ? null : Number(raw);
|
|
if (field.type === 'Number') value = raw === '' ? null : Number(raw);
|
|
@@ -249,7 +252,9 @@ export class AdminResourceComponent implements OnInit {
|
|
|
: this.className() === 'FontPicShape' ? 'saveFontShape'
|
|
: this.className() === 'FontPicShape' ? 'saveFontShape'
|
|
|
: this.className() === 'FontPicShapeType' ? 'saveFontShapeType'
|
|
: this.className() === 'FontPicShapeType' ? 'saveFontShapeType'
|
|
|
: this.className() === 'DesignAsk' ? 'saveSurvey'
|
|
: this.className() === 'DesignAsk' ? 'saveSurvey'
|
|
|
- : this.className() === 'DesignQuestion' ? 'saveSurveyQuestion' : 'save';
|
|
|
|
|
|
|
+ : this.className() === 'DesignQuestion' ? 'saveSurveyQuestion'
|
|
|
|
|
+ : this.className() === 'ServiceSeat' ? 'saveServiceSeat'
|
|
|
|
|
+ : this.className() === 'Temp' ? 'saveServiceCode' : 'save';
|
|
|
const payload: Record<string, unknown> = { className: this.className(), objectId: this.draftId() || undefined, fields: this.draft() };
|
|
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() === 'Node') payload['parentId'] = this.targetNodeParentId();
|
|
|
if (this.className() === 'Special') payload['pid'] = this.targetSpecialParentId();
|
|
if (this.className() === 'Special') payload['pid'] = this.targetSpecialParentId();
|
|
@@ -262,6 +267,7 @@ export class AdminResourceComponent implements OnInit {
|
|
|
if (this.className() === 'Grade') { payload['categoryId'] = this.targetGradeCategoryId(); payload['parentId'] = this.targetGradeParentId(); }
|
|
if (this.className() === 'Grade') { payload['categoryId'] = this.targetGradeCategoryId(); payload['parentId'] = this.targetGradeParentId(); }
|
|
|
if (this.className() === 'AdInfo') payload['zoneId'] = this.targetAdZoneId();
|
|
if (this.className() === 'AdInfo') payload['zoneId'] = this.targetAdZoneId();
|
|
|
if (this.className() === 'FontPicShape') payload['typeId'] = this.targetFontShapeTypeId();
|
|
if (this.className() === 'FontPicShape') payload['typeId'] = this.targetFontShapeTypeId();
|
|
|
|
|
+ if (this.className() === 'ServiceSeat') payload['username'] = this.targetServiceSeatUsername();
|
|
|
await this.functions.admin(operation, payload);
|
|
await this.functions.admin(operation, payload);
|
|
|
this.closeEditor(); await this.load();
|
|
this.closeEditor(); await this.load();
|
|
|
} catch (error) { this.error.set(error instanceof Error ? error.message : '保存失败'); }
|
|
} catch (error) { this.error.set(error instanceof Error ? error.message : '保存失败'); }
|
|
@@ -643,6 +649,15 @@ export class AdminResourceComponent implements OnInit {
|
|
|
catch (error) { this.surveyChartError.set(error instanceof Error ? error.message : '问卷统计加载失败'); }
|
|
catch (error) { this.surveyChartError.set(error instanceof Error ? error.message : '问卷统计加载失败'); }
|
|
|
finally { this.surveyChartLoading.set(false); }
|
|
finally { this.surveyChartLoading.set(false); }
|
|
|
}
|
|
}
|
|
|
|
|
+ async applyBulkServiceDelete(): Promise<void> {
|
|
|
|
|
+ const className = this.className(); const objectIds = this.selectedIds(); this.bulkError.set(''); this.bulkMessage.set('');
|
|
|
|
|
+ if (!['ServiceSeat', 'Temp'].includes(className) || !objectIds.length) { this.bulkError.set('请先选择客服席位或欢迎语'); return; }
|
|
|
|
|
+ if (!confirm(`确认删除选中的 ${objectIds.length} 条${className === 'ServiceSeat' ? '客服席位' : '欢迎语'}?`)) return;
|
|
|
|
|
+ this.updatingService.set(true);
|
|
|
|
|
+ try { const result = await this.functions.admin<{ updated: number }>('serviceBatch', { className, action: 'delete', objectIds }); await this.load(); this.bulkMessage.set(`已删除 ${result.updated} 条客服记录`); }
|
|
|
|
|
+ catch (error) { this.bulkError.set(error instanceof Error ? error.message : '客服记录删除失败'); }
|
|
|
|
|
+ finally { this.updatingService.set(false); }
|
|
|
|
|
+ }
|
|
|
async remove(row: Record<string, unknown>): Promise<void> {
|
|
async remove(row: Record<string, unknown>): Promise<void> {
|
|
|
const objectId = String(row['objectId'] ?? '');
|
|
const objectId = String(row['objectId'] ?? '');
|
|
|
const verb = ['CommonModel', 'Node', 'Guestbook'].includes(this.className()) ? '移入回收站' : '删除';
|
|
const verb = ['CommonModel', 'Node', 'Guestbook'].includes(this.className()) ? '移入回收站' : '删除';
|
|
@@ -654,6 +669,7 @@ export class AdminResourceComponent implements OnInit {
|
|
|
else if (this.className() === 'FontPicShape') await this.functions.admin('fontShapeBatch', { className: 'FontPicShape', action: 'delete', objectIds: [objectId] });
|
|
else if (this.className() === 'FontPicShape') await this.functions.admin('fontShapeBatch', { className: 'FontPicShape', action: 'delete', objectIds: [objectId] });
|
|
|
else if (this.className() === 'FontPicShapeType') await this.functions.admin('fontShapeTypeBatch', { className: 'FontPicShapeType', action: 'delete', objectIds: [objectId] });
|
|
else if (this.className() === 'FontPicShapeType') await this.functions.admin('fontShapeTypeBatch', { className: 'FontPicShapeType', action: 'delete', objectIds: [objectId] });
|
|
|
else if (['DesignAsk', 'DesignQuestion', 'DesignAnswer'].includes(this.className())) await this.functions.admin('surveyBatch', { className: this.className(), action: 'delete', objectIds: [objectId] });
|
|
else if (['DesignAsk', 'DesignQuestion', 'DesignAnswer'].includes(this.className())) await this.functions.admin('surveyBatch', { className: this.className(), action: 'delete', objectIds: [objectId] });
|
|
|
|
|
+ else if (['ServiceSeat', 'Temp'].includes(this.className())) await this.functions.admin('serviceBatch', { className: this.className(), action: 'delete', objectIds: [objectId] });
|
|
|
else await this.functions.admin('delete', { className: this.className(), objectId });
|
|
else await this.functions.admin('delete', { className: this.className(), objectId });
|
|
|
await this.load();
|
|
await this.load();
|
|
|
}
|
|
}
|
|
@@ -726,4 +742,5 @@ export class AdminResourceComponent implements OnInit {
|
|
|
private resetAdActions(detail: Record<string, unknown> = {}): void { this.targetAdZoneId.set(String(detail['zoneId'] || this.filterAdInfoZoneId() || '')); this.adPreview.set([]); this.adPreviewError.set(''); this.adPreviewLoading.set(false); }
|
|
private resetAdActions(detail: Record<string, unknown> = {}): void { this.targetAdZoneId.set(String(detail['zoneId'] || this.filterAdInfoZoneId() || '')); this.adPreview.set([]); this.adPreviewError.set(''); this.adPreviewLoading.set(false); }
|
|
|
private resetFontShapeActions(detail: Record<string, unknown> = {}): void { this.targetFontShapeTypeId.set(Number(detail['typeId']) || this.filterFontShapeTypeId()); this.fontShapePreview.set(String(detail['shape'] || '')); }
|
|
private resetFontShapeActions(detail: Record<string, unknown> = {}): void { this.targetFontShapeTypeId.set(Number(detail['typeId']) || this.filterFontShapeTypeId()); this.fontShapePreview.set(String(detail['shape'] || '')); }
|
|
|
private resetSurveyActions(): void { this.surveyOrderStart.set(1); this.surveyChart.set(null); this.surveyChartError.set(''); this.surveyChartLoading.set(false); }
|
|
private resetSurveyActions(): void { this.surveyOrderStart.set(1); this.surveyChart.set(null); this.surveyChartError.set(''); this.surveyChartLoading.set(false); }
|
|
|
|
|
+ private resetServiceActions(detail: Record<string, unknown> = {}): void { this.targetServiceSeatUsername.set(String(detail['sRemrk'] || '')); }
|
|
|
}
|
|
}
|