CommonContent.ts 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595
  1. import { DataModel, transformArrayDataModel, type KeyValue, type NewDataModel } from '@imengyu/js-request-transform';
  2. import { AppServerRequestModule } from './RequestModules';
  3. import { transformSomeToArray } from './Utils';
  4. import { RequestOptions, requireNotNull, type QueryParams } from '@imengyu/imengyu-utils';
  5. import ApiCofig from '@/common/config/ApiCofig';
  6. export class GetColumListParams extends DataModel<GetColumListParams> {
  7. public constructor() {
  8. super(GetColumListParams);
  9. this.setNameMapperCase('Camel', 'Snake');
  10. }
  11. setModelId(val: number) {
  12. this.modelId = val;
  13. return this;
  14. }
  15. setMainBodyColumnId(val: number) {
  16. this.mainBodyColumnId = val;
  17. return this;
  18. }
  19. setFlag(val: 'hot'|'recommend'|'top') {
  20. this.flag = val;
  21. return this;
  22. }
  23. setSize(val: number) {
  24. this.size = val;
  25. return this;
  26. }
  27. modelId?: number;
  28. /**
  29. * 主体栏目id
  30. */
  31. mainBodyColumnId: number = 0;
  32. /**
  33. * 标志:hot=热门,recommend=推荐,top=置顶
  34. */
  35. flag ?: 'hot'|'recommend'|'top';
  36. /**
  37. * 内容数量,默认4
  38. */
  39. size?: number;
  40. }
  41. export class GetContentListParams extends DataModel<GetContentListParams> {
  42. public constructor() {
  43. super(GetContentListParams);
  44. this.setNameMapperCase('Camel', 'Snake');
  45. this._convertTable = {
  46. ids: {
  47. customToServerFn: (val) => (val as number[]).join(','),
  48. customToClientFn: (val) => (val as string).split(',').map((item) => parseInt(item)),
  49. },
  50. }
  51. }
  52. setMainBodyColumnId(val: string|number|number[]|undefined) {
  53. if (val === undefined)
  54. return this;
  55. if (typeof val === 'string') {
  56. if (val.includes(',')) {
  57. val = val.split(',').map((item) => parseInt(item));
  58. } else {
  59. val = parseInt(val);
  60. }
  61. }
  62. this.mainBodyColumnId = val;
  63. return this;
  64. }
  65. setFlag(val: 'hot'|'recommend'|'top') {
  66. this.flag = val;
  67. return this;
  68. }
  69. setIds(val: number[]) {
  70. this.ids = val;
  71. return this;
  72. }
  73. setType(val: 1|2|3|4) {
  74. this.type = val;
  75. return this;
  76. }
  77. setSize(val: number) {
  78. this.size = val;
  79. return this;
  80. }
  81. setKeywords(val: string) {
  82. this.keywords = val;
  83. return this;
  84. }
  85. setModelId(val: number) {
  86. this.modelId = val;
  87. return this;
  88. }
  89. static TYPE_ARTICLE = 1;
  90. static TYPE_AUDIO = 2;
  91. static TYPE_VIDEO = 3;
  92. static TYPE_IMAGE = 4;
  93. static TYPE_ARCHIVE = 5;
  94. modelId ?: number;
  95. /**
  96. * 主体栏目id
  97. */
  98. mainBodyColumnId: number|number[] = 0;
  99. /**
  100. * 标志:hot=热门,recommend=推荐,top=置顶
  101. */
  102. flag ?: 'hot'|'recommend'|'top';
  103. /**
  104. * 内容id(逗号隔开)如:3 或者 1,2,3
  105. */
  106. ids?: number[];
  107. /**
  108. * 类型:1=文章,2=音频,3=视频,4=相册
  109. */
  110. type?: 1|2|3|4;
  111. /**
  112. * 内容数量,默认4
  113. */
  114. size ?: number;
  115. /**
  116. * 关键字查询
  117. */
  118. keywords?: string;
  119. }
  120. export class GetColumContentList extends DataModel<GetColumContentList> {
  121. constructor() {
  122. super(GetColumContentList, "主体栏目列表");
  123. this.setNameMapperCase('Camel', 'Snake');
  124. this._convertTable = {
  125. id: { clientSide: 'number', serverSide: 'number', clientSideRequired: true },
  126. name: { clientSide: 'string', serverSide: 'string', clientSideRequired: true },
  127. content_list: {
  128. clientSide: 'array',
  129. clientSideRequired: true,
  130. clientSideChildDataModel: GetContentListItem,
  131. },
  132. }
  133. }
  134. name = '';
  135. overview = '';
  136. }
  137. export class GetModelColumContentList extends DataModel<GetColumContentList> {
  138. constructor() {
  139. super(GetColumContentList, "模型的主体栏目列表");
  140. this.setNameMapperCase('Camel', 'Snake');
  141. this._convertTable = {
  142. id: { clientSide: 'number', serverSide: 'number', clientSideRequired: true },
  143. name: { clientSide: 'string', serverSide: 'string', clientSideRequired: true },
  144. iscontribute: { clientSide: 'boolean' },
  145. }
  146. }
  147. id = 0;
  148. name = '';
  149. modelId = 0;
  150. image = '';
  151. diyname = '';
  152. iscontribute = false;
  153. statusText = '';
  154. }
  155. export class GetContentListItem extends DataModel<GetContentListItem> {
  156. constructor() {
  157. super(GetContentListItem, "内容列表");
  158. this.setNameMapperCase('Camel', 'Snake');
  159. this._convertTable = {
  160. id: { clientSide: 'number', serverSide: 'number', clientSideRequired: true },
  161. mainBodyColumnId: { clientSide: 'number', serverSide: 'number', clientSideRequired: true },
  162. title: { clientSide: 'string', serverSide: 'string', clientSideRequired: true },
  163. isGuest: { clientSide: 'boolean', serverSide: 'number' },
  164. isLogin: { clientSide: 'boolean', serverSide: 'number' },
  165. isComment: { clientSide: 'boolean', serverSide: 'number' },
  166. isLike: { clientSide: 'boolean', serverSide: 'number' },
  167. isCollect: { clientSide: 'boolean', serverSide: 'number' },
  168. latitude: { clientSide: 'number', serverSide: 'number' },
  169. longitude: { clientSide: 'number', serverSide: 'number' },
  170. publishAt: { clientSide: 'date', serverSide: 'string' },
  171. flag: { clientSide: 'splitCommaArray', serverSide: 'commaArrayMerge' },
  172. tags: { clientSide: 'splitCommaArray', serverSide: 'commaArrayMerge' },
  173. keywords: { clientSide: 'splitCommaArray', serverSide: 'commaArrayMerge' },
  174. brandType: { clientSide: 'splitCommaArray', serverSide: 'commaArrayMerge' },
  175. type: { clientSide: 'number', serverSide: 'number' },
  176. };
  177. this._nameMapperServer = {
  178. 'column_name': 'mainBodyColumnName',
  179. };
  180. this._convertKeyType = (key, direction) => {
  181. if (key.endsWith('Time'))
  182. return {
  183. clientSide: 'date',
  184. serverSide: 'string',
  185. };
  186. return undefined;
  187. };
  188. }
  189. id = 0;
  190. modelId = 0;
  191. modelName = '';
  192. mainBodyColumnId = 0;
  193. mainBodyColumnName = '';
  194. latitude = 0;
  195. longitude = 0;
  196. mapX = '';
  197. mapY = '';
  198. from = '';
  199. title = '!title';
  200. region = 0;
  201. image = '';
  202. thumbnail = '';
  203. desc = '!desc';
  204. content = '!content';
  205. type = 0;
  206. keywords ?: string[];
  207. flag ?: string[];
  208. tags ?: string[];
  209. views = 0;
  210. comments = 0;
  211. likes = 0;
  212. collects = 0;
  213. dislikes = 0;
  214. district = '';
  215. publishAt = new Date();
  216. }
  217. export class GetContentDetailItem extends DataModel<GetContentDetailItem> {
  218. constructor() {
  219. super(GetContentDetailItem, "内容详情");
  220. this.setNameMapperCase('Camel', 'Snake');
  221. this._beforeSolveServer = (data) => {
  222. if (!data.id && data.content_id)
  223. data.id = Number(data.content_id);
  224. return data;
  225. }
  226. this._convertTable = {
  227. id: { clientSide: 'number', serverSide: 'number', clientSideRequired: true },
  228. title: { clientSide: 'string', serverSide: 'string', clientSideRequired: true },
  229. isGuest: { clientSide: 'boolean', serverSide: 'number' },
  230. isLogin: { clientSide: 'boolean', serverSide: 'number' },
  231. isComment: { clientSide: 'boolean', serverSide: 'number' },
  232. isLike: { clientSide: 'boolean', serverSide: 'number' },
  233. isCollect: { clientSide: 'boolean', serverSide: 'number' },
  234. publishAt: { clientSide: 'date', serverSide: 'string' },
  235. flag: { clientSide: 'splitCommaArray', serverSide: 'commaArrayMerge' },
  236. tags: { clientSide: 'splitCommaArray', serverSide: 'commaArrayMerge' },
  237. type: { clientSide: 'number', serverSide: 'number' },
  238. ichSitesList: { clientSide: 'array', clientSideChildDataModel: GetContentDetailItem },
  239. inheritorsList: { clientSide: 'array', clientSideChildDataModel: GetContentDetailItem },
  240. otherLevel: { clientSide: 'array', clientSideChildDataModel: GetContentDetailItem },
  241. }
  242. this._nameMapperServer = {
  243. 'column_name': 'mainBodyColumnName',
  244. };
  245. this._convertKeyType = (key, direction) => {
  246. if (key.endsWith('Time'))
  247. return {
  248. clientSide: 'date',
  249. serverSide: 'string',
  250. };
  251. else if (key.endsWith('List')) {
  252. return [
  253. { clientSide: 'map', serverSide: 'original'},
  254. { clientSide: 'array', clientSideChildDataModel: GetContentDetailItem, serverSide: 'original' },
  255. ]
  256. }
  257. return undefined;
  258. };
  259. this._afterSolveServer = () => {
  260. if (!this.image && this.images && this.images && this.images.length > 0 ) {
  261. this.image = this.images[0]
  262. }
  263. if ((!this.images || this.images.length == 0) && this.image) {
  264. this.images = [ this.image ]
  265. }
  266. if (this.publishVideo) {
  267. this.video = this.publishVideo
  268. }
  269. if (this.associationMeList) {
  270. this.associationMeFirstTitle = this.associationMeList[0]?.title || ''
  271. }
  272. if (this.otherLevel) {
  273. this.otherLevelCount = this.otherLevel.length + '个'
  274. }
  275. this.titleBox = Boolean(this.deathBirth);
  276. }
  277. }
  278. id = 0;
  279. from = '';
  280. modelId = 0;
  281. modelName = '';
  282. mainBodyColumnId = 0;
  283. mainBodyColumnName = '';
  284. type = 0;
  285. title = '';
  286. region = 0;
  287. image = '';
  288. images = [] as string[];
  289. audio = '';
  290. video = '';
  291. archives = '';
  292. publishVideo?: string;
  293. desc = '';
  294. flag ?: string[];
  295. tags ?: string[];
  296. views = 0;
  297. comments = 0;
  298. likes = 0;
  299. collects = 0;
  300. dislikes = 0;
  301. isLogin = false;
  302. isGuest = false;
  303. isComment = false;
  304. isLike = false;
  305. isCollect = false;
  306. content = '';
  307. publishAt = new Date();
  308. associationMeList = [] as {
  309. id: number,
  310. title: string,
  311. image: string,
  312. thumbnail: string,
  313. }[];
  314. associationMeFirstTitle = '';
  315. otherLevel : GetContentDetailItem[] = [];
  316. }
  317. export class CategoryListItem extends DataModel<CategoryListItem> {
  318. constructor() {
  319. super(CategoryListItem, "分类列表");
  320. this.setNameMapperCase('Camel', 'Snake');
  321. this._convertTable = {
  322. id: { clientSide: 'number', serverSide: 'number', clientSideRequired: true },
  323. pid: { clientSide: 'number', serverSide: 'number' },
  324. haschild: { clientSide: 'boolean', serverSide: 'number' },
  325. }
  326. }
  327. id !: number;
  328. pid !: number;
  329. title = '';
  330. status = 'normal';
  331. weight = 0;
  332. spacer = '';
  333. haschild = false;
  334. children?: CategoryListItem[];
  335. }
  336. export class FeedBackItem extends DataModel<FeedBackItem> {
  337. constructor() {
  338. super(FeedBackItem, "内容反馈");
  339. this.setNameMapperCase('Camel', 'Snake');
  340. this._convertTable = {};
  341. this._afterSolveClient = (data) => {
  342. data.page_url = `${this.page}?modelId=${data.modelId}&mainBodyColumnId=${data.mainBodyColumnId}&contentId=${data.contentId}`;
  343. }
  344. }
  345. type = null as number|null;
  346. content = '';
  347. images = [] as string[];
  348. contact = '';
  349. contentId = 0;
  350. title = '';
  351. page = '';
  352. modelId = 0;
  353. modelName = '';
  354. mainBodyColumnId = 0;
  355. mainBodyColumnName = '';
  356. }
  357. export class CommonContentApi extends AppServerRequestModule<DataModel> {
  358. constructor(
  359. mainBodyId = ApiCofig.mainBodyId,
  360. modelId = 0, debugName = 'CommonContent',
  361. mainBodyColumnId?: number|number[]) {
  362. super();
  363. this.modelId = modelId;
  364. this.mainBodyId = mainBodyId;
  365. this.mainBodyColumnId = mainBodyColumnId;
  366. this.debugName = debugName;
  367. this.description = debugName;
  368. }
  369. public description: string;
  370. public mainBodyId: number;
  371. public mainBodyColumnId?: number|number[];
  372. public modelId: number;
  373. protected debugName: string;
  374. private toStringArray(arr: number|number[]|undefined) {
  375. if (typeof arr === 'undefined')
  376. return '';
  377. return typeof arr === 'object' ? arr.join(',') : arr.toString();
  378. }
  379. /**
  380. * 获取分类列表
  381. * @param type 根级类型:1=区域、2=级别、3=文物类型、4=非遗类型、42=事件类型
  382. * @param withself 是否返回包含自己:true=是,false=否 ,默认false
  383. * @returns
  384. */
  385. async getCategoryList(
  386. type?: number,
  387. withself?: boolean,
  388. ) {
  389. const res = await (this.get<KeyValue[]>('/content/category/getCategoryList', '获取分类列表', {
  390. type,
  391. is_tree: false,
  392. withself,
  393. }))
  394. return transformArrayDataModel<CategoryListItem>(CategoryListItem, res.data!, `获取分类列表`, true);
  395. }
  396. /**
  397. * 用于获取某一个分类需要用的子级
  398. * @param pid 父级
  399. * @returns
  400. */
  401. async getCategoryChildList(pid?: number) {
  402. const res = await this.get('/content/category/getCategoryOnlyChildList', '获取分类子级列表', {
  403. pid,
  404. });
  405. return transformArrayDataModel<CategoryListItem>(
  406. CategoryListItem,
  407. transformSomeToArray(res.data),
  408. `获取分类列表`,
  409. true
  410. );
  411. }
  412. /**
  413. * 模型的主体栏目列表
  414. * @param params 参数
  415. * @param querys 额外参数
  416. * @returns
  417. */
  418. async getModelColumList<T extends DataModel = GetModelColumContentList>(
  419. modelId: number,
  420. mainBodyColumnId?: number,
  421. page: number = 1,
  422. pageSize: number = 50,
  423. querys?: QueryParams
  424. ) {
  425. const res = await this.get('/content/main_body_column/getColumnList', `${this.debugName} 模型的主体栏目列表`, {
  426. main_body_id: this.mainBodyId,
  427. model_id: modelId ?? this.modelId,
  428. main_body_column_id: mainBodyColumnId,
  429. page,
  430. pageSize,
  431. ...querys
  432. });
  433. return transformArrayDataModel<T>(GetModelColumContentList, res.data as any, `${this.debugName} 模型的主体栏目列表`, true);
  434. }
  435. /**
  436. * 主体栏目列表
  437. * @param params 参数
  438. * @param querys 额外参数
  439. * @returns
  440. */
  441. async getColumList<T extends DataModel = GetColumContentList>(params: GetColumListParams, modelClassCreator: NewDataModel = GetColumContentList, querys?: QueryParams) {
  442. const res = await this.get<{ list: T[], total: number }>('/content/content/getMainBodyColumnContentList', `${this.debugName} 主体栏目列表`, {
  443. main_body_id: this.mainBodyId,
  444. model_id: this.modelId,
  445. ...params.toServerSide(),
  446. ...querys,
  447. });
  448. return {
  449. list: transformArrayDataModel<T>(modelClassCreator, requireNotNull(res.data).list, `${this.debugName} 主体栏目列表`, true),
  450. total: requireNotNull(res.data).total as number,
  451. };
  452. }
  453. /**
  454. * 模型内容列表
  455. * @param params 参数
  456. * @param page 页码
  457. * @param pageSize 页大小
  458. * @param querys 额外参数
  459. * @returns
  460. */
  461. async getContentList<T extends DataModel = GetContentListItem>(params: GetContentListParams, page: number, pageSize: number = 10, modelClassCreator: NewDataModel = GetContentListItem, querys?: QueryParams) {
  462. const res = await this.get<{ list: T[], total: number }>('/content/content/getContentList', `${this.debugName} 模型内容列表`, {
  463. ...params.toServerSide(),
  464. model_id: params.modelId || this.modelId,
  465. main_body_id: params.mainBodyId || this.mainBodyId,
  466. main_body_column_id: this.toStringArray(params.mainBodyColumnId || this.mainBodyColumnId),
  467. page,
  468. pageSize,
  469. ...querys,
  470. });
  471. let resList : any = null;
  472. let resTotal : any = null;
  473. if (res.data?.list && Array.isArray(res.data.list)) {
  474. resList = res.data.list;
  475. resTotal = res.data.total ?? resList.length;
  476. }
  477. else if (res.data && Array.isArray(res.data)) {
  478. resList = res.data;
  479. resTotal = resList.length;
  480. } else
  481. resList = res.data;
  482. if (resList === null)
  483. return { list: [], total: 0 };
  484. return {
  485. list: transformArrayDataModel<T>(modelClassCreator, resList, `${this.debugName} 模型内容列表`, true),
  486. total: resTotal as number,
  487. };
  488. }
  489. /**
  490. * 内容详情
  491. * @param id id
  492. * @param querys 额外参数
  493. * @returns
  494. */
  495. async getContentDetail<T extends DataModel = GetContentDetailItem>(id: number, modelClassCreator: NewDataModel = GetContentDetailItem, modelId?: number, querys?: QueryParams) {
  496. const res = await this.get('/content/content/getContentDetail', `${this.debugName} (${id}) 内容详情`, {
  497. main_body_id: this.mainBodyId,
  498. model_id: modelId ?? this.modelId,
  499. id,
  500. ...querys,
  501. }, modelClassCreator);
  502. return res.data as T;
  503. }
  504. /**
  505. * 获取可投稿栏目
  506. * @returns
  507. */
  508. async getContributeColumnList(querys?: QueryParams) {
  509. const res = await this.get('/content/main_body_column/getColumnList', `获取可投稿栏目`, {
  510. main_body_id: this.mainBodyId,
  511. model_id: 11,
  512. iscontribute: 1,
  513. ...querys,
  514. }, undefined);
  515. return res.data as unknown as GetColumContentList[];
  516. }
  517. /**
  518. * 上传文件到服务器
  519. */
  520. async uploadFile(file: string, fileType?: "image" | "video" | "audio" | undefined, name = 'file', data?: any) {
  521. return new Promise<{
  522. fullurl: string,
  523. url: string
  524. }>((resolve, reject) => {
  525. let url = this.config.baseUrl + '/common/upload';
  526. let req : RequestOptions = {
  527. method: 'POST',
  528. data: data,
  529. headers: {},
  530. }
  531. if (this.config.requestInterceptor) {
  532. const { newReq, newUrl } = this.config.requestInterceptor(url, req);
  533. url = newUrl;
  534. data = newReq;
  535. }
  536. console.log(url);
  537. uni.uploadFile({
  538. url: url,
  539. name,
  540. header: req.headers,
  541. filePath: file,
  542. formData: data,
  543. fileType,
  544. success: (result) => {
  545. let data = JSON.parse(result.data);
  546. if (data.code !== 1)
  547. throw new Error(data.msg ?? 'code: ' + data.code);
  548. resolve(data.data);
  549. },
  550. fail(result) {
  551. reject(result);
  552. },
  553. })
  554. })
  555. }
  556. /**
  557. * 内容反馈
  558. * @param data
  559. * @returns
  560. */
  561. async feedBack(data: FeedBackItem) {
  562. return (this.post('/user/feedback', '内容反馈', data.toServerSide()));
  563. }
  564. }
  565. export default new CommonContentApi(undefined, 0, '默认通用内容');