FullDataList.vue 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. <template>
  2. <TopicFullDataListSection
  3. ref="sectionRef"
  4. title="全量数据列表"
  5. export-label="导出筛选结果"
  6. :columns="TOPIC1_FULL_COLUMNS"
  7. :rows="rows"
  8. :page-size="10"
  9. @export="handleExport"
  10. @row-action="$emit('row-action', $event)"
  11. >
  12. <template #filters>
  13. <div class="filter-bar">
  14. <label class="filter-item filter-item--wide">
  15. <span>关键词</span>
  16. <input
  17. :value="filters.keyword"
  18. type="search"
  19. placeholder="编号 / 坐落 / 企业"
  20. @input="patchFilters({ keyword: $event.target.value })"
  21. />
  22. </label>
  23. <BaseSelect
  24. text="房屋用途"
  25. :selected-text="fwUsageLabel"
  26. :options="fwUsageOptions"
  27. :select-width="168"
  28. :max-options-height="240"
  29. @selected="patchFilters({ fwUsage: $event })"
  30. />
  31. <BaseSelect
  32. text="所属集团"
  33. :selected-text="groupLabel"
  34. :options="GROUP_FILTER_OPTIONS"
  35. @selected="patchFilters({ group: $event })"
  36. />
  37. <BaseSelect
  38. text="房龄"
  39. :selected-text="ageLabel"
  40. :options="AGE_FILTER_OPTIONS"
  41. @selected="patchFilters({ age: $event })"
  42. />
  43. <BaseSelect
  44. text="使用状态"
  45. :selected-text="utilLabel"
  46. :options="UTIL_FILTER_OPTIONS"
  47. @selected="patchFilters({ util: $event })"
  48. />
  49. <BaseSelect
  50. text="土地类型"
  51. :selected-text="landTypeLabel"
  52. :options="landTypeOptions"
  53. :select-width="168"
  54. :max-options-height="240"
  55. @selected="patchFilters({ landUsage: $event })"
  56. />
  57. <BaseButton
  58. class="filter-bar__reset"
  59. text="重置"
  60. variant="outline"
  61. @click="$emit('reset')"
  62. />
  63. </div>
  64. </template>
  65. <template #hint>
  66. <p class="filter-hint">
  67. 当前筛选:<strong>{{ filterHint.summary }}</strong> · 共 {{ filterHint.total }} 条
  68. </p>
  69. </template>
  70. </TopicFullDataListSection>
  71. </template>
  72. <script setup>
  73. import { showSuccess, showWarning } from '@/utils/message';
  74. import { exportTableExcel } from '@/utils/exportExcel';
  75. import { computed, ref, defineProps, defineEmits, defineExpose } from 'vue';
  76. import BaseSelect from '@/components/base/BaseSelect.vue';
  77. import BaseButton from '@/components/base/BaseButton.vue';
  78. import TopicFullDataListSection from '@/components/stats/TopicFullDataListSection.vue';
  79. import { TOPIC1_FULL_COLUMNS } from '@/utils/fullListColumns';
  80. import {
  81. AGE_BUCKET_LABELS,
  82. AGE_FILTER_OPTIONS,
  83. GROUP_FILTER_OPTIONS,
  84. UTIL_FILTER_OPTIONS,
  85. buildFilterHint,
  86. } from '@/utils/topic1AssetList';
  87. const props = defineProps({
  88. filters: {
  89. type: Object,
  90. required: true,
  91. },
  92. rows: {
  93. type: Array,
  94. default: () => [],
  95. },
  96. fwUsageOptions: {
  97. type: Array,
  98. default: () => [{ text: '全部', value: '' }],
  99. },
  100. landTypeOptions: {
  101. type: Array,
  102. default: () => [{ text: '全部', value: '' }],
  103. },
  104. });
  105. const emit = defineEmits(['update:filters', 'reset', 'row-action']);
  106. const sectionRef = ref(null);
  107. const fwUsageLabel = computed(() => props.filters.fwUsage || '全部');
  108. const groupLabel = computed(() =>
  109. props.filters.group === '全部' ? '全部集团' : props.filters.group
  110. );
  111. const ageLabel = computed(() =>
  112. props.filters.age === '全部'
  113. ? '全部'
  114. : (AGE_BUCKET_LABELS[props.filters.age] ?? props.filters.age)
  115. );
  116. const utilLabel = computed(() =>
  117. props.filters.util === '全部' ? '全部' : props.filters.util
  118. );
  119. const landTypeLabel = computed(() => props.filters.landUsage || '全部');
  120. const filterHint = computed(() => buildFilterHint(props.filters, props.rows.length));
  121. const patchFilters = (patch) => {
  122. const pieKeys = ['fwUsage', 'landType', 'landUsage'];
  123. const clearsPie = 'group' in patch || 'age' in patch || 'util' in patch;
  124. const next = { ...props.filters, ...patch };
  125. if (clearsPie) {
  126. pieKeys.forEach((key) => {
  127. next[key] = '';
  128. });
  129. }
  130. if ('fwUsage' in patch) {
  131. next.landUsage = '';
  132. next.landType = '';
  133. }
  134. if ('landUsage' in patch) {
  135. next.fwUsage = '';
  136. next.landType = '';
  137. }
  138. emit('update:filters', next);
  139. };
  140. const handleExport = () => {
  141. const result = exportTableExcel({
  142. columns: TOPIC1_FULL_COLUMNS,
  143. rows: props.rows,
  144. filenameBase: '专题1-全量数据列表',
  145. });
  146. if (!result.ok) {
  147. showWarning('当前筛选结果为空,无法导出');
  148. return;
  149. }
  150. showSuccess(`已导出 ${result.count} 条记录(${result.filename})`);
  151. };
  152. defineExpose({
  153. scrollIntoView: () => {
  154. sectionRef.value?.scrollIntoView();
  155. },
  156. });
  157. </script>