康凯
2021-12-12 96c705e7c0eb114695c04a0500a4abc815739cf6
开发完成 版本1.0
4 files modified
46 files added
1 files deleted
7263 ■■■■■ changed files
.env.development 5 ●●●●● patch | view | raw | blame | history
.env.production 6 ●●●●● patch | view | raw | blame | history
package-lock.json 121 ●●●●● patch | view | raw | blame | history
package.json 7 ●●●● patch | view | raw | blame | history
src/App.vue 52 ●●●● patch | view | raw | blame | history
src/api/apilist.js 259 ●●●●● patch | view | raw | blame | history
src/api/jsonlint.js 673 ●●●●● patch | view | raw | blame | history
src/api/request.js 74 ●●●●● patch | view | raw | blame | history
src/assets/datadetail/detail@1x.png patch | view | raw | blame | history
src/assets/datalist/datalist@1x.png patch | view | raw | blame | history
src/assets/home_background@1x.png patch | view | raw | blame | history
src/assets/icon/demo.css 539 ●●●●● patch | view | raw | blame | history
src/assets/icon/demo_index.html 211 ●●●●● patch | view | raw | blame | history
src/assets/icon/iconfont.css 19 ●●●●● patch | view | raw | blame | history
src/assets/icon/iconfont.js 1 ●●●● patch | view | raw | blame | history
src/assets/icon/iconfont.json 16 ●●●●● patch | view | raw | blame | history
src/assets/icon/iconfont.ttf patch | view | raw | blame | history
src/assets/icon/iconfont.woff patch | view | raw | blame | history
src/assets/icon/iconfont.woff2 patch | view | raw | blame | history
src/assets/nav_memory@1x.png patch | view | raw | blame | history
src/assets/nav_personage@1x.png patch | view | raw | blame | history
src/assets/nav_scenery@1x.png patch | view | raw | blame | history
src/assets/nav_spirit@1x.png patch | view | raw | blame | history
src/assets/search/search@1x.png patch | view | raw | blame | history
src/components/CustomSearch1.vue 77 ●●●●● patch | view | raw | blame | history
src/components/CustomSearch2.vue 201 ●●●●● patch | view | raw | blame | history
src/components/CustomSearch3.vue 183 ●●●●● patch | view | raw | blame | history
src/components/HelloWorld.vue 58 ●●●●● patch | view | raw | blame | history
src/main.js 140 ●●●●● patch | view | raw | blame | history
src/views/home.vue 191 ●●●●● patch | view | raw | blame | history
src/views/layout/listIndex.vue 155 ●●●●● patch | view | raw | blame | history
src/views/layout/searchIndex.vue 75 ●●●●● patch | view | raw | blame | history
src/views/memory/detail.vue 510 ●●●●● patch | view | raw | blame | history
src/views/memory/detailImage.vue 133 ●●●●● patch | view | raw | blame | history
src/views/memory/detailvideo.vue 121 ●●●●● patch | view | raw | blame | history
src/views/memory/list.vue 154 ●●●●● patch | view | raw | blame | history
src/views/personage/detail.vue 510 ●●●●● patch | view | raw | blame | history
src/views/personage/detailImage.vue 133 ●●●●● patch | view | raw | blame | history
src/views/personage/detailvideo.vue 121 ●●●●● patch | view | raw | blame | history
src/views/personage/list.vue 190 ●●●●● patch | view | raw | blame | history
src/views/scenery/detail.vue 510 ●●●●● patch | view | raw | blame | history
src/views/scenery/detailImage.vue 133 ●●●●● patch | view | raw | blame | history
src/views/scenery/detailvideo.vue 121 ●●●●● patch | view | raw | blame | history
src/views/scenery/list.vue 190 ●●●●● patch | view | raw | blame | history
src/views/search/index.vue 175 ●●●●● patch | view | raw | blame | history
src/views/search/results.vue 268 ●●●●● patch | view | raw | blame | history
src/views/spirit/detail.vue 510 ●●●●● patch | view | raw | blame | history
src/views/spirit/detailImage.vue 133 ●●●●● patch | view | raw | blame | history
src/views/spirit/detailvideo.vue 121 ●●●●● patch | view | raw | blame | history
src/views/spirit/list.vue 153 ●●●●● patch | view | raw | blame | history
vue.config.js 14 ●●●●● patch | view | raw | blame | history
.env.development
New file
@@ -0,0 +1,5 @@
# just a flag
ENV = 'development'
# base api
VUE_APP_BASE_API = '/'
.env.production
New file
@@ -0,0 +1,6 @@
# just a flag
ENV = 'production'
# base api
VUE_APP_BASE_API = '/'
package-lock.json
@@ -2201,6 +2201,11 @@
      "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=",
      "dev": true
    },
    "array-find-index": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
      "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E="
    },
    "array-flatten": {
      "version": "1.1.1",
      "resolved": "https://registry.nlark.com/array-flatten/download/array-flatten-1.1.1.tgz",
@@ -2323,6 +2328,14 @@
      "integrity": "sha1-3TeelPDbgxCwgpH51kwyCXZmF/0=",
      "dev": true
    },
    "async-validator": {
      "version": "1.8.5",
      "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-1.8.5.tgz",
      "integrity": "sha512-tXBM+1m056MAX0E8TL2iCjg8WvSyXu0Zc8LNtYqrVeyoL3+esHRZ4SieE9fKQyyU09uONjnMEjrNBMqT0mbvmA==",
      "requires": {
        "babel-runtime": "6.x"
      }
    },
    "asynckit": {
      "version": "0.4.0",
      "resolved": "https://registry.nlark.com/asynckit/download/asynckit-0.4.0.tgz",
@@ -2370,6 +2383,14 @@
      "integrity": "sha1-1h9G2DslGSUOJ4Ta9bCUeai0HFk=",
      "dev": true
    },
    "axios": {
      "version": "0.24.0",
      "resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz",
      "integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==",
      "requires": {
        "follow-redirects": "^1.14.4"
      }
    },
    "babel-eslint": {
      "version": "10.1.0",
      "resolved": "https://registry.npmmirror.com/babel-eslint/download/babel-eslint-10.1.0.tgz",
@@ -2383,6 +2404,11 @@
        "eslint-visitor-keys": "^1.0.0",
        "resolve": "^1.12.0"
      }
    },
    "babel-helper-vue-jsx-merge-props": {
      "version": "2.0.3",
      "resolved": "https://registry.npmjs.org/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-2.0.3.tgz",
      "integrity": "sha512-gsLiKK7Qrb7zYJNgiXKpXblxbV5ffSwR0f5whkPAaBAR4fhi6bwRZxX9wBlIc5M/v8CCkXUbXZL4N/nSE97cqg=="
    },
    "babel-loader": {
      "version": "8.2.3",
@@ -2433,6 +2459,27 @@
      "dev": true,
      "requires": {
        "@babel/helper-define-polyfill-provider": "^0.3.0"
      }
    },
    "babel-runtime": {
      "version": "6.26.0",
      "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
      "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
      "requires": {
        "core-js": "^2.4.0",
        "regenerator-runtime": "^0.11.0"
      },
      "dependencies": {
        "core-js": {
          "version": "2.6.12",
          "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz",
          "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ=="
        },
        "regenerator-runtime": {
          "version": "0.11.1",
          "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
          "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
        }
      }
    },
    "balanced-match": {
@@ -4064,8 +4111,7 @@
    "deepmerge": {
      "version": "1.5.2",
      "resolved": "https://registry.npm.taobao.org/deepmerge/download/deepmerge-1.5.2.tgz?cache=0&sync_timestamp=1606805746825&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdeepmerge%2Fdownload%2Fdeepmerge-1.5.2.tgz",
      "integrity": "sha1-EEmdhohEza1P7ghC34x/bwyVp1M=",
      "dev": true
      "integrity": "sha1-EEmdhohEza1P7ghC34x/bwyVp1M="
    },
    "default-gateway": {
      "version": "5.0.5",
@@ -4513,6 +4559,19 @@
      "resolved": "https://registry.npmmirror.com/electron-to-chromium/download/electron-to-chromium-1.4.12.tgz",
      "integrity": "sha512-zjfhG9Us/hIy8AlQ5OzfbR/C4aBv1Dg/ak4GX35CELYlJ4tDAtoEcQivXvyBdqdNQ+R6PhlgQqV8UNPJmhkJog==",
      "dev": true
    },
    "element-ui": {
      "version": "2.15.6",
      "resolved": "https://registry.npmjs.org/element-ui/-/element-ui-2.15.6.tgz",
      "integrity": "sha512-rcYXEKd/j2G0AgficAOk1Zd1AsnHRkhmrK4yLHmNOiimU2JfsywgfKUjMoFuT6pQx0luhovj8lFjpE4Fnt58Iw==",
      "requires": {
        "async-validator": "~1.8.1",
        "babel-helper-vue-jsx-merge-props": "^2.0.0",
        "deepmerge": "^1.2.0",
        "normalize-wheel": "^1.0.1",
        "resize-observer-polyfill": "^1.5.0",
        "throttle-debounce": "^1.0.1"
      }
    },
    "elliptic": {
      "version": "6.5.4",
@@ -5401,8 +5460,7 @@
    "follow-redirects": {
      "version": "1.14.5",
      "resolved": "https://registry.npmmirror.com/follow-redirects/download/follow-redirects-1.14.5.tgz?cache=0&sync_timestamp=1635857764332&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Ffollow-redirects%2Fdownload%2Ffollow-redirects-1.14.5.tgz",
      "integrity": "sha1-8JpYSJgdPHcrU5Iwl3hSP42Fw4E=",
      "dev": true
      "integrity": "sha1-8JpYSJgdPHcrU5Iwl3hSP42Fw4E="
    },
    "for-in": {
      "version": "1.0.2",
@@ -7358,6 +7416,16 @@
        }
      }
    },
    "mint-ui": {
      "version": "2.2.13",
      "resolved": "https://registry.npmjs.org/mint-ui/-/mint-ui-2.2.13.tgz",
      "integrity": "sha512-Xz1SFagHSzKOprwQv3fcekXT5RJvhh939zwZHcWeazk1OJrCjsD4I2qm49AEUCfT1AoYzC+rsZIwGP/J6LwVVw==",
      "requires": {
        "array-find-index": "^1.0.2",
        "raf.js": "0.0.4",
        "vue-lazyload": "^1.0.1"
      }
    },
    "mississippi": {
      "version": "3.0.0",
      "resolved": "https://registry.nlark.com/mississippi/download/mississippi-3.0.0.tgz",
@@ -7610,6 +7678,11 @@
      "resolved": "https://registry.nlark.com/normalize-url/download/normalize-url-3.3.0.tgz",
      "integrity": "sha1-suHE3E98bVd0PfczpPWXjRhlBVk=",
      "dev": true
    },
    "normalize-wheel": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/normalize-wheel/-/normalize-wheel-1.0.1.tgz",
      "integrity": "sha1-rsiGr/2wRQcNhWRH32Ls+GFG7EU="
    },
    "npm-run-path": {
      "version": "2.0.2",
@@ -8952,6 +9025,11 @@
      "integrity": "sha1-M0WUG0FTy50ILY7uTNogFqmu9/Y=",
      "dev": true
    },
    "raf.js": {
      "version": "0.0.4",
      "resolved": "https://registry.npmjs.org/raf.js/-/raf.js-0.0.4.tgz",
      "integrity": "sha1-8Vr0RdJBsn+nExpXRQtn75xAL+w="
    },
    "randombytes": {
      "version": "2.1.0",
      "resolved": "https://registry.nlark.com/randombytes/download/randombytes-2.1.0.tgz",
@@ -9274,6 +9352,11 @@
      "resolved": "https://registry.npm.taobao.org/requires-port/download/requires-port-1.0.0.tgz",
      "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
      "dev": true
    },
    "resize-observer-polyfill": {
      "version": "1.5.1",
      "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
      "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="
    },
    "resolve": {
      "version": "1.20.0",
@@ -10484,6 +10567,11 @@
        "neo-async": "^2.6.0"
      }
    },
    "throttle-debounce": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-1.1.0.tgz",
      "integrity": "sha512-XH8UiPCQcWNuk2LYePibW/4qL97+ZQ1AN3FNXwZRBNPPowo/NRU5fAlDCSNBJIYCKbioZfuYtMhG4quqoJhVzg=="
    },
    "through": {
      "version": "2.3.8",
      "resolved": "https://registry.npm.taobao.org/through/download/through-2.3.8.tgz",
@@ -11048,6 +11136,11 @@
      "integrity": "sha1-UylVzB6yCKPZkLOp+acFdGV+CPI=",
      "dev": true
    },
    "vue-lazyload": {
      "version": "1.3.3",
      "resolved": "https://registry.npmjs.org/vue-lazyload/-/vue-lazyload-1.3.3.tgz",
      "integrity": "sha512-uHnq0FTEeNmqnbBC2aRKlmtd9LofMZ6Q3mWvgfLa+i9vhxU8fDK+nGs9c1iVT85axSua/AUnMttIq3xPaU9G3A=="
    },
    "vue-loader": {
      "version": "15.9.8",
      "resolved": "https://registry.npmmirror.com/vue-loader/download/vue-loader-15.9.8.tgz?cache=0&sync_timestamp=1636034570924&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fvue-loader%2Fdownload%2Fvue-loader-15.9.8.tgz",
@@ -11150,6 +11243,26 @@
        }
      }
    },
    "vue-meta": {
      "version": "2.4.0",
      "resolved": "https://registry.npmjs.org/vue-meta/-/vue-meta-2.4.0.tgz",
      "integrity": "sha512-XEeZUmlVeODclAjCNpWDnjgw+t3WA6gdzs6ENoIAgwO1J1d5p1tezDhtteLUFwcaQaTtayRrsx7GL6oXp/m2Jw==",
      "requires": {
        "deepmerge": "^4.2.2"
      },
      "dependencies": {
        "deepmerge": {
          "version": "4.2.2",
          "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
          "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg=="
        }
      }
    },
    "vue-router": {
      "version": "3.5.3",
      "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.5.3.tgz",
      "integrity": "sha512-FUlILrW3DGitS2h+Xaw8aRNvGTwtuaxrRkNSHWTizOfLUie7wuYwezeZ50iflRn8YPV5kxmU2LQuu3nM/b3Zsg=="
    },
    "vue-style-loader": {
      "version": "4.1.3",
      "resolved": "https://registry.nlark.com/vue-style-loader/download/vue-style-loader-4.1.3.tgz",
package.json
@@ -8,8 +8,13 @@
    "lint": "vue-cli-service lint"
  },
  "dependencies": {
    "axios": "^0.24.0",
    "core-js": "^3.6.5",
    "vue": "^2.6.11"
    "element-ui": "^2.15.6",
    "mint-ui": "^2.2.13",
    "vue": "^2.6.11",
    "vue-meta": "^2.4.0",
    "vue-router": "^3.5.3"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "~4.5.0",
src/App.vue
@@ -1,28 +1,66 @@
<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <HelloWorld msg="Welcome to Your Vue.js App"/>
    <router-view></router-view>
  </div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
  name: 'App',
  components: {
    HelloWorld
  components: {},
  metaInfo: {
    meta: [
      {
        name: "viewport",
        content: "width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1, maximum-scale=1;"
      }
    ]
  },
  created() {
    document.title = "吉林红色旅游";
  }
}
</script>
<style>
body{
  margin: 1px;
}
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
@media only screen and (min-width: 320px) {
  html {
    font-size: 6px !important;
  }
}
@media only screen and (min-width: 375px) {
  html {
    font-size: 8px !important;
  }
}
@media only screen and (min-width: 480px) {
  html {
    font-size: 12px !important;
  }
}
@media only screen and (min-width: 640px) {
  html {
    font-size: 14px !important;
  }
}
@media only screen and (min-width: 750px) {
  html {
    font-size: 16px !important;
  }
}
</style>
src/api/apilist.js
New file
@@ -0,0 +1,259 @@
import request from "@/api/request";
export function GetHomeQuickNav() {
    return new Promise((resolve, reject) => {
        request.get("/index.php/index/index")
            .then(res => {
                if (res.Code == "1") {
                    let hsjq = {
                        tab_pane_label: "红色景区",
                        tab_pane_content: res.Data.list.hsjq.map(a => {
                            return {id: a.id, type: a.type, title: a.title}
                        })
                    };
                    let hsjs = {
                        tab_pane_label: "红色精神",
                        tab_pane_content: res.Data.list.hsjs.map(a => {
                            return {id: a.id, type: a.type, title: a.title}
                        })
                    };
                    let hsjy = {
                        tab_pane_label: "红色记忆",
                        tab_pane_content: res.Data.list.hsjy.map(a => {
                            return {id: a.id, type: a.type, title: a.title}
                        })
                    };
                    let hsrw = {
                        tab_pane_label: "红色人物",
                        tab_pane_content: res.Data.list.hsrw.map(a => {
                            return {id: a.id, type: a.type, title: a.title}
                        })
                    };
                    resolve([hsjq, hsjs, hsjy, hsrw]);
                } else {
                    reject(res.Message);
                }
            }).catch(err => {
            throw err;
        });
    });
}
export function GetSearchInfo(searchType, searchName) {
    return new Promise((resolve, reject) => {
        request.get("/index.php/index/search?searchType=" + searchType + "&searchName=" + searchName)
            .then(res => {
                if (res.Code == "1") {
                    let hsjq = {
                        title: "红色景区",
                        data: res.Data.list.hsjq.map(a => {
                            return {id: a.id, type: a.type, name: a.title, keyWord: a.keywords, img: a.cover_path}
                        })
                    };
                    let hsjs = {
                        title: "红色精神",
                        data: res.Data.list.hsjs.map(a => {
                            return {id: a.id, type: a.type, name: a.title, keyWord: a.keywords, img: a.cover_path}
                        })
                    };
                    let hsjy = {
                        title: "红色记忆",
                        data: res.Data.list.hsjy.map(a => {
                            return {id: a.id, type: a.type, name: a.title, keyWord: a.keywords, img: a.cover_path}
                        })
                    };
                    let hsrw = {
                        title: "红色人物",
                        data: res.Data.list.hsrw.map(a => {
                            return {id: a.id, type: a.type, name: a.title, keyWord: a.keywords, img: a.cover_path}
                        })
                    };
                    resolve({hsjq, hsjs, hsjy, hsrw});
                } else {
                    reject(res.Message);
                }
            }).catch(err => {
            throw err;
        });
    });
}
export function GetSearchHomeInfo() {
    return new Promise((resolve, reject) => {
        request.get("/index.php/index/searchPage")
            .then(res => {
                if (res.Code == "1") {
                    let tjss = res.Data.tjss.map(a => {
                        return {id: a.id, title: a.title, type: a.type}
                    });
                    let rmtj = res.Data.rmtj.map(a => {
                        return {id: a.id, title: a.title, type: a.type, coverPath: a.cover_path}
                    });
                    resolve({tjss: tjss, rmtj: rmtj});
                } else {
                    reject(res.Message);
                }
            }).catch(err => {
            throw err;
        });
    });
}
//dataType(类型): 1=红色记忆,2=红色精神,3=红色景区,4,红色人物
export function GetDataList(dataType, searchType, searchName, pageIndex, pageSize) {
    return new Promise((resolve, reject) => {
        request.get("/index.php/index/list?type=" + dataType + "&searchType=" + searchType + "&searchName=" + searchName + "&page=" + pageIndex + "&rows=" + pageSize)
            .then(res => {
                if (res.Code == "1") {
                    console.log(res, "请求响应")
                    let sceneryTabel = {
                        currentPage: Number(res.Data.list.current_page),
                        pageSize: Number(res.Data.list.per_page),
                        total: res.Data.list.total,
                        data: res.Data.list.data.map(t => {
                            return {
                                id: t.id,
                                name: t.title,
                                keyWord: t.keywords,
                                img: t.cover_path,
                            };
                        }),
                    }
                    resolve(sceneryTabel);
                } else {
                    reject(res.Message);
                }
            }).catch(err => {
            throw err;
        });
    });
}
export function GetDataDetail(id) {
    return new Promise((resolve, reject) => {
        request.get("/index.php/index/deails?id=" + id)
            .then(res => {
                if (res.Code == "1") {
                    let detail = {
                        id: res.Data.list.id,
                        keyWord: res.Data.list.keywords,
                        introduction: res.Data.list.description,
                        file: res.Data.list.file,
                    }
                    resolve(detail);
                } else {
                    reject(res.Message);
                }
            }).catch(err => {
            throw err;
        });
    });
}
export function GetDataDetailImages(id, searchType, searchName, page, pageSize) {
    return new Promise((resolve, reject) => {
        request.get("/index.php/index/picList?id=" + id + "&searchType=" + searchType + "&searchName=" + searchName + "&page=" + page + "&rows=" + pageSize)
            .then(res => {
                if (res.Code == "1") {
                    let images = {
                        pageSize: Number(res.Data.list.per_page),
                        currentPage: Number(res.Data.list.current_page),
                        total: res.Data.list.total,
                        data: res.Data.list.data.map(d => {
                            return {
                                id: d.id,
                                name: d.title,
                                path: d.cover_path,
                            }
                        }),
                    }
                    resolve(images);
                } else {
                    reject(res.Message);
                }
            }).catch(err => {
            throw err;
        });
    });
}
export function GetDataDetailVideos(id, searchType, searchName, page, pageSize) {
    return new Promise((resolve, reject) => {
        request.get("/index.php/index/videoList?id=" + id + "&searchType=" + searchType + "&searchName=" + searchName + "&page=" + page + "&rows=" + pageSize)
            .then(res => {
                if (res.Code == "1") {
                    let videos = {
                        pageSize: Number(res.Data.list.per_page),
                        currentPage: Number(res.Data.list.current_page),
                        total: res.Data.list.total,
                        data: res.Data.list.data.map(d => {
                            return {
                                id: d.id,
                                name: d.title,
                                path: d.cover_path,
                                description: d.description,
                            }
                        }),
                    }
                    resolve(videos);
                } else {
                    reject(res.Message);
                }
            }).catch(err => {
            throw err;
        });
    });
}
export function GetImageDetail(id, page, pid, rows) {
    return new Promise((resolve, reject) => {
        request.get("/index.php/index/picDeails?id=" + id + "&page=" + page + "&pid=" + pid + "&rows=" + rows)
            .then(res => {
                if (res.Code == "1") {
                    let detail = {
                        pageSize: res.Data.list.per_page,
                        currentPage: res.Data.list.current_page,
                        total: res.Data.list.total,
                        data: res.Data.list.data.map(d => {
                            return {
                                id: d.id,
                                name: d.title,
                                path: d.cover_path,
                                keyWord: d.keywords,
                                introduction: d.description,
                            }
                        }),
                    }
                    resolve(detail);
                } else {
                    reject(res.Message);
                }
            }).catch(err => {
            throw err;
        });
    });
}
export function GetVideoDetail(id) {
    return new Promise((resolve, reject) => {
        request.get("/index.php/index/videoDeails?id=" + id)
            .then(res => {
                if (res.Code == "1") {
                    let detail = {
                        id: res.Data.list.id,
                        title: res.Data.list.title,
                        patch: res.Data.list.cover_path,
                        keyWord: res.Data.list.keywords,
                        introduction: res.Data.list.description,
                    }
                    resolve(detail);
                } else {
                    reject(res.Message);
                }
            }).catch(err => {
            throw err;
        });
    });
}
src/api/jsonlint.js
New file
@@ -0,0 +1,673 @@
/* parser generated by jison 0.4.18 */
/*
  Returns a Parser object of the following structure:
  Parser: {
    yy: {}
  }
  Parser.prototype: {
    yy: {},
    trace: function(),
    symbols_: {associative list: name ==> number},
    terminals_: {associative list: number ==> name},
    productions_: [...],
    performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$),
    table: [...],
    defaultActions: {...},
    parseError: function(str, hash),
    parse: function(input),
    lexer: {
        EOF: 1,
        parseError: function(str, hash),
        setInput: function(input),
        input: function(),
        unput: function(str),
        more: function(),
        less: function(n),
        pastInput: function(),
        upcomingInput: function(),
        showPosition: function(),
        test_match: function(regex_match_array, rule_index),
        next: function(),
        lex: function(),
        begin: function(condition),
        popState: function(),
        _currentRules: function(),
        topState: function(),
        pushState: function(condition),
        options: {
            ranges: boolean           (optional: true ==> token location info will include a .range[] member)
            flex: boolean             (optional: true ==> flex-like lexing behaviour where the rules are tested exhaustively to find the longest match)
            backtrack_lexer: boolean  (optional: true ==> lexer regexes are tested in order and for each matching regex the action code is invoked; the lexer terminates the scan when a token is returned by the action code)
        },
        performAction: function(yy, yy_, $avoiding_name_collisions, YY_START),
        rules: [...],
        conditions: {associative list: name ==> set},
    }
  }
  token location info (@$, _$, etc.): {
    first_line: n,
    last_line: n,
    first_column: n,
    last_column: n,
    range: [start_number, end_number]       (where the numbers are indexes into the input string, regular zero-based)
  }
  the parseError function receives a 'hash' object with these members for lexer and parser errors: {
    text:        (matched text)
    token:       (the produced terminal token, if any)
    line:        (yylineno)
  }
  while parser (grammar) errors will also provide these members, i.e. parser errors deliver a superset of attributes: {
    loc:         (yylloc)
    expected:    (string describing the set of expected tokens)
    recoverable: (boolean: TRUE when the parser has a error recovery rule available for this particular error)
  }
*/
var jsonlint = (function(){
    var o=function(k,v,o,l){for(o=o||{},l=k.length;l--;o[k[l]]=v);return o},$V0=[1,12],$V1=[1,13],$V2=[1,9],$V3=[1,10],$V4=[1,11],$V5=[1,14],$V6=[1,15],$V7=[14,18,22,24],$V8=[18,22],$V9=[22,24];
    var parser = {trace: function trace () { },
        yy: {},
        symbols_: {"error":2,"JSONString":3,"STRING":4,"JSONNumber":5,"NUMBER":6,"JSONNullLiteral":7,"NULL":8,"JSONBooleanLiteral":9,"TRUE":10,"FALSE":11,"JSONText":12,"JSONValue":13,"EOF":14,"JSONObject":15,"JSONArray":16,"{":17,"}":18,"JSONMemberList":19,"JSONMember":20,":":21,",":22,"[":23,"]":24,"JSONElementList":25,"$accept":0,"$end":1},
        terminals_: {2:"error",4:"STRING",6:"NUMBER",8:"NULL",10:"TRUE",11:"FALSE",14:"EOF",17:"{",18:"}",21:":",22:",",23:"[",24:"]"},
        productions_: [0,[3,1],[5,1],[7,1],[9,1],[9,1],[12,2],[13,1],[13,1],[13,1],[13,1],[13,1],[13,1],[15,2],[15,3],[20,3],[19,1],[19,3],[16,2],[16,3],[25,1],[25,3]],
        performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) {
            /* this == yyval */
            var $0 = $$.length - 1;
            switch (yystate) {
                case 1:
                    // replace escaped characters with actual character
                    this.$ = yytext.replace(/\\(\\|")/g, "$"+"1")
                        .replace(/\\n/g,'\n')
                        .replace(/\\r/g,'\r')
                        .replace(/\\t/g,'\t')
                        .replace(/\\v/g,'\v')
                        .replace(/\\f/g,'\f')
                        .replace(/\\b/g,'\b');
                    break;
                case 2:
                    this.$ = yytext == String(Number(yytext))? Number(yytext): yytext;
                    break;
                case 3:
                    this.$ = null;
                    break;
                case 4:
                    this.$ = true;
                    break;
                case 5:
                    this.$ = false;
                    break;
                case 6:
                    return this.$ = $$[$0-1];
                    break;
                case 13:
                    this.$ = {};
                    break;
                case 14: case 19:
                    this.$ = $$[$0-1];
                    break;
                case 15:
                    this.$ = [$$[$0-2], $$[$0]];
                    break;
                case 16:
                    this.$ = {}; this.$[$$[$0][0]] = $$[$0][1];
                    break;
                case 17:
                    this.$ = $$[$0-2]; $$[$0-2][$$[$0][0]] = $$[$0][1];
                    break;
                case 18:
                    this.$ = [];
                    break;
                case 20:
                    this.$ = [$$[$0]];
                    break;
                case 21:
                    this.$ = $$[$0-2]; $$[$0-2].push($$[$0]);
                    break;
            }
        },
        table: [{3:5,4:$V0,5:6,6:$V1,7:3,8:$V2,9:4,10:$V3,11:$V4,12:1,13:2,15:7,16:8,17:$V5,23:$V6},{1:[3]},{14:[1,16]},o($V7,[2,7]),o($V7,[2,8]),o($V7,[2,9]),o($V7,[2,10]),o($V7,[2,11]),o($V7,[2,12]),o($V7,[2,3]),o($V7,[2,4]),o($V7,[2,5]),o([14,18,21,22,24],[2,1]),o($V7,[2,2]),{3:20,4:$V0,18:[1,17],19:18,20:19},{3:5,4:$V0,5:6,6:$V1,7:3,8:$V2,9:4,10:$V3,11:$V4,13:23,15:7,16:8,17:$V5,23:$V6,24:[1,21],25:22},{1:[2,6]},o($V7,[2,13]),{18:[1,24],22:[1,25]},o($V8,[2,16]),{21:[1,26]},o($V7,[2,18]),{22:[1,28],24:[1,27]},o($V9,[2,20]),o($V7,[2,14]),{3:20,4:$V0,20:29},{3:5,4:$V0,5:6,6:$V1,7:3,8:$V2,9:4,10:$V3,11:$V4,13:30,15:7,16:8,17:$V5,23:$V6},o($V7,[2,19]),{3:5,4:$V0,5:6,6:$V1,7:3,8:$V2,9:4,10:$V3,11:$V4,13:31,15:7,16:8,17:$V5,23:$V6},o($V8,[2,17]),o($V8,[2,15]),o($V9,[2,21])],
        defaultActions: {16:[2,6]},
        parseError: function parseError (str, hash) {
            if (hash.recoverable) {
                this.trace(str);
            } else {
                var error = new Error(str);
                error.hash = hash;
                throw error;
            }
        },
        parse: function parse(input) {
            var self = this, stack = [0], tstack = [], vstack = [null], lstack = [], table = this.table, yytext = '', yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1;
            var args = lstack.slice.call(arguments, 1);
            var lexer = Object.create(this.lexer);
            var sharedState = { yy: {} };
            for (var k in this.yy) {
                if (Object.prototype.hasOwnProperty.call(this.yy, k)) {
                    sharedState.yy[k] = this.yy[k];
                }
            }
            lexer.setInput(input, sharedState.yy);
            sharedState.yy.lexer = lexer;
            sharedState.yy.parser = this;
            if (typeof lexer.yylloc == 'undefined') {
                lexer.yylloc = {};
            }
            var yyloc = lexer.yylloc;
            lstack.push(yyloc);
            var ranges = lexer.options && lexer.options.ranges;
            if (typeof sharedState.yy.parseError === 'function') {
                this.parseError = sharedState.yy.parseError;
            } else {
                this.parseError = Object.getPrototypeOf(this).parseError;
            }
            function popStack(n) {
                stack.length = stack.length - 2 * n;
                vstack.length = vstack.length - n;
                lstack.length = lstack.length - n;
            }
            _token_stack:
                var lex = function () {
                    var token;
                    token = lexer.lex() || EOF;
                    if (typeof token !== 'number') {
                        token = self.symbols_[token] || token;
                    }
                    return token;
                };
            var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected;
            while (true) {
                state = stack[stack.length - 1];
                if (this.defaultActions[state]) {
                    action = this.defaultActions[state];
                } else {
                    if (symbol === null || typeof symbol == 'undefined') {
                        symbol = lex();
                    }
                    action = table[state] && table[state][symbol];
                }
                if (typeof action === 'undefined' || !action.length || !action[0]) {
                    var errStr = '';
                    expected = [];
                    for (p in table[state]) {
                        if (this.terminals_[p] && p > TERROR) {
                            expected.push('\'' + this.terminals_[p] + '\'');
                        }
                    }
                    if (lexer.showPosition) {
                        errStr = 'Parse error on line ' + (yylineno + 1) + ':\n' + lexer.showPosition() + '\nExpecting ' + expected.join(', ') + ', got \'' + (this.terminals_[symbol] || symbol) + '\'';
                    } else {
                        errStr = 'Parse error on line ' + (yylineno + 1) + ': Unexpected ' + (symbol == EOF ? 'end of input' : '\'' + (this.terminals_[symbol] || symbol) + '\'');
                    }
                    this.parseError(errStr, {
                        text: lexer.match,
                        token: this.terminals_[symbol] || symbol,
                        line: lexer.yylineno,
                        loc: yyloc,
                        expected: expected
                    });
                }
                if (action[0] instanceof Array && action.length > 1) {
                    throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol);
                }
                switch (action[0]) {
                    case 1:
                        stack.push(symbol);
                        vstack.push(lexer.yytext);
                        lstack.push(lexer.yylloc);
                        stack.push(action[1]);
                        symbol = null;
                        if (!preErrorSymbol) {
                            yyleng = lexer.yyleng;
                            yytext = lexer.yytext;
                            yylineno = lexer.yylineno;
                            yyloc = lexer.yylloc;
                            if (recovering > 0) {
                                recovering--;
                            }
                        } else {
                            symbol = preErrorSymbol;
                            preErrorSymbol = null;
                        }
                        break;
                    case 2:
                        len = this.productions_[action[1]][1];
                        yyval.$ = vstack[vstack.length - len];
                        yyval._$ = {
                            first_line: lstack[lstack.length - (len || 1)].first_line,
                            last_line: lstack[lstack.length - 1].last_line,
                            first_column: lstack[lstack.length - (len || 1)].first_column,
                            last_column: lstack[lstack.length - 1].last_column
                        };
                        if (ranges) {
                            yyval._$.range = [
                                lstack[lstack.length - (len || 1)].range[0],
                                lstack[lstack.length - 1].range[1]
                            ];
                        }
                        r = this.performAction.apply(yyval, [
                            yytext,
                            yyleng,
                            yylineno,
                            sharedState.yy,
                            action[1],
                            vstack,
                            lstack
                        ].concat(args));
                        if (typeof r !== 'undefined') {
                            return r;
                        }
                        if (len) {
                            stack = stack.slice(0, -1 * len * 2);
                            vstack = vstack.slice(0, -1 * len);
                            lstack = lstack.slice(0, -1 * len);
                        }
                        stack.push(this.productions_[action[1]][0]);
                        vstack.push(yyval.$);
                        lstack.push(yyval._$);
                        newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
                        stack.push(newState);
                        break;
                    case 3:
                        return true;
                }
            }
            return true;
        }};
    /* generated by jison-lex 0.3.4 */
    var lexer = (function(){
        var lexer = ({
            EOF:1,
            parseError:function parseError(str, hash) {
                if (this.yy.parser) {
                    this.yy.parser.parseError(str, hash);
                } else {
                    throw new Error(str);
                }
            },
// resets the lexer, sets new input
            setInput:function (input, yy) {
                this.yy = yy || this.yy || {};
                this._input = input;
                this._more = this._backtrack = this.done = false;
                this.yylineno = this.yyleng = 0;
                this.yytext = this.matched = this.match = '';
                this.conditionStack = ['INITIAL'];
                this.yylloc = {
                    first_line: 1,
                    first_column: 0,
                    last_line: 1,
                    last_column: 0
                };
                if (this.options.ranges) {
                    this.yylloc.range = [0,0];
                }
                this.offset = 0;
                return this;
            },
// consumes and returns one char from the input
            input:function () {
                var ch = this._input[0];
                this.yytext += ch;
                this.yyleng++;
                this.offset++;
                this.match += ch;
                this.matched += ch;
                var lines = ch.match(/(?:\r\n?|\n).*/g);
                if (lines) {
                    this.yylineno++;
                    this.yylloc.last_line++;
                } else {
                    this.yylloc.last_column++;
                }
                if (this.options.ranges) {
                    this.yylloc.range[1]++;
                }
                this._input = this._input.slice(1);
                return ch;
            },
// unshifts one char (or a string) into the input
            unput:function (ch) {
                var len = ch.length;
                var lines = ch.split(/(?:\r\n?|\n)/g);
                this._input = ch + this._input;
                this.yytext = this.yytext.substr(0, this.yytext.length - len);
                //this.yyleng -= len;
                this.offset -= len;
                var oldLines = this.match.split(/(?:\r\n?|\n)/g);
                this.match = this.match.substr(0, this.match.length - 1);
                this.matched = this.matched.substr(0, this.matched.length - 1);
                if (lines.length - 1) {
                    this.yylineno -= lines.length - 1;
                }
                var r = this.yylloc.range;
                this.yylloc = {
                    first_line: this.yylloc.first_line,
                    last_line: this.yylineno + 1,
                    first_column: this.yylloc.first_column,
                    last_column: lines ?
                        (lines.length === oldLines.length ? this.yylloc.first_column : 0)
                        + oldLines[oldLines.length - lines.length].length - lines[0].length :
                        this.yylloc.first_column - len
                };
                if (this.options.ranges) {
                    this.yylloc.range = [r[0], r[0] + this.yyleng - len];
                }
                this.yyleng = this.yytext.length;
                return this;
            },
// When called from action, caches matched text and appends it on next action
            more:function () {
                this._more = true;
                return this;
            },
// When called from action, signals the lexer that this rule fails to match the input, so the next matching rule (regex) should be tested instead.
            reject:function () {
                if (this.options.backtrack_lexer) {
                    this._backtrack = true;
                } else {
                    return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n' + this.showPosition(), {
                        text: "",
                        token: null,
                        line: this.yylineno
                    });
                }
                return this;
            },
// retain first n characters of the match
            less:function (n) {
                this.unput(this.match.slice(n));
            },
// displays already matched input, i.e. for error messages
            pastInput:function () {
                var past = this.matched.substr(0, this.matched.length - this.match.length);
                return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, "");
            },
// displays upcoming input, i.e. for error messages
            upcomingInput:function () {
                var next = this.match;
                if (next.length < 20) {
                    next += this._input.substr(0, 20-next.length);
                }
                return (next.substr(0,20) + (next.length > 20 ? '...' : '')).replace(/\n/g, "");
            },
// displays the character position where the lexing error occurred, i.e. for error messages
            showPosition:function () {
                var pre = this.pastInput();
                var c = new Array(pre.length + 1).join("-");
                return pre + this.upcomingInput() + "\n" + c + "^";
            },
// test the lexed token: return FALSE when not a match, otherwise return token
            test_match:function(match, indexed_rule) {
                var token,
                    lines,
                    backup;
                if (this.options.backtrack_lexer) {
                    // save context
                    backup = {
                        yylineno: this.yylineno,
                        yylloc: {
                            first_line: this.yylloc.first_line,
                            last_line: this.last_line,
                            first_column: this.yylloc.first_column,
                            last_column: this.yylloc.last_column
                        },
                        yytext: this.yytext,
                        match: this.match,
                        matches: this.matches,
                        matched: this.matched,
                        yyleng: this.yyleng,
                        offset: this.offset,
                        _more: this._more,
                        _input: this._input,
                        yy: this.yy,
                        conditionStack: this.conditionStack.slice(0),
                        done: this.done
                    };
                    if (this.options.ranges) {
                        backup.yylloc.range = this.yylloc.range.slice(0);
                    }
                }
                lines = match[0].match(/(?:\r\n?|\n).*/g);
                if (lines) {
                    this.yylineno += lines.length;
                }
                this.yylloc = {
                    first_line: this.yylloc.last_line,
                    last_line: this.yylineno + 1,
                    first_column: this.yylloc.last_column,
                    last_column: lines ?
                        lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length :
                        this.yylloc.last_column + match[0].length
                };
                this.yytext += match[0];
                this.match += match[0];
                this.matches = match;
                this.yyleng = this.yytext.length;
                if (this.options.ranges) {
                    this.yylloc.range = [this.offset, this.offset += this.yyleng];
                }
                this._more = false;
                this._backtrack = false;
                this._input = this._input.slice(match[0].length);
                this.matched += match[0];
                token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]);
                if (this.done && this._input) {
                    this.done = false;
                }
                if (token) {
                    return token;
                } else if (this._backtrack) {
                    // recover context
                    for (var k in backup) {
                        this[k] = backup[k];
                    }
                    return false; // rule action called reject() implying the next rule should be tested instead.
                }
                return false;
            },
// return next match in input
            next:function () {
                if (this.done) {
                    return this.EOF;
                }
                if (!this._input) {
                    this.done = true;
                }
                var token,
                    match,
                    tempMatch,
                    index;
                if (!this._more) {
                    this.yytext = '';
                    this.match = '';
                }
                var rules = this._currentRules();
                for (var i = 0; i < rules.length; i++) {
                    tempMatch = this._input.match(this.rules[rules[i]]);
                    if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
                        match = tempMatch;
                        index = i;
                        if (this.options.backtrack_lexer) {
                            token = this.test_match(tempMatch, rules[i]);
                            if (token !== false) {
                                return token;
                            } else if (this._backtrack) {
                                match = false;
                                continue; // rule action called reject() implying a rule MISmatch.
                            } else {
                                // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
                                return false;
                            }
                        } else if (!this.options.flex) {
                            break;
                        }
                    }
                }
                if (match) {
                    token = this.test_match(match, rules[index]);
                    if (token !== false) {
                        return token;
                    }
                    // else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
                    return false;
                }
                if (this._input === "") {
                    return this.EOF;
                } else {
                    return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), {
                        text: "",
                        token: null,
                        line: this.yylineno
                    });
                }
            },
