Browse Source

第一版完成

jwyu 2 years ago
parent
commit
b315c5958c

+ 1 - 1
.env.development

@@ -1,5 +1,5 @@
 # 接口地址
-VITE_APP_API_URL="http://webapi.brilliantstart.cn/api"
+VITE_APP_API_URL="http://8.136.199.33:8302/api"
 # 路由根地址
 VITE_APP_BASE_URL="/"
 # 打包输入文件名

+ 1 - 1
.env.test

@@ -1,5 +1,5 @@
 # 接口地址
-VITE_APP_API_URL="http://webapi.brilliantstart.cn/api"
+VITE_APP_API_URL="http://8.136.199.33:8302/api"
 # 路由根地址
 VITE_APP_BASE_URL="/"
 # 打包输入文件名

+ 1 - 0
README.md

@@ -1,4 +1,5 @@
 # 弘则研报英文版
  
 1. 该项目为弘则研报英文版,包含移动端适配
+2. 测试服前端地址:http://8.136.199.33:8301/report/index
 

+ 1 - 1
src/api/crypto.js

@@ -1,4 +1,4 @@
-const key = 'KcSJaJoUBC2ZAA7HEWpaiH49';
+const key = 'ZwffiVNfOkPwzQARDfxOKWiO';
 
 class CryptoJS {
 	// 3DES加密,CBC/PKCS5Padding

+ 9 - 5
src/api/http.js

@@ -1,6 +1,6 @@
 "use strict";
 import axios from "axios";
-import { Toast } from 'vant';
+import { ElMessage } from 'element-plus'
 import CryptoJS from './crypto'
 
 let config = {
@@ -23,11 +23,15 @@ _axios.interceptors.request.use(
 // Add a response interceptor
 _axios.interceptors.response.use(
   function (response) {
-    const data=JSON.parse(CryptoJS.Des3Decrypt(response.data));//解密
-    // const data = response.data;
+    let data
+    if(import.meta.env.MODE==='production'){
+      data=JSON.parse(CryptoJS.Des3Decrypt(response.data));//解密
+    }else{
+      data=response.data
+    }
 
-    if(data.Ret === 403) {
-      Toast(data.Msg)
+    if(data.code === 400) {
+      ElMessage.error(data.msg)
     }
     return data;
   },

+ 28 - 3
src/api/report.js

@@ -6,12 +6,37 @@ import {get,post} from './http'
 
 /**
  * 研报详情
- * @param report_id
+ * @param report_code
+ * @param share_email 邮箱(如果是邮件推送的会带这个)
  */
 export const apiReportDetail=params=>{
-    return get('/english_report/share/detail',params)
+    return get('/english_report/detail',params)
 }
 
 /**
  * 研报分类
- */
+ */
+export const apiReportClassifyList=()=>{
+    return get('/english_report/classify',{})
+}
+
+/**
+ * 研报列表
+ * @param page_size
+ * @param current
+ * @param classify_id_first
+ * @param classify_id_second
+ */
+export const apiReportList=params=>{
+    return get('/english_report/list',params)
+}
+
+/**
+ * 报告搜索
+ * @param key_word
+ * @param page_size
+ * @param current
+ */
+export const apiReportSearch=params=>{
+    return get('/english_report/filter_by_es',params)
+}

BIN
src/assets/bg-1.png


BIN
src/assets/bg-2.png


BIN
src/assets/bg-3.png


BIN
src/assets/bg-4.png


+ 77 - 8
src/views/report/Detail.vue

@@ -1,19 +1,78 @@
 <script setup>
 import {onMounted, ref} from 'vue'
+import { useRoute, useRouter } from 'vue-router'
+import {apiReportDetail,apiReportClassifyList} from '@/api/report'
+
+const route=useRoute()
+const router=useRouter()
+
+//分类
+let reportClassify=ref([])
+async function getReportClassify(){
+    const res=await apiReportClassifyList()
+    if(res.code===200){
+        reportClassify.value=res.data.list||[]
+    }
+}
+getReportClassify()
+
+//点击分类
+function goIndex(item){
+    router.replace({
+        path:'/report/index',
+        query:{
+            firstclassifyid:item.Id
+        }
+    })
+}
+
+
+//报告详情
+const code=route.query.code
+const email=route.query.ShareEmail||0
+let info=ref(null)
+async function getReportDetail(){
+    const res=await apiReportDetail({
+        report_code:code,
+        share_email:email
+    })
+    if(res.code===200){
+        info.value=res.data.report
+    }
+}
+getReportDetail()
+
 
 let showDisclaimers=ref(false)
 let wwidth=ref(0)
+
+//预览图片
+let preViewImgs=ref([])
+let preViewImgIndex=ref(0)
+let showPreViewImg=ref(false)
+
+function handlePreviewImg(e){
+    const cSrc=e.target.src
+    const imgArr=document.querySelectorAll(".html-content img")
+    const temArr=Array.prototype.slice.call(imgArr)||[]
+    preViewImgs.value=temArr.map(item=>item.src)
+    const index=preViewImgs.value.indexOf(cSrc)
+    preViewImgIndex.value=index||0
+    if(index==-1) return
+    showPreViewImg.value=true
+}
+
 onMounted(()=>{
     wwidth.value=window.innerWidth
 })
 </script>
 
 <template>
-    <div class="report-detail-page">
+    <div class="report-detail-page" v-if="info">
         <div class="header-wrap">
             <div>
                 <span style="color:#00459F;margin-right:30px;">MORE REPORTS>></span>
-                <span>MACRO    COMMODITY</span>
+                <span v-for="item in reportClassify" :key="item.id" style="margin-right:20px;cursor: pointer;" @click="goIndex(item)">{{item.classify_name}}</span>
             </div>
             <div style="color:#00459F;cursor: pointer;" @click="$router.replace('/')">ABOUT US</div>
         </div>
@@ -21,29 +80,36 @@ onMounted(()=>{
             <span @click="$router.replace('/')">HORIZON INSIGHTS</span>
         </div>
         <div class="no-select-text detail-wrap">
-            <h2 class="title">【No.1|FICC】China Macro Digest (1124)</h2>
+            <h2 class="title">【No.{{info.stage}}|FICC】{{info.title}} ({{info.create_time.substring(5, 7)}}{{info.create_time.substring(8, 10)}})</h2>
             <p class="time">
                 <span>Horizon Insights FICC Team</span>
-                <span>Nov,23, 2022 09:49 PM </span>
+                <span>{{info.publish_time}}</span>
             </p>
             <div class="abstract-box">
-                <div>Abstract:The sentiment of land market remains weak, constricting future real estate investment growth.</div>
+                <div>Abstract:{{info.abstract}}</div>
                 <div class="notes">*Note: Please be sure to read the <span style="color:#00459F" @click="showDisclaimers=true">disclaimer</span></div>
             </div>
             <div class="overview-box">
                 <div class="label">Overview:</div>
-                <div>Real estate enterprises are still under the pressure from </div>
+                <div v-html="info.overview"></div>
+            </div>
+            <div class="html-content" v-html="info.content" @click="handlePreviewImg">
             </div>
-            <div class="html-content"></div>
         </div>
     </div>
     <!-- 免责申明 -->
-    <!-- 免责申明 -->
     <el-dialog v-model="showDisclaimers" title="Disclaimers" center draggable :width="wwidth<800?'90%':'40%'">
         <div class="disclaimers-box">
             <div style="margin-bottom:10px">This report is to be used solely by the clients of Horizon Insights (hereinafter referred to as the "Company"). The Company will not deem any other person as its client notwithstanding his receipt of this report. Under no circumstances shall the information contained herein or the opinions expressed herein form an investment recommendation to anyone. Under no circumstances shall the Company be held responsible for any loss caused by the use of any contents herein by anyone.</div>
         </div>
     </el-dialog>
+    <!-- 图片预览 -->
+    <el-image-viewer
+        v-if="showPreViewImg"
+        :initial-index="preViewImgIndex"
+        @close="showPreViewImg=false"
+        :url-list="preViewImgs"
+    />
 </template>
 
 <style lang="scss" scoped>
@@ -69,6 +135,7 @@ onMounted(()=>{
     justify-content: space-between;
     font-size: 20px;
     z-index: 99;
+    background-color: #fff;
 }
 .mobile-header-wrap{
     font-size: 17px;
@@ -131,8 +198,10 @@ onMounted(()=>{
     .overview-box{
         margin-top: 40px;
         padding: 20px;
+        margin-bottom: 20px;
         background: rgba(77, 130, 191, 0.1);
         border: 1px solid #E2E2E2;
+        line-height: 1.5;
         .label{
             font-size: 24px;
             font-weight: 700;

+ 114 - 160
src/views/report/Index.vue

@@ -1,105 +1,37 @@
 <script setup>
-import {ref,reactive,computed} from 'vue'
+import {ref,reactive, onMounted} from 'vue'
+import { useRoute, useRouter } from "vue-router";
+import {apiReportClassifyList,apiReportList} from '@/api/report'
 
-const demoArr=[
-            {
-                "Id": 0,
-                "ClassifyName": "ABOUT US",
-                "Sort": 0,
-                "ParentId": 0,
-                "CreateTime": "2022-11-01T17:44:20+08:00",
-                "ModifyTime": "2022-11-01T17:44:20+08:00",
-                "ClassifyLabel": "",
-                "ShowType": 0,
-                "IsShow": 1,
-                "Child": []
-            },
-            {
-                "Id": 8,
-                "ClassifyName": "PVC1",
-                "Sort": 0,
-                "ParentId": 0,
-                "CreateTime": "2022-11-01T17:04:22+08:00",
-                "ModifyTime": "2022-11-01T17:04:22+08:00",
-                "ClassifyLabel": "",
-                "ShowType": 0,
-                "IsShow": 1,
-                "Child": [
-                    {
-                        "Id": 9,
-                        "ClassifyName": "PVC(shandong)",
-                        "Sort": 2,
-                        "ParentId": 8,
-                        "CreateTime": "2022-11-01T16:48:37+08:00",
-                        "ModifyTime": "2022-11-01T16:48:37+08:00",
-                        "ClassifyLabel": "",
-                        "ShowType": 0,
-                        "IsShow": 1
-                    }
-                ]
-            },
+const router=useRouter()
+const route=useRoute()
+
+//分类
+let navList=ref([])
+async function getReportClassify(){
+    const res=await apiReportClassifyList()
+    if(res.code===200){
+        const arr=res.data.list||[]
+        navList.value=[
             {
-                "Id": 12,
-                "ClassifyName": "test",
-                "Sort": 1,
-                "ParentId": 0,
-                "CreateTime": "2022-11-01T13:59:54+08:00",
-                "ModifyTime": "2022-11-01T13:59:54+08:00",
-                "ClassifyLabel": "",
-                "ShowType": 0,
-                "IsShow": 1,
-                "Child": [
-                    {
-                        "Id": 19,
-                        "ClassifyName": "二级test",
-                        "Sort": 12,
-                        "ParentId": 12,
-                        "CreateTime": "2022-11-01T16:56:12+08:00",
-                        "ModifyTime": "2022-11-01T16:56:12+08:00",
-                        "ClassifyLabel": "",
-                        "ShowType": 0,
-                        "IsShow": 1
-                    }
-                ]
+                id: 0,
+                classify_name: "ABOUT US",
+                child: []
             },
-            {
-                "Id": 1,
-                "ClassifyName": "Macro",
-                "Sort": 4,
-                "ParentId": 0,
-                "CreateTime": "2022-11-01T16:46:49+08:00",
-                "ModifyTime": "2022-11-01T16:46:49+08:00",
-                "ClassifyLabel": "",
-                "ShowType": 0,
-                "IsShow": 1,
-                "Child": [
-                    {
-                        "Id": 4,
-                        "ClassifyName": "China Macro and Commodity",
-                        "Sort": 0,
-                        "ParentId": 1,
-                        "CreateTime": "2022-10-20T17:45:52+08:00",
-                        "ModifyTime": "2022-10-20T17:45:52+08:00",
-                        "ClassifyLabel": "",
-                        "ShowType": 0,
-                        "IsShow": 1
-                    },
-                    {
-                        "Id": 3,
-                        "ClassifyName": "China Macro Weekly",
-                        "Sort": 0,
-                        "ParentId": 1,
-                        "CreateTime": "2022-10-24T17:43:48+08:00",
-                        "ModifyTime": "2022-10-24T17:43:48+08:00",
-                        "ClassifyLabel": "",
-                        "ShowType": 0,
-                        "IsShow": 1
-                    }
-                ]
-            }
+            ...arr
         ]
 
-let navList=ref(demoArr)
+        if(route.query.firstclassifyid){
+            arr.forEach(item => {
+                if(item.Id==route.query.firstclassifyid){
+                    handleChangeFirstClassify(item)
+                }
+            });
+        }
+    }
+}
+getReportClassify()
+
 
 let listState = reactive({
     firstClassifyId:0,
@@ -116,42 +48,54 @@ let listState = reactive({
 // 切换一级分类
 function handleChangeFirstClassify(item){
     showFilter.value=false
-    if(listState.firstClassifyId===item.Id) return
-    listState.firstClassifyId=item.Id
-    listState.firstClassifyName=item.ClassifyName
+    if(listState.firstClassifyId===item.id) return
+    listState.firstClassifyId=item.id
+    listState.firstClassifyName=item.classify_name
     listState.secClassifyId=0
-    listState.secClassifyOpt=item.Child||[]
+    listState.secClassifyOpt=item.child||[]
+    initList()
 }
 // 切换二级分类
 function handleChangeSecClassify(item,fitem){
     showFilter.value=false
-    if(listState.secClassifyId===item.Id) return
-    listState.secClassifyId=item.Id
+    if(listState.secClassifyId===item.id) return
+    listState.secClassifyId=item.id
     if(fitem){
-        listState.firstClassifyId=fitem.Id 
-        listState.firstClassifyName=fitem.ClassifyName
+        listState.firstClassifyId=fitem.id 
+        listState.firstClassifyName=fitem.classify_name
+        listState.secClassifyOpt=fitem.child||[]
     }
-    
+   initList()
+}
 
-    
+//初始化列表
+function initList(){
+    listState.page=1
+    listState.finished=false
+    listState.list=[]
     getList()
 }
 
 // 获取列表数据
-function getList(){
+async function getList(){
     listState.loading=true
-    let arr=[]
-    if(listState.page<5){
-        for (let index = 0; index < 20; index++) {
-            arr.push('a')
-        }
-        listState.list=[...listState.list,...arr]
-    }else{
-        listState.finished=true
-    }
+    const res=await apiReportList({
+        page_size:listState.pageSize,
+        current:listState.page,
+        classify_id_first:listState.firstClassifyId,
+        classify_id_second:listState.secClassifyId
+    })
     setTimeout(() => {
         listState.loading=false
-    }, 300);
+    }, 100);
+    if(res.code===200){
+        const arr=res.data.list||[]
+        listState.list=[...listState.list,...arr]
+        if(arr.length<listState.pageSize){
+            listState.finished=true
+        }
+        
+    }
 }
 
 // 监听页面滚动
@@ -171,9 +115,21 @@ function listenScroll(){
 }
 listenScroll()
 
+//跳转详情
+function goReportDetail(item){
+    const url=router.resolve({
+        path:'/report/detail',
+        query:{
+            code:item.report_code
+        }
+    })
+    window.open(url.href,'_blank')
+}
+
 // 弹窗筛选
 let showFilter=ref(false)
 let filterSize=ref('30%')
+
 </script>
 
 <template>
@@ -190,73 +146,64 @@ let filterSize=ref('30%')
         <div class="nav-wrap">
             <img class="menu-icon" @click="showFilter=true;filterSize='30%'" src="@/assets/menu.svg" alt="">
             <span 
-                :class="['nav-item',item.Id===listState.firstClassifyId?'active':'']" 
+                :class="['nav-item',item.id===listState.firstClassifyId?'active':'']" 
                 v-for="item in navList" 
                 :key="item.Id"
                 @click="handleChangeFirstClassify(item)"
-            >{{item.ClassifyName}}</span>
+            >{{item.classify_name}}</span>
         </div>
         <div class="sub-nav-wrap">
             <h2 class="label">{{listState.firstClassifyName}}</h2>
             <div class="sub-nav-list">
                 <span 
-                    :class="['item',item.Id===listState.secClassifyId?'active':'']" 
+                    :class="['item',item.id===listState.secClassifyId?'active':'']" 
                     v-for="item in listState.secClassifyOpt" 
                     :key="item.Id"
                     @click="handleChangeSecClassify(item)"
-                >{{item.ClassifyName}}</span>
+                >{{item.classify_name}}</span>
             </div>
         </div>
         <!-- 固定展示的报告区域 -->
         <div class="fix-report-wrap" v-show="listState.firstClassifyId!=0&&listState.secClassifyId===0">
             <div class="left-wrap">
-                <div class="report-item-normal">
-                    <div class="title">China Iron Ore Express</div>
-                    <div class="intro">PLA Eastern Theater Command’s J-10C fighters hold interception exercise in far sea, show growing skills</div>
-                    <div class="time">23, 2022 09:49 PM </div>
-                </div>
-                <div class="report-item-normal">
-                    <div class="title">China Iron Ore Express</div>
-                    <div class="intro">PLA Eastern Theater Command’s J-10C fighters hold interception exercise in far sea, show growing skills</div>
-                    <div class="time">23, 2022 09:49 PM </div>
+                <div class="report-item-normal" v-for="item in listState.list.slice(0,3)" :key="item.id" @click="goReportDetail(item)">
+                    <div class="title">{{item.title}}</div>
+                    <div class="intro">{{item.abstract}}</div>
+                    <div class="time">{{item.publish_time}}</div>
                 </div>
-                <div class="report-item-normal">
-                    <div class="title">China Iron Ore Express</div>
-                    <div class="intro">PLA Eastern Theater Command’s J-10C fighters hold interception exercise in far sea, show growing skills</div>
-                    <div class="time">23, 2022 09:49 PM </div>
-                </div>
-                <img class="img" src="@/assets/bg-2.png" alt="">
+                
+                <img class="img" src="https://hzstatic.hzinsights.com/static/yb_en/bg-2.png" alt="">
             </div>
             <div class="center-wrap">
-                <img class="img-top" src="@/assets/bg-3.png" alt="">
-                <div class="report-item-normal">
-                    <div class="title">China Iron Ore Express</div>
-                    <div class="intro">PLA Eastern Theater Command’s J-10C fighters hold interception exercise in far sea, show growing skills</div>
-                    <div class="time">23, 2022 09:49 PM </div>
+                <img class="img-top" src="https://hzstatic.hzinsights.com/static/yb_en/bg-3.png" alt="">
+                <div class="report-item-normal" @click="goReportDetail(listState.list[3])">
+                    <div class="title">{{listState.list[3]&&listState.list[3].title}}</div>
+                    <div class="intro">{{listState.list[3]&&listState.list[3].abstract}}</div>
+                    <div class="time">{{listState.list[3]&&listState.list[3].publish_time}}</div>
                 </div>
                 <div class="bot-box">
-                    <div class="report-item-small">
-                        <div class="title">China Iron Ore Express</div>
-                        <div class="intro">PLA Eastern EasternEasternEastern Theater Command’s J-10C fighters hold interception exercise in far sea, show growing skills</div>
-                        <div class="time">23, 2022 09:49 PM </div>
+                    <div class="report-item-small" @click="goReportDetail(listState.list[4])">
+                        <div class="title">{{listState.list[4]&&listState.list[4].title}}</div>
+                        <div class="intro">{{listState.list[4]&&listState.list[4].abstract}}</div>
+                        <div class="time">{{listState.list[4]&&listState.list[4].publish_time}}</div>
                     </div>
-                    <img class="img-bot" src="@/assets/bg-4.png" alt="">
+                    <img class="img-bot" src="https://hzstatic.hzinsights.com/static/yb_en/bg-4.png" alt="">
                 </div>
             </div>
             <div class="right-wrap">
-                <div class="report-item-normal" v-for="item in 4" :key="item">
-                    <div class="title">China Iron Ore Express</div>
-                    <div class="intro">PLA Eastern Theater Command’s J-10C fighters hold interception exercise in far sea, show growing skills</div>
-                    <div class="time">23, 2022 09:49 PM </div>
+                <div class="report-item-normal" v-for="item in listState.list.slice(5,9)" :key="item.id" @click="goReportDetail(item)">
+                    <div class="title">{{item.title}}</div>
+                    <div class="intro">{{item.abstract}}</div>
+                    <div class="time">{{item.publish_time}}</div>
                 </div>
             </div>
         </div>
         <!-- 报告列表 -->
-        <div class="report-list-wrap" v-show="listState.firstClassifyId!=0">
-            <div class="item" v-for="item,index in listState.list" :key="index">
-                <div class="title">title</div>
-                <div class="intro">PLA Eastern Theater Command’s J-10C fighters hold interception exercise in far sea, show growing skills, confidence</div>
-                <div class="time">23, 2022 09:49 PM </div>
+        <div class="report-list-wrap" v-show="listState.secClassifyId!=0">
+            <div class="item" v-for="item in listState.list" :key="item.id" @click="goReportDetail(item)">
+                <div class="title">{{item.title}}</div>
+                <div class="intro">{{item.abstract}}</div>
+                <div class="time">{{item.publish_time}}</div>
             </div>
         </div>
 
@@ -264,7 +211,7 @@ let filterSize=ref('30%')
         <div class="about-us-box" v-show="listState.firstClassifyId==0">
             <div class="flex box top-box">
                 <div class="left">
-                    <video controls autoplay src="https://hongze.oss-cn-shanghai.aliyuncs.com/static/video_03.mp4"></video>
+                    <video controls autoplay loop src="https://hongze.oss-cn-shanghai.aliyuncs.com/static/video_03.mp4"></video>
                 </div>
                 <div class="right">
                     <div class="con">
@@ -288,7 +235,7 @@ let filterSize=ref('30%')
                     </div>
                 </div>
                 <div class="right">
-                    <img src="@/assets/bg-1.png" alt="">
+                    <img src="https://hzstatic.hzinsights.com/static/yb_en/bg-1.png" alt="">
                 </div>
             </div>
         </div>
@@ -302,9 +249,9 @@ let filterSize=ref('30%')
         class="self-drawer-box"
     >
         <div class="filter-wrap">
-            <div class="item" v-for="item in navList" :key="item.Id">
-                <span  class="title" @click="handleChangeFirstClassify(item)">{{item.ClassifyName}}</span>
-                <div class="text" v-for="_item in item.Child" :key="_item.Id" @click="handleChangeSecClassify(_item,item)">{{_item.ClassifyName}}</div>
+            <div class="item" v-for="item in navList" :key="item.id">
+                <span  class="title" @click="handleChangeFirstClassify(item)">{{item.classify_name}}</span>
+                <div class="text" v-for="_item in item.child" :key="_item.id" @click="handleChangeSecClassify(_item,item)">{{_item.classify_name}}</div>
             </div>
         </div>
     </el-drawer>
@@ -591,6 +538,8 @@ let filterSize=ref('30%')
             overflow: hidden;
             white-space: nowrap;
             text-overflow: ellipsis;
+            cursor: pointer;
+            word-break: break-word;
         }
         .intro{
             font-size: 14px;
@@ -603,6 +552,7 @@ let filterSize=ref('30%')
             text-overflow: ellipsis;
             -webkit-line-clamp: 2;
             -webkit-box-orient: vertical;
+            word-break: break-word;
         }
         .time{
             font-size: 14px;
@@ -658,6 +608,7 @@ let filterSize=ref('30%')
                     text-overflow: ellipsis;
                     -webkit-line-clamp: 2;
                     -webkit-box-orient: vertical;
+                    word-break: break-word;
                 }
                 .intro{
                     font-size: 14px;
@@ -670,6 +621,7 @@ let filterSize=ref('30%')
                     text-overflow: ellipsis;
                     -webkit-line-clamp: 6;
                     -webkit-box-orient: vertical;
+                    word-break: break-word;
                 }
                 .time{
                     font-size: 14px;
@@ -691,12 +643,14 @@ let filterSize=ref('30%')
 }
 
 .report-list-wrap{
+    padding-bottom: 50px;
     .item{
         padding: 20px 0;
         border-top: 1px solid #E6E6E6;
         .title{
             font-size: 20px;
             font-weight: 600;
+            cursor: pointer;
         }
         .intro{
             font-size: 14px;

+ 62 - 6
src/views/report/Search.vue

@@ -1,11 +1,58 @@
 <script setup>
 import {reactive} from 'vue'
 import { Search } from '@element-plus/icons-vue'
+import { apiReportSearch } from '@/api/report'
+import { useRouter } from 'vue-router'
+
+const router=useRouter()
 
 let listState=reactive({
     keywords:'',
+    page:1,
+    pageSize:20,
+    list:[],
+    loading:false,
+    finished:false
+})  
+
+async function getReportList(){
+    if(!listState.keywords) return
+    listState.loading=true
+    const res=await apiReportSearch({
+        key_word:listState.keywords,
+        page_size:listState.pageSize,
+        current:listState.page
+    })
+    setTimeout(() => {
+        listState.loading=false
+    }, 100);
+    if(res.code===200){
+        const arr=res.data.list||[]
+        listState.list=[...listState.list,...arr]
+        if(arr.length<listState.pageSize){
+            listState.finished=true
+        }
+    }
+}
+
+function handleSearch(){
+    listState.list=[]
+    listState.page=1
+    listState.finished=false
+    getReportList()
+}
+
+//跳转详情
+function goReportDetail(item){
+    const url=router.resolve({
+        path:'/report/detail',
+        query:{
+            code:item.report_code
+        }
+    })
+    window.open(url.href,'_blank')
+}
 
-})
 </script>
 
 <template>
@@ -19,13 +66,15 @@ let listState=reactive({
                 class="self-input"
                 placeholder="Please Input Keywords"
                 :suffix-icon="Search"
+                @change="handleSearch"
             />
         </div>
-        <div class="report-list-wrap">
-            <div class="item">
-                <div class="title">title</div>
-                <div class="intro">intro</div>
-                <div class="time">Nov,23, 2022 09:49 PM</div>
+        <div v-if="listState.list.length===0" class="empty">no results</div>
+        <div class="report-list-wrap" v-else>
+            <div class="item" v-for="item in listState.list" :key="item.id" @click="goReportDetail(item)">
+                <div class="title" v-html="item.title"></div>
+                <div class="intro" v-html="item.content_sub"></div>
+                <div class="time">{{item.publish_time}}</div>
             </div>
         </div>
     </div>
@@ -43,6 +92,7 @@ let listState=reactive({
     top: 0;
     background-color: #fff;
     z-index: 99;
+    cursor: pointer;
 }
 @media (max-width: 768px){
     .header-wrap{
@@ -76,6 +126,12 @@ let listState=reactive({
     }
 }
 
+.empty{
+    padding: 50px 0 ;
+    text-align: center;
+    color: #666;
+}
+
 .report-list-wrap{
     width: 600px;
     margin: 50px auto;