liyongli há 2 anos atrás
pai
commit
42d426f110

+ 16 - 0
src/api/index.js

@@ -93,4 +93,20 @@ export function getH5Mall(ori) {
             Authorization: localStorage.getItem("token")
         }
     })
+}
+
+/**
+ * 行政区划接口
+ * @param {Object} ori 
+ * @returns 
+ */
+export function getEconomize(ori) {
+    return ajax({
+        api: "/v3/config/district",
+        data: ori.data,
+        base: "GaoDeMap",
+        type: "ajax",
+        platfrom: "threeth",
+        method: 'GET'
+    })
 }

+ 2 - 1
src/config/index.js

@@ -1,6 +1,7 @@
 export default {
     base:{
         origin: "https://open.sxtvs.net",
-        oss1: "https://cxzx.smcic.net/topic/tool/img/cache"
+        oss1: "https://cxzx.smcic.net/topic/tool/img/cache",
+        GaoDeMap: "https://restapi.amap.com"
     }
 }

+ 7 - 0
src/router/allMedia.js

@@ -55,6 +55,13 @@ export default [
             /* webpackChunkName: "analysis" */ '../view/allMedia/analysis.vue'
           ),
       },
+      {
+        path: 'analysis_map',
+        component: () =>
+          import(
+            /* webpackChunkName: "analysis_map" */ '../view/allMedia/analysis_map.vue'
+          ),
+      },
       {
         path: 'convergence',
         component: () =>

+ 13 - 5
src/utils/request.js

@@ -26,11 +26,18 @@ function ajax(longRange) {
       if (this.readyState !== 4) return;
       loading.close();
       var data = JSON.parse(this.responseText || '{}');
-      if (this.status !== 200 || data.code !== 0) {
+      if (this.status !== 200) {
         errorStatus({ ...data, status: this.status });
         return reject({ ...data, status: this.status });
       }
-      return resolve(data.data);
+
+      if (!longRange.platfrom && data.code !== 0) {
+        errorStatus({ ...data, status: this.status });
+        return reject({ ...data, status: this.status });
+      }
+
+      const res = longRange.platfrom ? data || {} : data.data;
+      return resolve(res);
     };
   });
 }
@@ -40,7 +47,7 @@ function fetch(longRange) {
     const met = (longRange.method || 'GET').toUpperCase();
     const p = {
       method: met,
-    //   mode: 'no-cors',
+      //   mode: 'no-cors',
       headers: headerFunc(longRange.headers),
     };
     if (met !== 'GET') p.body = bodyFunc(longRange.data);
@@ -58,12 +65,13 @@ function fetch(longRange) {
       })
       .then(res => {
         loading.close();
-        if (res.code !== 0) {
+        if (!longRange.platfrom && res.code !== 0) {
           errorStatus(res);
           return reject(res);
         }
 
-        return resolve(res.data);
+        const Data = longRange.platfrom ? res || {} : res.data;
+        return resolve(Data);
       });
   });
 }

+ 542 - 0
src/view/allMedia/analysis_map.vue

