CommonCategoryList.vue 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. <template>
  2. <FlexCol>
  3. <FlexCol v-if="errorMessage" :padding="30" :gap="30" center height="100%">
  4. <Result status="error" :description="errorMessage" />
  5. <Button type="primary" @click="loadPageConfig">重新加载</Button>
  6. </FlexCol>
  7. <LoadingPage v-else-if="!loadState" />
  8. <CommonListPage
  9. v-else-if="currentCommonCategoryDefine && loadState"
  10. :startTabIndex="pageStartTab"
  11. v-bind="currentCommonCategoryDefine.content.props as any || undefined"
  12. :title="currentCommonCategoryDefine.title || undefined"
  13. :load="loadData"
  14. :tabs="tabs"
  15. :dropDownNames="dropdownNames"
  16. :showListTabIds="showListTabIds"
  17. :detailsPage="detailsPage"
  18. >
  19. <template #list="{ tabId }">
  20. <CommonCategoryBlocks
  21. v-if="tabRenderDefines[tabId]?.type === 'nestCategory'"
  22. :categoryDefine="tabRenderDefines[tabId].categoryDefine"
  23. />
  24. </template>
  25. </CommonListPage>
  26. <Footer text="我也是有底线的~" />
  27. </FlexCol>
  28. </template>
  29. <script setup lang="ts">
  30. import { computed, onMounted, ref, watch } from 'vue';
  31. import { injectCommonCategory } from './CommonCategoryGlobalLoader';
  32. import { navTo } from '@/components/utils/PageAction';
  33. import { doLoadDynamicCategoryDataMergeTypeGetColumns, doLoadDynamicDropdownData, doLoadDynamicListData } from './CommonCategoryDynamicData';
  34. import { CommonCategoryListTabNestCategoryDataToContent, type IHomeCommonCategoryDefine, type IHomeCommonCategoryListDefine, type IHomeCommonCategoryListTabDefine } from './CommonCategoryDefine';
  35. import { resolveCommonContentSolveProps } from '../common/CommonContent';
  36. import { waitTimeOut } from '@imengyu/imengyu-utils';
  37. import { formatError } from '@/common/composeabe/ErrorDisplay';
  38. import type { SimpleDropDownPickerItem } from '@/common/components/SimpleDropDownPicker.vue';
  39. import type { CommonListPageProps, DropDownNames } from '../common/CommonListPage.vue';
  40. import CommonListPage from '../common/CommonListPage.vue';
  41. import Result from '@/components/feedback/Result.vue';
  42. import CommonCategoryBlocks, { type CategoryDefine } from './CommonCategoryBlocks.vue';
  43. import Footer from '@/components/display/Footer.vue';
  44. import FlexCol from '@/components/layout/FlexCol.vue';
  45. import LoadingPage from '@/components/display/loading/LoadingPage.vue';
  46. import Button from '@/components/basic/Button.vue';
  47. /**
  48. * 动态通用内容 - 通用列表页
  49. */
  50. const loadState = ref(false);
  51. const errorMessage = ref('');
  52. const currentCommonCategoryDefine = ref<IHomeCommonCategoryDefine['page'][0]>();
  53. const currentCommonCategoryContentDefine = ref<IHomeCommonCategoryListDefine>();
  54. const commonCategory = injectCommonCategory();
  55. const props = defineProps({
  56. pageConfigName: {
  57. type: String,
  58. default: '',
  59. },
  60. pageStartTab: {
  61. type: Number,
  62. default: 0,
  63. },
  64. pageQuerys: {
  65. type: Object as () => Record<string, string|number|number[]|undefined>,
  66. default: () => ({}),
  67. },
  68. });
  69. async function loadPageConfig() {
  70. if (!props.pageConfigName) {
  71. errorMessage.value = '配置有误';
  72. return;
  73. }
  74. currentCommonCategoryDefine.value = commonCategory.value.page
  75. .find((item) => item.name === props.pageConfigName);
  76. if (!currentCommonCategoryDefine.value) {
  77. errorMessage.value = '未找到指定的分类配置:' + props.pageConfigName;
  78. return;
  79. }
  80. if (currentCommonCategoryDefine.value.content.type !== 'CommonList') {
  81. errorMessage.value = '分类配置:' + props.pageConfigName + ' 不是列表类型';
  82. return;
  83. }
  84. currentCommonCategoryContentDefine.value =
  85. currentCommonCategoryDefine.value.content as IHomeCommonCategoryListDefine;
  86. uni.setNavigationBarTitle({
  87. title: currentCommonCategoryDefine.value?.title || '',
  88. })
  89. await waitTimeOut(100);
  90. try {
  91. //特殊处理
  92. let hasNestCategory = false;
  93. for (const [_, tab] of Object.entries(tabDefines.value)) {
  94. if (tab.type === 'nestCategory') {
  95. tab.categorys = await doLoadDynamicCategoryDataMergeTypeGetColumns(tab.categorys)
  96. hasNestCategory = true;
  97. }
  98. }
  99. if (hasNestCategory)
  100. await waitTimeOut(100);
  101. //加载下拉列表
  102. const result = [] as DropDownNames[];
  103. for (const [key, tab] of Object.entries(tabRenderDefines.value)) {
  104. if (tab.type !== 'list')
  105. continue;
  106. if (tab.dropdownDefines) {
  107. for (const dropdown of tab.dropdownDefines) {
  108. const data : SimpleDropDownPickerItem[] = (dropdown.addAll ? [{
  109. id: 0,
  110. name: dropdown.addAll
  111. }] : []);
  112. if (dropdown.data) {
  113. data.push(...(await doLoadDynamicDropdownData(dropdown.data)).map((item) => ({
  114. id: item[dropdown.data.idKey || 'id'],
  115. name: item[dropdown.data.nameKey || 'title'],
  116. })))
  117. }
  118. result.push({
  119. options: data,
  120. activeTab: [Number(key)],
  121. defaultSelectedValue: dropdown.formQueryKey ? (
  122. props.pageQuerys[dropdown.formQueryKey] as number || 0
  123. ) : dropdown.defaultValue || 0,
  124. })
  125. }
  126. }
  127. }
  128. loadState.value = true;
  129. dropdownNames.value = result;
  130. } catch (error) {
  131. console.error(error);
  132. loadState.value = false;
  133. errorMessage.value = formatError(error);
  134. }
  135. }
  136. watch(() => props.pageConfigName, loadPageConfig);
  137. onMounted(loadPageConfig);
  138. type RenderTabDefine = IHomeCommonCategoryListTabDefine & {
  139. categoryDefine?: CategoryDefine[];
  140. };
  141. const tabDefines = computed(() => currentCommonCategoryContentDefine.value?.props.tabs || []);
  142. const tabRenderDefines = computed(() => {
  143. const result = {} as Record<number, RenderTabDefine>;
  144. try {
  145. tabDefines.value.forEach((item, i) => {
  146. const renderItem : RenderTabDefine = {
  147. ...item,
  148. };
  149. switch (item.type) {
  150. default:
  151. case 'list':
  152. break;
  153. case 'jump':
  154. break;
  155. case 'nestCategory':
  156. renderItem.categoryDefine = item.categorys
  157. .filter((item) => item.visible !== false)
  158. .map((item) => {
  159. return {
  160. ...item,
  161. showTitle: item.showTitle !== false,
  162. title: item.text,
  163. content: CommonCategoryListTabNestCategoryDataToContent(
  164. item.data, item
  165. ),
  166. type: item.type as CategoryDefine['type'],
  167. }
  168. });
  169. break;
  170. }
  171. result[i] = renderItem;
  172. });
  173. } catch (error) {
  174. errorMessage.value = formatError(error);
  175. }
  176. return result;
  177. });
  178. const showListTabIds = computed(() => {
  179. const define = tabDefines.value;
  180. if (define.length === 0)
  181. return undefined;
  182. return define
  183. .map((item, i) => ({ type: item.type, id: i }))
  184. .filter((item) => item.type === 'list')
  185. .map((item) => item.id);
  186. })
  187. const tabs = computed<CommonListPageProps['tabs']>(() => {
  188. const define = tabDefines.value;
  189. return define.map((item, i) => {
  190. switch (item.type) {
  191. default:
  192. case 'list':
  193. return {
  194. id: i,
  195. text: item.text,
  196. width: item.width,
  197. };
  198. case 'jump':
  199. return {
  200. id: i,
  201. text: item.text,
  202. onlyJump: true,
  203. jump: () => navTo(item.url, item.params),
  204. width: item.width,
  205. };
  206. case 'nestCategory':
  207. return {
  208. id: i,
  209. text: item.text,
  210. width: item.width,
  211. };
  212. }
  213. });
  214. });
  215. const dropdownNames = ref<DropDownNames[]>([]);
  216. const detailsPage = computed(() => {
  217. if (tabDefines.value.find((item) => item.detailsPage)) {
  218. const result = {} as Record<number, string>;
  219. tabDefines.value.forEach((item, i) => {
  220. result[i] = item.detailsPage || '';
  221. });
  222. return result;
  223. }
  224. return currentCommonCategoryContentDefine.value?.props.detailsPage || undefined;
  225. });
  226. async function loadData(
  227. page: number,
  228. pageSize: number,
  229. searchText: string,
  230. dropDownValues: number[],
  231. tabSelect: number
  232. ) {
  233. const tab = tabRenderDefines.value[tabSelect];
  234. if (!tab)
  235. throw new Error(`配置有误 tab:${tabSelect}`);
  236. if (tab.type !== 'list')
  237. return { list: [], total: 0 };
  238. const res = await doLoadDynamicListData(
  239. tab.data,
  240. page,
  241. pageSize,
  242. searchText,
  243. tab.dropdownDefines || [],
  244. dropDownValues,
  245. );
  246. if (res && tab.dataSolve)
  247. res.list = resolveCommonContentSolveProps(res.list, tab.dataSolve);
  248. return res;
  249. }
  250. </script>