analysis_map.vue 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. <template>
  2. <el-scrollbar ref="scrollbar" class="analysis" @scroll="scroll">
  3. <div class="head">
  4. <div class="title">地域热点</div>
  5. <div class="searchRow">
  6. <div class="searchCol searchTitle">省:</div>
  7. <div
  8. :class="{
  9. searchCol: true,
  10. searchActive: searchActive.area === optionindex,
  11. }"
  12. v-for="(optionitem, optionindex) in areaification"
  13. :key="optionindex + 'option'"
  14. v-text="optionitem.name"
  15. @click="() => clickSelect('area', optionindex)"
  16. ></div>
  17. </div>
  18. <div
  19. class="searchRow"
  20. v-if="
  21. areaification[searchActive.area] &&
  22. areaification[searchActive.area].child
  23. "
  24. >
  25. <div class="searchCol searchTitle">市:</div>
  26. <div
  27. :class="{
  28. searchCol: true,
  29. searchActive: searchActive.areaSon === optionindex,
  30. }"
  31. v-for="(optionitem, optionindex) in areaification[searchActive.area]
  32. .child"
  33. :key="optionindex + 'optionSon'"
  34. v-text="optionitem.name"
  35. @click="() => clickSelect('areaSon', optionindex)"
  36. ></div>
  37. </div>
  38. <div class="searchRow">
  39. <div class="searchCol searchTitle">分类:</div>
  40. <div
  41. :class="{
  42. searchCol: true,
  43. searchActive: searchActive.classification === optionindex,
  44. }"
  45. v-for="(optionitem, optionindex) in classification"
  46. :key="optionindex + 'option'"
  47. v-text="optionitem.name"
  48. @click="() => clickSelect('classification', optionindex)"
  49. ></div>
  50. </div>
  51. <div class="searchRow">
  52. <div class="searchCol searchTitle">时间:</div>
  53. <div
  54. :class="{
  55. searchCol: true,
  56. searchActive: searchActive.time === optionindex,
  57. }"
  58. v-for="(optionitem, optionindex) in time"
  59. :key="optionindex + 'option'"
  60. v-text="optionitem.name"
  61. @click="() => clickSelect('time', optionindex)"
  62. ></div>
  63. <div
  64. :class="{
  65. searchCol: true,
  66. searchActive: searchActive.time === -1,
  67. }"
  68. @click="() => clickSelect('time', -1)"
  69. >
  70. 自定义
  71. </div>
  72. <div class="searchCol">
  73. <el-date-picker
  74. v-model="date"
  75. :disabled="searchActive.time !== -1"
  76. @change="change"
  77. :disabled-date="disDate"
  78. type="daterange"
  79. :clearable="false"
  80. value-format="YYYY-MM-DD"
  81. range-separator="-"
  82. start-placeholder="开始时间"
  83. end-placeholder="结束时间"
  84. />
  85. </div>
  86. </div>
  87. <div class="searchRow">
  88. <div class="searchCol searchTitle">搜索:</div>
  89. <div class="searchCol">
  90. <el-input v-model="searchText" placeholder="搜索文章">
  91. <template #suffix>
  92. <el-icon @click="search"><Search /></el-icon>
  93. </template>
  94. </el-input>
  95. </div>
  96. </div>
  97. </div>
  98. <div class="body">
  99. <analysisList ref="analysisListEle" />
  100. </div>
  101. <analysisHotList
  102. @changeSearch="hotList"
  103. :province="
  104. areaification[searchActive.area]
  105. ? areaification[searchActive.area].name
  106. : undefined
  107. "
  108. />
  109. <el-icon :size="45" class="upload" v-show="showUpload" @click="upload"
  110. ><Upload
  111. /></el-icon>
  112. </el-scrollbar>
  113. </template>
  114. <script setup>
  115. import dayjs from 'dayjs';
  116. import { ref, onMounted } from 'vue';
  117. import { getEconomize, getClass } from '../../api/index';
  118. import analysisList from './components/analysis_list.vue';
  119. import analysisHotList from './components/analysis_hot_list.vue';
  120. const nowTime = Date.now();
  121. const scrollbar = ref();
  122. const analysisListEle = ref();
  123. const showUpload = ref(false);
  124. const searchActive = ref({
  125. classification: 0,
  126. time: 0,
  127. area: 0,
  128. areaSon: 0,
  129. });
  130. const defaultOption = {
  131. type: 'option',
  132. name: '全部',
  133. id: 0,
  134. };
  135. const classification = ref([defaultOption]);
  136. const areaification = ref([defaultOption]);
  137. const time = [
  138. {
  139. type: 'option',
  140. time: nowTime - 86400000,
  141. name: '24小时',
  142. id: 1,
  143. },
  144. {
  145. type: 'option',
  146. time: nowTime - 172800000,
  147. name: '48小时',
  148. id: 2,
  149. },
  150. {
  151. type: 'option',
  152. time: nowTime - 604800000,
  153. name: '近7天',
  154. id: 3,
  155. },
  156. {
  157. type: 'option',
  158. time: nowTime - 2592000000,
  159. name: '近30天',
  160. id: 4,
  161. },
  162. ];
  163. const searchText = ref('');
  164. const date = ref([]);
  165. const pageSize = 10;
  166. let page = 1;
  167. onMounted(() => {
  168. getList();
  169. });
  170. getEconomize({
  171. data: {
  172. // key: 'b264662362c25150a1e6612013a7b921',
  173. // keywords: '中国',
  174. // subdistrict: 2,
  175. },
  176. }).then(r => {
  177. const list = r || [];
  178. for (let i = 0; i < list.length; i++) {
  179. const v = list[i];
  180. const city = [
  181. {
  182. type: 'option',
  183. name: '全部',
  184. id: -1,
  185. },
  186. ...v.districts.map((item, index) => {
  187. return {
  188. type: 'option',
  189. name: item.alias,
  190. id: index,
  191. };
  192. }),
  193. ];
  194. areaification.value.push({
  195. type: 'option',
  196. name: v.alias,
  197. child: city,
  198. id: i,
  199. });
  200. }
  201. });
  202. getClass({}).then(res => {
  203. const li = res || [];
  204. const l = [];
  205. for (let i = 0; i < li.length; i++) {
  206. const v = li[i];
  207. l.push({
  208. type: 'option',
  209. name: v,
  210. });
  211. }
  212. classification.value.push(...l);
  213. });
  214. const getList = () => {
  215. const search = {
  216. category:
  217. classification.value[searchActive.value.classification].name || undefined,
  218. keywords: searchText.value,
  219. page: page++,
  220. pageSize,
  221. };
  222. const sheng = areaification.value[searchActive.value.area] || {};
  223. if (sheng.name && sheng.name !== '全部') {
  224. const city =
  225. sheng.child[searchActive.value.areaSon] &&
  226. sheng.child[searchActive.value.areaSon].name;
  227. const l = [sheng.name];
  228. if (city !== '全部') l.push(city || '');
  229. search.city = l.join(',');
  230. }
  231. search.category === '全部' ? (search.category = '') : '';
  232. search.city === '全部' ? (search.city = '') : '';
  233. // 时间区间
  234. if (searchActive.value['time'] === -1) {
  235. search.start = date.value[0];
  236. search.end = date.value[1];
  237. } else {
  238. search.start = dayjs(time[searchActive.value['time']].time).format(
  239. 'YYYY-MM-DD HH:mm:ss'
  240. );
  241. search.end = dayjs(nowTime).format('YYYY-MM-DD HH:mm:ss');
  242. }
  243. analysisListEle.value.getlist(search);
  244. };
  245. const clickSelect = (select, index) => {
  246. searchActive.value[select] = index;
  247. if (index === -1) return;
  248. page = 1;
  249. getList();
  250. };
  251. const change = () => {
  252. date.value = [date.value[0] + ' 00:00:00', date.value[1] + ' 23:59:59'];
  253. page = 1;
  254. getList();
  255. };
  256. const search = () => {
  257. page = 1;
  258. getList();
  259. };
  260. const hotList = searchTextHot => {
  261. if (!searchTextHot) return;
  262. page = 1;
  263. searchText.value = searchTextHot;
  264. getList();
  265. };
  266. const scroll = e => {
  267. const height =
  268. document.querySelector('.analysis .head').offsetHeight +
  269. document.querySelector('.analysis .body').offsetHeight -
  270. document.querySelector('.analysis').offsetHeight;
  271. const scrollNum = e.scrollTop.toFixed(2) - 0;
  272. if (!showUpload.value && scrollNum > 180) showUpload.value = true;
  273. else if (scrollNum <= 180) showUpload.value = false;
  274. if (height - scrollNum > 0) return;
  275. getList();
  276. };
  277. const upload = () => {
  278. scrollbar.value.setScrollTop(0);
  279. };
  280. const nowT = Date.now();
  281. const disDate = date => {
  282. return date.getTime() > nowT;
  283. };
  284. </script>
  285. <style scoped>
  286. .analysis {
  287. height: 100%;
  288. /* min-width: 1305px; */
  289. position: relative;
  290. }
  291. .analysis .head,
  292. .analysis .body {
  293. margin: 0 1em;
  294. width: calc(100% - 400px);
  295. min-width: 855px;
  296. }
  297. .analysis .body {
  298. border: 1px solid #f3f3f3;
  299. margin: 1em;
  300. }
  301. .title {
  302. font-size: 18px;
  303. font-weight: 600;
  304. height: 49px;
  305. line-height: 49px;
  306. padding-left: 8px;
  307. border-bottom: 1px solid #f5f5f5;
  308. }
  309. .searchRow {
  310. margin: 0.5em 0;
  311. }
  312. .searchCol {
  313. display: inline-block;
  314. margin: 0 0.5em;
  315. padding: 0 0.5em;
  316. height: 35px;
  317. line-height: 35px;
  318. cursor: pointer;
  319. }
  320. .searchCol:hover {
  321. color: rgb(64, 158, 255);
  322. }
  323. .searchActive {
  324. font-weight: 600;
  325. color: rgb(64, 158, 255);
  326. border-radius: 5px;
  327. background-color: rgba(64, 158, 255, 0.1);
  328. border-bottom: none;
  329. }
  330. .searchRow .searchTitle {
  331. color: #b9c0d3;
  332. }
  333. .body .el-checkbox {
  334. margin-right: 15px;
  335. }
  336. .source {
  337. color: #22ac38;
  338. }
  339. .upload {
  340. position: absolute;
  341. right: 25px;
  342. bottom: 25px;
  343. background-color: #e9e9e990;
  344. border-radius: 50%;
  345. padding: 5px;
  346. cursor: pointer;
  347. }
  348. </style>