|
|
@@ -141,18 +141,19 @@ export class AdminResourceComponent implements OnInit {
|
|
|
readonly filterBaikeStatus = signal(-100);
|
|
|
readonly filterBaikeElite = signal(-100);
|
|
|
readonly updatingBaike = signal(false);
|
|
|
+ readonly updatingCrmType = signal(false);
|
|
|
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', 'qtitle', 'sName', 'storeName', 'styleName', 'count', 'content', 'str1', 'categoryname', 'dicname', 'cateName', 'gradeName', 'cClassName', 'testPoint', 'kName', 'tname', 'username', 'userName', 'realName', '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', 'value', 'remark', 'qtitle', 'sName', 'storeName', 'styleName', 'count', 'content', 'str1', 'categoryname', 'dicname', 'cateName', 'gradeName', 'cClassName', 'testPoint', 'kName', 'tname', 'username', 'userName', 'realName', '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'].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'].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));
|
|
|
@@ -188,7 +189,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' : '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' : '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(); }
|
|
|
@@ -281,7 +282,8 @@ export class AdminResourceComponent implements OnInit {
|
|
|
: this.className() === 'StoreApplication' ? 'saveStoreApplication'
|
|
|
: this.className() === 'StoreStyle' ? 'saveStoreStyle'
|
|
|
: this.className() === 'ContentTagKey' ? 'saveContentTagKeys'
|
|
|
- : this.className() === 'UserLevel' ? 'saveUserLevel' : 'save';
|
|
|
+ : this.className() === 'UserLevel' ? 'saveUserLevel'
|
|
|
+ : this.className() === 'CRMSAttr' ? 'saveCrmClientType' : '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();
|
|
|
@@ -731,6 +733,15 @@ export class AdminResourceComponent implements OnInit {
|
|
|
catch (error) { this.bulkError.set(error instanceof Error ? error.message : '积分等级删除失败'); }
|
|
|
finally { this.updatingUserLevel.set(false); }
|
|
|
}
|
|
|
+ async applyBulkCrmClientTypeDelete(): Promise<void> {
|
|
|
+ const objectIds = this.selectedIds(); this.bulkError.set(''); this.bulkMessage.set('');
|
|
|
+ if (this.className() !== 'CRMSAttr' || !objectIds.length) { this.bulkError.set('请先选择 CRM 客户类型'); return; }
|
|
|
+ if (!confirm(`确认删除选中的 ${objectIds.length} 个客户类型?`)) return;
|
|
|
+ this.updatingCrmType.set(true);
|
|
|
+ try { const result = await this.functions.admin<{ updated: number }>('crmClientTypeBatch', { className: 'CRMSAttr', action: 'delete', objectIds }); await this.load(); this.bulkMessage.set(`已删除 ${result.updated} 个客户类型`); }
|
|
|
+ catch (error) { this.bulkError.set(error instanceof Error ? error.message : '客户类型删除失败'); }
|
|
|
+ finally { this.updatingCrmType.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; }
|