// return next match that has a token
            lex:function lex () {
                var r = this.next();
                if (r) {
                    return r;
                } else {
                    return this.lex();
                }
            },
// activates a new lexer condition state (pushes the new lexer condition state onto the condition stack)
            begin:function begin (condition) {
                this.conditionStack.push(condition);
            },
// pop the previously active lexer condition state off the condition stack
            popState:function popState () {
                var n = this.conditionStack.length - 1;
                if (n > 0) {
                    return this.conditionStack.pop();
                } else {
                    return this.conditionStack[0];
                }
            },
// produce the lexer rule set which is active for the currently active lexer condition state
            _currentRules:function _currentRules () {
                if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) {
                    return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
                } else {
                    return this.conditions["INITIAL"].rules;
                }
            },
// return the currently active lexer condition state; when an index argument is provided it produces the N-th previous condition state, if available
            topState:function topState (n) {
                n = this.conditionStack.length - 1 - Math.abs(n || 0);
                if (n >= 0) {
                    return this.conditionStack[n];
                } else {
                    return "INITIAL";
                }
            },
// alias for begin(condition)
            pushState:function pushState (condition) {
                this.begin(condition);
            },
// return the number of states currently on the stack
            stateStackSize:function stateStackSize() {
                return this.conditionStack.length;
            },
            options: {},
            performAction: function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) {
                var YYSTATE=YY_START;
                switch($avoiding_name_collisions) {
                    case 0:/* skip whitespace */
                        break;
                    case 1:return 6
                        break;
                    case 2:yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2); return 4
                        break;
                    case 3:return 17
                        break;
                    case 4:return 18
                        break;
                    case 5:return 23
                        break;
                    case 6:return 24
                        break;
                    case 7:return 22
                        break;
                    case 8:return 21
                        break;
                    case 9:return 10
                        break;
                    case 10:return 11
                        break;
                    case 11:return 8
                        break;
                    case 12:return 14
                        break;
                    case 13:return 'INVALID'
                        break;
                }
            },
            rules: [/^(?:\s+)/,/^(?:(-?([0-9]|[1-9][0-9]+))(\.[0-9]+)?([eE][-+]?[0-9]+)?\b)/,/^(?:"(?:\\[\\"bfnrt/]|\\u[a-fA-F0-9]{4}|[^\\\0-\x09\x0a-\x1f"])*")/,/^(?:\{)/,/^(?:\})/,/^(?:\[)/,/^(?:\])/,/^(?:,)/,/^(?::)/,/^(?:true\b)/,/^(?:false\b)/,/^(?:null\b)/,/^(?:$)/,/^(?:.)/],
            conditions: {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13],"inclusive":true}}
        });
        return lexer;
    })();
    parser.lexer = lexer;
    function Parser () {
        this.yy = {};
    }
    Parser.prototype = parser;parser.Parser = Parser;
    return new Parser;
})();
if (typeof require !== 'undefined' && typeof exports !== 'undefined') {
    exports.parser = jsonlint;
    exports.Parser = jsonlint.Parser;
    exports.parse = function () { return jsonlint.parse.apply(jsonlint, arguments); };
    exports.main = function commonjsMain (args) {
        if (!args[1]) {
            console.log('Usage: '+args[0]+' FILE');
            process.exit(1);
        }
        var source = require('fs').readFileSync(require('path').normalize(args[1]), "utf8");
        return exports.parser.parse(source);
    };
    if (typeof module !== 'undefined' && require.main === module) {
        exports.main(process.argv.slice(1));
    }
}
src/api/request.js
New file
@@ -0,0 +1,74 @@
import axios from 'axios'
import {Message} from 'element-ui'
import jsonlint from "@/api/jsonlint.js"
const service = axios.create({
    baseURL: process.env.VUE_APP_BASE_API,
    timeout: 60000, // request timeout
    headers: {},
    transformResponse: [function (data) {
        if (typeof data == "string") {
            try {
                data = jsonlint.parse((data));
            } catch (e) {
                console.log(e, 'axios:transformResponse异常');
            }
        }
        return data;
    }]
})
service.interceptors.request.use(
    config => {
        return config
    },
    error => {
        return Promise.reject(error)
    })
service.interceptors.response.use(
    response => {
        if (response.status == 200) {
            const resData = response.data;
            return resData;
        } else {
            return Promise.reject(response)
        }
    },
    error => {
        Message({message: error.response.data.msg || '系统错误', type: 'error', duration: 2 * 1000})
        return Promise.reject(error)
    })
