|
|
@@ -15,12 +15,12 @@ const CLASS_LABELS = {
|
|
|
GradeCate: '多级字典分类', Grade: '多级字典选项',
|
|
|
Currency: '货币管理', SysHoliday: '节假日管理',
|
|
|
Product: '商品', StoreProduct: '门店商品', StoreApplication: '门店申请', ShopFareTlp: '运费模板', ShopMoneyRegular: '金额规则', PayPlat: '支付平台',
|
|
|
- GuestBar: '互动社区', Guestbook: '留言', Guestcate: '留言分类', Feedback: '反馈', Baike: '百科', Search: '后台快捷入口', AdZone: '广告位管理', AdInfo: '广告内容管理', FontPicShape: '字体图形素材', FontPicShapeType: '字体图形分类', DesignAsk: '问卷调查', DesignQuestion: '问卷题目', DesignAnswer: '问卷答卷', ServiceSeat: '客服席位', Temp: '客服欢迎语', StoreApplication: '店铺管理', StoreStyle: '店铺样式', ContentTagKey: '内容标签词库', UserLevel: '积分等级', UserMoneyLog: '资金积分流水', Agency: '代理机构', DeliveryCenter: '交付中心'
|
|
|
+ GuestBar: '互动社区', Guestbook: '留言', Guestcate: '留言分类', Feedback: '反馈', Baike: '百科审核', Search: '后台快捷入口', AdZone: '广告位管理', AdInfo: '广告内容管理', FontPicShape: '字体图形素材', FontPicShapeType: '字体图形分类', DesignAsk: '问卷调查', DesignQuestion: '问卷题目', DesignAnswer: '问卷答卷', ServiceSeat: '客服席位', Temp: '客服欢迎语', StoreApplication: '店铺管理', StoreStyle: '店铺样式', ContentTagKey: '内容标签词库', UserLevel: '积分等级', UserMoneyLog: '资金积分流水', Agency: '代理机构', DeliveryCenter: '交付中心'
|
|
|
};
|
|
|
const ALLOWED_CLASSES = new Set([
|
|
|
'PageTemplate','PaperQuestions','PayPlat','Permission','PlatComp','App','DesignAnswer','DesignAsk','Attachment','DesignPage','DesignQuestion','DesignRes','Feedback','DesignScence','StudentAchieve','ContentArticle','DesignSiteInfo','Profile','AdInfo','AdZone','ARoleAuth','Baike','ExamSysQuestions','ContactInfo','VocabularyWord','AssessmentProfile','Agency','MemoryPracticeRecord','DeliveryCenter','CourseBinding','PracticeRecord','CourseAppointment','Account','SurveyItem','SurveyLog','LessonRecord','DailyStudyRecord','CommonModel','ContentPublish','Company','_Role','_User','CRMSAttr','Currency','Datadic','Datadiccategory','DesignTlp','DocModel','DocPermission','ExamClass','ExamSysPapers','ExamType','ExamPoint','ExTeacher','FontPicShape','FontPicShapeType','Grade','GradeCate','Group','GroupModel','GuestBar','Guestbook','Guestcate','MailTemp','Manager','MisProcedure','MisProLevel','MisSign','MisType','PageStyle','Model','ModelField','Node','NodeAuth','NodeModelTemplate','Product','PlatUserRole','Pub','PubTw','PubWTHD','PubZXDC','PublishNode','QuestionsKnowledge','Role','StoreProduct','SafeMobile','Search','SenTask','ServiceSeat','ShopFareTlp','ShopMoneyRegular','Special','StoreApplication','StoreStyle','SysCSSManage','SysHoliday','SysLog','Temp','ThirdPlatInfo','UserCredit','UserDummyPoint','UserFriendGroup','UserLevel','UserSIcon','UserUserPoint','UserExpDomP','UserExpHis'
|
|
|
]);
|
|
|
-const READ_ONLY_CLASSES = new Set(['_Role','Permission','PayPlat','ThirdPlatInfo','GuestBar','DesignAnswer']);
|
|
|
+const READ_ONLY_CLASSES = new Set(['_Role','Permission','PayPlat','ThirdPlatInfo','GuestBar','DesignAnswer','Baike']);
|
|
|
const SYSTEM_FIELDS = new Set(['objectId','createdAt','updatedAt','ACL','company','password','authData','sessionToken','legacyPasswordHash','legacyPasswordHashType','appPassword','newapiToken','fmodeApiToken','useMasterKey','adminPassword','randNumber','adminRoleKey','isAdmin','roles','role','isDisabled','legacyUserId','legacyGroupId','legacyUserData','groupId']);
|
|
|
const HIDDEN_FIELDS = new Set(['password','authData','sessionToken','legacyPasswordHash','legacyPasswordHashType','appPassword','newapiToken','fmodeApiToken','useMasterKey','adminPassword','randNumber','apiKey','appSecret','secret','token']);
|
|
|
const GENERIC_WRITE_TYPES = new Set(['String','Number','Boolean','Date','Pointer','Object','Array']);
|
|
|
@@ -1260,6 +1260,21 @@ async function handler(request, response) {
|
|
|
Config_Submit: '即使存储积分与用户组参数,目标也没有问答发布/回复/推荐运行时执行这些规则,不能伪造保存生效'
|
|
|
}; if (!Object.prototype.hasOwnProperty.call(blockers, action)) fail(400, '不支持的旧问答动作'); fail(501, 'migration_blocked: ' + blockers[action]);
|
|
|
}
|
|
|
+ if (operation === 'baikeEntries') {
|
|
|
+ const page = Math.max(1, Number(input.page) || 1); const pageSize = Math.min(100, Math.max(1, Number(input.pageSize) || 20)); const search = String(input.search || '').trim().toLowerCase(); const status = Number(input.status == null ? -100 : input.status); const elite = Number(input.elite == null ? -100 : input.elite); if (search.length > 100 || ![-100,0,1].includes(status) || ![-100,0,1].includes(elite)) fail(400, '百科搜索或状态筛选无效'); const fields = await schemaFor('Baike'); const query = new Parse.Query('Baike'); applyTenant(query, fields, context, input.companyId); query.limit(1000); let results = await query.find({ useMasterKey: true }); results = results.filter((entry) => (status === -100 || Number(entry.get('status')) === status) && (elite === -100 || Number(entry.get('elite')) === elite) && (!search || [entry.get('tittle'),entry.get('brief'),entry.get('contents'),entry.get('userName'),entry.get('classification')].some((value) => String(value || '').toLowerCase().includes(search)))); results.sort((left,right) => Number(right.get('id') || 0) - Number(left.get('id') || 0)); const total = results.length; results = results.slice((page - 1) * pageSize, page * pageSize); return response.json({ success: true, data: { className: 'Baike', page, pageSize, total, results: results.map(serializeObject) } });
|
|
|
+ }
|
|
|
+ if (operation === 'baikeBatch') {
|
|
|
+ const action = String(input.action || ''); if (!['audit','unaudit','elite','unelite'].includes(action)) fail(400, '不支持的百科批量操作'); const requestedIds = Array.isArray(input.objectIds) ? input.objectIds : [input.objectId]; const objectIds = [...new Set(requestedIds.map((value) => String(value || '').trim()).filter(Boolean))]; if (!objectIds.length || objectIds.length > 100) fail(400, '每次请选择 1 至 100 个百科词条'); const fields = await schemaFor('Baike'); const query = new Parse.Query('Baike'); applyTenant(query, fields, context, input.companyId); query.containedIn('objectId', objectIds); query.limit(objectIds.length); const targets = await query.find({ useMasterKey: true }); if (targets.length !== objectIds.length) fail(404, '部分百科词条不存在或不属于当前帐套'); for (const target of targets) { if (action === 'audit') target.set('status', 1); if (action === 'unaudit') target.set('status', 0); if (action === 'elite') target.set('elite', 1); if (action === 'unelite') target.set('elite', 0); } await Parse.Object.saveAll(targets, { useMasterKey: true }); for (const target of targets) await audit({ ...context, company: target.get('company') || context.company }, 'baike-' + action, 'Baike', target.id); return response.json({ success: true, data: { action, updated: targets.length, results: targets.map(serializeObject) } });
|
|
|
+ }
|
|
|
+ if (operation === 'legacyBaikeBlocker') {
|
|
|
+ const action = String(input.action || ''); const blockers = {
|
|
|
+ BKVersionList: '目标 Schema 缺少旧 BaikeEdit 版本表、待审核版本内容与历史版本数据',
|
|
|
+ Version_API: '目标无 BaikeEdit 版本记录,无法审核后 Apply、取消审核、驳回或删除版本',
|
|
|
+ BKList: '旧 BKList 按 Flow 读取 BaikeEdit 词条版本链,目标仅保留一条 Baike 主记录',
|
|
|
+ Config: '目标没有 GuestConfig.BKOption 百科运行时、用户组权限和积分奖励消费者',
|
|
|
+ Config_Submit: '目标没有百科创建/编辑/推荐运行时执行 CreatePoint/EditPoint/RemmPoint 规则,不能伪造配置生效'
|
|
|
+ }; if (!Object.prototype.hasOwnProperty.call(blockers, action)) fail(400, '不支持的旧百科动作'); fail(501, 'migration_blocked: ' + blockers[action]);
|
|
|
+ }
|
|
|
if (operation === 'saveExamClass') {
|
|
|
const objectId = String(input.objectId || '');
|
|
|
const payload = input.fields && typeof input.fields === 'object' ? input.fields : {};
|