@@ -0,0 +1,542 @@
+<template>
+  <el-scrollbar ref="scrollbar" class="analysis" @scroll="scroll">
+    <div class="head">
+      <div class="title">分类舆情</div>
+      <div class="searchRow">
+        <div class="searchCol searchTitle">省:</div>
+        <div
+          :class="{
+            searchCol: true,
+            searchActive: searchActive.area === optionindex,
+          }"
+          v-for="(optionitem, optionindex) in areaification"
+          :key="optionindex + 'option'"
+          v-text="optionitem.name"
+          @click="() => clickSelect('area', optionindex)"
+        ></div>
+      </div>
+      <div
+        class="searchRow"
+        v-if="
+          areaification[searchActive.area] &&
+          areaification[searchActive.area].child
+        "
+      >
+        <div class="searchCol searchTitle">市:</div>
+        <div
+          :class="{
+            searchCol: true,
+            searchActive: searchActive.areaSon === optionindex,
+          }"
+          v-for="(optionitem, optionindex) in areaification[searchActive.area]
+            .child"
+          :key="optionindex + 'optionSon'"
+          v-text="optionitem.name"
+          @click="() => clickSelect('areaSon', optionindex)"
+        ></div>
+      </div>
+      <div class="searchRow">
+        <div class="searchCol searchTitle">分类:</div>
+        <div
+          :class="{
+            searchCol: true,
+            searchActive: searchActive.classification === optionindex,
+          }"
+          v-for="(optionitem, optionindex) in classification"
+          :key="optionindex + 'option'"
+          v-text="optionitem.name"
+          @click="() => clickSelect('classification', optionindex)"
+        ></div>
+      </div>
+      <div class="searchRow">
+        <div class="searchCol searchTitle">时间:</div>
+        <div
+          :class="{
+            searchCol: true,
+            searchActive: searchActive.time === optionindex,
+          }"
+          v-for="(optionitem, optionindex) in time"
+          :key="optionindex + 'option'"
+          v-text="optionitem.name"
+          @click="() => clickSelect('time', optionindex)"
+        ></div>
+        <div
+          :class="{
+            searchCol: true,
+            searchActive: searchActive.time === -1,
+          }"
+          @click="() => clickSelect('time', -1)"
+        >
+          自定义
+        </div>
+        <div class="searchCol">
+          <el-date-picker
+            v-model="date"
+            :disabled="searchActive.time !== -1"
+            @change="change"
+            type="daterange"
+            :clearable="false"
+            value-format="YYYY-MM-DD"
+            range-separator="-"
+            start-placeholder="开始时间"
+            end-placeholder="结束时间"
+          />
+        </div>
+      </div>
+      <div class="searchRow">
+        <div class="searchCol searchTitle">搜索:</div>
+        <div class="searchCol">
+          <el-input v-model="searchText" placeholder="搜索文章">
+            <template #suffix>
+              <el-icon @click="search"><Search /></el-icon>
+            </template>
+          </el-input>
+        </div>
+      </div>
+    </div>
+    <div class="body">
+      <div class="mainTitle">
+        <div class="mainTitleTool" v-if="selectlist.length">
+          <el-select
+            v-model="selectValue"
+            class="m-2"
+            placeholder="Select"
+            @change="changeSelect"
+          >
+            <el-option
+              v-for="item in selectlist"
+              :key="item.value"
+              :label="item.label"
+              :value="item.value"
+            />
+          </el-select>
+        </div>
+        文章列表
+      </div>
+      <br />
+      <div class="lists">
+        <div
+          class="list"
+          v-for="item in listTable"
+          :key="item.title"
+          @click="() => toDetail(item)"
+        >
+          <div class="listHead" v-text="item ? item.title || '' : ''"></div>
+          <div
+            class="listSubtitle"
+            v-html="item ? item.summary || '' : ''"
+          ></div>
+          <el-row>
+            <el-col :span="12" style="color: #9aa8c4">
+              <el-icon><Clock /></el-icon>
+              <span v-text="item.publishTime"></span>
+            </el-col>
+            <el-col :span="12" style="text-align: right">
+              来源:
+              <span class="source" v-text="item.sourceWebsite"></span>
+            </el-col>
+          </el-row>
+        </div>
+      </div>
+    </div>
+
+    <div class="hotList">
+      <div class="title">
+        <img :src="hotIcon" style="width: 18px; height: 18px" />
+        热度排行
+      </div>
+      <div
+        class="hotItem"
+        v-for="(item, index) in listHot"
+        :key="item.rk"
+        @click="() => searchHot(item.content)"
+      >
+        <span
+          :style="{ color: colorRanking[index] || '#999', 'font-size': '14px' }"
+          >{{ index + 1 }}</span
+        >
+        {{ item.content }}
+      </div>
+    </div>
+
+    <el-icon :size="45" class="upload" v-show="showUpload" @click="upload"
+      ><Upload
+    /></el-icon>
+  </el-scrollbar>
+</template>
+
+<script setup>
+import dayjs from 'dayjs';
+import { ref } from 'vue';
+import { useRouter } from 'vue-router';
+import { getEconomize, hotRank, searchData, getClass } from '../../api/index';
+
+import hotIcon from '../../assets/img/hot.png';
+
+const router = useRouter();
+const colorRanking = ['#FE2D46', '#F60', '#FAA90E'];
+const nowTime = Date.now();
+const scrollbar = ref();
+const showUpload = ref(false);
+const searchActive = ref({
+  classification: 0,
+  time: 0,
+  area: 0,
+  areaSon: 0,
+});
+const defaultOption = {
+  type: 'option',
+  name: '全部',
+  id: 0,
+};
+const classification = ref([defaultOption]);
+const areaification = ref([defaultOption]);
+const time = [
+  {
+    type: 'option',
+    time: nowTime - 86400000,
+    name: '24小时',
+    id: 1,
+  },
+  {
+    type: 'option',
+    time: nowTime - 172800000,
+    name: '48小时',
+    id: 2,
+  },
+  {
+    type: 'option',
+    time: nowTime - 604800000,
+    name: '近7天',
+    id: 3,
+  },
+  {
+    type: 'option',
+    time: nowTime - 2592000000,
+    name: '近30天',
+    id: 4,
+  },
+];
+const searchText = ref('');
+const selectlist = [
+  //   {
+  //     label: '按发布时间降序',
+  //     value: 0,
+  //   },
+  //   {
+  //     label: '按发布时间升序',
+  //     value: 1,
+  //   },
+  //   {
+  //     label: '按发情感值升序',
+  //     value: 2,
+  //   },
+  //   {
+  //     label: '按发情感值降序',
+  //     value: 3,
+  //   },
+];
+const selectValue = ref(0);
+const date = ref([]);
+
+const listTable = ref([]);
+const listHot = ref([]);
+
+const pageSize = 10;
+let page = 1;
+let total = -1;
+let T = undefined;
+
+if (localStorage.getItem('Economize')) {
+  areaification.value = JSON.parse(localStorage.getItem('Economize'));
+} else
+  getEconomize({
+    data: {
+      key: 'b264662362c25150a1e6612013a7b921',
+      keywords: '中国',
+      subdistrict: 2,
+    },
+  }).then(r => {
+    const list = r.districts[0].districts || [];
+    for (let i = 0; i < list.length; i++) {
+      const v = list[i];
+      areaification.value.push({
+        type: 'option',
+        name: v.name,
+        child: v.districts.map((item, index) => {
+          return {
+            type: 'option',
+            name: item.name,
+            id: index,
+          };
+        }),
+        id: i,
+      });
+    }
+    localStorage.setItem('Economize', JSON.stringify(areaification.value));
+    console.log(areaification.value);
+  });
+
+getClass({}).then(res => {
+  const li = res || [];
+  const l = [];
+  for (let i = 0; i < li.length; i++) {
+    const v = li[i];
+    l.push({
+      type: 'option',
+      name: v,
+    });
+  }
+  classification.value.push(...l);
+});
+hotRank({}).then(res => {
+  listHot.value = res || [];
+});
+const toDetail = item => {
+  router.push({
+    path: '/analysis_detail',
+    query: {
+      detail: JSON.stringify(item),
+    },
+  });
+};
+
+const getList = () => {
+  const search = {
+    category:
+      classification.value[searchActive.value.classification].name || undefined,
+    keywords: searchText.value,
+    page: page++,
+    pageSize,
+  };
+
+  const sheng = areaification.value[searchActive.value.area] || {};
+  if (areaification.value.length && sheng.name) {
+    const city = [sheng.name];
+    sheng.child && sheng.child.length && city.push(sheng.child[searchActive.value.areaSon].name);
+    search.city = city.join(",");
+  }
+  search.category === '全部' ? (search.category = '') : '';
+  // 时间区间
+  if (searchActive.value['time'] === -1) {
+    search.start = date.value[0];
+    search.end = date.value[1];
+  } else {
+    search.start = dayjs(time[searchActive.value['time']].time).format(
+      'YYYY-MM-DD HH:mm:ss'
+    );
+    search.end = dayjs(nowTime).format('YYYY-MM-DD HH:mm:ss');
+  }
+  searchData({
+    data: search,
+  })
+    .then(res => {
+      const li = res.records || [];
+      listTable.value.push(...li);
+      total = res.total || 0;
+      if (T) T = window.clearTimeout(T);
+    })
+    .catch(() => {
+      if (T) T = window.clearTimeout(T);
+    });
+};
+
+const clickSelect = (select, index) => {
+  searchActive.value[select] = index;
+  if (index === -1) return;
+  page = 1;
+  total = -1;
+  listTable.value = [];
+  changeInput();
+};
+const changeSelect = () => {
+  // 更改排序
+  console.log(selectValue.value);
+};
+
+const change = () => {
+  date.value = [date.value[0] + ' 00:00:00', date.value[1] + ' 23:59:59'];
+  page = 1;
+  total = -1;
+  listTable.value = [];
+  changeInput();
+};
+
+const changeInput = () => {
+  if (page !== 1 && total < page * pageSize) return;
+  if (T) T = window.clearTimeout(T);
+  T = window.setTimeout(() => {
+    getList();
+  }, 200);
+};
+
+const search = () => {
+  page = 1;
+  total = -1;
+  listTable.value = [];
+  changeInput();
+};
+
+const searchHot = text => {
+  searchText.value = text;
+  page = 1;
+  total = -1;
+  listTable.value = [];
+  changeInput();
+};
+
+const scroll = e => {
+  const height =
+    document.querySelector('.analysis .head').offsetHeight +
+    document.querySelector('.analysis .body').offsetHeight -
+    document.querySelector('.analysis').offsetHeight;
+  const scrollNum = e.scrollTop.toFixed(2) - 0;
+  if (!showUpload.value && scrollNum > 180) showUpload.value = true;
+  else if (scrollNum <= 180) showUpload.value = false;
+  if (height - scrollNum > 0 || T) return;
+  changeInput();
+};
+
+const upload = () => {
+  scrollbar.value.setScrollTop(0);
+};
+
+getList();
+</script>
+
+<style scoped>
+.analysis {
+  height: 100%;
+  min-width: 1305px;
+  position: relative;
+}
+.analysis .head,
+.analysis .body {
+  margin: 0 1em;
+  width: calc(100% - 400px);
+  min-width: 855px;
+}
+
+.analysis .body {
+  border: 1px solid #f3f3f3;
+  margin: 1em;
+}
+
+.analysis .hotList {
+  position: absolute;
+  width: 300px;
+  right: 50px;
+  top: 100px;
+}
+
+.title {
+  font-size: 18px;
+  font-weight: 600;
+  height: 49px;
+  line-height: 49px;
+  padding-left: 8px;
+  border-bottom: 1px solid #f5f5f5;
+}
+
+.searchRow {
+  margin: 0.5em 0;
+}
+
+.searchCol {
+  display: inline-block;
+  margin: 0 0.5em;
+  padding: 0 0.5em;
+  height: 35px;
+  line-height: 35px;
+  cursor: pointer;
+}
+.searchCol:hover {
+  color: rgb(64, 158, 255);
+}
+
+.searchActive,
+.hotItem:hover {
+  font-weight: 600;
+  color: rgb(64, 158, 255);
+  border-radius: 5px;
+  background-color: rgba(64, 158, 255, 0.1);
+  border-bottom: none;
+}
+
+.searchRow .searchTitle {
+  color: #b9c0d3;
+}
+
+.body .mainTitle {
+  padding: 0 20px;
+  position: relative;
+  line-height: 60px;
+  border-bottom: 1px solid #f5f5f5;
+}
+.body .mainTitleTool {
+  position: absolute;
+  right: 20px;
+  line-height: 60px;
+  top: 0;
+  text-align: right;
+}
+.body .el-checkbox {
+  margin-right: 15px;
+}
+
+.listHead,
+.listSubtitle {
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+
+.lists {
+  padding: 0.5em;
+}
+
+.list {
+  border-radius: 5px;
+  padding: 0.5em;
+  cursor: pointer;
+  line-height: 1.8em;
+  font-size: 16px;
+}
+.list:hover {
+  background-color: rgba(64, 158, 255, 0.1);
+}
+.list:not(:last-child) {
+  border-bottom: 1px dashed #b9c0d3;
+}
+
+.listSubtitle {
+  color: #b9c0d3;
+}
+
+.source {
+  color: #22ac38;
+}
+
+.hotItem {
+  line-height: 1em;
+  font-size: 16px;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  cursor: pointer;
+  padding: 0.6em;
+}
+
+.hotItem:not(:last-child) {
+  border-bottom: 1px dashed #e9e9e9;
+}
+
+.upload {
+  position: absolute;
+  right: 25px;
+  bottom: 25px;
+  background-color: #e9e9e990;
+  border-radius: 50%;
+  padding: 5px;
+  cursor: pointer;
+}
+</style>

+ 5 - 0
src/view/allMedia/main.vue

@@ -39,6 +39,11 @@ const menu = ref([
     icon: require('../../assets/img/sj.png'),
     path: '/main_home/analysis',
   },
+  {
+    title: '地域热点',
+    icon: require('../../assets/img/sj.png'),
+    path: '/main_home/analysis_map',
+  },
   {
     title: '数据汇聚',
     icon: require('../../assets/img/hj.png'),