export default {
    //get请求
    get(url, param) {
        return new Promise(resolve => {
            service({
                method: 'get',
                url,
                params: param,
            }).then(res => {
                resolve(res);
            }).catch(err => {
                console.log(err, 'axios异常');
                throw err;
            });
        });
    },
    //post请求
    post(url, param) {
        return new Promise(resolve => {
            service({
                method: 'post',
                url,
                data: param,
            }).then(res => {
                resolve(res);
            }).catch(err => {
                console.log(err, 'axios异常');
                throw err;
            });
        });
    },
}
src/assets/datadetail/detail@1x.png
src/assets/datalist/datalist@1x.png
src/assets/home_background@1x.png
src/assets/icon/demo.css
New file
@@ -0,0 +1,539 @@
/* Logo 字体 */
@font-face {
  font-family: "iconfont logo";
  src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');
  src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),
    url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),
    url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),
    url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');
}
.logo {
  font-family: "iconfont logo";
  font-size: 160px;
  font-style: normal;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
/* tabs */
.nav-tabs {
  position: relative;
}
.nav-tabs .nav-more {
  position: absolute;
  right: 0;
  bottom: 0;
  height: 42px;
  line-height: 42px;
  color: #666;
}
#tabs {
  border-bottom: 1px solid #eee;
}
#tabs li {
  cursor: pointer;
  width: 100px;
  height: 40px;
  line-height: 40px;
  text-align: center;
  font-size: 16px;
  border-bottom: 2px solid transparent;
  position: relative;
  z-index: 1;
  margin-bottom: -1px;
  color: #666;
}
#tabs .active {
  border-bottom-color: #f00;
  color: #222;
}
.tab-container .content {
  display: none;
}
/* 页面布局 */
.main {
  padding: 30px 100px;
  width: 960px;
  margin: 0 auto;
}
.main .logo {
  color: #333;
  text-align: left;
  margin-bottom: 30px;
  line-height: 1;
  height: 110px;
  margin-top: -50px;
  overflow: hidden;
  *zoom: 1;
}
.main .logo a {
  font-size: 160px;
  color: #333;
}
.helps {
  margin-top: 40px;
}
.helps pre {
  padding: 20px;
  margin: 10px 0;
  border: solid 1px #e7e1cd;
  background-color: #fffdef;
  overflow: auto;
}
.icon_lists {
  width: 100% !important;
  overflow: hidden;
  *zoom: 1;
}
.icon_lists li {
  width: 100px;
  margin-bottom: 10px;
  margin-right: 20px;
  text-align: center;
  list-style: none !important;
  cursor: default;
}
.icon_lists li .code-name {
  line-height: 1.2;
}
.icon_lists .icon {
  display: block;
  height: 100px;
  line-height: 100px;
  font-size: 42px;
  margin: 10px auto;
  color: #333;
  -webkit-transition: font-size 0.25s linear, width 0.25s linear;
  -moz-transition: font-size 0.25s linear, width 0.25s linear;
  transition: font-size 0.25s linear, width 0.25s linear;
}
.icon_lists .icon:hover {
  font-size: 100px;
}
.icon_lists .svg-icon {
  /* 通过设置 font-size 来改变图标大小 */
  width: 1em;
  /* 图标和文字相邻时,垂直对齐 */
  vertical-align: -0.15em;
  /* 通过设置 color 来改变 SVG 的颜色/fill */
  fill: currentColor;
  /* path 和 stroke 溢出 viewBox 部分在 IE 下会显示
      normalize.css 中也包含这行 */
  overflow: hidden;
}
.icon_lists li .name,
.icon_lists li .code-name {
  color: #666;
}
/* markdown 样式 */
.markdown {
  color: #666;
  font-size: 14px;
  line-height: 1.8;
}
.highlight {
  line-height: 1.5;
}
.markdown img {
  vertical-align: middle;
  max-width: 100%;
}
.markdown h1 {
  color: #404040;
  font-weight: 500;
  line-height: 40px;
  margin-bottom: 24px;
}
.markdown h2,
.markdown h3,
.markdown h4,
.markdown h5,
.markdown h6 {
  color: #404040;
  margin: 1.6em 0 0.6em 0;
  font-weight: 500;
  clear: both;
}
.markdown h1 {
  font-size: 28px;
}
.markdown h2 {
  font-size: 22px;
}
.markdown h3 {
  font-size: 16px;
}
.markdown h4 {
  font-size: 14px;
}
.markdown h5 {
  font-size: 12px;
}
.markdown h6 {
  font-size: 12px;
}
.markdown hr {
  height: 1px;
  border: 0;
  background: #e9e9e9;
  margin: 16px 0;
  clear: both;
}
.markdown p {
  margin: 1em 0;
}
.markdown>p,
.markdown>blockquote,
.markdown>.highlight,
.markdown>ol,
.markdown>ul {
  width: 80%;
}
.markdown ul>li {
  list-style: circle;
}
.markdown>ul li,
.markdown blockquote ul>li {
  margin-left: 20px;
  padding-left: 4px;
}
.markdown>ul li p,
.markdown>ol li p {
  margin: 0.6em 0;
}
.markdown ol>li {
  list-style: decimal;
}
.markdown>ol li,
.markdown blockquote ol>li {
  margin-left: 20px;
  padding-left: 4px;
}
.markdown code {
  margin: 0 3px;
  padding: 0 5px;
  background: #eee;
  border-radius: 3px;
}
.markdown strong,
.markdown b {
  font-weight: 600;
}
.markdown>table {
  border-collapse: collapse;
  border-spacing: 0px;
  empty-cells: show;
  border: 1px solid #e9e9e9;
  width: 95%;
  margin-bottom: 24px;
}
.markdown>table th {
  white-space: nowrap;
  color: #333;
  font-weight: 600;
}
.markdown>table th,
.markdown>table td {
  border: 1px solid #e9e9e9;
  padding: 8px 16px;
  text-align: left;
}
.markdown>table th {
  background: #F7F7F7;
}
.markdown blockquote {
  font-size: 90%;
  color: #999;
  border-left: 4px solid #e9e9e9;
  padding-left: 0.8em;
  margin: 1em 0;
}
.markdown blockquote p {
  margin: 0;
}
.markdown .anchor {
  opacity: 0;
  transition: opacity 0.3s ease;
  margin-left: 8px;
}
.markdown .waiting {
  color: #ccc;
}
.markdown h1:hover .anchor,
.markdown h2:hover .anchor,
.markdown h3:hover .anchor,
.markdown h4:hover .anchor,
.markdown h5:hover .anchor,
.markdown h6:hover .anchor {
  opacity: 1;
  display: inline-block;
}
.markdown>br,
.markdown>p>br {
  clear: both;
}
.hljs {
  display: block;
  background: white;
  padding: 0.5em;
  color: #333333;
  overflow-x: auto;
}
.hljs-comment,
.hljs-meta {
  color: #969896;
}
.hljs-string,
.hljs-variable,
.hljs-template-variable,
.hljs-strong,
.hljs-emphasis,
.hljs-quote {
  color: #df5000;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-type {
  color: #a71d5d;
}
.hljs-literal,
.hljs-symbol,
.hljs-bullet,
.hljs-attribute {
  color: #0086b3;
}
.hljs-section,
.hljs-name {
  color: #63a35c;
}
.hljs-tag {
  color: #333333;
}
.hljs-title,
.hljs-attr,
.hljs-selector-id,
.hljs-selector-class,
.hljs-selector-attr,
.hljs-selector-pseudo {
  color: #795da3;
}
.hljs-addition {
  color: #55a532;
  background-color: #eaffea;
}
.hljs-deletion {
  color: #bd2c00;
  background-color: #ffecec;
}
.hljs-link {
  text-decoration: underline;
}
/* 代码高亮 */
/* PrismJS 1.15.0
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
/**
 * prism.js default theme for JavaScript, CSS and HTML
 * Based on dabblet (http://dabblet.com)
 * @author Lea Verou
 */
