CommonContent.ts 16 KB

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