code[class*="language-"],
pre[class*="language-"] {
  color: black;
  background: none;
  text-shadow: 0 1px white;
  font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
  text-align: left;
  white-space: pre;
  word-spacing: normal;
  word-break: normal;
  word-wrap: normal;
  line-height: 1.5;
  -moz-tab-size: 4;
  -o-tab-size: 4;
  tab-size: 4;
  -webkit-hyphens: none;
  -moz-hyphens: none;
  -ms-hyphens: none;
  hyphens: none;
}
pre[class*="language-"]::-moz-selection,
pre[class*="language-"] ::-moz-selection,
code[class*="language-"]::-moz-selection,
code[class*="language-"] ::-moz-selection {
  text-shadow: none;
  background: #b3d4fc;
}
pre[class*="language-"]::selection,
pre[class*="language-"] ::selection,
code[class*="language-"]::selection,
code[class*="language-"] ::selection {
  text-shadow: none;
  background: #b3d4fc;
}
@media print {
  code[class*="language-"],
  pre[class*="language-"] {
    text-shadow: none;
  }
}
/* Code blocks */
pre[class*="language-"] {
  padding: 1em;
  margin: .5em 0;
  overflow: auto;
}
:not(pre)>code[class*="language-"],
pre[class*="language-"] {
  background: #f5f2f0;
}
/* Inline code */
:not(pre)>code[class*="language-"] {
  padding: .1em;
  border-radius: .3em;
  white-space: normal;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
  color: slategray;
}
.token.punctuation {
  color: #999;
}
.namespace {
  opacity: .7;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
  color: #905;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
  color: #690;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
  color: #9a6e3a;
  background: hsla(0, 0%, 100%, .5);
}
.token.atrule,
.token.attr-value,
.token.keyword {
  color: #07a;
}
.token.function,
.token.class-name {
  color: #DD4A68;
}
.token.regex,
.token.important,
.token.variable {
  color: #e90;
}
.token.important,
.token.bold {
  font-weight: bold;
}
.token.italic {
  font-style: italic;
}
.token.entity {
  cursor: help;
}
src/assets/icon/demo_index.html
New file
@@ -0,0 +1,211 @@
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8"/>
  <title>iconfont Demo</title>
  <link rel="shortcut icon" href="//img.alicdn.com/imgextra/i2/O1CN01ZyAlrn1MwaMhqz36G_!!6000000001499-73-tps-64-64.ico" type="image/x-icon"/>
  <link rel="icon" type="image/svg+xml" href="//img.alicdn.com/imgextra/i4/O1CN01EYTRnJ297D6vehehJ_!!6000000008020-55-tps-64-64.svg"/>
  <link rel="stylesheet" href="https://g.alicdn.com/thx/cube/1.3.2/cube.min.css">
  <link rel="stylesheet" href="demo.css">
  <link rel="stylesheet" href="iconfont.css">
  <script src="iconfont.js"></script>
  <!-- jQuery -->
  <script src="https://a1.alicdn.com/oss/uploads/2018/12/26/7bfddb60-08e8-11e9-9b04-53e73bb6408b.js"></script>
  <!-- 代码高亮 -->
  <script src="https://a1.alicdn.com/oss/uploads/2018/12/26/a3f714d0-08e6-11e9-8a15-ebf944d7534c.js"></script>
  <style>
    .main .logo {
      margin-top: 0;
      height: auto;
    }
    .main .logo a {
      display: flex;
      align-items: center;
    }
    .main .logo .sub-title {
      margin-left: 0.5em;
      font-size: 22px;
      color: #fff;
      background: linear-gradient(-45deg, #3967FF, #B500FE);
      -webkit-background-clip: text;
      -webkit-text-fill-color: transparent;
    }
  </style>
</head>
<body>
  <div class="main">
    <h1 class="logo"><a href="https://www.iconfont.cn/" title="iconfont 首页" target="_blank">
      <img width="200" src="https://img.alicdn.com/imgextra/i3/O1CN01Mn65HV1FfSEzR6DKv_!!6000000000514-55-tps-228-59.svg">
    </a></h1>
    <div class="nav-tabs">
      <ul id="tabs" class="dib-box">
        <li class="dib active"><span>Unicode</span></li>
        <li class="dib"><span>Font class</span></li>
        <li class="dib"><span>Symbol</span></li>
      </ul>
      <a href="https://www.iconfont.cn/manage/index?manage_type=myprojects&projectId=2997242" target="_blank" class="nav-more">查看项目</a>
    </div>
    <div class="tab-container">
      <div class="content unicode" style="display: block;">
          <ul class="icon_lists dib-box">
            <li class="dib">
              <span class="icon iconfont">&#xe82e;</span>
                <div class="name">search</div>
                <div class="code-name">&amp;#xe82e;</div>
              </li>
          </ul>
          <div class="article markdown">
          <h2 id="unicode-">Unicode 引用</h2>
          <hr>
          <p>Unicode 是字体在网页端最原始的应用方式,特点是:</p>
          <ul>
            <li>支持按字体的方式去动态调整图标大小,颜色等等。</li>
            <li>默认情况下不支持多色,直接添加多色图标会自动去色。</li>
          </ul>
          <blockquote>
            <p>注意:新版 iconfont 支持两种方式引用多色图标:SVG symbol 引用方式和彩色字体图标模式。(使用彩色字体图标需要在「编辑项目」中开启「彩色」选项后并重新生成。)</p>
          </blockquote>
          <p>Unicode 使用步骤如下:</p>
          <h3 id="-font-face">第一步:拷贝项目下面生成的 <code>@font-face</code></h3>
<pre><code class="language-css"
>@font-face {
  font-family: 'iconfont';
  src: url('iconfont.woff2?t=1638945390871') format('woff2'),
       url('iconfont.woff?t=1638945390871') format('woff'),
       url('iconfont.ttf?t=1638945390871') format('truetype');
}
</code></pre>
          <h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
<pre><code class="language-css"
>.iconfont {
  font-family: "iconfont" !important;
  font-size: 16px;
  font-style: normal;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
</code></pre>
          <h3 id="-">第三步:挑选相应图标并获取字体编码,应用于页面</h3>
<pre>
<code class="language-html"
>&lt;span class="iconfont"&gt;&amp;#x33;&lt;/span&gt;
</code></pre>
          <blockquote>
            <p>"iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。</p>
          </blockquote>
          </div>
      </div>
      <div class="content font-class">
        <ul class="icon_lists dib-box">
          <li class="dib">
            <span class="icon iconfont icon-search"></span>
            <div class="name">
              search
            </div>
            <div class="code-name">.icon-search
            </div>
          </li>
        </ul>
        <div class="article markdown">
        <h2 id="font-class-">font-class 引用</h2>
        <hr>
        <p>font-class 是 Unicode 使用方式的一种变种,主要是解决 Unicode 书写不直观,语意不明确的问题。</p>
        <p>与 Unicode 使用方式相比,具有如下特点:</p>
        <ul>
          <li>相比于 Unicode 语意明确,书写更直观。可以很容易分辨这个 icon 是什么。</li>
          <li>因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class 里面的 Unicode 引用。</li>
        </ul>
        <p>使用步骤如下:</p>
        <h3 id="-fontclass-">第一步:引入项目下面生成的 fontclass 代码:</h3>
<pre><code class="language-html">&lt;link rel="stylesheet" href="./iconfont.css"&gt;
</code></pre>
        <h3 id="-">第二步:挑选相应图标并获取类名,应用于页面:</h3>
<pre><code class="language-html">&lt;span class="iconfont icon-xxx"&gt;&lt;/span&gt;
</code></pre>
        <blockquote>
          <p>"
            iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。</p>
        </blockquote>
      </div>
      </div>
      <div class="content symbol">
          <ul class="icon_lists dib-box">
            <li class="dib">
                <svg class="icon svg-icon" aria-hidden="true">
                  <use xlink:href="#icon-search"></use>
                </svg>
                <div class="name">search</div>
                <div class="code-name">#icon-search</div>
            </li>
          </ul>
          <div class="article markdown">
          <h2 id="symbol-">Symbol 引用</h2>
          <hr>
          <p>这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇<a href="">文章</a>
            这种用法其实是做了一个 SVG 的集合,与另外两种相比具有如下特点:</p>
          <ul>
            <li>支持多色图标了,不再受单色限制。</li>
            <li>通过一些技巧,支持像字体那样,通过 <code>font-size</code>, <code>color</code> 来调整样式。</li>
            <li>兼容性较差,支持 IE9+,及现代浏览器。</li>
            <li>浏览器渲染 SVG 的性能一般,还不如 png。</li>
          </ul>
          <p>使用步骤如下:</p>
          <h3 id="-symbol-">第一步:引入项目下面生成的 symbol 代码:</h3>
<pre><code class="language-html">&lt;script src="./iconfont.js"&gt;&lt;/script&gt;
</code></pre>
          <h3 id="-css-">第二步:加入通用 CSS 代码(引入一次就行):</h3>
<pre><code class="language-html">&lt;style&gt;
.icon {
  width: 1em;
  height: 1em;
  vertical-align: -0.15em;
  fill: currentColor;
  overflow: hidden;
}
&lt;/style&gt;
</code></pre>
          <h3 id="-">第三步:挑选相应图标并获取类名,应用于页面:</h3>
<pre><code class="language-html">&lt;svg class="icon" aria-hidden="true"&gt;
  &lt;use xlink:href="#icon-xxx"&gt;&lt;/use&gt;
&lt;/svg&gt;
</code></pre>
          </div>
      </div>
    </div>
  </div>
  <script>
  $(document).ready(function () {
      $('.tab-container .content:first').show()
      $('#tabs li').click(function (e) {
        var tabContent = $('.tab-container .content')
        var index = $(this).index()
        if ($(this).hasClass('active')) {
          return
        } else {
          $('#tabs li').removeClass('active')
          $(this).addClass('active')
          tabContent.hide().eq(index).fadeIn()
        }
      })
    })
  </script>
</body>
</html>
src/assets/icon/iconfont.css
New file
@@ -0,0 +1,19 @@
@font-face {
  font-family: "iconfont"; /* Project id 2997242 */
  src: url('iconfont.woff2?t=1638945390871') format('woff2'),
       url('iconfont.woff?t=1638945390871') format('woff'),
       url('iconfont.ttf?t=1638945390871') format('truetype');
}
.iconfont {
  font-family: "iconfont" !important;
  font-size: 16px;
  font-style: normal;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
.icon-search:before {
  content: "\e82e";
}
src/assets/icon/iconfont.js
New file
@@ -0,0 +1 @@
!function(e){var t,n,o,i,c,d='<svg><symbol id="icon-search" viewBox="0 0 1024 1024"><path d="M1005.312 914.752l-198.528-198.464A448 448 0 1 0 0 448a448 448 0 0 0 716.288 358.784l198.4 198.4a64 64 0 1 0 90.624-90.432zM448 767.936A320 320 0 1 1 448 128a320 320 0 0 1 0 640z" fill="#262626" ></path></symbol></svg>',a=(a=document.getElementsByTagName("script"))[a.length-1].getAttribute("data-injectcss"),l=function(e,t){t.parentNode.insertBefore(e,t)};if(a&&!e.__iconfont__svg__cssinject__){e.__iconfont__svg__cssinject__=!0;try{document.write("<style>.svgfont {display: inline-block;width: 1em;height: 1em;fill: currentColor;vertical-align: -0.1em;font-size:16px;}</style>")}catch(e){console&&console.log(e)}}function s(){c||(c=!0,o())}function r(){try{i.documentElement.doScroll("left")}catch(e){return void setTimeout(r,50)}s()}t=function(){var e,t;(t=document.createElement("div")).innerHTML=d,d=null,(e=t.getElementsByTagName("svg")[0])&&(e.setAttribute("aria-hidden","true"),e.style.position="absolute",e.style.width=0,e.style.height=0,e.style.overflow="hidden",t=e,(e=document.body).firstChild?l(t,e.firstChild):e.appendChild(t))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(t,0):(n=function(){document.removeEventListener("DOMContentLoaded",n,!1),t()},document.addEventListener("DOMContentLoaded",n,!1)):document.attachEvent&&(o=t,i=e.document,c=!1,r(),i.onreadystatechange=function(){"complete"==i.readyState&&(i.onreadystatechange=null,s())})}(window);
src/assets/icon/iconfont.json
New file
@@ -0,0 +1,16 @@
{
  "id": "2997242",
  "name": "name",
  "font_family": "iconfont",
  "css_prefix_text": "icon-",
  "description": "",
  "glyphs": [
    {
      "icon_id": "6151301",
      "name": "search",
      "font_class": "search",
      "unicode": "e82e",
      "unicode_decimal": 59438
    }
  ]
}
src/assets/icon/iconfont.ttf
Binary files differ
src/assets/icon/iconfont.woff
Binary files differ
src/assets/icon/iconfont.woff2
Binary files differ
src/assets/nav_memory@1x.png
src/assets/nav_personage@1x.png
src/assets/nav_scenery@1x.png
src/assets/nav_spirit@1x.png
src/assets/search/search@1x.png
src/components/CustomSearch1.vue
New file
@@ -0,0 +1,77 @@
<template>
  <div class="custom-search1">
    <input class="input-inner" type="text" autocapitalize="off" placeholder="请输入检索词" v-model="searchName"/>
    <div class="input-append" v-on:click="$emit('search',searchName)">
      <svg t="1638943404588" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
           p-id="6664" width="200" height="200">
        <path
            d="M469.333 192c153.174 0 277.334 124.16 277.334 277.333 0 68.054-24.534 130.411-65.216 178.688L846.336 818.24l-48.341 49.877L630.4 695.125a276.053 276.053 0 0 1-161.067 51.542C316.16 746.667 192 622.507 192 469.333S316.16 192 469.333 192z m0 64C351.51 256 256 351.51 256 469.333s95.51 213.334 213.333 213.334 213.334-95.51 213.334-213.334S587.157 256 469.333 256z"
            p-id="6665"></path>
      </svg>
    </div>
  </div>
</template>
<script>
export default {
  name: "CustomSearch1",
  data() {
    return {
      searchName: ""
    }
  }
}
</script>
<style scoped>
.icon {
  fill: currentColor;
  color: #EFC587;
}
.custom-search1 {
  width: 99%;
  height: 8vh;
  border: 4px solid #EFC587;
  box-sizing: border-box;
  border-radius: 200px;
  background-color: rgba(0, 0, 0, 0.23);
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  justify-content: center;
  align-items: center;
}
.custom-search1 .input-inner {
  width: 80%;
  height: 95%;
  border: 0;
  border-radius: 200px;
  background-color: rgba(0, 0, 0, 0);
  font-size: 1.75rem;
  font-family: Microsoft YaHei;
  font-weight: 400;
  line-height: 1.25rem;
  color: #EFC587;
  opacity: 1;
}
.custom-search1 .input-inner:focus {
  outline: none;
}
.custom-search1 .input-append {
  width: 9%;
  height: 95%;
  cursor: pointer;
}
.custom-search1 .input-append svg {
  max-width: 2.68rem;
  width: 100%;
  height: 100%;
}
</style>
src/components/CustomSearch2.vue
New file
@@ -0,0 +1,201 @@
<template>
  <div class="custom-search2">
    <div class="custom-search-before" @click="ActionSheet">
      <input class="input-inner" type="text" readonly="readonly" autocomplete="off" placeholder="请选择"
             v-model="searchType.text">
      <span class="input-append">
        <svg t="1638954207837" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
             p-id="6664" width="128" height="128"><path
            d="M500.8 604.779L267.307 371.392l-45.227 45.27 278.741 278.613L779.307 416.66l-45.248-45.248z" p-id="6665"
            fill="#EFC587"></path></svg>
      </span>
    </div>
    <div class="custom-search-after">
      <input class="input-inner" type="text" autocapitalize="off" placeholder="请输入检索词" v-model="searchName"  v-on:focus="Focus"/>
      <div class="input-append" v-on:click="Search">
        <svg t="1638943404588" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
             p-id="6664" width="200" height="200">
          <path
              d="M469.333 192c153.174 0 277.334 124.16 277.334 277.333 0 68.054-24.534 130.411-65.216 178.688L846.336 818.24l-48.341 49.877L630.4 695.125a276.053 276.053 0 0 1-161.067 51.542C316.16 746.667 192 622.507 192 469.333S316.16 192 469.333 192z m0 64C351.51 256 256 351.51 256 469.333s95.51 213.334 213.333 213.334 213.334-95.51 213.334-213.334S587.157 256 469.333 256z"
              p-id="6665"></path>
        </svg>
      </div>
    </div>
    <actionsheet
        :actions="searchTypeItems"
        v-model="actionsheet">
    </actionsheet>
  </div>
</template>
<script>
import {Actionsheet} from 'mint-ui';
export default {
  name: "CustomSearch2",
  components: {Actionsheet},
  data() {
    return {
      actionsheet: false,
      searchType: {
        text: "名称",
        value: "title",
      },
      searchName: "",
      searchTypeItems: [{
        name: "名称",
        value: "title",
        method: this.SearchTypeItem
      }, {
        name: "关键字",
        value: "keywords",
        method: this.SearchTypeItem
      }, {
        name: "简介",
        value: "descriprion",
        method: this.SearchTypeItem
      }],
    }
  },
  methods: {
    ActionSheet: function () {
      this.actionsheet = true;
    },
    SearchTypeItem: function (obj) {
      this.searchType = {
        text: obj.name,
        value: obj.value,
      }
    },
    Search: function () {
      if (this.searchName != "") {
        if (localStorage.searchHistory) {
          let hisArray = eval(localStorage.searchHistory);
          hisArray.push({
            searchType: this.searchType.value,
            searchName: this.searchName,
          });
          localStorage.searchHistory = JSON.stringify(hisArray);
        } else {
          let hisArray = [{
            searchType: this.searchType.value,
            searchName: this.searchName,
          }];
          localStorage.searchHistory = JSON.stringify(hisArray);
        }
      }
      this.$emit('search', this.searchType.value, this.searchName)
    },
    Focus: function () {
      this.$emit('focus')
    }
  }
}
</script>
<style scoped>
.icon {
  fill: currentColor;
  color: #EFC587;
}
.custom-search2 {
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  justify-content: center;
  align-items: center;
}
.custom-search-before {
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  justify-content: center;
  align-items: center;
  width: 30%;
  height: 4vh;
  background: rgba(0, 0, 0, 0.46);
  border: 2px solid #EFC587;
  border-radius: 6px;
  margin-right: 1rem;
}
.custom-search-before .input-inner {
  width: 70%;
  height: 100%;
  border: 0;
  background-color: rgba(0, 0, 0, 0);
  font-size: 1.6rem;
  font-family: Source Han Sans CN;
  font-weight: 400;
  line-height: 2rem;
  color: #EFC587;
  cursor: pointer
}
.custom-search-before .input-inner:focus {
  outline: none;
}
.custom-search-before .input-append {
  width: 30%;
  height: 100%;
  cursor: pointer;
}
.custom-search-before .input-append svg {
  max-width: 1.6rem;
  width: 100%;
  height: 100%;
}
.custom-search-after {
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  justify-content: center;
  align-items: center;
  width: 99%;
  height: 4vh;
  background: rgba(0, 0, 0, 0.59);
  border: 2px solid #EFC587;
  opacity: 1;
  border-radius: 6px;
}
.custom-search-after .input-inner {
  width: 90%;
  height: 95%;
  border: 0;
  border-radius: 200px;
  background-color: rgba(0, 0, 0, 0);
  font-size: 1.31rem;
  font-family: Microsoft YaHei;
  font-weight: 400;
  line-height: 3.33rem;
  color: rgba(239, 197, 135, 0.6);
  opacity: 1;
}
.custom-search-after .input-inner:focus {
  outline: none;
}
.custom-search-after .input-append {
  width: 9%;
  height: 95%;
  cursor: pointer;
}
.custom-search-after .input-append svg {
  max-width: 1.6rem;
  width: 100%;
  height: 100%;
}
</style>
src/components/CustomSearch3.vue
New file
@@ -0,0 +1,183 @@
<template>
  <div class="custom-search3">
    <div class="custom-search-before" @click="ActionSheet">
      <input class="input-inner" type="text" readonly="readonly" autocomplete="off" placeholder="请选择"
             v-model="searchType.text">
      <span class="input-append">
        <svg t="1638954207837" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
             p-id="6664" width="128" height="128"><path
            d="M500.8 604.779L267.307 371.392l-45.227 45.27 278.741 278.613L779.307 416.66l-45.248-45.248z" p-id="6665"
            fill="#606060"></path></svg>
      </span>
    </div>
    <div class="custom-search-after">
      <input class="input-inner" type="text" autocapitalize="off" placeholder="请输入检索词" v-model="searchName"/>
      <div class="input-append" v-on:click="Search">
        <svg t="1638943404588" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
             p-id="6664" width="200" height="200">
          <path
              d="M469.333 192c153.174 0 277.334 124.16 277.334 277.333 0 68.054-24.534 130.411-65.216 178.688L846.336 818.24l-48.341 49.877L630.4 695.125a276.053 276.053 0 0 1-161.067 51.542C316.16 746.667 192 622.507 192 469.333S316.16 192 469.333 192z m0 64C351.51 256 256 351.51 256 469.333s95.51 213.334 213.333 213.334 213.334-95.51 213.334-213.334S587.157 256 469.333 256z"
              p-id="6665" fill="#BC0000"></path>
        </svg>
      </div>
    </div>
    <actionsheet
        :actions="searchTypeItems"
        v-model="actionsheet">
    </actionsheet>
  </div>
</template>
<script>
import {Actionsheet} from 'mint-ui';
export default {
  name: "CustomSearch3",
  components: {Actionsheet},
  data() {
    return {
      actionsheet: false,
      searchType: {
        text: "名称",
        value: "title",
      },
      searchName: "",
      searchTypeItems: [{
        name: "名称",
        value: "title",
        method: this.SearchTypeItem
      }, {
        name: "关键字",
        value: "keywords",
        method: this.SearchTypeItem
      }, {
        name: "简介",
        value: "descriprion",
        method: this.SearchTypeItem
      }],
    }
  },
  methods: {
    ActionSheet: function () {
      this.actionsheet = true;
    },
    SearchTypeItem: function (obj) {
      this.searchType = {
        text: obj.name,
        value: obj.value,
      }
    },
    Search: function () {
      this.$emit('search', this.searchType.value, this.searchName)
    }
  }
}
</script>
<style scoped>
.icon {
  fill: currentColor;
  color: #EFC587;
}
.custom-search3 {
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  justify-content: center;
  align-items: center;
  width: 100%;
}
.custom-search-before {
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  justify-content: center;
  align-items: center;
  width: 25%;
  height: 4vh;
  background: #FAFAFA;
  border: 2px solid #EAEAEA;
  border-radius: 6px;
  margin-right: 1rem;
}
.custom-search-before .input-inner {
  width: 70%;
  height: 100%;
  border: 0;
  background-color: rgba(0, 0, 0, 0);
  font-size: 1.5rem;
  font-family: Source Han Sans CN;
  font-weight: 400;
  line-height: 1.5rem;
  color: #606060;
  cursor: pointer
}
.custom-search-before .input-inner:focus {
  outline: none;
}
.custom-search-before .input-append {
  width: 30%;
  height: 100%;
  cursor: pointer;
}
.custom-search-before .input-append svg {
  max-width: 2rem;
  width: 100%;
  height: 100%;
}
.custom-search-after {
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  justify-content: center;
  align-items: center;
  width: 75%;
  height: 4vh;
  background: white;
  border: 2px solid #BC0000;
  opacity: 1;
  border-radius: 6px;
}
.custom-search-after .input-inner {
  width: 90%;
  height: 3vh;
  border: 0;
  border-radius: 200px;
  font-size: 1.4rem;
  font-family: Microsoft YaHei;
  font-weight: 400;
  line-height: 1.4rem;
  color: #767676;
  opacity: 1;
}
.custom-search-after .input-inner:focus {
  outline: none;
}
.custom-search-after .input-append {
  width: 9%;
  height: 95%;
  cursor: pointer;
}
.custom-search-after .input-append svg {
  max-width: 2rem;
  width: 100%;
  height: 100%;
}
</style>
src/components/HelloWorld.vue
File was deleted
src/main.js
@@ -1,8 +1,148 @@
import Vue from 'vue'
import VueRouter from 'vue-router'
import MintUI from 'mint-ui'
import 'mint-ui/lib/style.css'
import '../src/assets/icon/iconfont.css'
import Meta from "vue-meta";
import App from './App.vue'
import LayoutList from './views/layout/listIndex'
import LayoutSearch from './views/layout/searchIndex'
import HomePage from './views/home'
import SearchIndex from './views/search/index'
import SearchResults from './views/search/results'
import SceneryList from './views/scenery/list'
import SceneryDetail from './views/scenery/detail'
import SceneryDetailImage from './views/scenery/detailImage'
import SceneryDetailVideo from './views/scenery/detailvideo'
import MemoryList from './views/memory/list'
import MemoryDetail from './views/memory/detail'
import MemoryDetailImage from './views/memory/detailImage'
import MemoryDetailVideo from './views/memory/detailvideo'
import SpiritList from './views/spirit/list'
import SpiritDetail from './views/spirit/detail'
import SpiritDetailImage from './views/spirit/detailImage'
import SpiritDetailVideo from './views/spirit/detailvideo'
import PersonageList from './views/personage/list'
import PersonageDetail from './views/personage/detail'
import PersonageDetailImage from './views/personage/detailImage'
import PersonageDetailVideo from './views/personage/detailvideo'
Vue.config.productionTip = false
const routes = [
    {
        name: 'default', path: '/', redirect: '/home', meta: {
            title: '首页'
        }
    },
    {name: 'home', path: '/home', component: HomePage},
    {
        name: 'search', path: '/search', component: LayoutSearch,
        meta: {
            title: '数据检索'
        },
        children: [
            {name: 'search-index', path: 'index', component: SearchIndex},
            {name: 'search-results', path: 'results', component: SearchResults},
        ]
    },
    {
        name: 'scenery', path: '/scenery', component: LayoutList,
        meta: {
            title: '红色景区库'
        },
        children: [
            {name: 'scenery-list', path: 'list', component: SceneryList},
        ],
    },
    {
        name: 'scenery', path: '/scenery', component: App,
        meta: {
            title: '红色景区库'
        },
        children: [
            {name: 'scenery-detail', path: 'detail', component: SceneryDetail},
            {name: 'scenery-detail-image', path: 'detail/image', component: SceneryDetailImage},
            {name: 'scenery-detail-video', path: 'detail/video', component: SceneryDetailVideo},
        ],
    },
    {
        name: 'memory', path: '/memory', component: LayoutList,
        meta: {
            title: '红色记忆库'
        },
        children: [
            {name: 'memory-list', path: 'list', component: MemoryList},
        ],
    },
    {
        name: 'memory', path: '/memory', component: App,
        meta: {
            title: '红色记忆库'
        },
        children: [
            {name: 'memory-detail', path: 'detail', component: MemoryDetail},
            {name: 'memory-detail-image', path: 'detail/image', component: MemoryDetailImage},
            {name: 'memory-detail-video', path: 'detail/video', component: MemoryDetailVideo},
        ],
    },
    {
        name: 'spirit', path: '/spirit', component: LayoutList,
        meta: {
            title: '红色精神库'
        },
        children: [
            {name: 'spirit-list', path: 'list', component: SpiritList},
        ],
    },
    {
        name: 'spirit', path: '/spirit', component: App,
        meta: {
            title: '红色精神库'
        },
        children: [
            {name: 'spirit-detail', path: 'detail', component: SpiritDetail},
            {name: 'spirit-detail-image', path: 'detail/image', component: SpiritDetailImage},
            {name: 'spirit-detail-video', path: 'detail/video', component: SpiritDetailVideo},
        ],
    },
    {
        name: 'personage', path: '/personage', component: LayoutList,
        meta: {
            title: '红色人物库'
        },
        children: [
            {name: 'personage-list', path: 'list', component: PersonageList},
        ],
    },
    {
        name: 'personage', path: '/personage', component: App,
        meta: {
            title: '红色人物库'
        },
        children: [
            {name: 'personage-detail', path: 'detail', component: PersonageDetail},
            {name: 'personage-detail-image', path: 'detail/image', component: PersonageDetailImage},
            {name: 'personage-detail-video', path: 'detail/video', component: PersonageDetailVideo},
        ],
    },
];
const router = new VueRouter({
    routes
});
Vue.use(VueRouter);
Vue.use(MintUI);
Vue.use(Meta);
new Vue({
  render: h => h(App),
    router
}).$mount('#app')
src/views/home.vue
New file
@@ -0,0 +1,191 @@
<template>
  <div class="home">
    <h1>吉林省红色旅游数据库</h1>
    <div class="search-div">
      <div class="search-type">
        <ul>
          <li :class="searchType=='title'?'selected':''" @click="SwitchSearchType('title')">名称</li>
          <li :class="searchType=='keywords'?'selected':''" @click="SwitchSearchType('keywords')">关键词</li>
          <li :class="searchType=='description'?'selected':''" @click="SwitchSearchType('description')">简介</li>
        </ul>
      </div>
      <div class="search-name">
        <CustomSearch1 v-on:search="Search"></CustomSearch1>
      </div>
    </div>
    <div class="navigation-div">
      <div class="nav-div nav-memory" @click="NavigationGo(1)">
        红色记忆
      </div>
      <div class="nav-div nav-personage" @click="NavigationGo(4)">
        红色人物
      </div>
      <div class="nav-div nav-scenery" @click="NavigationGo(3)">
        红色景区
      </div>
      <div class="nav-div nav-spirit" @click="NavigationGo(2)">
        红色精神
      </div>
    </div>
  </div>
</template>
<script>
import CustomSearch1 from '../components/CustomSearch1'
export default {
  name: "home",
  components: {
    CustomSearch1
  },
  data() {
    return {
      searchType: "title",
    }
  },
  methods: {
    Search: function (searchName) {
      this.$router.push({name: "search-results", query: {searchType: this.searchType, searchName: searchName}});
    },
    SwitchSearchType: function (searchType) {
      this.searchType = searchType;
    },
    NavigationGo(type) {
      switch (type) {
        case 1:
          this.$router.push({name: "memory-list", query: {}});
          break;
        case 2:
          this.$router.push({name: "spirit-list", query: {}});
          break;
        case 3:
          this.$router.push({name: "scenery-list", query: {}});
          break;
        case 4:
          this.$router.push({name: "personage-list", query: {}});
          break;
      }
    }
  }
}
</script>
<style scoped>
.home {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 99vh;
  background: url("../assets/home_background@1x.png") no-repeat 100% 100%;
  background-size: cover;
}
h1 {
  width: 70%;
  font-size: 4.5rem;
  font-family: FZZhengHeiS-DB-GB;
  font-weight: 400;
  line-height: 6.87rem;
  color: #FFFFFF;
}
.search-div {
  width: 90%;
  padding-bottom: 3.8vh;
}
.search-div ul {
  text-align: left;
}
.search-div ul li {
  cursor: pointer;
  display: inline-block;
  list-style-type: none;
  padding-right: 5vw;
  font-size: 1.75rem;
  font-family: Source Han Sans CN;
  font-weight: 400;
  color: #FFFFFF;
}
.search-div ul li.selected {
  font-size: 2rem;
  font-family: Source Han Sans CN;
  font-weight: 500;
  color: #EFC587;
}
.navigation-div {
  width: 90%;
}
.navigation-div .nav-div {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 10vh;
  border-radius: 10px;
  margin-bottom: 3vh;
  cursor: pointer;
}
.navigation-div .nav-memory {
  background: url("../assets/nav_memory@1x.png") no-repeat 100% 100%;
  background-size: cover;
  font-size: 3.37rem;
  font-family: FZDaBiaoSong-B06S;
  font-weight: 400;
  line-height: 1.93rem;
  color: #BC0000;
  text-shadow: 0px 3px 6px rgba(255, 255, 255, 0.16);
  opacity: 1;
}
.navigation-div .nav-personage {
  background: url("../assets/nav_personage@1x.png") no-repeat 100% 100%;
  background-size: cover;
  font-size: 3.37rem;
  font-family: FZDaBiaoSong-B06S;
  font-weight: 400;
  line-height: 1.93rem;
  color: #BC0000;
  opacity: 1;
}
.navigation-div .nav-scenery {
  background: url("../assets/nav_scenery@1x.png") no-repeat 100% 100%;
  background-size: cover;
  font-size: 3.37rem;
  font-family: FZDaBiaoSong-B06S;
  font-weight: 400;
  line-height: 1.93rem;
  color: #FFE36C;
  text-shadow: 0px 3px 6px rgba(0, 0, 0, 0.16);
  opacity: 1;
}
.navigation-div .nav-spirit {
  background: url("../assets/nav_spirit@1x.png") no-repeat 100% 100%;
  background-size: cover;
  font-size: 3.37rem;
  font-family: FZDaBiaoSong-B06S;
  font-weight: 400;
  line-height: 1.93rem;
  color: #FFE36C;
  text-shadow: 0px 3px 6px rgba(0, 0, 0, 0.16);
  opacity: 1;
}
</style>
src/views/layout/listIndex.vue
New file
@@ -0,0 +1,155 @@
<template>
  <div class="datalist">
    <div class="data-title">
      <div @click="ToHome">吉林省红色旅游数据库</div>
      <div @click="ToHome">红色景点库</div>
    </div>
    <div class="data-content">
      <transition name="fade-transform" mode="out-in">
        <router-view :key="key"/>
      </transition>
    </div>
    <mt-tabbar v-model="dataType" :fixed="true">
      <mt-tab-item id="1">红色记忆</mt-tab-item>
      <mt-tab-item id="2">红色精神</mt-tab-item>
      <mt-tab-item id="3">红色景区</mt-tab-item>
      <mt-tab-item id="4">红色人物</mt-tab-item>
    </mt-tabbar>
  </div>
</template>
<script>
export default {
  name: "listIndex",
  data() {
    return {
      dataType: ""
    }
  },
  methods: {
    ToHome: function () {
      this.$router.push({name: "home"});
    }
  },
  watch: {
    dataType: function () {
      switch (this.dataType) {
        case "1":
          this.$router.push({name: "memory-list"});
          break;
        case "2":
          this.$router.push({name: "spirit-list"});
          break;
        case "3":
          this.$router.push({name: "scenery-list"});
          break;
        case "4":
          this.$router.push({name: "personage-list"});
          break;
      }
    },
  },
  computed: {
    key() {
      return this.$route.path
    }
  },
  created() {
    if (this.dataType == "") {
      switch (this.$route.name) {
        case "memory-list":
          this.dataType = "1";
          break;
        case "spirit-list":
          this.dataType = "2"
          break;
        case "scenery-list":
          this.dataType = "3";
          break;
        case "personage-list":
          this.dataType = "4";
          break;
      }
    }
  }
}
</script>
<style scoped>
.datalist {
  width: 100%;
  height: 100vh;
}
.data-title {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 16vh;
  background: url("../../assets/datalist/datalist@1x.png") no-repeat 100% 100%;
  background-size: cover;
}
.data-title > div {
  width: 100%;
  text-align: left;
  font-size: 2.87rem;
  font-family: FZZhengHeiS-DB-GB;
  font-weight: 400;
  line-height: 4.37rem;
  color: #FFFFFF;
  opacity: 1;
  padding-left: 2rem;
}
.data-content {
  width: 100%;
  height: 75vh;
  background: #FFFFFF;
  border-radius: 10px 10px 0px 0px;
  position: relative;
  z-index: 5;
}
.data-content .list-root{
  height: 100%;
  width: 100%;
}
.mint-tabbar {
  height: 10vh;
  background: white;
  z-index: 9;
}
.mint-tabbar /deep/ .mint-tab-item {
  padding: 20px 0;
}
.mint-tabbar /deep/ .mint-tab-item-label {
  font-size: 1.75rem;
  font-family: Source Han Sans CN;
  font-weight: 400;
  line-height: 1.93rem;
  color: #767676;
  opacity: 1;
}
.mint-tabbar /deep/ .is-selected {
  background-color: white;
  border-top: 0.5vh solid #BC0000;
}
.mint-tabbar /deep/ .is-selected .mint-tab-item-label {
  font-size: 1.75rem;
  font-family: Source Han Sans CN;
  font-weight: bold;
  line-height: 1.93rem;
  color: #BC0000;
  opacity: 1;
}
</style>
src/views/layout/searchIndex.vue
New file
@@ -0,0 +1,75 @@
<template>
  <div class="search">
    <div class="search-input">
      <custom-search2 v-on:search="Search" v-on:focus="Focus"></custom-search2>
    </div>
    <div class="search-content">
      <transition name="fade-transform" mode="out-in">
        <router-view :key="key"/>
      </transition>
    </div>
  </div>
</template>
<script>
import CustomSearch2 from "@/components/CustomSearch2";
export default {
  name: "searchIndex",
  components: {CustomSearch2},
  methods: {
    Search: function (searchType, searchName) {
      this.$router.push({
        name: 'search-results',
        query: {
          searchType: searchType,
          searchName: searchName
        }
      });
    },
    Focus: function () {
      this.$router.push({
        name: 'search-index'
      });
    }
  },
  computed: {
    key() {
      return this.$route.path
    }
  }
}
</script>
<style scoped>
.search {
  width: 100%;
}
.search .search-input {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 10vh;
  background: url("../../assets/search/search@1x.png") no-repeat 100% 100%;
  background-size: cover;
}
.search .search-input .custom-search2 {
  width: 90%;
}
.search .search-content {
  width: 100%;
  background: #FFFFFF;
  border-radius: 10px 10px 0px 0px;
  position: relative;
  top: -10px;
  z-index: 10;
}
</style>
src/views/memory/detail.vue
New file
@@ -0,0 +1,510 @@
<template>
  <div class="data-detail">
    <div class="title">
      <div class="title-left">
        <div class="title-name" @click="ToListPage">{{ titleName }}</div>
        <div class="title-introduce">{{ titleIntroduce }}</div>
      </div>
      <div class="title-right">
        <div class="online-preview" @click="OnlinePreview(basisInfo.file)">在线浏览</div>
      </div>
    </div>
    <div class="content">
      <mt-navbar ref="navbar" v-model="navbarIndex">
        <mt-tab-item id="1" data-type="1">基本信息</mt-tab-item>
        <mt-tab-item id="2" data-type="2">相关图片</mt-tab-item>
        <mt-tab-item id="3" data-type="3">相关视频</mt-tab-item>
      </mt-navbar>
      <mt-tab-container v-model="navbarIndex">
        <mt-tab-container-item id="1">
          <div class="content-keyword">
            <div class="item-name">关键字</div>
            {{ basisInfo.keyWord }}
          </div>
          <div class="content-introduction">
            <div class="item-name">简介</div>
            {{ basisInfo.introduction }}
          </div>
        </mt-tab-container-item>
        <mt-tab-container-item id="2">
          <CustomSearch3 v-on:search="SearchImages"></CustomSearch3>
          <div class="content-images"
               v-infinite-scroll="NextImages"
               :infinite-scroll-disabled="images.scrollDisabled"
               :infinite-scroll-distance="10">
            <div class="content-item"
                 v-for="item in images.data"
                 :key="item.id"
                 @click="ToImageDetail(item.id)">
              <div class="img-div">
                <img :src="item.path"/>
              </div>
              <div class="item-name">{{ item.name }}</div>
            </div>
          </div>
        </mt-tab-container-item>
        <mt-tab-container-item id="3">
          <CustomSearch3 v-on:search="SearchVideos"></CustomSearch3>
          <div class="content-videos"
               v-infinite-scroll="NextVideos"
               :infinite-scroll-disabled="videos.scrollDisabled"
               :infinite-scroll-distance="10">
            <div class="content-item"
                 v-for="item in videos.data"
                 :key="item.id"
                 @click="ToVideoDetail(item.id)">
              <div class="item-left">
                <img :src="item.cover"/>
              </div>
              <div class="item-right">
                <div class="item-name">{{ item.name }}</div>
                <div class="item-introduce">{{ item.description }}</div>
              </div>
            </div>
          </div>
        </mt-tab-container-item>
      </mt-tab-container>
    </div>
  </div>
</template>
<script>
import CustomSearch3 from "@/components/CustomSearch3";
import {
  GetDataDetail as Api_GetDataDetail,
  GetDataDetailImages as Api_GetDataDetailImages,
  GetDataDetailVideos as Api_GetDataDetailVideos,
} from "@/api/apilist";
export default {
  name: "detail",
  components: {CustomSearch3},
  data() {
    return {
      titleName: "",
      titleIntroduce: "",
      navbarIndex: "1",
      basisInfo: {
        id: "",
        keyWord: "",
        introduction: "",
        file: "",
      },
      images: {
        searchType: "title",
        searchName: "",
        pageSize: 10,
        currentPage: 1,
        total: 0,
        data: [],
        scrollDisabled: false,
      },
      videos: {
        searchType: "title",
        searchName: "",
        pageSize: 10,
        currentPage: 1,
        total: 0,
        data: [],
        scrollDisabled: false,
      },
    }
  },
  methods: {
    OnlinePreview: function (fileUrl) {
      if (fileUrl) {
        if (fileUrl.replace(/\\/g, '').toLowerCase().indexOf('.pdf') >= 0) {
          window.open(fileUrl);
        } else {
          //https://view.officeapps.live.com/op/view.aspx?src=
          window.open("http://www.xdocin.com/xdoc?_func=to&_format=html&_cache=1&_xdoc=" + fileUrl.replace(/\\/g, ''));
        }
      }
    },
    SearchBasisInfo: function (id) {
      Api_GetDataDetail(id).then(res => {
        this.basisInfo = res;
        this.titleIntroduce = res.keyWord;
      }, rej => {
        alert(rej);
      }).catch(err => {
        console.log(err);
        alert('错误的请求!');
      });
    },
    SearchImages: function (searchType, searchName) {
      this.images.searchType = searchType;
      this.images.searchName = searchName;
      Api_GetDataDetailImages(this.$route.query.id, searchType, searchName, 1, 10).then(res => {
        this.images.currentPage = res.currentPage;
        this.images.pageSize = res.pageSize;
        this.images.total = res.total;
        this.images.data = res.data;
      }, rej => {
        alert(rej);
      }).catch(err => {
        console.log(err);
        alert('错误的请求!');
      });
    },
    NextImages: function () {
      let searchType = this.images.searchType;
      let searchName = this.images.searchName;
      let currentPage = this.images.currentPage + 1;
      let pageSize = this.images.pageSize;
      Api_GetDataDetailImages(this.$route.query.id, searchType, searchName, currentPage, pageSize).then(res => {
        if (res.data.length > 0) {
          this.images.total = res.total;
          this.images.currentPage = res.currentPage;
          this.images.data = this.images.data.concat(res.data);
        }
      }, rej => {
        alert(rej);
      }).catch(err => {
        console.log(err);
        alert('错误的请求!');
      });
    },
    SearchVideos: function (searchType, searchName) {
      this.videos.searchType = searchType;
      this.videos.searchName = searchName;
      Api_GetDataDetailVideos(this.$route.query.id, searchType, searchName, 1, 10).then(res => {
        this.videos.currentPage = res.currentPage;
        this.videos.pageSize = res.pageSize;
        this.videos.total = res.total;
        this.videos.data = res.data;
      }, rej => {
        alert(rej);
      }).catch(err => {
        console.log(err);
        alert('错误的请求!');
      });
    },
    NextVideos: function () {
      let searchType = this.videos.searchType;
      let searchName = this.videos.searchName;
      let currentPage = this.videos.currentPage + 1;
      let pageSize = this.videos.pageSize;
      Api_GetDataDetailVideos(this.$route.query.id, searchType, searchName, currentPage, pageSize).then(res => {
        if (res.data.length > 0) {
          this.videos.total = res.total;
          this.videos.currentPage = res.currentPage;
          this.videos.data = this.videos.data.concat(res.data);
        }
      }, rej => {
        alert(rej);
      }).catch(err => {
        console.log(err);
        alert('错误的请求!');
      });
    },
    ToImageDetail: function (id) {
      let objId = this.$route.query.id;
      this.$router.push({name: "memory-detail-image", query: {id: id, objId: objId}});
    },
    ToVideoDetail: function (id) {
      let objId = this.$route.query.id;
      this.$router.push({name: "memory-detail-video", query: {id: id, objId: objId}});
    },
    ToListPage: function () {
      this.$router.push({name: "memory-list"})
    },
  },
  watch: {
    navbarIndex: function () {
      switch (this.navbarIndex) {
        case 1:
          this.images.scrollDisabled = true;
          this.videos.scrollDisabled = true;
          break;
        case 2:
          this.images.scrollDisabled = false;
          this.videos.scrollDisabled = true;
          break;
        case 3:
          this.images.scrollDisabled = true;
          this.videos.scrollDisabled = false;
          break;
      }
    }
  },
  created() {
    let id = this.$route.query.id;
    this.titleName = this.$route.query.name;
    this.SearchBasisInfo(id);
    this.SearchImages("title", "");
    this.SearchVideos("title", "");
  }
}
</script>
<style scoped>
.data-detail {
  width: 100%;
}
.data-detail .title {
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  height: 15.9vh;
  background: url("../../assets/datadetail/detail@1x.png") no-repeat 100% 100%;
  background-size: cover;
  border-radius: 10px 10px 0 0;
}
.data-detail .title .title-left {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-start;
  width: 60%;
  height: 100%;
  padding-left: 2vh;
}
.data-detail .title .title-name {
  width: 100%;
  text-align: left;
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
  font-size: 2.62rem;
  font-family: Source Han Serif CN;
  font-weight: bold;
  line-height: 5.24rem;
  color: #FFFFFF;
  opacity: 1;
}
.data-detail .title .title-introduce {
  width: 100%;
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
  font-size: 2rem;
  font-family: Source Han Sans CN;
  font-weight: 400;
  line-height: 3.37rem;
  color: #FFFFFF;
  opacity: 1;
}
.data-detail .title .title-right {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-start;
  width: 30%;
  height: 100%;
}
.data-detail .title .online-preview {
  width: 80%;
  background: #EFC587;
  opacity: 1;
  border-radius: 60px;
  font-size: 1.75rem;
  font-family: Source Han Sans CN;
  font-weight: bold;
  line-height: 3.87vh;
  color: #BC0000;
  opacity: 1;
}
.data-detail .content {
  width: 90%;
  height: 84.1vh;
  margin-left: 5%;
  border-radius: 30px;
}
.mint-navbar /deep/ .mint-tab-item-label {
  font-size: 2rem;
  font-family: Source Han Sans CN;
  font-weight: 500;
  line-height: 2rem;
  color: #767676;
  opacity: 1;
}
.mint-navbar /deep/ .is-selected {
  color: #BC0000;
  border-bottom: 0.3vh solid #BC0000;
}
.mint-navbar /deep/ .is-selected .mint-tab-item-label {
  color: #BC0000;
}
.mint-tab-container /deep/ .mint-tab-container-item:nth-child(1) {
  padding-top: 5vh;
}
.content-keyword {
  text-align: left;
  font-size: 1.87rem;
  font-family: Source Han Serif CN;
  font-weight: 400;
  line-height: 3rem;
  color: #767676;
  opacity: 1;
}
.content-keyword .item-name {
  text-align: left;
  font-size: 2rem;
  font-family: Source Han Sans CN;
  font-weight: bold;
  line-height: 6rem;
  color: #BC0000;
  opacity: 1;
}
.content-introduction {
  text-align: left;
  font-size: 1.87rem;
  font-family: Source Han Serif CN;
  font-weight: 400;
  line-height: 3rem;
  color: #767676;
  opacity: 1;
}
.content-introduction .item-name {
  text-align: left;
  font-size: 2rem;
  font-family: Source Han Sans CN;
  font-weight: bold;
  line-height: 6rem;
  color: #BC0000;
  opacity: 1;
}
.mint-tab-container /deep/ .mint-tab-container-item:nth-child(2) {
  padding-top: 2vh;
}
.custom-search3 {
  margin-bottom: 2vh;
}
.content-images {
  display: flex;
  flex-wrap: wrap;
  flex-direction: row;
  justify-content: flex-start;
  align-items: flex-start;
}
.content-images .content-item {
  width: 50%;
  height: 25vh;
}
.content-images .content-item .img-div {
  width: 90%;
  height: 80%;
  border-radius: 10px;
  box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.16);
}
.content-images .content-item .img-div img {
  width: 100%;
  height: 100%;
  border-radius: 10px;
  object-fit: cover;
}
.content-images .content-item .item-name {
  width: 90%;
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
  font-size: 2em;
  font-family: Source Han Serif CN;
  font-weight: bold;
  line-height: 2em;
  color: #333333;
  opacity: 1;
}
.mint-tab-container /deep/ .mint-tab-container-item:nth-child(3) {
  padding-top: 2vh;
}
.content-videos {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  align-items: center;
}
.content-videos .content-item {
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  justify-content: flex-start;
  align-items: center;
  height: 10vh;
  margin: 2vh auto;
}
.content-videos .item-left {
  width: 30%;
  height: 100%;
}
.content-videos .item-left img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.content-videos .item-right {
  width: 70%;
  height: 100%;
  padding-left: 2vw;
}
.content-videos .item-name {
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
  text-align: left;
  font-size: 2rem;
  font-family: Source Han Serif CN;
  font-weight: bold;
  line-height: 4rem;
  color: #BC0000;
  opacity: 1;
}
.content-videos .item-introduce {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  text-overflow: ellipsis;
  overflow: hidden;
  text-align: left;
  font-size: 1.62rem;
  font-family: Source Han Sans CN;
  font-weight: 400;
  line-height: 3rem;
  color: #767676;
  opacity: 1;
}
</style>
src/views/memory/detailImage.vue
New file
@@ -0,0 +1,133 @@
<template>
  <div class="data-detail-image">
    <div class="images">
      <mt-swipe :show-indicators="false" :auto="0" :continuous="false" @change="ChangeImage">
        <mt-swipe-item v-for="item in images.data" :key="item.key">
          <img :src="item.path"/>
        </mt-swipe-item>
      </mt-swipe>
    </div>
    <div class="content">
      <mt-navbar v-model="navIndex">
        <mt-tab-item id="1">关键词</mt-tab-item>
        <mt-tab-item id="2">简介</mt-tab-item>
      </mt-navbar>
      <mt-tab-container v-model="navIndex">
        <mt-tab-container-item id="1">
          {{ image.keyWord }}
        </mt-tab-container-item>
        <mt-tab-container-item id="2">
          {{ image.introduction }}
        </mt-tab-container-item>
      </mt-tab-container>
    </div>
  </div>
</template>
<script>
import {GetImageDetail as Api_GetImageDetail} from "@/api/apilist";
export default {
  name: "detailImage",
  data() {
    return {
      navIndex: "1",
      images: {
        pageSize: 10,
        currentPage: 1,
        total: 0,
        data: []
      },
      image: {
        id: "",
        name: "",
        path: "",
        keyWord: "",
        introduction: "",
      }
    }
  },
  methods: {
    ChangeImage: function (index) {
      this.image = this.images.data[index];
    },
  },
  created() {
    let imageId = this.$route.query.id;
    let objId = this.$route.query.objId;
    Api_GetImageDetail(imageId, 1, objId, 999).then(res => {
      this.images = res;
      this.image = res.data[0];
    }, rej => {
      alert(rej);
    }).catch(err => {
      console.log(err);
      alert('错误的请求!');
    });
  }
}
</script>
<style scoped>
.data-detail-image {
  width: 100%;
}
.images {
  width: 100%;
  height: 31.5vh;
}
.images img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.content {
  width: 100%;
  height: 66vh;
  box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.16);
  opacity: 1;
  border-radius: 10px;
  padding-top: 1vh;
}
.content > div{
  width: 90%;
  margin-left: 5%;
}
.mint-navbar{
  margin-bottom: 4vh;
}
.mint-navbar .mint-tab-item /deep/ .mint-tab-item-label {
  font-size: 2rem;
  font-family: Source Han Sans CN;
  font-weight: 500;
  line-height: 3rem;
  color: #767676;
  opacity: 1;
}
.mint-navbar .is-selected {
  border-bottom: 0.3rem solid #BC0000;
}
.mint-navbar .is-selected /deep/ .mint-tab-item-label {
  color: #BC0000;
  font-weight: bold;
}
.mint-tab-container {
  text-align: left;
  font-size: 1.87rem;
  font-family: Source Han Serif CN;
  font-weight: 400;
  line-height: 3rem;
  color: #585858;
  opacity: 1;
}
</style>
src/views/memory/detailvideo.vue
New file
@@ -0,0 +1,121 @@
<template>
  <div class="data-detail-video">
    <div class="videos">
      <video poster="" :src="video.patch" controls="controls">
        您的浏览器不支持 video 标签。
      </video>
    </div>
    <div class="content">
      <mt-navbar v-model="navIndex">
        <mt-tab-item id="1">关键词</mt-tab-item>
        <mt-tab-item id="2">简介</mt-tab-item>
      </mt-navbar>
      <mt-tab-container v-model="navIndex">
        <mt-tab-container-item id="1">
          {{ video.keyWord }}
        </mt-tab-container-item>
        <mt-tab-container-item id="2">
          {{ video.introduction }}
        </mt-tab-container-item>
      </mt-tab-container>
    </div>
  </div>
</template>
<script>
import {GetVideoDetail as Api_GetVideoDetail} from "@/api/apilist";
export default {
  name: "detailVideo",
  data() {
    return {
      navIndex: "1",
      video: {
        id: "",
        name: "",
        path: "",
        keyWord: "",
        introduction: "",
      },
    }
  },
  methods: {
  },
  created() {
    let id = this.$route.query.id;
    Api_GetVideoDetail(id).then(res => {
      this.video = res;
    }, rej => {
      alert(rej);
    }).catch(err => {
      console.log(err);
      alert('错误的请求!');
    });
  }
}
</script>
<style scoped>
.data-detail-video {
  width: 100%;
}
.videos {
  width: 100%;
  height: 31.5vh;
}
.videos video {
  width: 100%;
  height: 100%;
  background: black;
}
.content {
  width: 100%;
  height: 66vh;
  box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.16);
  opacity: 1;
  border-radius: 10px;
  padding-top: 1vh;
}
.content > div{
  width: 90%;
  margin-left: 5%;
}
.mint-navbar{
  margin-bottom: 4vh;
}
.mint-navbar .mint-tab-item /deep/ .mint-tab-item-label {
  font-size: 2rem;
  font-family: Source Han Sans CN;
  font-weight: 500;
  line-height: 3rem;
  color: #767676;
  opacity: 1;
}
.mint-navbar .is-selected {
  border-bottom: 0.3rem solid #BC0000;
}
.mint-navbar .is-selected /deep/ .mint-tab-item-label {
  color: #BC0000;
  font-weight: bold;
}
.mint-tab-container {
  text-align: left;
  font-size: 1.87rem;
  font-family: Source Han Serif CN;
  font-weight: 400;
  line-height: 3rem;
  color: #585858;
  opacity: 1;
}
</style>
src/views/memory/list.vue
New file
@@ -0,0 +1,154 @@
<template>
  <div class="list-root">
    <div class="search">
      <CustomSearch3 v-on:search="Search"></CustomSearch3>
    </div>
    <div class="line"></div>
    <div class="data-list"
         v-infinite-scroll="loadBottom"
         :infinite-scroll-disabled="allLoaded"
         :infinite-scroll-distance="10">
      <template v-for="item in data.data">
        <div class="text-item" :key="item.key" @click="ToDetail(item.id, item.name)">
          <div class="item-title">{{ item.name }}</div>
          <div class="item-context">{{ item.keyWord }}</div>
        </div>
        <div class="line" :key="item.key"></div>
      </template>
    </div>
  </div>
</template>
<script>
import CustomSearch3 from "@/components/CustomSearch3";
import {GetDataList as Api_GetDataList} from "@/api/apilist";
export default {
  name: "list",
  components: {CustomSearch3},
  data() {
    return {
      dataType: 1,
      searchType: "title",
      searchName: "",
      data: {
        currentPage: 1,
        pageSize: 5,
        total: 0,
        data: []
      },
      allLoaded: false
    };
  },
  methods: {
    Search: function (searchType, searchName) {
      this.searchType = searchType;
      this.searchName = searchName;
      Api_GetDataList(this.dataType, searchType, searchName, 1, this.data.pageSize).then(res => {
        this.currentPage = res.currentPage;
        this.pageSize = res.pageSize;
        this.total = res.total;
        this.data = res;
      }, rej => {
        alert(rej);
      }).catch(err => {
        console.log(err);
        alert("错误的请求!");
      });
    },
    loadBottom: function () {
      Api_GetDataList(this.dataType, this.searchType, this.searchName, this.data.currentPage + 1, this.data.pageSize).then(res => {
        this.data.currentPage = res.currentPage;
        this.data.pageSize = res.pageSize;
        this.data.total = res.total;
        if (res.data.length > 0) {
          this.data.data = this.data.data.concat(res.data);
        }
        else{
          this.allLoaded = true;
        }
      }, rej => {
        alert(rej);
      }).catch(err => {
        console.log(err);
        alert("错误的请求!");
      });
    },
    ToDetail: function (id, name) {
      this.$router.push({name: "memory-detail", query: {id: id, name: name}})
    }
  },
  created() {
    this.Search("title", "");
  }
}
</script>
<style scoped>
li {
  list-style-type: none;
}
.list-root {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  align-items: center;
  width: 100%;
}
.search {
  width: 100%;
  margin-top: 3vh;
}
.search .custom-search3 {
  width: 90%;
  margin-left: 5%;
}
.line {
  width: 100%;
  border: 1px solid #EEEEEE;
  margin-top: 3vh;
  margin-bottom: 3vh;
  opacity: 1;
}
.data-list {
  width: 90%;
  height: 65vh;
  margin-left: 5%;
  overflow: scroll;
}
.data-list .line {
  width: 100%;
  margin-bottom: 2vh;
}
.data-list /deep/ .text-item {
  width: 90%;
  margin-bottom: 2vh;
}
.data-list /deep/ .text-item .item-title {
  text-align: left;
  font-size: 2rem;
  font-family: Source Han Serif CN;
  font-weight: bold;
  line-height: 4rem;
  color: #BC0000;
}
.data-list /deep/ .text-item .item-context {
  text-align: left;
  font-size: 1.62rem;
  font-family: Source Han Sans CN;
  font-weight: 400;
  line-height: 2rem;
  color: #767676;
  text-align: left;
}
</style>
src/views/personage/detail.vue
New file
@@ -0,0 +1,510 @@
<template>
  <div class="data-detail">
    <div class="title">
      <div class="title-left">
        <div class="title-name" @click="ToListPage">{{ titleName }}</div>
        <div class="title-introduce">{{ titleIntroduce }}</div>
      </div>
      <div class="title-right">
        <div class="online-preview" @click="OnlinePreview(basisInfo.file)">在线浏览</div>
      </div>
    </div>
    <div class="content">
      <mt-navbar ref="navbar" v-model="navbarIndex">
        <mt-tab-item id="1" data-type="1">基本信息</mt-tab-item>
        <mt-tab-item id="2" data-type="2">相关图片</mt-tab-item>
        <mt-tab-item id="3" data-type="3">相关视频</mt-tab-item>
      </mt-navbar>
      <mt-tab-container v-model="navbarIndex">
        <mt-tab-container-item id="1">
          <div class="content-keyword">
            <div class="item-name">关键字</div>
            {{ basisInfo.keyWord }}
          </div>
          <div class="content-introduction">
            <div class="item-name">简介</div>
            {{ basisInfo.introduction }}
          </div>
        </mt-tab-container-item>
        <mt-tab-container-item id="2">
          <CustomSearch3 v-on:search="SearchImages"></CustomSearch3>
          <div class="content-images"
               v-infinite-scroll="NextImages"
               :infinite-scroll-disabled="images.scrollDisabled"
               :infinite-scroll-distance="10">
            <div class="content-item"
                 v-for="item in images.data"
                 :key="item.id"
                 @click="ToImageDetail(item.id)">
              <div class="img-div">
                <img :src="item.path"/>
              </div>
              <div class="item-name">{{ item.name }}</div>
            </div>
          </div>
        </mt-tab-container-item>
        <mt-tab-container-item id="3">
          <CustomSearch3 v-on:search="SearchVideos"></CustomSearch3>
          <div class="content-videos"
               v-infinite-scroll="NextVideos"
               :infinite-scroll-disabled="videos.scrollDisabled"
               :infinite-scroll-distance="10">
            <div class="content-item"
                 v-for="item in videos.data"
                 :key="item.id"
                 @click="ToVideoDetail(item.id)">
              <div class="item-left">
                <img :src="item.cover"/>
              </div>
              <div class="item-right">
                <div class="item-name">{{ item.name }}</div>
                <div class="item-introduce">{{ item.description }}</div>
              </div>
            </div>
          </div>
        </mt-tab-container-item>
      </mt-tab-container>
    </div>
  </div>
</template>
<script>
import CustomSearch3 from "@/components/CustomSearch3";
import {
  GetDataDetail as Api_GetDataDetail,
  GetDataDetailImages as Api_GetDataDetailImages,
  GetDataDetailVideos as Api_GetDataDetailVideos,
} from "@/api/apilist";
export default {
  name: "detail",
  components: {CustomSearch3},
  data() {
    return {
      titleName: "",
      titleIntroduce: "",
      navbarIndex: "1",
      basisInfo: {
        id: "",
        keyWord: "",
        introduction: "",
        file: "",
      },
      images: {
        searchType: "title",
        searchName: "",
        pageSize: 10,
        currentPage: 1,
        total: 0,
        data: [],
        scrollDisabled: false,
      },
      videos: {
        searchType: "title",
        searchName: "",
        pageSize: 10,
        currentPage: 1,
        total: 0,
        data: [],
        scrollDisabled: false,
      },
    }
  },
  methods: {
    OnlinePreview: function (fileUrl) {
      if (fileUrl) {
        if (fileUrl.replace(/\\/g, '').toLowerCase().indexOf('.pdf') >= 0) {
          window.open(fileUrl);
        } else {
          //https://view.officeapps.live.com/op/view.aspx?src=
          window.open("http://www.xdocin.com/xdoc?_func=to&_format=html&_cache=1&_xdoc=" + fileUrl.replace(/\\/g, ''));
        }
      }
    },
    SearchBasisInfo: function (id) {
      Api_GetDataDetail(id).then(res => {
        this.basisInfo = res;
        this.titleIntroduce = res.keyWord;
      }, rej => {
        alert(rej);
      }).catch(err => {
        console.log(err);
        alert('错误的请求!');
      });
    },
    SearchImages: function (searchType, searchName) {
      this.images.searchType = searchType;
      this.images.searchName = searchName;
      Api_GetDataDetailImages(this.$route.query.id, searchType, searchName, 1, 10).then(res => {
        this.images.currentPage = res.currentPage;
        this.images.pageSize = res.pageSize;
        this.images.total = res.total;
        this.images.data = res.data;
      }, rej => {
        alert(rej);
      }).catch(err => {
        console.log(err);
        alert('错误的请求!');
      });
    },
    NextImages: function () {
      let searchType = this.images.searchType;
      let searchName = this.images.searchName;
      let currentPage = this.images.currentPage + 1;
      let pageSize = this.images.pageSize;
      Api_GetDataDetailImages(this.$route.query.id, searchType, searchName, currentPage, pageSize).then(res => {
        if (res.data.length > 0) {
          this.images.total = res.total;
          this.images.currentPage = res.currentPage;
          this.images.data = this.images.data.concat(res.data);
        }
      }, rej => {
        alert(rej);
      }).catch(err => {
        console.log(err);
        alert('错误的请求!');
      });
    },
    SearchVideos: function (searchType, searchName) {
      this.videos.searchType = searchType;
      this.videos.searchName = searchName;
      Api_GetDataDetailVideos(this.$route.query.id, searchType, searchName, 1, 10).then(res => {
        this.videos.currentPage = res.currentPage;
        this.videos.pageSize = res.pageSize;
        this.videos.total = res.total;
        this.videos.data = res.data;
      }, rej => {
        alert(rej);
      }).catch(err => {
        console.log(err);
        alert('错误的请求!');
      });
    },
    NextVideos: function () {
      let searchType = this.videos.searchType;
      let searchName = this.videos.searchName;
      let currentPage = this.videos.currentPage + 1;
      let pageSize = this.videos.pageSize;
      Api_GetDataDetailVideos(this.$route.query.id, searchType, searchName, currentPage, pageSize).then(res => {
        if (res.data.length > 0) {
          this.videos.total = res.total;
          this.videos.currentPage = res.currentPage;
          this.videos.data = this.videos.data.concat(res.data);
        }
      }, rej => {
        alert(rej);
      }).catch(err => {
        console.log(err);
        alert('错误的请求!');
      });
    },
    ToImageDetail: function (id) {
      let objId = this.$route.query.id;
      this.$router.push({name: "personage-detail-image", query: {id: id, objId: objId}});
    },
    ToVideoDetail: function (id) {
      let objId = this.$route.query.id;
      this.$router.push({name: "personage-detail-video", query: {id: id, objId: objId}});
    },
    ToListPage: function () {
      this.$router.push({name: "personage-list"})
    },
  },
  watch: {
    navbarIndex: function () {
      switch (this.navbarIndex) {
        case 1:
          this.images.scrollDisabled = true;
          this.videos.scrollDisabled = true;
          break;
        case 2:
          this.images.scrollDisabled = false;
          this.videos.scrollDisabled = true;
          break;
        case 3:
          this.images.scrollDisabled = true;
          this.videos.scrollDisabled = false;
          break;
      }
    }
  },
  created() {
    let id = this.$route.query.id;
    this.titleName = this.$route.query.name;
    this.SearchBasisInfo(id);
    this.SearchImages("title", "");
    this.SearchVideos("title", "");
  }
}
</script>
<style scoped>
.data-detail {
  width: 100%;
}
.data-detail .title {
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  height: 15.9vh;
  background: url("../../assets/datadetail/detail@1x.png") no-repeat 100% 100%;
  background-size: cover;
  border-radius: 10px 10px 0 0;
}
.data-detail .title .title-left {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-start;
  width: 60%;
  height: 100%;
  padding-left: 2vh;
}
.data-detail .title .title-name {
  width: 100%;
  text-align: left;
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
  font-size: 2.62rem;
  font-family: Source Han Serif CN;
  font-weight: bold;
  line-height: 5.24rem;
  color: #FFFFFF;
  opacity: 1;
}
.data-detail .title .title-introduce {
  width: 100%;
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
  font-size: 2rem;
  font-family: Source Han Sans CN;
  font-weight: 400;
  line-height: 3.37rem;
  color: #FFFFFF;
  opacity: 1;
}
.data-detail .title .title-right {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-start;
  width: 30%;
  height: 100%;
}
.data-detail .title .online-preview {
  width: 80%;
  background: #EFC587;
  opacity: 1;
  border-radius: 60px;
  font-size: 1.75rem;
  font-family: Source Han Sans CN;
  font-weight: bold;
  line-height: 3.87vh;
  color: #BC0000;
  opacity: 1;
}
.data-detail .content {
  width: 90%;
  height: 84.1vh;
  margin-left: 5%;
  border-radius: 30px;
}
.mint-navbar /deep/ .mint-tab-item-label {
  font-size: 2rem;
  font-family: Source Han Sans CN;
  font-weight: 500;
  line-height: 2rem;
  color: #767676;
  opacity: 1;
}
.mint-navbar /deep/ .is-selected {
  color: #BC0000;
  border-bottom: 0.3vh solid #BC0000;
}
.mint-navbar /deep/ .is-selected .mint-tab-item-label {
  color: #BC0000;
}
.mint-tab-container /deep/ .mint-tab-container-item:nth-child(1) {
  padding-top: 5vh;
}
.content-keyword {
  text-align: left;
  font-size: 1.87rem;
  font-family: Source Han Serif CN;
  font-weight: 400;
  line-height: 3rem;
  color: #767676;
  opacity: 1;
}
.content-keyword .item-name {
  text-align: left;
  font-size: 2rem;
  font-family: Source Han Sans CN;
  font-weight: bold;
  line-height: 6rem;
  color: #BC0000;
  opacity: 1;
}
.content-introduction {
  text-align: left;
  font-size: 1.87rem;
  font-family: Source Han Serif CN;
  font-weight: 400;
  line-height: 3rem;
  color: #767676;
  opacity: 1;
}
.content-introduction .item-name {
  text-align: left;
  font-size: 2rem;
  font-family: Source Han Sans CN;
  font-weight: bold;
  line-height: 6rem;
  color: #BC0000;
  opacity: 1;
}
.mint-tab-container /deep/ .mint-tab-container-item:nth-child(2) {
  padding-top: 2vh;
}
.custom-search3 {
  margin-bottom: 2vh;
}
.content-images {
  display: flex;
  flex-wrap: wrap;
  flex-direction: row;
  justify-content: flex-start;
  align-items: flex-start;
}
.content-images .content-item {
  width: 50%;
  height: 25vh;
}
.content-images .content-item .img-div {
  width: 90%;
  height: 80%;
  border-radius: 10px;
  box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.16);
}
.content-images .content-item .img-div img {
  width: 100%;
  height: 100%;
  border-radius: 10px;
  object-fit: cover;
}
.content-images .content-item .item-name {
  width: 90%;
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
  font-size: 2em;
  font-family: Source Han Serif CN;
  font-weight: bold;
  line-height: 2em;
  color: #333333;
  opacity: 1;
}
.mint-tab-container /deep/ .mint-tab-container-item:nth-child(3) {
  padding-top: 2vh;
}
.content-videos {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  align-items: center;
}
.content-videos .content-item {
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  justify-content: flex-start;
  align-items: center;
  height: 10vh;
  margin: 2vh auto;
}
.content-videos .item-left {
  width: 30%;
  height: 100%;
}
.content-videos .item-left img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.content-videos .item-right {
  width: 70%;
  height: 100%;
  padding-left: 2vw;
}
.content-videos .item-name {
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
  text-align: left;
  font-size: 2rem;
  font-family: Source Han Serif CN;
  font-weight: bold;
  line-height: 4rem;
  color: #BC0000;
  opacity: 1;
}
.content-videos .item-introduce {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  text-overflow: ellipsis;
  overflow: hidden;
  text-align: left;
  font-size: 1.62rem;
  font-family: Source Han Sans CN;
  font-weight: 400;
  line-height: 3rem;
  color: #767676;
  opacity: 1;
}
</style>
src/views/personage/detailImage.vue
New file
@@ -0,0 +1,133 @@
<template>
  <div class="data-detail-image">
    <div class="images">
      <mt-swipe :show-indicators="false" :auto="0" :continuous="false" @change="ChangeImage">
        <mt-swipe-item v-for="item in images.data" :key="item.key">
          <img :src="item.path"/>
        </mt-swipe-item>
      </mt-swipe>
    </div>
    <div class="content">
      <mt-navbar v-model="navIndex">
        <mt-tab-item id="1">关键词</mt-tab-item>
        <mt-tab-item id="2">简介</mt-tab-item>
      </mt-navbar>
      <mt-tab-container v-model="navIndex">
        <mt-tab-container-item id="1">
          {{ image.keyWord }}
        </mt-tab-container-item>
        <mt-tab-container-item id="2">
          {{ image.introduction }}
        </mt-tab-container-item>
      </mt-tab-container>
    </div>
  </div>
</template>
<script>
import {GetImageDetail as Api_GetImageDetail} from "@/api/apilist";
export default {
  name: "detailImage",
  data() {
    return {
      navIndex: "1",
      images: {
        pageSize: 10,
        currentPage: 1,
        total: 0,
        data: []
      },
      image: {
        id: "",
        name: "",
        path: "",
        keyWord: "",
        introduction: "",
      }
    }
  },
  methods: {
    ChangeImage: function (index) {
      this.image = this.images.data[index];
    },
  },
  created() {
    let imageId = this.$route.query.id;
    let objId = this.$route.query.objId;
    Api_GetImageDetail(imageId, 1, objId, 999).then(res => {
      this.images = res;
      this.image = res.data[0];
    }, rej => {
      alert(rej);
    }).catch(err => {
      console.log(err);
      alert('错误的请求!');
    });
  }
}
</script>
<style scoped>
.data-detail-image {
  width: 100%;
}
.images {
  width: 100%;
  height: 31.5vh;
}
.images img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.content {
  width: 100%;
  height: 66vh;
  box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.16);
  opacity: 1;
  border-radius: 10px;
  padding-top: 1vh;
}
.content > div{
  width: 90%;
  margin-left: 5%;
}
.mint-navbar{
  margin-bottom: 4vh;
}
.mint-navbar .mint-tab-item /deep/ .mint-tab-item-label {
  font-size: 2rem;
  font-family: Source Han Sans CN;
  font-weight: 500;
  line-height: 3rem;
  color: #767676;
  opacity: 1;
}
.mint-navbar .is-selected {
  border-bottom: 0.3rem solid #BC0000;
}
.mint-navbar .is-selected /deep/ .mint-tab-item-label {
  color: #BC0000;
  font-weight: bold;
}
.mint-tab-container {
  text-align: left;
  font-size: 1.87rem;
  font-family: Source Han Serif CN;
  font-weight: 400;
  line-height: 3rem;
  color: #585858;
  opacity: 1;
}
</style>
src/views/personage/detailvideo.vue
New file
@@ -0,0 +1,121 @@
<template>
  <div class="data-detail-video">
    <div class="videos">
      <video poster="" :src="video.patch" controls="controls">
        您的浏览器不支持 video 标签。
      </video>
    </div>
    <div class="content">
      <mt-navbar v-model="navIndex">
        <mt-tab-item id="1">关键词</mt-tab-item>
        <mt-tab-item id="2">简介</mt-tab-item>
      </mt-navbar>
      <mt-tab-container v-model="navIndex">
        <mt-tab-container-item id="1">
          {{ video.keyWord }}
        </mt-tab-container-item>
        <mt-tab-container-item id="2">
          {{ video.introduction }}
        </mt-tab-container-item>
      </mt-tab-container>
    </div>
  </div>
</template>
<script>
import {GetVideoDetail as Api_GetVideoDetail} from "@/api/apilist";
export default {
  name: "detailVideo",
  data() {
    return {
      navIndex: "1",
      video: {
        id: "",
        name: "",
        path: "",
        keyWord: "",
        introduction: "",
      },
    }
  },
  methods: {
  },
  created() {
    let id = this.$route.query.id;
    Api_GetVideoDetail(id).then(res => {
      this.video = res;
    }, rej => {
      alert(rej);
    }).catch(err => {
      console.log(err);
      alert('错误的请求!');
    });
  }
}
</script>
<style scoped>
.data-detail-video {
  width: 100%;
}
.videos {
  width: 100%;
  height: 31.5vh;
}
.videos video {
  width: 100%;
  height: 100%;
  background: black;
}
.content {
  width: 100%;
  height: 66vh;
  box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.16);
  opacity: 1;
  border-radius: 10px;
  padding-top: 1vh;
}
.content > div{
  width: 90%;
  margin-left: 5%;
}
.mint-navbar{
  margin-bottom: 4vh;
}
.mint-navbar .mint-tab-item /deep/ .mint-tab-item-label {
  font-size: 2rem;
  font-family: Source Han Sans CN;
  font-weight: 500;
  line-height: 3rem;
  color: #767676;
  opacity: 1;
}
.mint-navbar .is-selected {
  border-bottom: 0.3rem solid #BC0000;
}
.mint-navbar .is-selected /deep/ .mint-tab-item-label {
  color: #BC0000;
  font-weight: bold;
}
.mint-tab-container {
  text-align: left;
  font-size: 1.87rem;
  font-family: Source Han Serif CN;
  font-weight: 400;
  line-height: 3rem;
  color: #585858;
  opacity: 1;
}
</style>
src/views/personage/list.vue
New file
@@ -0,0 +1,190 @@
<template>
  <div class="list-root">
    <div class="search">
      <CustomSearch3 v-on:search="Search"></CustomSearch3>
    </div>
    <div class="line"></div>
    <div class="data-list"
         v-infinite-scroll="loadBottom"
         :infinite-scroll-disabled="allLoaded"
         :infinite-scroll-distance="10">
      <template v-for="item in data.data">
        <div class="image-item"
             :key="item.key"
             @click="ToDetail(item.id,item.name)">
          <div class="item-left">
            <img :src="item.img"/>
          </div>
          <div class="item-right">
            <div class="item-title">{{ item.name }}</div>
            <div class="item-context">{{ item.keyWord }}</div>
          </div>
        </div>
        <div :key="item.key" class="line"></div>
      </template>
    </div>
  </div>
</template>
<script>
import CustomSearch3 from "@/components/CustomSearch3";
import {GetDataList as Api_GetDataList} from "@/api/apilist";
export default {
  name: "list",
  components: {CustomSearch3},
  data() {
    return {
      dataType: 4,
      searchType: "title",
      searchName: "",
      data: {
        currentPage: 1,
        pageSize: 5,
        total: 0,
        data: []
      },
      allLoaded: false
    };
  },
  methods: {
    Search: function (searchType, searchName) {
      this.searchType = searchType;
      this.searchName = searchName;
      Api_GetDataList(this.dataType, searchType, searchName, 1, this.data.pageSize).then(res => {
        this.currentPage = res.currentPage;
        this.pageSize = res.pageSize;
        this.total = res.total;
        this.data = res;
      }, rej => {
        alert(rej);
      }).catch(err => {
        console.log(err);
        alert("错误的请求!");
      });
    },
    loadBottom: function () {
      Api_GetDataList(this.dataType, this.searchType, this.searchName, this.data.currentPage + 1, this.data.pageSize).then(res => {
        this.data.currentPage = res.currentPage;
        this.data.pageSize = res.pageSize;
        this.data.total = res.total;
        if (res.data.length > 0) {
          this.data.data = this.data.data.concat(res.data);
        } else {
          this.allLoaded = true;
        }
      }, rej => {
        alert(rej);
      }).catch(err => {
        console.log(err);
        alert("错误的请求!");
      });
    },
    ToDetail: function (id, name) {
      this.$router.push({name: "personage-detail", query: {id: id, name: name}})
    }
  },
  created() {
    this.Search("title", "");
  }
}
</script>
<style scoped>
li {
  list-style-type: none;
}
.list-root {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  align-items: center;
  width: 100%;
}
.search {
  width: 100%;
  margin-top: 3vh;
}
.search .custom-search3 {
  width: 90%;
  margin-left: 5%;
}
.line {
  width: 100%;
  border: 1px solid #EEEEEE;
  margin-top: 3vh;
  margin-bottom: 3vh;
  opacity: 1;
}
.data-list {
  width: 90%;
  height: 65vh;
  margin-left: 5%;
  overflow: scroll;
}
.data-list .line {
  width: 100%;
  margin-bottom: 2vh;
}
.data-list /deep/ .image-item {
  display: flex;
  flex-direction: row;
  justify-content: flex-start;
  align-items: flex-start;
  width: 100%;
  margin-bottom: 2vh;
}
.data-list /deep/ .image-item .item-left {
  width: 30%;
}
.data-list /deep/ .image-item .item-left img {
  width: 100%;
  height: 12vh;
  border-radius: 10px;
  object-fit: cover;
}
.data-list /deep/ .image-item .item-right {
  width: 70%;
}
.data-list /deep/ .image-item .item-title {
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
  padding-left: 2rem;
  text-align: left;
  font-size: 2rem;
  font-family: Source Han Serif CN;
  font-weight: bold;
  line-height: 4rem;
  color: #BC0000;
}
.data-list /deep/ .image-item .item-context {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  text-overflow: ellipsis;
  overflow: hidden;
  padding-left: 2rem;
  font-size: 1.62rem;
  font-family: Source Han Sans CN;
  font-weight: 400;
  line-height: 2rem;
  color: #767676;
  text-align: left;
}
</style>
src/views/scenery/detail.vue
New file
@@ -0,0 +1,510 @@
<template>
  <div class="data-detail">
    <div class="title">
      <div class="title-left">
        <div class="title-name" @click="ToListPage">{{ titleName }}</div>
        <div class="title-introduce">{{ titleIntroduce }}</div>
      </div>
      <div class="title-right">
        <div class="online-preview" @click="OnlinePreview(basisInfo.file)">在线浏览</div>
      </div>
    </div>
    <div class="content">
      <mt-navbar ref="navbar" v-model="navbarIndex">
        <mt-tab-item id="1" data-type="1">基本信息</mt-tab-item>
        <mt-tab-item id="2" data-type="2">相关图片</mt-tab-item>
        <mt-tab-item id="3" data-type="3">相关视频</mt-tab-item>
      </mt-navbar>
      <mt-tab-container v-model="navbarIndex">
        <mt-tab-container-item id="1">
          <div class="content-keyword">
            <div class="item-name">关键字</div>
            {{ basisInfo.keyWord }}
          </div>
          <div class="content-introduction">
            <div class="item-name">简介</div>
            {{ basisInfo.introduction }}
          </div>
        </mt-tab-container-item>
        <mt-tab-container-item id="2">
          <CustomSearch3 v-on:search="SearchImages"></CustomSearch3>
          <div class="content-images"
               v-infinite-scroll="NextImages"
               :infinite-scroll-disabled="images.scrollDisabled"
               :infinite-scroll-distance="10">
            <div class="content-item"
                 v-for="item in images.data"
                 :key="item.id"
                 @click="ToImageDetail(item.id)">
              <div class="img-div">
                <img :src="item.path"/>
              </div>
              <div class="item-name">{{ item.name }}</div>
            </div>
          </div>
        </mt-tab-container-item>
        <mt-tab-container-item id="3">
          <CustomSearch3 v-on:search="SearchVideos"></CustomSearch3>
          <div class="content-videos"
               v-infinite-scroll="NextVideos"
               :infinite-scroll-disabled="videos.scrollDisabled"
               :infinite-scroll-distance="10">
            <div class="content-item"
                 v-for="item in videos.data"
                 :key="item.id"
                 @click="ToVideoDetail(item.id)">
              <div class="item-left">
                <img :src="item.cover"/>
              </div>
              <div class="item-right">
                <div class="item-name">{{ item.name }}</div>
                <div class="item-introduce">{{ item.description }}</div>
              </div>
            </div>
          </div>
        </mt-tab-container-item>
      </mt-tab-container>
    </div>
  </div>
</template>
<script>
import CustomSearch3 from "@/components/CustomSearch3";
import {
  GetDataDetail as Api_GetDataDetail,
  GetDataDetailImages as Api_GetDataDetailImages,
  GetDataDetailVideos as Api_GetDataDetailVideos,
} from "@/api/apilist";
export default {
  name: "detail",
  components: {CustomSearch3},
  data() {
    return {
      titleName: "",
      titleIntroduce: "",
      navbarIndex: "1",
      basisInfo: {
        id: "",
        keyWord: "",
        introduction: "",
        file: "",
      },
      images: {
        searchType: "title",
        searchName: "",
        pageSize: 10,
        currentPage: 1,
        total: 0,
        data: [],
        scrollDisabled: false,
      },
      videos: {
        searchType: "title",
        searchName: "",
        pageSize: 10,
        currentPage: 1,
        total: 0,
        data: [],
        scrollDisabled: false,
      },
    }
  },
  methods: {
    OnlinePreview: function (fileUrl) {
      if (fileUrl) {
        if (fileUrl.replace(/\\/g, '').toLowerCase().indexOf('.pdf') >= 0) {
          window.open(fileUrl);
        } else {
          //https://view.officeapps.live.com/op/view.aspx?src=
          window.open("http://www.xdocin.com/xdoc?_func=to&_format=html&_cache=1&_xdoc=" + fileUrl.replace(/\\/g, ''));
        }
      }
    },
    SearchBasisInfo: function (id) {
      Api_GetDataDetail(id).then(res => {
        this.basisInfo = res;
        this.titleIntroduce = res.keyWord;
      }, rej => {
        alert(rej);
      }).catch(err => {
        console.log(err);
        alert('错误的请求!');
      });
    },
    SearchImages: function (searchType, searchName) {
      this.images.searchType = searchType;
      this.images.searchName = searchName;
      Api_GetDataDetailImages(this.$route.query.id, searchType, searchName, 1, 10).then(res => {
        this.images.currentPage = res.currentPage;
        this.images.pageSize = res.pageSize;
        this.images.total = res.total;
        this.images.data = res.data;
      }, rej => {
        alert(rej);
      }).catch(err => {
        console.log(err);
        alert('错误的请求!');
      });
    },
    NextImages: function () {
      let searchType = this.images.searchType;
      let searchName = this.images.searchName;
      let currentPage = this.images.currentPage + 1;
      let pageSize = this.images.pageSize;
      Api_GetDataDetailImages(this.$route.query.id, searchType, searchName, currentPage, pageSize).then(res => {
        if (res.data.length > 0) {
          this.images.total = res.total;
          this.images.currentPage = res.currentPage;
          this.images.data = this.images.data.concat(res.data);
        }
      }, rej => {
        alert(rej);
      }).catch(err => {
        console.log(err);
        alert('错误的请求!');
      });
    },
    SearchVideos: function (searchType, searchName) {
      this.videos.searchType = searchType;
      this.videos.searchName = searchName;
      Api_GetDataDetailVideos(this.$route.query.id, searchType, searchName, 1, 10).then(res => {
        this.videos.currentPage = res.currentPage;
        this.videos.pageSize = res.pageSize;
        this.videos.total = res.total;
        this.videos.data = res.data;
      }, rej => {
        alert(rej);
      }).catch(err => {
        console.log(err);
        alert('错误的请求!');
      });
    },
    NextVideos: function () {
      let searchType = this.videos.searchType;
      let searchName = this.videos.searchName;
      let currentPage = this.videos.currentPage + 1;
      let pageSize = this.videos.pageSize;
      Api_GetDataDetailVideos(this.$route.query.id, searchType, searchName, currentPage, pageSize).then(res => {
        if (res.data.length > 0) {
          this.videos.total = res.total;
          this.videos.currentPage = res.currentPage;
          this.videos.data = this.videos.data.concat(res.data);
        }
      }, rej => {
        alert(rej);
      }).catch(err => {
        console.log(err);
        alert('错误的请求!');
      });
    },
    ToImageDetail: function (id) {
      let objId = this.$route.query.id;
      this.$router.push({name: "scenery-detail-image", query: {id: id, objId: objId}});
    },
    ToVideoDetail: function (id) {
      let objId = this.$route.query.id;
      this.$router.push({name: "scenery-detail-video", query: {id: id, objId: objId}});
    },
    ToListPage: function () {
      this.$router.push({name: "scenery-list"})
    },
  },
  watch: {
    navbarIndex: function () {
      switch (this.navbarIndex) {
        case 1:
          this.images.scrollDisabled = true;
          this.videos.scrollDisabled = true;
          break;
        case 2:
          this.images.scrollDisabled = false;
          this.videos.scrollDisabled = true;
          break;
        case 3:
          this.images.scrollDisabled = true;
          this.videos.scrollDisabled = false;
          break;
      }
    }
  },
  created() {
    let id = this.$route.query.id;
    this.titleName = this.$route.query.name;
    this.SearchBasisInfo(id);
    this.SearchImages("title", "");
    this.SearchVideos("title", "");
  }
}
</script>
<style scoped>
.data-detail {
  width: 100%;
}
.data-detail .title {
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  height: 15.9vh;
  background: url("../../assets/datadetail/detail@1x.png") no-repeat 100% 100%;
  background-size: cover;
  border-radius: 10px 10px 0 0;
}
.data-detail .title .title-left {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-start;
  width: 60%;
  height: 100%;
  padding-left: 2vh;
}
.data-detail .title .title-name {
  width: 100%;
  text-align: left;
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
  font-size: 2.62rem;
  font-family: Source Han Serif CN;
  font-weight: bold;
  line-height: 5.24rem;
  color: #FFFFFF;
  opacity: 1;
}
.data-detail .title .title-introduce {
  width: 100%;
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
  font-size: 2rem;
  font-family: Source Han Sans CN;
  font-weight: 400;
  line-height: 3.37rem;
  color: #FFFFFF;
  opacity: 1;
}
.data-detail .title .title-right {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-start;
  width: 30%;
  height: 100%;
}
.data-detail .title .online-preview {
  width: 80%;
  background: #EFC587;
  opacity: 1;
  border-radius: 60px;
  font-size: 1.75rem;
  font-family: Source Han Sans CN;
  font-weight: bold;
  line-height: 3.87vh;
  color: #BC0000;
  opacity: 1;
}
.data-detail .content {
  width: 90%;
  height: 84.1vh;
  margin-left: 5%;
  border-radius: 30px;
}
.mint-navbar /deep/ .mint-tab-item-label {
  font-size: 2rem;
  font-family: Source Han Sans CN;
  font-weight: 500;
  line-height: 2rem;
  color: #767676;
  opacity: 1;
}
.mint-navbar /deep/ .is-selected {
  color: #BC0000;
  border-bottom: 0.3vh solid #BC0000;
}
.mint-navbar /deep/ .is-selected .mint-tab-item-label {
  color: #BC0000;
}
.mint-tab-container /deep/ .mint-tab-container-item:nth-child(1) {
  padding-top: 5vh;
}
.content-keyword {
  text-align: left;
  font-size: 1.87rem;
  font-family: Source Han Serif CN;
  font-weight: 400;
  line-height: 3rem;
  color: #767676;
  opacity: 1;
}
.content-keyword .item-name {
  text-align: left;
  font-size: 2rem;
  font-family: Source Han Sans CN;
  font-weight: bold;
  line-height: 6rem;
  color: #BC0000;
  opacity: 1;
}
.content-introduction {
  text-align: left;
  font-size: 1.87rem;
  font-family: Source Han Serif CN;
  font-weight: 400;
  line-height: 3rem;
  color: #767676;
  opacity: 1;
}
.content-introduction .item-name {
  text-align: left;
  font-size: 2rem;
  font-family: Source Han Sans CN;
  font-weight: bold;
  line-height: 6rem;
  color: #BC0000;
  opacity: 1;
}
.mint-tab-container /deep/ .mint-tab-container-item:nth-child(2) {
  padding-top: 2vh;
}
.custom-search3 {
  margin-bottom: 2vh;
}
.content-images {
  display: flex;
  flex-wrap: wrap;
  flex-direction: row;
  justify-content: flex-start;
  align-items: flex-start;
}
.content-images .content-item {
  width: 50%;
  height: 25vh;
}
.content-images .content-item .img-div {
  width: 90%;
  height: 80%;
  border-radius: 10px;
  box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.16);
}
.content-images .content-item .img-div img {
  width: 100%;
  height: 100%;
  border-radius: 10px;
  object-fit: cover;
}
.content-images .content-item .item-name {
  width: 90%;
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
  font-size: 2em;
  font-family: Source Han Serif CN;
  font-weight: bold;
  line-height: 2em;
  color: #333333;
  opacity: 1;
}
.mint-tab-container /deep/ .mint-tab-container-item:nth-child(3) {
  padding-top: 2vh;
}
.content-videos {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  align-items: center;
}
.content-videos .content-item {
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  justify-content: flex-start;
  align-items: center;
  height: 10vh;
  margin: 2vh auto;
}
.content-videos .item-left {
  width: 30%;
  height: 100%;
}
.content-videos .item-left img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.content-videos .item-right {
  width: 70%;
  height: 100%;
  padding-left: 2vw;
}
.content-videos .item-name {
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
  text-align: left;
  font-size: 2rem;
  font-family: Source Han Serif CN;
  font-weight: bold;
  line-height: 4rem;
  color: #BC0000;
  opacity: 1;
}
.content-videos .item-introduce {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  text-overflow: ellipsis;
  overflow: hidden;
  text-align: left;
  font-size: 1.62rem;
  font-family: Source Han Sans CN;
  font-weight: 400;
  line-height: 3rem;
  color: #767676;
  opacity: 1;
}
</style>
src/views/scenery/detailImage.vue
New file
@@ -0,0 +1,133 @@
<template>
  <div class="data-detail-image">
    <div class="images">
      <mt-swipe :show-indicators="false" :auto="0" :continuous="false" @change="ChangeImage">
        <mt-swipe-item v-for="item in images.data" :key="item.key">
          <img :src="item.path"/>
        </mt-swipe-item>
      </mt-swipe>
    </div>
    <div class="content">
      <mt-navbar v-model="navIndex">
        <mt-tab-item id="1">关键词</mt-tab-item>
        <mt-tab-item id="2">简介</mt-tab-item>
      </mt-navbar>
      <mt-tab-container v-model="navIndex">
        <mt-tab-container-item id="1">
          {{ image.keyWord }}
        </mt-tab-container-item>
        <mt-tab-container-item id="2">
          {{ image.introduction }}
        </mt-tab-container-item>
      </mt-tab-container>
    </div>
  </div>
</template>
<script>
import {GetImageDetail as Api_GetImageDetail} from "@/api/apilist";
export default {
  name: "detailImage",
  data() {
    return {
      navIndex: "1",
      images: {
        pageSize: 10,
        currentPage: 1,
        total: 0,
        data: []
      },
      image: {
        id: "",
        name: "",
        path: "",
        keyWord: "",
        introduction: "",
      }
    }
  },
  methods: {
    ChangeImage: function (index) {
      this.image = this.images.data[index];
    },
  },
  created() {
    let imageId = this.$route.query.id;
    let objId = this.$route.query.objId;
    Api_GetImageDetail(imageId, 1, objId, 999).then(res => {
      this.images = res;
      this.image = res.data[0];
    }, rej => {
      alert(rej);
    }).catch(err => {
      console.log(err);
      alert('错误的请求!');
    });
  }
}
</script>
<style scoped>
.data-detail-image {
  width: 100%;
}
.images {
  width: 100%;
  height: 31.5vh;
}
.images img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.content {
  width: 100%;
  height: 66vh;
  box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.16);
  opacity: 1;
  border-radius: 10px;
  padding-top: 1vh;
}
.content > div{
  width: 90%;
  margin-left: 5%;
}
.mint-navbar{
  margin-bottom: 4vh;
}
.mint-navbar .mint-tab-item /deep/ .mint-tab-item-label {
  font-size: 2rem;
  font-family: Source Han Sans CN;
  font-weight: 500;
  line-height: 3rem;
  color: #767676;
  opacity: 1;
}
.mint-navbar .is-selected {
  border-bottom: 0.3rem solid #BC0000;
}
.mint-navbar .is-selected /deep/ .mint-tab-item-label {
  color: #BC0000;
  font-weight: bold;
}
.mint-tab-container {
  text-align: left;
  font-size: 1.87rem;
  font-family: Source Han Serif CN;
  font-weight: 400;
  line-height: 3rem;
  color: #585858;
  opacity: 1;
}
</style>
src/views/scenery/detailvideo.vue
New file
@@ -0,0 +1,121 @@
<template>
  <div class="data-detail-video">
    <div class="videos">
      <video poster="" :src="video.patch" controls="controls">
        您的浏览器不支持 video 标签。
      </video>
    </div>
    <div class="content">
      <mt-navbar v-model="navIndex">
        <mt-tab-item id="1">关键词</mt-tab-item>
        <mt-tab-item id="2">简介</mt-tab-item>
      </mt-navbar>
      <mt-tab-container v-model="navIndex">
        <mt-tab-container-item id="1">
          {{ video.keyWord }}
        </mt-tab-container-item>
        <mt-tab-container-item id="2">
          {{ video.introduction }}
        </mt-tab-container-item>
      </mt-tab-container>
    </div>
  </div>
</template>
<script>
import {GetVideoDetail as Api_GetVideoDetail} from "@/api/apilist";
export default {
  name: "detailVideo",
  data() {
    return {
      navIndex: "1",
      video: {
        id: "",
        name: "",
        path: "",
        keyWord: "",
        introduction: "",
      },
    }
  },
  methods: {
  },
  created() {
    let id = this.$route.query.id;
    Api_GetVideoDetail(id).then(res => {
      this.video = res;
    }, rej => {
      alert(rej);
    }).catch(err => {
      console.log(err);
      alert('错误的请求!');
    });
  }
}
</script>
<style scoped>
.data-detail-video {
  width: 100%;
}
.videos {
  width: 100%;
  height: 31.5vh;
}
.videos video {
  width: 100%;
  height: 100%;
  background: black;
}
.content {
  width: 100%;
  height: 66vh;
  box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.16);
  opacity: 1;
  border-radius: 10px;
  padding-top: 1vh;
}
.content > div{
  width: 90%;
  margin-left: 5%;
}
.mint-navbar{
  margin-bottom: 4vh;
}
.mint-navbar .mint-tab-item /deep/ .mint-tab-item-label {
  font-size: 2rem;
  font-family: Source Han Sans CN;
  font-weight: 500;
  line-height: 3rem;
  color: #767676;
  opacity: 1;
}
.mint-navbar .is-selected {
  border-bottom: 0.3rem solid #BC0000;
}
.mint-navbar .is-selected /deep/ .mint-tab-item-label {
  color: #BC0000;
  font-weight: bold;
}
.mint-tab-container {
  text-align: left;
  font-size: 1.87rem;
  font-family: Source Han Serif CN;
  font-weight: 400;
  line-height: 3rem;
  color: #585858;
  opacity: 1;
}
</style>
src/views/scenery/list.vue
New file
@@ -0,0 +1,190 @@
<template>
  <div class="list-root">
    <div class="search">
      <CustomSearch3 v-on:search="Search"></CustomSearch3>
    </div>
    <div class="line"></div>
    <div class="data-list"
         v-infinite-scroll="loadBottom"
         :infinite-scroll-disabled="allLoaded"
         :infinite-scroll-distance="10">
      <template v-for="item in data.data">
        <div class="image-item"
             :key="item.key"
             @click="ToDetail(item.id,item.name)">
          <div class="item-left">
            <img :src="item.img"/>
          </div>
          <div class="item-right">
            <div class="item-title">{{ item.name }}</div>
            <div class="item-context">{{ item.keyWord }}</div>
          </div>
        </div>
        <div :key="item.key" class="line"></div>
      </template>
    </div>
  </div>
</template>
<script>
import CustomSearch3 from "@/components/CustomSearch3";
import {GetDataList as Api_GetDataList} from "@/api/apilist";
export default {
  name: "list",
  components: {CustomSearch3},
  data() {
    return {
      dataType: 3,
      searchType: "title",
      searchName: "",
      data: {
        currentPage: 1,
        pageSize: 10,
        total: 0,
        data: []
      },
      allLoaded: false
    };
  },
  methods: {
    Search: function (searchType, searchName) {
      this.searchType = searchType;
      this.searchName = searchName;
      Api_GetDataList(this.dataType, searchType, searchName, 1, this.data.pageSize).then(res => {
        this.currentPage = res.currentPage;
        this.pageSize = res.pageSize;
        this.total = res.total;
        this.data = res;
      }, rej => {
        alert(rej);
      }).catch(err => {
        console.log(err);
        alert("错误的请求!");
      });
    },
    loadBottom: function () {
      Api_GetDataList(this.dataType, this.searchType, this.searchName, this.data.currentPage + 1, this.data.pageSize).then(res => {
        this.data.currentPage = res.currentPage;
        this.data.pageSize = res.pageSize;
        this.data.total = res.total;
        if (res.data.length > 0) {
          this.data.data = this.data.data.concat(res.data);
        } else {
          //加载完全部数据,上拉加载事件将不再执行
          this.allLoaded = false;
        }
      }, rej => {
        alert(rej);
      }).catch(err => {
        console.log(err);
        alert("错误的请求!");
      });
    },
    ToDetail: function (id, name) {
      this.$router.push({name: "scenery-detail", query: {id: id, name: name}})
    }
  },
  created() {
    this.Search("title", "");
  }
}
</script>
<style scoped>
li {
  list-style-type: none;
}
.list-root {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  align-items: center;
  width: 100%;
}
.search {
  width: 100%;
  margin-top: 3vh;
}
.search .custom-search3 {
  width: 90%;
  margin-left: 5%;
}
.line {
  width: 100%;
  border: 1px solid #EEEEEE;
  margin-top: 3vh;
  margin-bottom: 3vh;
  opacity: 1;
}
.data-list {
  width: 90%;
  margin-left: 5%;
  overflow: scroll;
}
.data-list .line {
  width: 100%;
  margin-bottom: 2vh;
}
.data-list /deep/ .image-item {
  display: flex;
  flex-direction: row;
  justify-content: flex-start;
  align-items: flex-start;
  width: 100%;
  margin-bottom: 2vh;
}
.data-list /deep/ .image-item .item-left {
  width: 30%;
}
.data-list /deep/ .image-item .item-left img {
  width: 100%;
  height: 12vh;
  border-radius: 10px;
  object-fit: cover;
}
.data-list /deep/ .image-item .item-right {
  width: 70%;
}
.data-list /deep/ .image-item .item-title {
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
  padding-left: 2rem;
  text-align: left;
  font-size: 2rem;
  font-family: Source Han Serif CN;
  font-weight: bold;
  line-height: 4rem;
  color: #BC0000;
}
.data-list /deep/ .image-item .item-context {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  text-overflow: ellipsis;
  overflow: hidden;
  padding-left: 2rem;
  font-size: 1.62rem;
  font-family: Source Han Sans CN;
  font-weight: 400;
  line-height: 2rem;
  color: #767676;
  text-align: left;
}
</style>
src/views/search/index.vue
New file
@@ -0,0 +1,175 @@
<template>
  <div class="search-index">
    <div class="index-title1">热门搜索</div>
    <div class="index-hot">
      <div v-for="item in hotList" :key="item.id" @click="SearchHot(item)">
        {{ item.title }}
      </div>
    </div>
    <div class="index-title2">
      历史搜索
      <span class="remove-btn" @click="ClearHis">清除</span>
    </div>
    <div class="index-history">
      <template v-for="item in historyList">
        <div class="search-msg" :key="item.key" @click="SearchHis(item)">
          <svg t="1639023179293" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
               p-id="6665" width="200" height="200">
            <path
                d="M512 160c194.410667 0 352 157.589333 352 352S706.410667 864 512 864l-2.538667-0.106667c-91.477333-7.274667-165.738667-38.08-221.44-91.989333L288 842.666667h-64V640H405.333333v64h-92.842666c46.250667 56.917333 112.490667 88.725333 200.768 96l6.677333-0.106667C675.328 795.690667 800 668.394667 800 512c0-159.061333-128.938667-288-288-288S224 352.938667 224 512h-64c0-194.410667 157.589333-352 352-352zM469.333333 320h64v160h160v64H469.333333V320z"
                p-id="6666" fill="#C7C7C7"></path>
          </svg>
          <span>{{ item.searchName }}</span>
        </div>
        <div class="line" :key="item.key"></div>
      </template>
    </div>
  </div>
</template>
<script>
import {
  GetSearchHomeInfo as Api_GetSearchHomeInfo,
} from '@/api/apilist'
export default {
  name: "index",
  data() {
    return {
      hotList: [],
      historyList: [],
    }
  },
  methods: {
    SearchHot(item) {
      console.log(item);
      this.$router.push({
        name: "search-results",
        query: {searchType: "title", searchName: item.title, type: item.type}
      });
    },
    SearchHis(item) {
      this.$router.push({
        name: "search-results",
        query: {searchType: item.searchType, searchName: item.searchName}
      });
    },
    ClearHis() {
      localStorage.clear();
      this.historyList = [];
    }
  },
  created() {
    Api_GetSearchHomeInfo().then(res => {
      this.hotList = res.rmtj;
    }, rej => {
      alert(rej);
    }).catch(err => {
      console.log(err);
      alert("请求错误!");
    });
    if (localStorage.searchHistory) {
      this.historyList = eval(localStorage.searchHistory).reverse();
    }
  }
}
</script>
<style scoped>
.search-index {
  width: 90%;
  margin-left: 5%;
}
.index-title1 {
  text-align: left;
  font-size: 1.87rem;
  font-family: Source Han Serif CN;
  font-weight: bold;
  line-height: 5.87rem;
  color: #BC0000;
  opacity: 1;
}
.index-hot {
  display: flex;
  flex-wrap: wrap;
  flex-direction: row;
  justify-content: flex-start;
  align-items: flex-start;
}
.index-hot > div {
  width: 30%;
  border: 1px solid #999999;
  border-radius: 140px;
  margin-right: 3%;
  margin-bottom: 2vh;
  cursor: pointer;
  font-size: 1.62rem;
  font-family: Source Han Sans CN;
  font-weight: 400;
  line-height: 3.37rem;
  color: #767676;
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
}
.index-hot > div:first-child {
  border: 0;
  color: #FFFFFF;
  background: #BC0000;
}
.index-title2 {
  text-align: left;
  font-size: 1.75rem;
  font-family: Source Han Serif CN;
  font-weight: bold;
  line-height: 5.87rem;
  color: #333333;
}
.index-title2 .remove-btn {
  float: right;
  font-size: 1.5rem;
  font-family: Source Han Serif CN;
  font-weight: 400;
  line-height: 5.87rem;
  color: #767676;
  cursor: pointer;
}
.index-history .search-msg {
  display: flex;
  flex-direction: row;
  justify-content: flex-start;
  align-items: center;
  font-size: 1.62rem;
  font-family: Source Han Sans CN;
  font-weight: 400;
  line-height: 3.37rem;
  color: #999999;
}
.search-msg span {
  cursor: pointer;
}
.search-msg svg {
  width: 3vh;
  height: 3vh;
  margin-right: 1vh;
  cursor: pointer;
}
.index-history .line {
  border: 1px solid #E4E4E4;
  margin-top: 1vh;
  margin-bottom: 1vh;
}
</style>
src/views/search/results.vue
New file
@@ -0,0 +1,268 @@
<template>
  <div class="search-results">
    <div class="results-title">搜索结果</div>
    <div class="results-list">
      <navbar ref="navbar" v-model="type">
        <tab-item id="1" data-type="1">红色记忆</tab-item>
        <tab-item id="2" data-type="2">红色精神</tab-item>
        <tab-item id="3" data-type="3">红色景区</tab-item>
        <tab-item id="4" data-type="4">红色人物</tab-item>
      </navbar>
      <tab-container v-model="type">
        <tab-container-item id="1">
          <template v-for="item in searchItems.hsjy.data">
            <div class="text-item" :key="item.key" @click="ToMemoryDetail(item.id,item.name)">
              <div class="item-title">{{ item.name }}</div>
              <div class="item-context">{{ item.keyWord }}</div>
            </div>
            <div class="line" :key="item.key"></div>
          </template>
        </tab-container-item>
        <tab-container-item id="2">
          <template v-for="item in searchItems.hsjs.data">
            <div class="text-item" :key="item.key" @click="ToSpiritDetail(item.id,item.name)">
              <div class="item-title">{{ item.name }}</div>
              <div class="item-context">{{ item.keyWord }}</div>
            </div>
            <div class="line" :key="item.key"></div>
          </template>
        </tab-container-item>
        <tab-container-item id="3">
          <template v-for="item in searchItems.hsjq.data">
            <div class="image-item" :key="item.key" @click="ToSceneryDetail(item.id,item.name)">
              <div class="item-left">
                <img :src="item.img"/>
              </div>
              <div class="item-right">
                <div class="item-title">{{ item.name }}</div>
                <div class="item-context">{{ item.keyWord }}</div>
              </div>
            </div>
            <div class="line" :key="item.key"></div>
          </template>
        </tab-container-item>
        <tab-container-item id="4">
          <template v-for="item in searchItems.hsrw.data">
            <div class="image-item" :key="item.key" @click="ToPersonageDetail(item.id,item.name)">
              <div class="item-left">
                <img :src="item.img"/>
              </div>
              <div class="item-right">
                <div class="item-title">{{ item.name }}</div>
                <div class="item-context">{{ item.keyWord }}</div>
              </div>
            </div>
            <div class="line" :key="item.key"></div>
          </template>
        </tab-container-item>
      </tab-container>
    </div>
  </div>
</template>
<script>
import {Navbar, TabItem, TabContainer, TabContainerItem} from 'mint-ui';
import {
  GetSearchInfo as Api_GetSearchInfo,
} from '@/api/apilist'
export default {
  name: "results",
  components: {Navbar, TabItem, TabContainer, TabContainerItem},
  data() {
    return {
      type: "1",
      searchItems: [],
    };
  },
  methods: {
    ToMemoryDetail: function (id, name) {
      this.$router.push({name: "memory-detail", query: {id: id, name: name}});
    },
    ToPersonageDetail: function (id, name) {
      this.$router.push({name: "personage-detail", query: {id: id, name: name}});
    },
    ToSceneryDetail: function (id, name) {
      this.$router.push({name: "scenery-detail", query: {id: id, name: name}});
    },
    ToSpiritDetail: function (id, name) {
      this.$router.push({name: "spirit-detail", query: {id: id, name: name}});
    },
  },
  watch: {},
  created: function () {
    let searchType = this.$route.query.searchType;
    let searchName = this.$route.query.searchName;
    let type = this.$route.query.type;
    if (type) {
      this.type = type.toString();
    }
    Api_GetSearchInfo(searchType, searchName).then(res => {
      this.searchItems = res;
    }, rej => {
      alert(rej);
    }).catch(err => {
      console.log(err);
      alert("请求错误!");
    });
  },
  beforeRouteUpdate(to, from, next) {
    if (to.fullPath != from.fullPath) {
      let searchType = to.query.searchType
      let searchName = to.query.searchName;
      let type = to.query.type;
      if (type) {
        this.type = type.toString();
      }
      Api_GetSearchInfo(searchType, searchName).then(res => {
        this.searchItems = [];
        this.searchItems = res;
      }, rej => {
        alert(rej);
      }).catch(err => {
        console.log(err);
        alert("请求错误!");
      });
    }
    next();
  },
}
</script>
<style scoped>
.search-results {
  width: 90%;
  margin-left: 5%;
}
.results-title {
  text-align: left;
  font-size: 1.87rem;
  font-family: Source Han Serif CN;
  font-weight: bold;
  line-height: 5.87rem;
  color: #767676;
  opacity: 1;
}
.search-results .mint-navbar {
  margin-bottom: 2vh;
}
.search-results .mint-navbar .mint-tab-item /deep/ .mint-tab-item-label {
  font-size: 1.62rem;
  font-family: Source Han Sans CN;
  font-weight: 400;
  line-height: 1.93rem;
  color: #767676;
  opacity: 1;
  cursor: pointer
}
.search-results .mint-navbar .is-selected {
  border-bottom: 2px solid #BC0000;
}
.search-results .mint-navbar .is-selected /deep/ .mint-tab-item-label {
  color: #BC0000;
}
.search-results .mint-tab-container {
}
.search-results .mint-tab-container .mint-tab-container-item {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  align-items: center;
}
.search-results .mint-tab-container .mint-tab-container-item .line {
  width: 100%;
  border: 1px solid #EEEEEE;
  margin-bottom: 2vh;
}
.search-results .mint-tab-container .mint-tab-container-item .text-item {
  width: 90%;
  margin-bottom: 2vh;
}
.search-results .mint-tab-container .mint-tab-container-item .text-item .item-title {
  text-align: left;
  font-size: 2rem;
  font-family: Source Han Sans CN;
  font-weight: 500;
  line-height: 4rem;
  color: #BC0000;
  opacity: 1;
}
.search-results .mint-tab-container .mint-tab-container-item .text-item .item-context {
  text-align: left;
  font-size: 1.5rem;
  font-family: Source Han Sans CN;
  font-weight: 400;
  line-height: 2.5rem;
  color: #9B9B9B;
  opacity: 1;
}
.search-results .mint-tab-container .mint-tab-container-item .image-item {
  display: flex;
  flex-direction: row;
  justify-content: flex-start;
  align-items: flex-start;
  width: 90%;
  margin-bottom: 2vh;
}
.search-results .mint-tab-container .mint-tab-container-item .image-item .item-left {
  width: 30%;
}
.search-results .mint-tab-container .mint-tab-container-item .image-item .item-left img {
  width: 100%;
  height: 10vh;
  border-radius: 10px;
  object-fit: cover;
}
.search-results .mint-tab-container .mint-tab-container-item .image-item .item-right {
  width: 70%;
}
.search-results .mint-tab-container .mint-tab-container-item .image-item .item-title {
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
  padding-left: 4vw;
  font-size: 2rem;
  font-family: Source Han Serif CN;
  font-weight: bold;
  line-height: 4rem;
  color: #BC0000;
  text-align: left;
}
.search-results .mint-tab-container .mint-tab-container-item .image-item .item-context {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  text-overflow: ellipsis;
  overflow: hidden;
  padding-left: 4vw;
  font-size: 1.62rem;
  font-family: Source Han Sans CN;
  font-weight: 400;
  line-height: 2rem;
  color: #767676;
  text-align: left;
}
</style>
src/views/spirit/detail.vue
New file
@@ -0,0 +1,510 @@
<template>
  <div class="data-detail">
    <div class="title">
      <div class="title-left">
        <div class="title-name" @click="ToListPage">{{ titleName }}</div>
        <div class="title-introduce">{{ titleIntroduce }}</div>
      </div>
      <div class="title-right">
        <div class="online-preview" @click="OnlinePreview(basisInfo.file)">在线浏览</div>
      </div>
    </div>
    <div class="content">
      <mt-navbar ref="navbar" v-model="navbarIndex">
        <mt-tab-item id="1" data-type="1">基本信息</mt-tab-item>
        <mt-tab-item id="2" data-type="2">相关图片</mt-tab-item>
        <mt-tab-item id="3" data-type="3">相关视频</mt-tab-item>
      </mt-navbar>
      <mt-tab-container v-model="navbarIndex">
        <mt-tab-container-item id="1">
          <div class="content-keyword">
            <div class="item-name">关键字</div>
            {{ basisInfo.keyWord }}
          </div>
          <div class="content-introduction">
            <div class="item-name">简介</div>
            {{ basisInfo.introduction }}
          </div>
        </mt-tab-container-item>
        <mt-tab-container-item id="2">
          <CustomSearch3 v-on:search="SearchImages"></CustomSearch3>
          <div class="content-images"
               v-infinite-scroll="NextImages"
               :infinite-scroll-disabled="images.scrollDisabled"
               :infinite-scroll-distance="10">
            <div class="content-item"
                 v-for="item in images.data"
                 :key="item.id"
                 @click="ToImageDetail(item.id)">
              <div class="img-div">
                <img :src="item.path"/>
              </div>
              <div class="item-name">{{ item.name }}</div>
            </div>
          </div>
        </mt-tab-container-item>
        <mt-tab-container-item id="3">
          <CustomSearch3 v-on:search="SearchVideos"></CustomSearch3>
          <div class="content-videos"
               v-infinite-scroll="NextVideos"
               :infinite-scroll-disabled="videos.scrollDisabled"
               :infinite-scroll-distance="10">
            <div class="content-item"
                 v-for="item in videos.data"
                 :key="item.id"
                 @click="ToVideoDetail(item.id)">
              <div class="item-left">
                <img :src="item.cover"/>
              </div>
              <div class="item-right">
                <div class="item-name">{{ item.name }}</div>
                <div class="item-introduce">{{ item.description }}</div>
              </div>
            </div>
          </div>
        </mt-tab-container-item>
      </mt-tab-container>
    </div>
  </div>
</template>
<script>
import CustomSearch3 from "@/components/CustomSearch3";
import {
  GetDataDetail as Api_GetDataDetail,
  GetDataDetailImages as Api_GetDataDetailImages,
  GetDataDetailVideos as Api_GetDataDetailVideos,
} from "@/api/apilist";
export default {
  name: "detail",
  components: {CustomSearch3},
  data() {
    return {
      titleName: "",
      titleIntroduce: "",
      navbarIndex: "1",
      basisInfo: {
        id: "",
        keyWord: "",
        introduction: "",
        file: "",
      },
      images: {
        searchType: "title",
        searchName: "",
        pageSize: 10,
        currentPage: 1,
        total: 0,
        data: [],
        scrollDisabled: false,
      },
      videos: {
        searchType: "title",
        searchName: "",
        pageSize: 10,
        currentPage: 1,
        total: 0,
        data: [],
        scrollDisabled: false,
      },
    }
  },
  methods: {
    OnlinePreview: function (fileUrl) {
      if (fileUrl) {
        if (fileUrl.replace(/\\/g, '').toLowerCase().indexOf('.pdf') >= 0) {
          window.open(fileUrl);
        } else {
          //https://view.officeapps.live.com/op/view.aspx?src=
          window.open("http://www.xdocin.com/xdoc?_func=to&_format=html&_cache=1&_xdoc=" + fileUrl.replace(/\\/g, ''));
        }
      }
    },
    SearchBasisInfo: function (id) {
      Api_GetDataDetail(id).then(res => {
        this.basisInfo = res;
        this.titleIntroduce = res.keyWord;
      }, rej => {
        alert(rej);
      }).catch(err => {
        console.log(err);
        alert('错误的请求!');
      });
    },
    SearchImages: function (searchType, searchName) {
      this.images.searchType = searchType;
      this.images.searchName = searchName;
      Api_GetDataDetailImages(this.$route.query.id, searchType, searchName, 1, 10).then(res => {
        this.images.currentPage = res.currentPage;
        this.images.pageSize = res.pageSize;
        this.images.total = res.total;
        this.images.data = res.data;
      }, rej => {
        alert(rej);
      }).catch(err => {
        console.log(err);
        alert('错误的请求!');
      });
    },
    NextImages: function () {
      let searchType = this.images.searchType;
      let searchName = this.images.searchName;
      let currentPage = this.images.currentPage + 1;
      let pageSize = this.images.pageSize;
      Api_GetDataDetailImages(this.$route.query.id, searchType, searchName, currentPage, pageSize).then(res => {
        if (res.data.length > 0) {
          this.images.total = res.total;
          this.images.currentPage = res.currentPage;
          this.images.data = this.images.data.concat(res.data);
        }
      }, rej => {
        alert(rej);
      }).catch(err => {
        console.log(err);
        alert('错误的请求!');
      });
    },
    SearchVideos: function (searchType, searchName) {
      this.videos.searchType = searchType;
      this.videos.searchName = searchName;
      Api_GetDataDetailVideos(this.$route.query.id, searchType, searchName, 1, 10).then(res => {
        this.videos.currentPage = res.currentPage;
        this.videos.pageSize = res.pageSize;
        this.videos.total = res.total;
        this.videos.data = res.data;
      }, rej => {
        alert(rej);
      }).catch(err => {
        console.log(err);
        alert('错误的请求!');
      });
    },
    NextVideos: function () {
      let searchType = this.videos.searchType;
      let searchName = this.videos.searchName;
      let currentPage = this.videos.currentPage + 1;
      let pageSize = this.videos.pageSize;
      Api_GetDataDetailVideos(this.$route.query.id, searchType, searchName, currentPage, pageSize).then(res => {
        if (res.data.length > 0) {
          this.videos.total = res.total;
          this.videos.currentPage = res.currentPage;
          this.videos.data = this.videos.data.concat(res.data);
        }
      }, rej => {
        alert(rej);
      }).catch(err => {
        console.log(err);
        alert('错误的请求!');
      });
    },
    ToImageDetail: function (id) {
      let objId = this.$route.query.id;
      this.$router.push({name: "spirit-detail-image", query: {id: id, objId: objId}});
    },
    ToVideoDetail: function (id) {
      let objId = this.$route.query.id;
      this.$router.push({name: "spirit-detail-video", query: {id: id, objId: objId}});
    },
    ToListPage: function () {
      this.$router.push({name: "spirit-list"})
    },
  },
  watch: {
    navbarIndex: function () {
      switch (this.navbarIndex) {
        case 1:
          this.images.scrollDisabled = true;
          this.videos.scrollDisabled = true;
          break;
        case 2:
          this.images.scrollDisabled = false;
          this.videos.scrollDisabled = true;
          break;
        case 3:
          this.images.scrollDisabled = true;
          this.videos.scrollDisabled = false;
          break;
      }
    }
  },
  created() {
    let id = this.$route.query.id;
    this.titleName = this.$route.query.name;
    this.SearchBasisInfo(id);
    this.SearchImages("title", "");
    this.SearchVideos("title", "");
  }
}
</script>
<style scoped>
.data-detail {
  width: 100%;
}
.data-detail .title {
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  height: 15.9vh;
  background: url("../../assets/datadetail/detail@1x.png") no-repeat 100% 100%;
  background-size: cover;
  border-radius: 10px 10px 0 0;
}
.data-detail .title .title-left {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-start;
  width: 60%;
  height: 100%;
  padding-left: 2vh;
}
.data-detail .title .title-name {
  width: 100%;
  text-align: left;
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
  font-size: 2.62rem;
  font-family: Source Han Serif CN;
  font-weight: bold;
  line-height: 5.24rem;
  color: #FFFFFF;
  opacity: 1;
}
.data-detail .title .title-introduce {
  width: 100%;
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
  font-size: 2rem;
  font-family: Source Han Sans CN;
  font-weight: 400;
  line-height: 3.37rem;
  color: #FFFFFF;
  opacity: 1;
}
.data-detail .title .title-right {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-start;
  width: 30%;
  height: 100%;
}
.data-detail .title .online-preview {
  width: 80%;
  background: #EFC587;
  opacity: 1;
  border-radius: 60px;
  font-size: 1.75rem;
  font-family: Source Han Sans CN;
  font-weight: bold;
  line-height: 3.87vh;
  color: #BC0000;
  opacity: 1;
}
.data-detail .content {
  width: 90%;
  height: 84.1vh;
  margin-left: 5%;
  border-radius: 30px;
}
.mint-navbar /deep/ .mint-tab-item-label {
  font-size: 2rem;
  font-family: Source Han Sans CN;
  font-weight: 500;
  line-height: 2rem;
  color: #767676;
  opacity: 1;
}
.mint-navbar /deep/ .is-selected {
  color: #BC0000;
  border-bottom: 0.3vh solid #BC0000;
}
.mint-navbar /deep/ .is-selected .mint-tab-item-label {
  color: #BC0000;
}
.mint-tab-container /deep/ .mint-tab-container-item:nth-child(1) {
  padding-top: 5vh;
}
.content-keyword {
  text-align: left;
  font-size: 1.87rem;
  font-family: Source Han Serif CN;
  font-weight: 400;
  line-height: 3rem;
  color: #767676;
  opacity: 1;
}
.content-keyword .item-name {
  text-align: left;
  font-size: 2rem;
  font-family: Source Han Sans CN;
  font-weight: bold;
  line-height: 6rem;
  color: #BC0000;
  opacity: 1;
}
.content-introduction {
  text-align: left;
  font-size: 1.87rem;
  font-family: Source Han Serif CN;
  font-weight: 400;
  line-height: 3rem;
  color: #767676;
  opacity: 1;
}
.content-introduction .item-name {
  text-align: left;
  font-size: 2rem;
  font-family: Source Han Sans CN;
  font-weight: bold;
  line-height: 6rem;
  color: #BC0000;
  opacity: 1;
}
.mint-tab-container /deep/ .mint-tab-container-item:nth-child(2) {
  padding-top: 2vh;
}
.custom-search3 {
  margin-bottom: 2vh;
}
.content-images {
  display: flex;
  flex-wrap: wrap;
  flex-direction: row;
  justify-content: flex-start;
  align-items: flex-start;
}
.content-images .content-item {
  width: 50%;
  height: 25vh;
}
.content-images .content-item .img-div {
  width: 90%;
  height: 80%;
  border-radius: 10px;
  box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.16);
}
.content-images .content-item .img-div img {
  width: 100%;
  height: 100%;
  border-radius: 10px;
  object-fit: cover;
}
.content-images .content-item .item-name {
  width: 90%;
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
  font-size: 2em;
  font-family: Source Han Serif CN;
  font-weight: bold;
  line-height: 2em;
  color: #333333;
  opacity: 1;
}
.mint-tab-container /deep/ .mint-tab-container-item:nth-child(3) {
  padding-top: 2vh;
}
.content-videos {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  align-items: center;
}
.content-videos .content-item {
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  justify-content: flex-start;
  align-items: center;
  height: 10vh;
  margin: 2vh auto;
}
.content-videos .item-left {
  width: 30%;
  height: 100%;
}
.content-videos .item-left img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.content-videos .item-right {
  width: 70%;
  height: 100%;
  padding-left: 2vw;
}
.content-videos .item-name {
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
  text-align: left;
  font-size: 2rem;
  font-family: Source Han Serif CN;
  font-weight: bold;
  line-height: 4rem;
  color: #BC0000;
  opacity: 1;
}
.content-videos .item-introduce {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  text-overflow: ellipsis;
  overflow: hidden;
  text-align: left;
  font-size: 1.62rem;
  font-family: Source Han Sans CN;
  font-weight: 400;
  line-height: 3rem;
  color: #767676;
  opacity: 1;
}
</style>
src/views/spirit/detailImage.vue
New file
@@ -0,0 +1,133 @@
<template>
  <div class="data-detail-image">
    <div class="images">
      <mt-swipe :show-indicators="false" :auto="0" :continuous="false" @change="ChangeImage">
        <mt-swipe-item v-for="item in images.data" :key="item.key">
          <img :src="item.path"/>
        </mt-swipe-item>
      </mt-swipe>
    </div>
    <div class="content">
      <mt-navbar v-model="navIndex">
        <mt-tab-item id="1">关键词</mt-tab-item>
        <mt-tab-item id="2">简介</mt-tab-item>
      </mt-navbar>
      <mt-tab-container v-model="navIndex">
        <mt-tab-container-item id="1">
          {{ image.keyWord }}
        </mt-tab-container-item>
        <mt-tab-container-item id="2">
          {{ image.introduction }}
        </mt-tab-container-item>
      </mt-tab-container>
    </div>
  </div>
</template>
<script>
import {GetImageDetail as Api_GetImageDetail} from "@/api/apilist";
export default {
  name: "detailImage",
  data() {
    return {
      navIndex: "1",
      images: {
        pageSize: 10,
        currentPage: 1,
        total: 0,
        data: []
      },
      image: {
        id: "",
        name: "",
        path: "",
        keyWord: "",
        introduction: "",
      }
    }
  },
  methods: {
    ChangeImage: function (index) {
      this.image = this.images.data[index];
    },
  },
  created() {
    let imageId = this.$route.query.id;
    let objId = this.$route.query.objId;
    Api_GetImageDetail(imageId, 1, objId, 999).then(res => {
      this.images = res;
      this.image = res.data[0];
    }, rej => {
      alert(rej);
    }).catch(err => {
      console.log(err);
      alert('错误的请求!');
    });
  }
}
</script>
<style scoped>
.data-detail-image {
  width: 100%;
}
.images {
  width: 100%;
  height: 31.5vh;
}
.images img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.content {
  width: 100%;
  height: 66vh;
  box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.16);
  opacity: 1;
  border-radius: 10px;
  padding-top: 1vh;
}
.content > div{
  width: 90%;
  margin-left: 5%;
}
.mint-navbar{
  margin-bottom: 4vh;
}
.mint-navbar .mint-tab-item /deep/ .mint-tab-item-label {
  font-size: 2rem;
  font-family: Source Han Sans CN;
  font-weight: 500;
  line-height: 3rem;
  color: #767676;
  opacity: 1;
}
.mint-navbar .is-selected {
  border-bottom: 0.3rem solid #BC0000;
}
.mint-navbar .is-selected /deep/ .mint-tab-item-label {
  color: #BC0000;
  font-weight: bold;
}
.mint-tab-container {
  text-align: left;
  font-size: 1.87rem;
  font-family: Source Han Serif CN;
  font-weight: 400;
  line-height: 3rem;
  color: #585858;
  opacity: 1;
}
</style>
src/views/spirit/detailvideo.vue
New file
@@ -0,0 +1,121 @@
<template>
  <div class="data-detail-video">
    <div class="videos">
      <video poster="" :src="video.patch" controls="controls">
        您的浏览器不支持 video 标签。
      </video>
    </div>
    <div class="content">
      <mt-navbar v-model="navIndex">
        <mt-tab-item id="1">关键词</mt-tab-item>
        <mt-tab-item id="2">简介</mt-tab-item>
      </mt-navbar>
      <mt-tab-container v-model="navIndex">
        <mt-tab-container-item id="1">
          {{ video.keyWord }}
        </mt-tab-container-item>
        <mt-tab-container-item id="2">
          {{ video.introduction }}
        </mt-tab-container-item>
      </mt-tab-container>
    </div>
  </div>
</template>
<script>
import {GetVideoDetail as Api_GetVideoDetail} from "@/api/apilist";
export default {
  name: "detailVideo",
  data() {
    return {
      navIndex: "1",
      video: {
        id: "",
        name: "",
        path: "",
        keyWord: "",
        introduction: "",
      },
    }
  },
  methods: {
  },
  created() {
    let id = this.$route.query.id;
    Api_GetVideoDetail(id).then(res => {
      this.video = res;
    }, rej => {
      alert(rej);
    }).catch(err => {
      console.log(err);
      alert('错误的请求!');
    });
  }
}
</script>
<style scoped>
.data-detail-video {
  width: 100%;
}
.videos {
  width: 100%;
  height: 31.5vh;
}
.videos video {
  width: 100%;
  height: 100%;
  background: black;
}
.content {
  width: 100%;
  height: 66vh;
  box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.16);
  opacity: 1;
  border-radius: 10px;
  padding-top: 1vh;
}
.content > div{
  width: 90%;
  margin-left: 5%;
}
.mint-navbar{
  margin-bottom: 4vh;
}
.mint-navbar .mint-tab-item /deep/ .mint-tab-item-label {
  font-size: 2rem;
  font-family: Source Han Sans CN;
  font-weight: 500;
  line-height: 3rem;
  color: #767676;
  opacity: 1;
}
.mint-navbar .is-selected {
  border-bottom: 0.3rem solid #BC0000;
}
.mint-navbar .is-selected /deep/ .mint-tab-item-label {
  color: #BC0000;
  font-weight: bold;
}
.mint-tab-container {
  text-align: left;
  font-size: 1.87rem;
  font-family: Source Han Serif CN;
  font-weight: 400;
  line-height: 3rem;
  color: #585858;
  opacity: 1;
}
</style>
src/views/spirit/list.vue
New file
@@ -0,0 +1,153 @@
<template>
  <div class="list-root">
    <div class="search">
      <CustomSearch3 v-on:search="Search"></CustomSearch3>
    </div>
    <div class="line"></div>
    <div class="data-list"
         v-infinite-scroll="loadBottom"
         :infinite-scroll-disabled="allLoaded"
         :infinite-scroll-distance="10">
      <template v-for="item in data.data">
        <div class="text-item" :key="item.key" @click="ToDetail(item.id, item.name)">
          <div class="item-title">{{ item.name }}</div>
          <div class="item-context">{{ item.keyWord }}</div>
        </div>
        <div class="line" :key="item.key"></div>
      </template>
    </div>
  </div>
</template>
<script>
import CustomSearch3 from "@/components/CustomSearch3";
import {GetDataList as Api_GetDataList} from "@/api/apilist";
export default {
  name: "list",
  components: {CustomSearch3},
  data() {
    return {
      dataType: 2,
      searchType: "title",
      searchName: "",
      data: {
        currentPage: 1,
        pageSize: 5,
        total: 0,
        data: []
      },
      allLoaded: false
    };
  },
  methods: {
    Search: function (searchType, searchName) {
      this.searchType = searchType;
      this.searchName = searchName;
      Api_GetDataList(this.dataType, searchType, searchName, 1, this.data.pageSize).then(res => {
        this.currentPage = res.currentPage;
        this.pageSize = res.pageSize;
        this.total = res.total;
        this.data = res;
      }, rej => {
        alert(rej);
      }).catch(err => {
        console.log(err);
        alert("错误的请求!");
      });
    },
    loadBottom: function () {
      Api_GetDataList(this.dataType, this.searchType, this.searchName, this.data.currentPage + 1, this.data.pageSize).then(res => {
        this.data.currentPage = res.currentPage;
        this.data.pageSize = res.pageSize;
        this.data.total = res.total;
        if (res.data.length > 0) {
          this.data.data = this.data.data.concat(res.data);
        }else{
          this.allLoaded = true;
        }
      }, rej => {
        alert(rej);
      }).catch(err => {
        console.log(err);
        alert("错误的请求!");
      });
    },
    ToDetail: function (id, name) {
      this.$router.push({name: "spirit-detail", query: {id: id, name: name}})
    }
  },
  created() {
    this.Search("title", "");
  }
}
</script>
<style scoped>
li {
  list-style-type: none;
}
.list-root {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  align-items: center;
  width: 100%;
}
.search {
  width: 100%;
  margin-top: 3vh;
}
.search .custom-search3 {
  width: 90%;
  margin-left: 5%;
}
.line {
  width: 100%;
  border: 1px solid #EEEEEE;
  margin-top: 3vh;
  margin-bottom: 3vh;
  opacity: 1;
}
.data-list {
  width: 90%;
  height: 65vh;
  margin-left: 5%;
  overflow: scroll;
}
.data-list .line {
  width: 100%;
  margin-bottom: 2vh;
}
data-list /deep/ .text-item {
  width: 90%;
  margin-bottom: 2vh;
}
data-list /deep/ .text-item .item-title {
  text-align: left;
  font-size: 2rem;
  font-family: Source Han Serif CN;
  font-weight: bold;
  line-height: 4rem;
  color: #BC0000;
}
data-list /deep/ .text-item .item-context {
  text-align: left;
  font-size: 1.62rem;
  font-family: Source Han Sans CN;
  font-weight: 400;
  line-height: 2rem;
  color: #767676;
  text-align: left;
}
</style>
vue.config.js
New file
@@ -0,0 +1,14 @@
module.exports = {
    publicPath:'./',
    devServer: {
        proxy: {
            '/api': {
                target: 'http://hsly.xingyao100.com/',
                changeOrigin: true,
                pathRewrite: {
                    '^/api': '/'
                }
            }
        }
    },
}