Browse Source

江夏大屏

master
xuhuajiao 6 months ago
parent
commit
1a2acf3cc8
  1. 9
      .env.production
  2. 197
      .eslintrc.js
  3. 23
      .gitignore
  4. 38
      README.md
  5. 11
      babel.config.js
  6. 61
      package.json
  7. BIN
      public/favicon.ico
  8. 18
      public/index.html
  9. 5
      public/static/config.js
  10. 41
      src/App.vue
  11. 185
      src/api/library.js
  12. BIN
      src/assets/fonts/DingTalk_JinBuTi_Regular.ttf
  13. 6
      src/assets/fonts/fonts.css
  14. BIN
      src/assets/images/arrow1.png
  15. BIN
      src/assets/images/arrow2.png
  16. BIN
      src/assets/images/bg.png
  17. BIN
      src/assets/images/bg2.png
  18. BIN
      src/assets/images/book_03.png
  19. BIN
      src/assets/images/bottom-bg.png
  20. BIN
      src/assets/images/circle-bg.png
  21. BIN
      src/assets/images/database-icon1.png
  22. BIN
      src/assets/images/database-icon2.png
  23. BIN
      src/assets/images/database-img2.png
  24. BIN
      src/assets/images/database-middle.png
  25. BIN
      src/assets/images/default-img.png
  26. BIN
      src/assets/images/header-bg.png
  27. BIN
      src/assets/images/header_03.png
  28. BIN
      src/assets/images/header_05.png
  29. BIN
      src/assets/images/header_07.png
  30. BIN
      src/assets/images/header_09.png
  31. BIN
      src/assets/images/header_11.png
  32. BIN
      src/assets/images/header_13.png
  33. BIN
      src/assets/images/header_13_b.png
  34. BIN
      src/assets/images/header_15.png
  35. BIN
      src/assets/images/lib.jpg
  36. BIN
      src/assets/images/lib2.jpg
  37. BIN
      src/assets/images/lib3.jpg
  38. BIN
      src/assets/images/lib4.jpg
  39. BIN
      src/assets/images/lib5.jpg
  40. BIN
      src/assets/images/lib6.jpg
  41. BIN
      src/assets/images/line.png
  42. BIN
      src/assets/images/map-bg2.png
  43. BIN
      src/assets/images/map-hx-big2.png
  44. BIN
      src/assets/images/map-hx-dot.png
  45. BIN
      src/assets/images/map-hx-small.png
  46. BIN
      src/assets/images/mapBg.png
  47. BIN
      src/assets/images/map_03.png
  48. BIN
      src/assets/images/map_10.png
  49. BIN
      src/assets/images/map_18.png
  50. BIN
      src/assets/images/map_20.png
  51. BIN
      src/assets/images/map_28.png
  52. BIN
      src/assets/images/map_30.png
  53. BIN
      src/assets/images/page4_02.png
  54. BIN
      src/assets/images/page4_03.png
  55. BIN
      src/assets/images/page4_06.png
  56. BIN
      src/assets/images/pageOne-1.png
  57. BIN
      src/assets/images/pageOne-2.png
  58. BIN
      src/assets/images/pageOne-3.png
  59. BIN
      src/assets/images/pageOne-4.png
  60. BIN
      src/assets/images/pageOne-5.png
  61. BIN
      src/assets/images/pageOne-6.png
  62. BIN
      src/assets/images/poster.png
  63. BIN
      src/assets/images/ranking01.png
  64. BIN
      src/assets/images/ranking02.png
  65. BIN
      src/assets/images/ranking03.png
  66. BIN
      src/assets/images/title-big.png
  67. BIN
      src/assets/images/title-middle.png
  68. BIN
      src/assets/images/title-small.png
  69. BIN
      src/assets/images/wechat-img1.png
  70. BIN
      src/assets/images/wechat-img2.png
  71. BIN
      src/assets/images/wq.png
  72. 63
      src/assets/js/META.common.min.js
  73. 50
      src/assets/js/METAWA.umd.min.js
  74. 244
      src/assets/js/rollSlide.js
  75. 336
      src/assets/js/tagscloud.js
  76. 1
      src/assets/json/jx.json
  77. 3
      src/assets/json/lib.json
  78. 23
      src/assets/json/lib2.json
  79. 1
      src/assets/json/qy.json
  80. BIN
      src/assets/logo.png
  81. 46
      src/assets/styles/font-some.css
  82. 1681
      src/assets/styles/index.scss
  83. 91
      src/assets/styles/style.scss
  84. 147
      src/common/flexible.js
  85. 61
      src/common/scrollMixins.js
  86. 63
      src/components/SvgIcon/index.vue
  87. 248
      src/components/echart/barEcharts.vue
  88. 263
      src/components/echart/lineChart.vue
  89. 274
      src/components/echart/todayCircle.vue
  90. 292
      src/components/echart/yearCircle.vue
  91. 10
      src/icons/index.js
  92. 1
      src/icons/svg/map.svg
  93. 1
      src/icons/svg/place.svg
  94. 71
      src/main.js
  95. 22
      src/router/index.js
  96. 15
      src/store/index.js
  97. 105
      src/utils/index.js
  98. 162
      src/utils/mixins.js
  99. 46
      src/utils/request.js
  100. 55
      src/utils/resizeMixins.js

9
.env.production

@ -0,0 +1,9 @@
ENV = 'production'
# 如果使用 Nginx 代理后端接口,那么此处需要改为 '/',文件查看 Docker 部署篇,Nginx 配置
# 接口地址,注意协议,如果你没有配置 ssl,需要将 https 改为 http
VUE_APP_BASE_API = 'http://192.168.1.80:7070'
VUE_APP_LIB_API = 'http://118.253.150.248:8099'
# VUE_APP_BASE_API = 'http://127.0.0.1:8080'
# 如果接口是 http 形式, wss 需要改为 ws
VUE_APP_WS_API = 'ws://192.168.1.80:7071'

197
.eslintrc.js

@ -0,0 +1,197 @@
module.exports = {
root: true,
parserOptions: {
parser: 'babel-eslint',
sourceType: 'module'
},
env: {
browser: true,
node: true,
es6: true,
},
extends: ['plugin:vue/recommended', 'eslint:recommended'],
rules: {
"vue/max-attributes-per-line": [2, {
"singleline": 10,
"multiline": {
"max": 1,
"allowFirstLine": false
}
}],
"vue/singleline-html-element-content-newline": "off",
"vue/multiline-html-element-content-newline":"off",
"vue/name-property-casing": ["error", "PascalCase"],
"vue/no-v-html": "off",
'accessor-pairs': 2,
'arrow-spacing': [2, {
'before': true,
'after': true
}],
'block-spacing': [2, 'always'],
'brace-style': [2, '1tbs', {
'allowSingleLine': true
}],
'camelcase': [0, {
'properties': 'always'
}],
'comma-dangle': [2, 'never'],
'comma-spacing': [2, {
'before': false,
'after': true
}],
'comma-style': [2, 'last'],
'constructor-super': 2,
'curly': [2, 'multi-line'],
'dot-location': [2, 'property'],
'eol-last': 2,
'eqeqeq': ["error", "always", {"null": "ignore"}],
'generator-star-spacing': [2, {
'before': true,
'after': true
}],
'handle-callback-err': [2, '^(err|error)$'],
'indent': [2, 2, {
'SwitchCase': 1
}],
'jsx-quotes': [2, 'prefer-single'],
'key-spacing': [2, {
'beforeColon': false,
'afterColon': true
}],
'keyword-spacing': [2, {
'before': true,
'after': true
}],
'new-cap': [2, {
'newIsCap': true,
'capIsNew': false
}],
'new-parens': 2,
'no-array-constructor': 2,
'no-caller': 2,
'no-console': 'off',
'no-class-assign': 2,
'no-cond-assign': 2,
'no-const-assign': 2,
'no-control-regex': 0,
'no-delete-var': 2,
'no-dupe-args': 2,
'no-dupe-class-members': 2,
'no-dupe-keys': 2,
'no-duplicate-case': 2,
'no-empty-character-class': 2,
'no-empty-pattern': 2,
'no-eval': 2,
'no-ex-assign': 2,
'no-extend-native': 2,
'no-extra-bind': 2,
'no-extra-boolean-cast': 2,
'no-extra-parens': [2, 'functions'],
'no-fallthrough': 2,
'no-floating-decimal': 2,
'no-func-assign': 2,
'no-implied-eval': 2,
'no-inner-declarations': [2, 'functions'],
'no-invalid-regexp': 2,
'no-irregular-whitespace': 2,
'no-iterator': 2,
'no-label-var': 2,
'no-labels': [2, {
'allowLoop': false,
'allowSwitch': false
}],
'no-lone-blocks': 2,
'no-mixed-spaces-and-tabs': 2,
'no-multi-spaces': 2,
'no-multi-str': 2,
'no-multiple-empty-lines': [2, {
'max': 1
}],
'no-native-reassign': 2,
'no-negated-in-lhs': 2,
'no-new-object': 2,
'no-new-require': 2,
'no-new-symbol': 2,
'no-new-wrappers': 2,
'no-obj-calls': 2,
'no-octal': 2,
'no-octal-escape': 2,
'no-path-concat': 2,
'no-proto': 2,
'no-redeclare': 2,
'no-regex-spaces': 2,
'no-return-assign': [2, 'except-parens'],
'no-self-assign': 2,
'no-self-compare': 2,
'no-sequences': 2,
'no-shadow-restricted-names': 2,
'no-spaced-func': 2,
'no-sparse-arrays': 2,
'no-this-before-super': 2,
'no-throw-literal': 2,
'no-trailing-spaces': 2,
'no-undef':'off',
'no-undef-init': 2,
'no-unexpected-multiline': 2,
'no-unmodified-loop-condition': 2,
'no-unneeded-ternary': [2, {
'defaultAssignment': false
}],
'no-unreachable': 2,
'no-unsafe-finally': 2,
'no-unused-vars': [2, {
'vars': 'all',
'args': 'none'
}],
'no-useless-call': 2,
'no-useless-computed-key': 2,
'no-useless-constructor': 2,
'no-useless-escape': 0,
'no-whitespace-before-property': 2,
'no-with': 2,
'one-var': [2, {
'initialized': 'never'
}],
'operator-linebreak': [2, 'after', {
'overrides': {
'?': 'before',
':': 'before'
}
}],
'padded-blocks': [2, 'never'],
'quotes': [2, 'single', {
'avoidEscape': true,
'allowTemplateLiterals': true
}],
'semi': [2, 'never'],
'semi-spacing': [2, {
'before': false,
'after': true
}],
'space-before-blocks': [2, 'always'],
'space-before-function-paren': [2, 'never'],
'space-in-parens': [2, 'never'],
'space-infix-ops': 2,
'space-unary-ops': [2, {
'words': true,
'nonwords': false
}],
'spaced-comment': [2, 'always', {
'markers': ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ',']
}],
'template-curly-spacing': [2, 'never'],
'use-isnan': 2,
'valid-typeof': 2,
'wrap-iife': [2, 'any'],
'yield-star-spacing': [2, 'both'],
'yoda': [2, 'never'],
'prefer-const': 2,
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
'object-curly-spacing': [2, 'always', {
objectsInObjects: false
}],
'array-bracket-spacing': [2, 'never']
}
}

23
.gitignore

@ -0,0 +1,23 @@
.DS_Store
node_modules
dist/
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
package-lock.json

38
README.md

@ -0,0 +1,38 @@
江夏区图书馆智慧大屏
```bash
# install dependency
npm install
# develop
npm run serve
# 构建生产环境
npm run build
```
```bash
## 项目结构
├── src # 源代码
│ ├── api # 所有请求
│ ├── assets # 主题 字体等静态资源
│ ├── components # 全局组件
│ │ ├── echart # echart
│ ├── router # 路由
│ ├── views # views 所有页面
│ │ ├── header # 头部
│ │ ├── map # 地图页 第二页
│ │ ├── pageFour # 第四页
│ │ ├── pageOne # 第一页
│ │ ├── pageThree # 第三页
│ │ ├── index # 主页
│ ├── App.vue # 入口页面
│ ├── main.js # 入口文件 加载组件 初始化等
├── .env.xxx # 环境变量配置
├── .eslintrc.js # eslint 配置项
├── .babelrc # babel-loader 配置
├── .travis.yml # 自动化CI配置
├── vue.config.js # vue-cli 配置
├── postcss.config.js # postcss 配置
└── package.json # package.json
```

11
babel.config.js

@ -0,0 +1,11 @@
const plugins = ['@vue/babel-plugin-transform-vue-jsx', '@babel/plugin-proposal-optional-chaining', '@babel/plugin-proposal-nullish-coalescing-operator']
// 生产环境移除console
if (process.env.NODE_ENV === 'production') {
plugins.push('transform-remove-console')
}
module.exports = {
plugins: plugins,
presets: [
'@vue/cli-plugin-babel/preset'
]
}

61
package.json

@ -0,0 +1,61 @@
{
"name": "qy-big-screen",
"version": "1.0.0",
"description": "江夏区图书馆智慧大屏",
"scripts": {
"serve": "SET NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service serve",
"build": "SET NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service build",
"lint": "SET NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service lint"
},
"dependencies": {
"@babel/core": "^7.19.0",
"@babel/preset-env": "^7.19.0",
"@jiaminghi/data-view": "^2.7.3",
"@types/echarts": "^4.4.3",
"axios": "^0.27.2",
"core-js": "^3.6.4",
"echarts": "^4.6.0",
"element-ui": "^2.15.10",
"jquery": "^3.7.1",
"svg-sprite-loader": "^6.0.11",
"TagCloud": "^2.5.0",
"vue": "^2.6.11",
"vue-awesome": "^4.0.2",
"vue-count-to": "^1.0.13",
"vue-router": "^3.1.5",
"vue-seamless-scroll": "^1.1.23",
"vuex": "^3.1.2"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^4.2.0",
"@vue/cli-plugin-eslint": "^4.2.0",
"@vue/cli-service": "^4.2.0",
"babel-eslint": "^10.0.3",
"babel-plugin-transform-remove-console": "^6.9.4",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.1.2",
"sass": "^1.25.0",
"sass-loader": "^8.0.2",
"videojs-contrib-hls": "^5.15.0",
"vue-awesome-swiper": "^3.1.3",
"vue-template-compiler": "^2.6.11"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "babel-eslint"
},
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions"
]
}

BIN
public/favicon.ico

18
public/index.html

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
<script type="text/javascript" src="/static/config.js"></script>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

5
public/static/config.js

@ -0,0 +1,5 @@
window.g = {
AXIOS_TIMEOUT: 10000,
ApiUrl: 'http://192.168.3.5:8080', // 配置服务器地址,
LibUrl: 'http://118.253.150.248:8099' // 图创地址
}

41
src/App.vue

@ -0,0 +1,41 @@
<template>
<div id="app">
<router-view v-if="isRouterAlive" />
</div>
</template>
<script>
export default {
name: 'App',
//
provide() {
return {
reload: this.reload
}
},
data() {
return {
isRouterAlive: true
}
},
methods: {
reload() {
this.isRouterAlive = false
this.$nextTick(() => {
this.isRouterAlive = true
})
}
}
}
</script>
<style lang="scss">
body {
margin: 0;
}
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
</style>

185
src/api/library.js

@ -0,0 +1,185 @@
import request from '@/utils/request'
import qs from 'qs'
// 获取token
export function FetchInitToken(params) {
return request({
url: '/openlib/service/barcode/token' + '?' + qs.stringify(params, { indices: false }),
method: 'get',
urlType: 'interlib'
})
}
// 馆藏量
export function FetchLibBookTotal(params) {
return request({
url: '/qyzt/sync35' + '?' + qs.stringify(params, { indices: false }),
method: 'get',
urlType: 'local'
})
}
// 办证量统计
export function FetchUsertotal(params) {
return request({
url: '/qyzt/usertotal' + '?' + qs.stringify(params, { indices: false }),
method: 'get',
urlType: 'local'
})
}
// page1 获取公众号总粉丝数
export function FetchFansCount(params) {
return request({
url: '/qyzt/getfansCount' + '?' + qs.stringify(params, { indices: false }),
method: 'get',
urlType: 'local'
})
}
// page1 累计借出
export function FetchLendingTotal(params) {
return request({
url: '/qyzt/sync82' + '?' + qs.stringify(params, { indices: false }),
method: 'get',
urlType: 'local'
})
}
// 获取初始化数据
export function FetchInitSetting(params) {
return request({
url: '/qyzt/initSetting' + '?' + qs.stringify(params, { indices: false }),
method: 'get',
urlType: 'local'
})
}
// 人流数据
export function FetchInitJXSetting(params) {
return request({
url: '/qyzt/initJXSetting' + '?' + qs.stringify(params, { indices: false }),
method: 'get',
urlType: 'local'
})
}
// page1 云标签
export function FetchHotSearch(params) {
return request({
url: '/qyzt/getHotSearch' + '?' + qs.stringify(params, { indices: false }),
method: 'get',
urlType: 'local'
})
}
// page1 新书推荐
export function FetchNewBook(params) {
return request({
url: '/qyzt/getNewBook' + '?' + qs.stringify(params, { indices: false }),
method: 'get',
urlType: 'local'
})
}
// 通过isbn获取图书详细信息
export function FetchMarcByISBN(params) {
return request({
url: '/qyzt/marcByISBN' + '?' + qs.stringify(params, { indices: false }),
method: 'get',
urlType: 'local'
})
}
// page2 获取分馆显示内容
export function FetchLibcodeDetails(params) {
return request({
url: '/qyzt/getLibcodeDetails' + '?' + qs.stringify(params, { indices: false }),
method: 'get',
urlType: 'local'
})
}
// 获取分馆图片资料
export function FetchLibcodeResouceDetails(params) {
return request({
url: '/qyzt/getLibcodeResouceDetails' + '?' + qs.stringify(params, { indices: false }),
method: 'get',
urlType: 'local'
})
}
// page2 读者借阅排行榜
export function FetchReadRanking(params) {
return request({
url: '/qyzt/sync37' + '?' + qs.stringify(params, { indices: false }),
method: 'get',
urlType: 'local'
})
}
// page4 获取通知
export function FetchNoticeList(params) {
return request({
url: '/qyzt/getNoticeList' + '?' + qs.stringify(params, { indices: false }),
method: 'get',
urlType: 'local'
})
}
// page4 文献排行榜
export function FetchSync36(params) {
return request({
url: '/qyzt/sync36' + '?' + qs.stringify(params, { indices: false }),
method: 'get',
urlType: 'local'
})
}
// page4 获取总馆资料
export function FetchTotalResource(params) {
return request({
url: '/qyzt/getTotalResource' + '?' + qs.stringify(params, { indices: false }),
method: 'get',
urlType: 'local'
})
}
// 获取当日每小时借还信息
export function FetchTodayJH(params) {
return request({
url: '/qyzt/getTodayJH' + '?' + qs.stringify(params, { indices: false }),
method: 'get',
urlType: 'local'
})
}
// 获取一周内借还信息
export function FetchWeekJH(params) {
return request({
url: '/qyzt/getWeekJH' + '?' + qs.stringify(params, { indices: false }),
method: 'get',
urlType: 'local'
})
}
export default {
FetchInitToken,
FetchLibBookTotal,
FetchUsertotal,
FetchFansCount,
FetchLendingTotal,
FetchInitSetting,
FetchInitJXSetting,
FetchHotSearch,
FetchNewBook,
FetchMarcByISBN,
FetchReadRanking,
FetchLibcodeDetails,
FetchLibcodeResouceDetails,
FetchNoticeList,
FetchSync36,
FetchTotalResource,
FetchTodayJH,
FetchWeekJH
}

BIN
src/assets/fonts/DingTalk_JinBuTi_Regular.ttf

6
src/assets/fonts/fonts.css

@ -0,0 +1,6 @@
@font-face {
font-family: "DingTalk_JinBuTi_Regular";
src: url('DingTalk_JinBuTi_Regular.ttf');
font-weight: normal;
font-style: normal;
}

BIN
src/assets/images/arrow1.png

After

Width: 22  |  Height: 23  |  Size: 455 B

BIN
src/assets/images/arrow2.png

After

Width: 22  |  Height: 23  |  Size: 439 B

BIN
src/assets/images/bg.png

After

Width: 1885  |  Height: 1080  |  Size: 335 KiB

BIN
src/assets/images/bg2.png

After

Width: 1920  |  Height: 1080  |  Size: 457 KiB

BIN
src/assets/images/book_03.png

After

Width: 112  |  Height: 160  |  Size: 40 KiB

BIN
src/assets/images/bottom-bg.png

After

Width: 1461  |  Height: 58  |  Size: 33 KiB

BIN
src/assets/images/circle-bg.png

After

Width: 132  |  Height: 131  |  Size: 16 KiB

BIN
src/assets/images/database-icon1.png

After

Width: 200  |  Height: 88  |  Size: 21 KiB

BIN
src/assets/images/database-icon2.png

After

Width: 200  |  Height: 88  |  Size: 20 KiB

BIN
src/assets/images/database-img2.png

After

Width: 158  |  Height: 140  |  Size: 19 KiB

BIN
src/assets/images/database-middle.png

After

Width: 466  |  Height: 512  |  Size: 418 KiB

BIN
src/assets/images/default-img.png

After

Width: 66  |  Height: 83  |  Size: 4.2 KiB

BIN
src/assets/images/header-bg.png

After

Width: 1451  |  Height: 85  |  Size: 72 KiB

BIN
src/assets/images/header_03.png

After

Width: 11  |  Height: 6  |  Size: 1.1 KiB

BIN
src/assets/images/header_05.png

After

Width: 11  |  Height: 6  |  Size: 1.1 KiB

BIN
src/assets/images/header_07.png

After

Width: 11  |  Height: 6  |  Size: 1.1 KiB

BIN
src/assets/images/header_09.png

After

Width: 11  |  Height: 6  |  Size: 1.2 KiB

BIN
src/assets/images/header_11.png

After

Width: 11  |  Height: 6  |  Size: 1.1 KiB

BIN
src/assets/images/header_13.png

After

Width: 64  |  Height: 5  |  Size: 1.3 KiB

BIN
src/assets/images/header_13_b.png

After

Width: 196  |  Height: 6  |  Size: 1.5 KiB

BIN
src/assets/images/header_15.png

After

Width: 11  |  Height: 6  |  Size: 1.1 KiB

BIN
src/assets/images/lib.jpg

After

Width: 400  |  Height: 350  |  Size: 27 KiB

BIN
src/assets/images/lib2.jpg

After

Width: 400  |  Height: 350  |  Size: 30 KiB

BIN
src/assets/images/lib3.jpg

After

Width: 400  |  Height: 350  |  Size: 32 KiB

BIN
src/assets/images/lib4.jpg

After

Width: 400  |  Height: 350  |  Size: 26 KiB

BIN
src/assets/images/lib5.jpg

After

Width: 400  |  Height: 350  |  Size: 31 KiB

BIN
src/assets/images/lib6.jpg

After

Width: 400  |  Height: 350  |  Size: 35 KiB

BIN
src/assets/images/line.png

After

Width: 12  |  Height: 145  |  Size: 2.0 KiB

BIN
src/assets/images/map-bg2.png

After

Width: 149  |  Height: 291  |  Size: 93 KiB

BIN
src/assets/images/map-hx-big2.png

After

Width: 905  |  Height: 905  |  Size: 56 KiB

BIN
src/assets/images/map-hx-dot.png

After

Width: 1306  |  Height: 1037  |  Size: 38 KiB

BIN
src/assets/images/map-hx-small.png

After

Width: 905  |  Height: 723  |  Size: 49 KiB

BIN
src/assets/images/mapBg.png

After

Width: 1920  |  Height: 1080  |  Size: 2.3 MiB

BIN
src/assets/images/map_03.png

After

Width: 152  |  Height: 122  |  Size: 21 KiB

BIN
src/assets/images/map_10.png

After

Width: 61  |  Height: 43  |  Size: 6.8 KiB

BIN
src/assets/images/map_18.png

After

Width: 58  |  Height: 52  |  Size: 3.4 KiB

BIN
src/assets/images/map_20.png

After

Width: 58  |  Height: 52  |  Size: 2.6 KiB

BIN
src/assets/images/map_28.png

After

Width: 58  |  Height: 52  |  Size: 2.5 KiB

BIN
src/assets/images/map_30.png

After

Width: 62  |  Height: 42  |  Size: 3.1 KiB

BIN
src/assets/images/page4_02.png

After

Width: 1265  |  Height: 3  |  Size: 1.1 KiB

BIN
src/assets/images/page4_03.png

After

Width: 1330  |  Height: 871  |  Size: 28 KiB

BIN
src/assets/images/page4_06.png

After

Width: 467  |  Height: 170  |  Size: 53 KiB

BIN
src/assets/images/pageOne-1.png

After

Width: 267  |  Height: 102  |  Size: 24 KiB

BIN
src/assets/images/pageOne-2.png

After

Width: 267  |  Height: 102  |  Size: 24 KiB

BIN
src/assets/images/pageOne-3.png

After

Width: 391  |  Height: 314  |  Size: 108 KiB

BIN
src/assets/images/pageOne-4.png

After

Width: 432  |  Height: 275  |  Size: 127 KiB

BIN
src/assets/images/pageOne-5.png

After

Width: 31  |  Height: 31  |  Size: 3.5 KiB

BIN
src/assets/images/pageOne-6.png

After

Width: 610  |  Height: 163  |  Size: 11 KiB

BIN
src/assets/images/poster.png

After

Width: 1261  |  Height: 710  |  Size: 525 KiB

BIN
src/assets/images/ranking01.png

After

Width: 18  |  Height: 25  |  Size: 2.3 KiB

BIN
src/assets/images/ranking02.png

After

Width: 18  |  Height: 25  |  Size: 2.4 KiB

BIN
src/assets/images/ranking03.png

After

Width: 18  |  Height: 25  |  Size: 2.4 KiB

BIN
src/assets/images/title-big.png

After

Width: 1160  |  Height: 48  |  Size: 20 KiB

BIN
src/assets/images/title-middle.png

After

Width: 475  |  Height: 27  |  Size: 13 KiB

BIN
src/assets/images/title-small.png

After

Width: 483  |  Height: 48  |  Size: 14 KiB

BIN
src/assets/images/wechat-img1.png

After

Width: 322  |  Height: 432  |  Size: 76 KiB

BIN
src/assets/images/wechat-img2.png

After

Width: 152  |  Height: 153  |  Size: 738 B

BIN
src/assets/images/wq.png

After

Width: 391  |  Height: 314  |  Size: 39 KiB

63
src/assets/js/META.common.min.js
File diff suppressed because it is too large
View File

50
src/assets/js/METAWA.umd.min.js
File diff suppressed because it is too large
View File

244
src/assets/js/rollSlide.js

@ -0,0 +1,244 @@
/**
* Created by f on 2015/5/8.
*/
(function($) {
$.fn.rollSlide = function(obj) {
var $self = this
var orientation = obj.orientation || 'left' // 滚动方式
var num = obj.num || 1 // 滚动数量
var v = (typeof obj.v === 'number') ? obj.v : 0 // 滚动速度
var minTime = (typeof obj.space === 'number') ? ((obj.space >= 100) ? obj.space : 100) : 100 // 最小间隔为 100 ms ,
var space = minTime + v || 5000 + v // 滚动间隔 默认 5000ms
var isRoll = obj.isRoll // 自动播放
var isStart = true
var roll = function(ori, n, v) {
var $ul = $self.find('.roll__list')
var $item = $ul.find('li')
var range = 0
var i; var len = $item.length
var sliceItem = []
var cloneSliceItem = []
var startTime = (new Date()).getTime()
// 存放滚动过的 item
var memory = function() {
var arr = []
if (ori === 'left' || ori === 'top') {
for (i = 0; i < n; i++) {
range += ori === 'left' ? $($item[i]).outerWidth(true) : $($item[i]).outerHeight(true) // left 取 width,top 取 height
arr.push($item[i])
}
} else if (ori === 'right' || ori === 'bottom') {
for (i = len - n; n > 0; n--, i++) {
range += ori === 'right' ? $($item[i]).outerWidth(true) : $($item[i]).outerHeight(true)
arr.push($item[i])
}
}
return arr
}
isStart = false // 关闭滚动
sliceItem = memory()
cloneSliceItem = $(sliceItem).clone()
// 判断往哪个方向移动
switch (ori) {
case 'left':
$ul.append(cloneSliceItem)
$ul.animate({
'left': -range + 'px'
}, v, function() {
$(this).css({ 'left': 0 })
$(sliceItem).remove()
isStart = true // 开启滚动
})
break
case 'right':
$ul.prepend(cloneSliceItem)
$ul.css('left', -range + 'px')
$ul.animate({
'left': 0
}, v, function() {
$(sliceItem).remove()
isStart = true // 开启滚动
})
break
case 'top':
$ul.append(cloneSliceItem)
$ul.animate({
'top': -range + 'px'
}, v, function() {
$(this).css({ 'top': 0 })
$(sliceItem).remove()
isStart = true // 开启滚动
})
break
case 'bottom':
$ul.prepend(cloneSliceItem)
$ul.css('top', -range + 'px')
$ul.animate({
'top': 0
}, v, function() {
$(sliceItem).remove()
isStart = true // 开启滚动
})
break
}
}
var init = function() {
var $ul = $self.find('.roll__list')
var $item = $ul.find('li')
var len = $item.length
var timer
num = num <= len ? num : len // 滚动个数超过列表数,取列表数
if (len > 1) {
$self.on('click', '.pre', function() {
if (isStart) {
// 横向滚动
if (orientation === 'left' || orientation === 'right') {
roll('right', num, v)
} else { // 纵向滚动
roll('bottom', num, v)
}
}
})
.on('click', '.next', function() {
if (isStart) {
// 横向滚动
if (orientation === 'left' || orientation === 'right') {
roll('left', num, v)
} else { // 纵向滚动
roll('top', num, v)
}
}
})
.hover(function() {
clearInterval(timer)
}, function() {
if (isRoll) {
timer = setInterval(function() {
roll(orientation, num, v)
}, space)
}
})
.trigger('mouseout')
}
}
init()
}
$.fn.rollNoInterval = function() {
var $self = this
var $ul = $self.find('.roll__list')
var $item = $ul.find('li')
var len = $item.length
var timer
var left = function() {
var offset, i,
range,
$sliceItem
$sliceItem = $($item[0])
range = $sliceItem.outerWidth(true)
timer = setInterval(function() {
offset = $ul.css('left')
offset = parseInt(offset)
if (offset > -range) {
i = offset - 1
$ul.css('left', i + 'px')
offset = $ul.css('left')
} else {
$sliceItem.detach()
$ul.css('left', 0)
$ul.append($sliceItem)
$sliceItem = $($ul.find('li')[0])
range = $sliceItem.outerWidth(true)
}
}, 50)
}
var right = function() {
var offset, i,
range,
$sliceItem
$sliceItem = $($item[len - 1])
range = $sliceItem.outerWidth(true)
timer = setInterval(function() {
offset = $ul.css('right')
offset = parseInt(offset)
if (offset > -range) {
i = offset - 1
$ul.css('right', i + 'px')
offset = $ul.css('right')
} else {
$sliceItem.detach()
$ul.css('right', 0)
$ul.prepend($sliceItem)
$sliceItem = $($ul.find('li')[len - 1])
range = $sliceItem.outerWidth(true)
}
}, 50)
}
var top = function() {
var offset, i,
range,
$sliceItem
$sliceItem = $($item[0])
range = $sliceItem.outerHeight(true)
timer = setInterval(function() {
offset = $ul.css('top')
offset = parseInt(offset)
if (offset > -range) {
i = offset - 1
$ul.css('top', i + 'px')
offset = $ul.css('top')
} else {
$sliceItem.detach()
$ul.css('top', 0)
$ul.append($sliceItem)
$sliceItem = $($ul.find('li')[0])
range = $sliceItem.outerHeight(true)
}
}, 50)
}
var bottom = function() {
var offset, i,
range,
$sliceItem
$sliceItem = $($item[len - 1])
range = $sliceItem.outerHeight(true)
timer = setInterval(function() {
offset = $ul.css('bottom')
offset = parseInt(offset)
if (offset > -range) {
i = offset - 1
$ul.css('bottom', i + 'px')
offset = $ul.css('bottom')
} else {
$sliceItem.detach()
$ul.css('bottom', 0)
$ul.prepend($sliceItem)
$sliceItem = $($ul.find('li')[len - 1])
range = $sliceItem.outerHeight(true)
}
}, 50)
}
var init = function() {
$self.hover(function() {
clearInterval(timer)
}, function() {
})
}
// init();
return {
left: left,
right: right,
top: top,
bottom: bottom
}
}
})(jQuery)

336
src/assets/js/tagscloud.js

@ -0,0 +1,336 @@
/**
* TagCloud.js (c) 2016-2019 @ Cong Min
* MIT License - https://github.com/cong-min/TagCloud
*/
class TagCloud {
/* constructor */
constructor(container = document.body, texts, options) {
const self = this
if (!container || container.nodeType !== 1) return new Error('Incorrect element type')
// params
self.$container = container
self.texts = texts || []
self.config = { ...TagCloud._defaultConfig, ...options || {}}
// calculate config
self.radius = self.config.radius // rolling radius
self.depth = 2 * self.radius // rolling depth
self.size = 1.5 * self.radius // rolling area size with mouse
self.maxSpeed = TagCloud._getMaxSpeed(self.config.maxSpeed) // rolling max speed
self.initSpeed = TagCloud._getInitSpeed(self.config.initSpeed) // rolling init speed
self.direction = self.config.direction // rolling init direction
self.keep = self.config.keep // whether to keep rolling after mouse out area
self.paused = false // keep state to pause the animation
// create element
self._createElment()
// init
self._init()
// set elements and instances
TagCloud.list.push({ el: self.$el, container, instance: self })
}
/* static method */
// all TagCloud list
static list = [];
// default config
static _defaultConfig = {
radius: 100, // rolling radius, unit `px`
maxSpeed: 'normal', // rolling max speed, optional: `slow`, `normal`(default), `fast`
initSpeed: 'normal', // rolling init speed, optional: `slow`, `normal`(default), `fast`
direction: 135, // rolling init direction, unit clockwise `deg`, optional: `0`(top) , `90`(left), `135`(right-bottom)(default)...
keep: true, // whether to keep rolling after mouse out area, optional: `false`, `true`(default)(decelerate to rolling init speed, and keep rolling with mouse)
reverseDirection: false,
useContainerInlineStyles: true,
useItemInlineStyles: true,
containerClass: 'tagcloud',
itemClass: 'tagcloud--item',
useHTML: false
};
// speed value
static _getMaxSpeed = (name) => ({ slow: 0.5, normal: 1, fast: 2 })[name] || 1;
static _getInitSpeed = (name) => ({ slow: 16, normal: 32, fast: 80 })[name] || 32;
// event listener
static _on(el, ev, handler, cap) {
if (el.addEventListener) {
el.addEventListener(ev, handler, cap)
} else if (el.attachEvent) {
el.attachEvent(`on${ev}`, handler)
} else {
el[`on${ev}`] = handler
}
}
/* instance property method */
// create elment
_createElment() {
const self = this
// create container
const $el = document.createElement('div')
$el.className = self.config.containerClass
if (self.config.useContainerInlineStyles) {
$el.style.position = 'relative'
$el.style.width = `${2 * self.radius}px`
$el.style.height = `${2 * self.radius}px`
}
// create texts
self.items = []
self.texts.forEach((text, index) => {
const item = self._createTextItem(text, index)
$el.appendChild(item.el)
self.items.push(item)
})
self.$container.appendChild($el)
self.$el = $el
}
// create a text
_createTextItem(text, index = 0) {
const self = this
const itemEl = document.createElement('span')
itemEl.className = self.config.itemClass
if (self.config.useItemInlineStyles) {
itemEl.style.willChange = 'transform, opacity, filter'
itemEl.style.position = 'absolute'
itemEl.style.top = '50%'
itemEl.style.left = '50%'
itemEl.style.zIndex = index + 1
itemEl.style.filter = 'alpha(opacity=0)'
itemEl.style.opacity = 0
const transformOrigin = '50% 50%'
itemEl.style.WebkitTransformOrigin = transformOrigin
itemEl.style.MozTransformOrigin = transformOrigin
itemEl.style.OTransformOrigin = transformOrigin
itemEl.style.transformOrigin = transformOrigin
const transform = 'translate3d(-50%, -50%, 0) scale(1)'
itemEl.style.WebkitTransform = transform
itemEl.style.MozTransform = transform
itemEl.style.OTransform = transform
itemEl.style.transform = transform
}
if (self.config.useHTML) {
itemEl.innerHTML = text
} else {
itemEl.innerText = text
}
return {
el: itemEl,
...self._computePosition(index) // distributed in appropriate place
}
}
// calculate appropriate place
_computePosition(index, random = false) {
const self = this
const textsLength = self.texts.length
// if random `true`, It means that a random appropriate place is generated, and the position will be independent of `index`
if (random) index = Math.floor(Math.random() * (textsLength + 1))
const phi = Math.acos(-1 + (2 * index + 1) / textsLength)
const theta = Math.sqrt((textsLength + 1) * Math.PI) * phi
return {
x: (self.size * Math.cos(theta) * Math.sin(phi)) / 2,
y: (self.size * Math.sin(theta) * Math.sin(phi)) / 2,
z: (self.size * Math.cos(phi)) / 2
}
}
_requestInterval(fn, delay) {
const requestAnimFrame = ((() => window.requestAnimationFrame) || ((callback, element) => {
window.setTimeout(callback, 1000 / 60)
}))()
let start = new Date().getTime()
const handle = {}
function loop() {
handle.value = requestAnimFrame(loop)
const current = new Date().getTime()
const delta = current - start
if (delta >= delay) {
fn.call()
start = new Date().getTime()
}
}
handle.value = requestAnimFrame(loop)
return handle
}
// init
_init() {
const self = this
self.active = false // whether the mouse is activated
self.mouseX0 = self.initSpeed * Math.sin(self.direction * (Math.PI / 180)) // init distance between the mouse and rolling center x axis
self.mouseY0 = -self.initSpeed * Math.cos(self.direction * (Math.PI / 180)) // init distance between the mouse and rolling center y axis
self.mouseX = self.mouseX0 // current distance between the mouse and rolling center x axis
self.mouseY = self.mouseY0 // current distance between the mouse and rolling center y axis
const isTouchDevice = window.matchMedia('(hover: hover)')
if (!isTouchDevice || isTouchDevice.matches) {
// mouseover
TagCloud._on(self.$el, 'mouseover', () => { self.active = true })
// mouseout
TagCloud._on(self.$el, 'mouseout', () => { self.active = false })
// mousemove
TagCloud._on(self.keep ? window : self.$el, 'mousemove', (ev) => {
ev = ev || window.event
const rect = self.$el.getBoundingClientRect()
self.mouseX = (ev.clientX - (rect.left + rect.width / 2)) / 5
self.mouseY = (ev.clientY - (rect.top + rect.height / 2)) / 5
})
}
// update state regularly
self._next() // init update state
self.interval = self._requestInterval(() => {
self._next.call(self)
}, 10)
}
// calculate the next state
_next() {
const self = this
if (self.paused) {
return
}
// if keep `false`, pause rolling after moving mouse out area
if (!self.keep && !self.active) {
self.mouseX = Math.abs(self.mouseX - self.mouseX0) < 1
? self.mouseX0 : (self.mouseX + self.mouseX0) / 2 // reset distance between the mouse and rolling center x axis
self.mouseY = Math.abs(self.mouseY - self.mouseY0) < 1
? self.mouseY0 : (self.mouseY + self.mouseY0) / 2 // reset distance between the mouse and rolling center y axis
}
let a = -(Math.min(Math.max(-self.mouseY, -self.size), self.size) / self.radius) *
self.maxSpeed
let b = (Math.min(Math.max(-self.mouseX, -self.size), self.size) / self.radius) *
self.maxSpeed
// inverse direction if enabled
if (self.config.reverseDirection) {
a = -a
b = -b
}
if (Math.abs(a) <= 0.01 && Math.abs(b) <= 0.01) return // pause
// calculate offset
const l = Math.PI / 180
const sc = [
Math.sin(a * l),
Math.cos(a * l),
Math.sin(b * l),
Math.cos(b * l)
]
self.items.forEach(item => {
const rx1 = item.x
const ry1 = item.y * sc[1] + item.z * (-sc[0])
const rz1 = item.y * sc[0] + item.z * sc[1]
const rx2 = rx1 * sc[3] + rz1 * sc[2]
const ry2 = ry1
const rz2 = rz1 * sc[3] - rx1 * sc[2]
const per = (2 * self.depth) / (2 * self.depth + rz2) // todo
item.x = rx2
item.y = ry2
item.z = rz2
item.scale = per.toFixed(3)
let alpha = per * per - 0.25
alpha = (alpha > 1 ? 1 : alpha).toFixed(3)
const itemEl = item.el
const left = (item.x - itemEl.offsetWidth / 2).toFixed(2)
const top = (item.y - itemEl.offsetHeight / 2).toFixed(2)
const transform = `translate3d(${left}px, ${top}px, 0) scale(${item.scale})`
itemEl.style.WebkitTransform = transform
itemEl.style.MozTransform = transform
itemEl.style.OTransform = transform
itemEl.style.transform = transform
itemEl.style.filter = `alpha(opacity=${100 * alpha})`
itemEl.style.opacity = alpha
})
}
/* export instance properties and methods */
// update
update(texts) {
const self = this
// params
self.texts = texts || []
// judging and processing items based on texts
self.texts.forEach((text, index) => {
let item = self.items[index]
if (!item) { // if not had, then create
item = self._createTextItem(text, index)
Object.assign(item, self._computePosition(index, true)) // random place
self.$el.appendChild(item.el)
self.items.push(item)
}
// if had, replace text
if (self.config.useHTML) {
item.el.innerHTML = text
} else {
item.el.innerText = text
}
})
// remove redundant self.items
const textsLength = self.texts.length
const itemsLength = self.items.length
if (textsLength < itemsLength) {
const removeList = self.items.splice(textsLength, itemsLength - textsLength)
removeList.forEach(item => {
self.$el.removeChild(item.el)
})
}
}
// destroy
destroy() {
const self = this
self.interval = null
// clear in TagCloud.list
const index = TagCloud.list.findIndex(e => e.el === self.$el)
if (index !== -1) TagCloud.list.splice(index, 1)
// clear element
if (self.$container && self.$el) {
self.$container.removeChild(self.$el)
}
}
pause() {
const self = this
self.paused = true
}
resume() {
const self = this
self.paused = false
}
}
export default (els, texts, options) => {
if (typeof els === 'string') els = document.querySelectorAll(els)
if (!els.forEach) els = [els]
const instances = []
els.forEach(el => {
if (el) {
instances.push(new TagCloud(el, texts, options))
}
})
return instances.length <= 1 ? instances[0] : instances
}

1
src/assets/json/jx.json
File diff suppressed because it is too large
View File

3
src/assets/json/lib.json

@ -0,0 +1,3 @@
{
"江夏区图书馆":[114.349685,30.357841]
}

23
src/assets/json/lib2.json

@ -0,0 +1,23 @@
{
"陶铸图书馆":[111.848657, 26.588519],
"龙山街道分馆":[111.86478,26.599231],
"黎家坪分馆": [111.823424,26.693962],
"大村甸分馆": [111.77655,26.663866],
"邵家岭自助馆":[111.856979,26.59469],
"下马渡分馆":[111.895584,26.611702],
"复兴路自助馆":[111.843102,26.57896],
"七里桥分馆": [111.902703,26.571593],
"少儿馆":[111.842537,26.58196],
"茅竹镇分馆":[111.796508,26.510589],
"观音滩镇分馆":[111.897118,26.48444],
"凯俊盛科城分馆":[111.851548,26.550191],
"进宝塘镇分馆":[112.085297,26.436849],
"三口塘镇分馆":[111.819018,26.412155],
"肖家镇分馆":[112.009764,26.355137],
"潘市镇分馆": [112.051186,26.489878],
"大忠桥镇分馆":[111.873254,26.369761],
"浯溪街道分馆":[111.855175,26.574414],
"长虹街道分馆":[111.850902,26.586461],
"白水镇分馆": [111.989802,26.421353],
"白竹湖自助馆":[111.862001,26.580311]
}

1
src/assets/json/qy.json
File diff suppressed because it is too large
View File

BIN
src/assets/logo.png

After

Width: 200  |  Height: 200  |  Size: 6.7 KiB

46
src/assets/styles/font-some.css

@ -0,0 +1,46 @@
.chartNum{
display: flex;
justify-content: flex-start;
padding-left: .425rem;
}
.box-items {
position: relative;
display: flex;
height: .5rem;
text-align: center;
}
/*滚动数字设置*/
.number-item {
position: relative;
display: flex;
justify-content: center;
text-align: center;
width: .25rem;
height: .5rem;
line-height: .4rem;
}
.number-item span.items-int{
position: relative;
display: inline-block;
width: 100%;
height: 100%;
writing-mode: vertical-rl;
text-orientation: upright;
overflow: hidden;
}
.number-item span.items-int i{
font-style: normal;
position: absolute;
top: 0;
left: 50%;
font-size: .35rem;
font-weight: 600;
z-index: 99999;
color: #fff;
/* background: -webkit-linear-gradient(90deg, rgba(14,197,236,1) 20%,rgba(239,252,254,1) 70%);
background: linear-gradient(90deg, rgba(14,197,236,1) 20%,rgba(239,252,254,1) 70%);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent; */
text-shadow: 0 2px 8px rgba(5,28,55,0.42);
}

1681
src/assets/styles/index.scss
File diff suppressed because it is too large
View File

91
src/assets/styles/style.scss

@ -0,0 +1,91 @@
// 全局样式
* {
margin: 0;
padding: 0;
list-style-type: none;
box-sizing: border-box;
outline: none;
}
html {
margin: 0;
padding: 0;
}
body {
font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif;
background-color: #f1f1f1;
margin: 0;
padding: 0;
}
a {
color: #343440;
text-decoration: none;
}
ul{
margin: 0;
padding: 0;
li{
list-style: none;
}
}
img[src=""],img:not([src]){
opacity: 0;
border:none;
visibility: hidden;
max-width: none;
}
.clearfix {
&::after {
content: "";
display: table;
height: 0;
line-height: 0;
visibility: hidden;
clear: both;
}
}
pre{
font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif;
word-wrap: break-word;
white-space: pre-wrap;
}
/**滚动条的宽度*/
::-webkit-scrollbar {
width: 4px;
height: 4px;
}
//滚动条的滑块
::-webkit-scrollbar-thumb {
background-color: #13439E;
border-radius: 3px;
}
.icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
//浮动
.float-r {
float: right;
}
//文章一行显示多余省略号显示
.title-item {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
overflow: hidden;
text-overflow: ellipsis;
}

147
src/common/flexible.js

@ -0,0 +1,147 @@
(function(win, lib) {
var doc = win.document
var docEl = doc.documentElement
var metaEl = doc.querySelector('meta[name="viewport"]')
var flexibleEl = doc.querySelector('meta[name="flexible"]')
var dpr = 0
var scale = 0
var tid
var flexible = lib.flexible || (lib.flexible = {})
if (metaEl) {
console.warn('将根据已有的meta标签来设置缩放比例')
var match = metaEl
.getAttribute('content')
// eslint-disable-next-line no-useless-escape
.match(/initial\-scale=([\d\.]+)/)
if (match) {
scale = parseFloat(match[1])
dpr = parseInt(1 / scale)
}
} else if (flexibleEl) {
var content = flexibleEl.getAttribute('content')
if (content) {
// eslint-disable-next-line no-useless-escape
var initialDpr = content.match(/initial\-dpr=([\d\.]+)/)
// eslint-disable-next-line no-useless-escape
var maximumDpr = content.match(/maximum\-dpr=([\d\.]+)/)
if (initialDpr) {
dpr = parseFloat(initialDpr[1])
scale = parseFloat((1 / dpr).toFixed(2))
}
if (maximumDpr) {
dpr = parseFloat(maximumDpr[1])
scale = parseFloat((1 / dpr).toFixed(2))
}
}
}
if (!dpr && !scale) {
// eslint-disable-next-line no-unused-vars
var isAndroid = win.navigator.appVersion.match(/android/gi)
var isIPhone = win.navigator.appVersion.match(/iphone/gi)
var devicePixelRatio = win.devicePixelRatio
if (isIPhone) {
// iOS下,对于2和3的屏,用2倍的方案,其余的用1倍方案
if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) {
dpr = 3
} else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)) {
dpr = 2
} else {
dpr = 1
}
} else {
// 其他设备下,仍旧使用1倍的方案
dpr = 1
}
scale = 1 / dpr
}
docEl.setAttribute('data-dpr', dpr)
if (!metaEl) {
metaEl = doc.createElement('meta')
metaEl.setAttribute('name', 'viewport')
metaEl.setAttribute(
'content',
'initial-scale=' +
scale +
', maximum-scale=' +
scale +
', minimum-scale=' +
scale +
', user-scalable=no'
)
if (docEl.firstElementChild) {
docEl.firstElementChild.appendChild(metaEl)
} else {
var wrap = doc.createElement('div')
wrap.appendChild(metaEl)
doc.write(wrap.innerHTML)
}
}
function refreshRem() {
var width = docEl.getBoundingClientRect().width
// 最小1366px,最大适配2560px
if (width / dpr < 1366) {
width = 1366 * dpr
} else if (width / dpr > 2560) {
width = 2560 * dpr
}
// 设置成24等份,设计稿时1920px的,这样1rem就是80px
var rem = width / 24
docEl.style.fontSize = rem + 'px'
flexible.rem = win.rem = rem
}
win.addEventListener(
'resize',
function() {
clearTimeout(tid)
tid = setTimeout(refreshRem, 300)
},
false
)
win.addEventListener(
'pageshow',
function(e) {
if (e.persisted) {
clearTimeout(tid)
tid = setTimeout(refreshRem, 300)
}
},
false
)
if (doc.readyState === 'complete') {
doc.body.style.fontSize = 12 * dpr + 'px'
} else {
doc.addEventListener(
'DOMContentLoaded',
// eslint-disable-next-line no-unused-vars
function(e) {
doc.body.style.fontSize = 12 * dpr + 'px'
},
false
)
}
refreshRem()
flexible.dpr = win.dpr = dpr
flexible.refreshRem = refreshRem
flexible.rem2px = function(d) {
var val = parseFloat(d) * this.rem
if (typeof d === 'string' && d.match(/rem$/)) {
val += 'px'
}
return val
}
flexible.px2rem = function(d) {
var val = parseFloat(d) / this.rem
if (typeof d === 'string' && d.match(/px$/)) {
val += 'rem'
}
return val
}
})(window, window['lib'] || (window['lib'] = {}))

61
src/common/scrollMixins.js

@ -0,0 +1,61 @@
export default {
data() {
return {
scrollDom: null,
interval: null,
scrollTimer: null, // 滚动定时器
pauseTimer: null, // 暂停定时器
timeout: null,
step: null
}
},
created() {
},
mounted() {
// this.dataCompleteFun()
},
destroyed() {
// 清理定时器
clearTimeout(this.pauseTimer)
this.pauseTimer = null
clearInterval(this.scrollTimer)
this.scrollTimer = null
// 清理点击监听
window.document.removeEventListener('click', this.pauseScroll)
},
methods: {
autoScroll() {
// 滚动长度为0
if (this.scrollDom.scrollHeight - this.scrollDom.clientHeight > 0) {
// 如果定时器存在
if (this.scrollTimer) {
// 则先清除
clearInterval(this.scrollTimer)
clearTimeout(this.pauseTimer)
this.scrollTimer = null
this.pauseTimer = null
}
this.scrollTimer = setInterval(() => {
const scrollHeight = this.scrollDom.scrollHeight
const clientHeight = this.scrollDom.clientHeight
const scroll = scrollHeight - clientHeight
// 获取当前滚动条距离顶部高度
const scrollTop = this.scrollDom.scrollTop
// 当滚动到底部时,间隔时间后重回顶部开始
if (scrollTop + this.step >= scroll) {
this.scrollDom.scrollTop = scroll
this.pauseTimer = setTimeout(() => {
this.scrollDom.scrollTop = 0
this.autoScroll()
}, this.timeout)
} else { // 没有则继续滚动
this.scrollDom.scrollTop = scrollTop + this.step
}
// console.log(scrollHeight, clientHeight, scroll, scrollTop)
}, this.interval)
} else {
return
}
}
}
}

63
src/components/SvgIcon/index.vue

@ -0,0 +1,63 @@
<template>
<div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$listeners" />
<svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners">
<use :xlink:href="iconName" />
</svg>
</template>
<script>
// doc: https://panjiachen.github.io/vue-element-admin-site/feature/component/svg-icon.html#usage
import { isExternal } from '@/utils/index'
export default {
name: 'SvgIcon',
props: {
iconClass: {
type: String,
required: true
},
className: {
type: String,
default: ''
}
},
computed: {
isExternal() {
return isExternal(this.iconClass)
},
iconName() {
return `#icon-${this.iconClass}`
},
svgClass() {
if (this.className) {
return 'svg-icon ' + this.className
} else {
return 'svg-icon'
}
},
styleExternalIcon() {
return {
mask: `url(${this.iconClass}) no-repeat 50% 50%`,
'-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%`
}
}
}
}
</script>
<style scoped>
.svg-icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
.svg-external-icon {
background-color: currentColor;
mask-size: cover !important;
display: inline-block;
}
</style>

248
src/components/echart/barEcharts.vue

@ -0,0 +1,248 @@
<template>
<!-- 近七日借阅统计 -->
<div ref="barContainer" :style="{height:height,width:width}" />
</template>
<script>
import echarts from 'echarts'
import resize from '@/utils/resizeMixins.js'
export default {
name: 'BarEcharts',
mixins: [resize],
props: {
chartWeeklyData: {
type: Object,
require: true,
default: function() {
return {}
}
},
width: {
type: String,
default: '100%'
},
height: {
type: String,
default: '100%'
}
},
data() {
return {
chart: null,
option: null
}
},
watch: {
chartWeeklyData: {
handler(val) {
setTimeout(() => {
this.initChart()
}, 100)
},
immediate: true,
deep: true
}
},
beforeDestroy() {
if (!this.chart) {
return
}
this.chart.dispose()
this.chart = null
},
mounted() {
this.$nextTick(() => {
this.initChart()
})
window.addEventListener('resize', this.__resizeHandler)
this.resetPieChartData()
},
methods: {
// bar
resetPieChartData() {
clearInterval(this.timeRePie)
this.timeRePie = setInterval(() => {
// debugger;
if (!this.chart) {
return
}
// chart
this.chart.clear()
this.initChart()
}, 8000)
},
initChart() {
// const dom = document.getElementById('main2')
const dom = this.$refs.barContainer
this.chart = echarts.init(dom)
this.setOptions(this.chartWeeklyData)
},
setOptions({ date, outchartWeeklyData, inchartWeeklyData } = {}) {
//
var today = new Date()
//
var oneWeekAgo = new Date(today.getTime() - (7 * 24 * 60 * 60 * 1000))
// X使
var xAxisData = []
for (var i = 0; i < 7; i++) {
var day = new Date(oneWeekAgo.getTime() + (i * 24 * 60 * 60 * 1000))
xAxisData.push(echarts.format.formatTime('yyyy-MM-dd', day))
}
this.chart.setOption({
baseOption: {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
legend: { //
right: 20,
top: 10,
icon: 'rect',
itemHeight: 6,
itemWidth: 11,
textStyle: {
color: '#fff',
fontSize: 18
},
data: [
{
name: '借出',
icon: 'rect',
textStyle: {
color: '#41A3FF',
fontFamily: 'DingTalk_JinBuTi_Regular'
}
},
{
name: '归还',
icon: 'rect',
textStyle: {
color: '#FFD050',
fontFamily: 'DingTalk_JinBuTi_Regular'
}
}
]
},
grid: {
left: '3%',
right: '3%',
bottom: '8%',
top: '17%',
containLabel: true
},
xAxis: [{
type: 'category',
axisTick: { show: false },
data: date,
axisLine: { // 线
lineStyle: {
color: '#113D72'
}
},
axisLabel: { // x
show: true,
interval: 0,
textStyle: {
color: '#79B8FF',
fontSize: 16,
fontFamily: 'DingTalk_JinBuTi_Regular'
}
},
splitLine: { // 线
lineStyle: {
color: '#113D72',
type: 'solid'
}
}
}],
yAxis: [{
min: 0,
max: function(value) {
return Math.ceil(value.max + (value.max - value.min) * 0.2)
},
minInterval: 1,
type: 'value',
axisLine: { // 线
show: false
},
axisLabel: { //
show: true,
interval: 'auto',
formatter: function(value) {
// 使formatter使
return Math.round(value)
},
textStyle: {
color: '#79B8FF',
fontSize: 16,
fontFamily: 'DingTalk_JinBuTi_Regular'
}
},
axisTick: { // 线
show: false
},
splitLine: { // 线
lineStyle: {
color: 'rgba(66, 139, 221, 0.2)',
type: 'solid'
}
}
}],
series: [
{
name: '借出',
type: 'bar',
barWidth: 14, //
barGap: '30%',
emphasis: {
focus: 'series'
},
data: outchartWeeklyData,
itemStyle: {
color: '#41A3FF'
}
},
{
name: '归还',
type: 'bar',
barWidth: 14, //
emphasis: {
focus: 'series'
},
data: inchartWeeklyData,
itemStyle: {
color: '#FFD14F'
}
}
]
},
media: [
{
query: {
maxWidth: 675
},
option: {
xAxis: [{
data: date.map(dateStr => {
const parts = dateStr.split('/')
return parts.slice(1).join('/') //
})
}]
}
}
]
})
}
}
}
</script>
<style lang="scss" scoped>
</style>

263
src/components/echart/lineChart.vue

@ -0,0 +1,263 @@
<template>
<div ref="lineContainer" :style="{height:height,width:width}" />
</template>
<script>
import echarts from 'echarts'
import resize from '@/utils/resizeMixins.js'
export default {
name: 'LineEcharts',
mixins: [resize],
props: {
chartDayData: {
type: Object,
require: true,
default: function() {
return {}
}
},
width: {
type: String,
default: '100%'
},
height: {
type: String,
default: '100%'
}
},
data() {
return {
chart: null,
option: null
}
},
watch: {
chartDayData: {
deep: true,
mmediate: true,
handler(val) {
setTimeout(() => {
this.initChart()
}, 100)
}
}
},
beforeDestroy() {
if (!this.chart) {
return
}
this.chart.dispose()
this.chart = null
},
mounted() {
this.$nextTick(() => {
this.initChart()
})
window.addEventListener('resize', this.__resizeHandler)
this.resetPiechartDayData()
},
methods: {
resetPiechartDayData() {
clearInterval(this.timeRePie)
this.timeRePie = setInterval(() => {
// debugger;
if (!this.chart) {
return
}
// chart
this.chart.clear()
this.initChart()
}, 8000)
},
initChart() {
// const dom = document.getElementById('main2')
const dom = this.$refs.lineContainer
this.chart = echarts.init(dom, 'dark')
this.setOptions(this.chartDayData)
},
setOptions({ timeData, returnData, borrowedData } = {}) {
this.chart.setOption({
backgroundColor: '#01103D',
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
label: {
backgroundColor: '#6a7985'
}
}
},
legend: {
top: '4%',
right: '4%',
icon: 'rect',
itemHeight: 6,
itemWidth: 11,
textStyle: {
color: '#339CFF',
fontSize: 18
},
data: [
{
name: '借出',
icon: 'rect',
textStyle: {
color: '#41A3FF',
fontFamily: 'DingTalk_JinBuTi_Regular'
}
},
{
name: '归还',
icon: 'rect',
textStyle: {
color: '#FFD050',
fontFamily: 'DingTalk_JinBuTi_Regular'
}
}
]
},
grid: {
left: '2%',
right: '4%',
bottom: '4%',
containLabel: true
},
xAxis: [{
type: 'category',
data: timeData,
axisLabel: {
show: true,
formatter: function(value, idx) {
return value
},
color: '#79B8FF',
fontSize: 16,
fontFamily: 'DingTalk_JinBuTi_Regular'
},
axisLine: {
show: false,
lineStyle: {
width: '1',
color: '#113D72',
type: 'solid'
}
},
axisTick: {
show: false
},
splitLine: {
show: false,
lineStyle: {
color: '#333'
}
},
boundaryGap: false
}],
yAxis: [
{
type: 'value',
//
max: function(value) {
return Math.ceil(value.max + (value.max - value.min) * 0.2)
},
min: 0,
axisLabel: {
interval: 'auto',
formatter: function(value) {
// 使formatter使
return Math.round(value)
},
textStyle: {
color: '#79B8FF',
fontSize: 16,
fontFamily: 'DingTalk_JinBuTi_Regular'
}
},
// 线
axisLine: {
show: false,
lineStyle: {
color: '#113D72',
width: '1',
type: 'solid'
}
},
//
axisTick: {
show: false
},
// 线
splitLine: {
show: true,
lineStyle: {
color: 'rgba(66, 139, 221, 0.2)',
type: 'solid',
//
opacity: 1,
width: 1
}
}
}
],
series: [
{
name: '借出',
type: 'line',
stack: 'Total',
itemStyle: {
color: '#41A3FF'
},
lineStyle: {
width: 3,
color: '#41A3FF'
},
showSymbol: false,
areaStyle: {
opacity: 0.6,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: 'rgba(254, 128, 66, 0)'
},
{
offset: 1,
color: '#41A3FF'
}
])
},
data: borrowedData
},
{
name: '归还',
type: 'line',
stack: 'Total',
lineStyle: {
width: 3,
color: '#FFD14F'
},
showSymbol: false,
itemStyle: {
color: '#FFD14F'
},
areaStyle: {
opacity: 0.6,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: 'rgba(24, 176, 143, 0)'
},
{
offset: 1,
color: '#FFD14F'
}
])
},
data: returnData
}
]
})
}
}
}
</script>

274
src/components/echart/todayCircle.vue

@ -0,0 +1,274 @@
<template>
<div style="height: calc(100% - 200px); display: flex; align-items: center; justify-content: flex-start;">
<div id="todayType" style="width:400px; height: 230px" />
</div>
</template>
<script>
export default {
props: {
todayAllNum: {
type: Object,
require: true,
default: function() {
return {}
}
}
},
data() {
return {
}
},
watch: {
'todayAllNum': {
handler(val) {
setTimeout(() => {
this.initTodayCircle()
}, 100)
},
immediate: true,
deep: true
}
},
created() {
},
beforeDestroy() {
},
mounted() {
this.initTodayCircle()
},
methods: {
initTodayCircle() {
const optionData = [
{ value: this.todayAllNum.headerLib || 0, name: '总馆' }
// { value: this.todayAllNum.branchLib || 0, name: '' }
]
const myChart = this.$echarts.init(document.getElementById('todayType'))
function arrCount(arr) {
let count = 0
arr.forEach(item => {
count = count + item.value
})
return count
}
var centerImg = require('@/assets/images/circle-bg.png')
const option = {
baseOption: {
tooltip: {
show: false,
trigger: 'item',
position: 'bottom',
textStyle: {
color: '#EEF6FF',
fontSize: '18'
}
// backgroundColor: 'rgba(74, 144, 226, 0.84)',
// formatter: (params) => {
// return `<div>${params.seriesName} <br> ${params.data.name}${this.$parent.formatter(params.data.value)} (${params.percent}%)</div>`
// }
},
legend: {
orient: 'vertical',
right: 70,
top: 125,
// textStyle: {
// color: '#EEF6FF',
// padding: [20, 0, 18, 4],
// fontSize: '14'
// },
itemWidth: 10,
itemHeight: 10,
icon: 'circle',
selectedMode: false,
data: ['总馆'],
formatter: (name) => {
// `${name} ${((flag.value / count).toFixed(2)) * 100 + '%'}`
const count = arrCount(optionData)
if (optionData) {
const flag = optionData?.find(item => name === item.name)
if (flag) {
const percentage = count > 0 ? ((flag.value / count) * 100).toFixed(0) + '%' : '0%'
return [`{name|${name}}`, `{num|${percentage}}`]
}
}
return name
},
textStyle: {
rich: {
name: {
fontSize: 18,
color: '#EEF6FF',
padding: [20, 0, 20, 4],
fontFamily: 'DingTalk_JinBuTi_Regular'
},
num: {
fontSize: 20,
fontWeight: 600,
padding: [20, 0, 20, 15],
color: '#4C90FF',
fontFamily: 'DingTalk_JinBuTi_Regular'
}
}
}
},
// ()
graphic: [
{
type: 'image',
id: 'logo',
left: '8.5%', //
top: '22%', //
z: -10,
bounding: 'raw',
rotation: 0, //
origin: [64.5, 32.5], //
scale: [1.0, 1.0], //
//
style: {
image: centerImg,
width: 132,
height: 131,
opacity: 1
}
}
],
series: [
{
name: '今日累计借阅',
type: 'pie',
left: '-50%',
radius: ['60%', '70%'],
avoidLabelOverlap: false,
label: {
show: false,
position: 'center'
},
labelLine: {
show: true
},
itemStyle: {
borderWidth: 2,
borderColor: 'rgba(16,16,21,0.4)'
},
emphasis: {
label: {
show: true,
// params
formatter: function(params) {
const { value, name } = params
return [
`{c| ${value}}`,
`{b| ${name}}`
].join('\n') //
},
rich: {
c: {
fontSize: 24,
fontWeight: 600,
color: '#317FFF',
fontFamily: 'DingTalk_JinBuTi_Regular',
lineHeight: 34
},
b: {
fontSize: 18,
color: '#fff',
fontFamily: 'DingTalk_JinBuTi_Regular'
}
}
}
},
color: ['#317FFF'],
data: optionData
}
]
},
media: [
{
query: {
maxWidth: 317
},
option: {
legend: {
right: 30,
top: 'center',
textStyle: {
rich: {
name: {
fontSize: 14
},
num: {
fontSize: 16
}
}
}
},
// ()
graphic: [
{
left: '8%', //
top: '26%', //
z: -10,
bounding: 'raw',
rotation: 0, //
origin: [64.5, 32.5], //
scale: [1.0, 1.0], //
//
style: {
image: centerImg,
width: 110,
height: 110,
opacity: 1
}
}
],
series: [
{
type: 'pie',
radius: ['50%', '55%'],
emphasis: {
label: {
rich: {
c: {
fontSize: 22,
lineHeight: 28
},
b: {
fontSize: 16
}
}
}
}
}
]
}
}
]
}
myChart.setOption(option)
// //
// var step = 0
// setInterval(function() {
// // 1
// myChart.setOption({
// graphic: {
// id: 'logo',
// style: {
// transform: 'rotate(' + (step++ % 360) + 'deg)' //
// }
// }
// })
// }, 1000)
this.$LoopShowTooltip(myChart, option.baseOption, { loopSeries: true, interval: 4000 })
}
}
}
</script>
<style lang="scss">
@import "~@/assets/styles/index.scss";
@import "~@/assets/styles/font-some.css";
</style>

292
src/components/echart/yearCircle.vue

@ -0,0 +1,292 @@
<template>
<div style="height: calc(100% - 200px); display: flex; align-items: center; justify-content: flex-start;">
<div id="modelType" style="width:400px; height: 230px" />
</div>
</template>
<script>
export default {
props: {
yearAllNum: {
type: Object,
require: true,
default: function() {
return {}
}
}
},
data() {
return {
}
},
watch: {
'yearAllNum': {
handler(val) {
setTimeout(() => {
this.initYearCircle()
}, 100)
},
immediate: true,
deep: true
}
},
created() {
},
beforeDestroy() {
},
mounted() {
this.initYearCircle()
},
methods: {
initYearCircle() {
const optionData = [
{ value: this.yearAllNum.headerLib || 0, name: '总馆' }
// { value: this.yearAllNum.branchLib || 0, name: '' }
]
const myChart = this.$echarts.init(document.getElementById('modelType'))
function arrCount(arr) {
let count = 0
arr.forEach(item => {
count = count + item.value
})
return count
}
var centerImg = require('@/assets/images/circle-bg.png')
const option = {
baseOption: {
tooltip: {
show: false,
trigger: 'item',
position: 'bottom',
textStyle: {
color: '#EEF6FF',
fontSize: '18'
}
// backgroundColor: 'rgba(74, 144, 226, 0.84)',
// formatter: (params) => {
// return `<div>${params.seriesName} <br> ${params.data.name}${this.$parent.formatter(params.data.value)} (${params.percent}%)</div>`
// }
},
legend: {
orient: 'vertical',
right: 70,
// top: 55,
top: 125,
// textStyle: {
// color: '#EEF6FF',
// padding: [20, 0, 18, 4],
// fontSize: '14'
// },
itemWidth: 10,
itemHeight: 10,
icon: 'circle',
selectedMode: false,
// data: ['', ''],
data: ['总馆'],
formatter: (name) => {
// `${name} ${((flag.value / count).toFixed(2)) * 100 + '%'}`
const count = arrCount(optionData)
if (optionData) {
const flag = optionData?.find(item => name === item.name)
if (flag) {
const percentage = count > 0 ? ((flag.value / count) * 100).toFixed(0) + '%' : '0%'
return [`{name|${name}}`, `{num|${percentage}}`]
}
}
return name
},
textStyle: {
rich: {
name: {
fontSize: 18,
color: '#EEF6FF',
fontFamily: 'DingTalk_JinBuTi_Regular',
padding: [20, 0, 20, 4]
},
num: {
fontSize: 20,
fontWeight: 600,
padding: [20, 0, 20, 15],
color: '#4C90FF',
fontFamily: 'DingTalk_JinBuTi_Regular'
}
}
}
// formatter: function(name) {
// let tarValue
// const count = arrCount(optionData)
// for (let i = 0; i < optionData.length; i++) {
// if (data[i].name === name) {
// tarValue = data[i].value
// }
// }
// return [`{name|${name}}`, `{num|${((tarValue / count).toFixed(2)) * 100 + '%'}}`].join('\n')
// }
},
// ()
graphic: [
{
type: 'image',
id: 'logo',
left: '8.5%', //
top: '22%', //
z: -10,
bounding: 'raw',
rotation: 0, //
origin: [64.5, 32.5], //
scale: [1.0, 1.0], //
//
style: {
image: centerImg,
width: 132,
height: 131,
opacity: 1
}
}
],
series: [
{
name: '本年累计借阅',
type: 'pie',
left: '-50%',
radius: ['60%', '70%'],
avoidLabelOverlap: false,
label: {
show: false,
position: 'center'
},
labelLine: {
show: true
},
itemStyle: {
borderWidth: 2,
borderColor: 'rgba(16,16,21,0.4)'
},
emphasis: {
label: {
show: true,
// params
formatter: function(params) {
const { value, name } = params
return [
`{c| ${value}}`,
`{b| ${name}}`
].join('\n') //
},
rich: {
c: {
fontSize: 24,
fontWeight: 600,
color: '#317FFF',
fontFamily: 'DingTalk_JinBuTi_Regular',
// color: {
// type: 'linear',
// x: 0,
// y: 0,
// x2: 0,
// y2: 1,
// colorStops: [
// {
// offset: 0,
// color: 'red' // 0%
// },
// {
// offset: 1,
// color: 'yellow' // 100%
// }
// ],
// globalCoord: false // false
// },
lineHeight: 34
},
b: {
fontSize: 18,
color: '#fff',
fontFamily: 'DingTalk_JinBuTi_Regular'
}
}
}
},
// color: ['#317FFF', '#31DFFF'],
color: ['#317FFF'],
data: optionData
}
]
},
media: [
{
query: {
maxWidth: 317
},
option: {
legend: {
right: 30,
top: 'center',
textStyle: {
rich: {
name: {
fontSize: 14
},
num: {
fontSize: 16
}
}
}
},
// ()
graphic: [
{
left: '8%', //
top: '26%', //
z: -10,
bounding: 'raw',
rotation: 0, //
origin: [64.5, 32.5], //
scale: [1.0, 1.0], //
//
style: {
image: centerImg,
width: 110,
height: 110,
opacity: 1
}
}
],
series: [
{
type: 'pie',
radius: ['50%', '55%'],
emphasis: {
label: {
rich: {
c: {
fontSize: 22,
lineHeight: 28
},
b: {
fontSize: 16
}
}
}
}
}
]
}
}
]
}
myChart.setOption(option)
this.$LoopShowTooltip(myChart, option.baseOption, { loopSeries: true, interval: 4000 })
}
}
}
</script>
<style lang="scss">
@import "~@/assets/styles/index.scss";
@import "~@/assets/styles/font-some.css";
</style>

10
src/icons/index.js

@ -0,0 +1,10 @@
import Vue from 'vue'
import SvgIcon from '@/components/SvgIcon'// svg component
// register globally
Vue.component('svg-icon', SvgIcon)
// 进行导入所有的svg格式 如果手动引入 需要依次引入
const req = require.context('./svg', false, /\.svg$/)
const requireAll = requireContext => requireContext.keys().map(requireContext)
requireAll(req)

1
src/icons/svg/map.svg

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" pointer-events="none" class="leaflet-zoom-animated" width="1447" height="826" viewBox="-601 -370 1447 826" style="transform: translate3d(-601px, -370px, 0px);"><g><path class="leaflet-interactive" stroke="black" stroke-opacity="1" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="#fff" fill-opacity="1" fill-rule="evenodd" d="M7 -108L5 -106L6 -104L15 -93L21 -91L28 -83L35 -81L38 -77L44 -75L47 -77L50 -75L55 -76L58 -74L58 -69L60 -65L66 -67L68 -66L64 -59L64 -56L71 -52L73 -49L83 -48L83 -45L81 -43L82 -39L78 -35L79 -30L82 -29L77 -25L78 -20L75 -19L90 -9L90 -2L87 1L89 6L89 17L93 25L93 34L88 39L92 46L92 54L99 53L102 56L106 65L105 76L108 91L105 97L108 97L109 100L112 101L114 104L111 111L115 113L113 121L121 131L121 142L124 144L129 144L133 142L140 146L145 144L144 148L149 148L149 152L153 153L151 159L152 162L156 165L159 171L164 170L165 172L171 186L170 196L175 207L175 213L168 222L170 227L174 225L180 228L185 241L184 243L178 245L178 252L183 268L187 272L195 271L197 273L196 277L205 283L210 288L209 290L213 291L218 295L221 295L226 292L231 294L234 293L235 291L232 289L239 285L239 276L242 269L255 277L256 278L253 281L249 279L244 282L243 284L245 289L240 292L240 294L245 298L245 302L257 306L257 311L265 320L263 324L267 328L269 328L275 323L288 309L296 307L307 296L315 291L321 290L323 292L332 283L335 283L337 276L336 270L334 270L332 267L332 261L326 260L328 251L323 252L317 248L312 240L317 233L315 219L318 215L319 210L320 196L318 189L324 181L326 169L323 166L319 171L317 170L317 168L313 168L309 173L308 172L308 161L310 151L308 147L304 148L303 145L298 144L297 146L294 144L293 133L295 127L290 125L289 123L289 113L291 113L293 116L295 116L296 114L294 112L294 108L296 107L296 101L292 98L290 93L297 92L301 86L298 84L298 81L295 78L302 73L298 65L301 62L305 62L306 60L308 60L316 67L317 72L318 66L325 58L339 57L342 52L342 40L334 33L326 32L306 46L296 58L291 57L293 53L292 46L296 39L300 39L299 36L293 33L296 31L298 27L299 29L302 29L307 19L303 17L305 15L305 12L303 10L298 7L292 7L290 5L289 0L291 0L291 -5L294 -8L295 -12L289 -16L287 -15L285 -19L283 -18L279 -20L276 -23L278 -26L273 -29L269 -28L269 -24L266 -24L265 -17L263 -17L263 -19L253 -24L246 -25L239 -23L231 -28L230 -26L220 -26L215 -23L214 -20L219 -15L219 -12L224 -14L223 -12L227 -9L222 4L220 4L215 -1L212 -7L212 -12L204 -15L196 -25L197 -27L192 -35L192 -39L187 -50L187 -53L179 -62L174 -74L174 -84L168 -85L164 -88L162 -92L159 -94L157 -100L152 -104L149 -113L144 -113L140 -107L131 -105L128 -102L122 -104L126 -110L126 -115L124 -116L114 -113L114 -111L110 -107L105 -107L99 -113L99 -118L95 -119L90 -117L85 -120L85 -127L89 -130L89 -132L87 -132L88 -137L86 -137L82 -132L78 -132L73 -140L70 -141L63 -139L63 -134L59 -134L57 -132L54 -132L45 -138L37 -136L33 -128L34 -115L30 -114L32 -112L27 -110L25 -107L20 -108L15 -105L9 -107z" id="祁阳市"/></g></svg>

1
src/icons/svg/place.svg

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1717578633468" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5528" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><path d="M512.9082 73.160632c194.265533 0.331794 351.701904 157.768165 352.033698 352.033698 0.497691 92.570595-35.999676 181.408505-101.446092 246.854921l-5.474605 4.562171L512.991148 920.72904 268.87353 677.523856l-5.474605-5.474605c-65.446416-65.446416-102.026731-154.284326-101.446092-246.854921-0.331794-194.099635 156.689834-351.701904 350.706521-352.033698h0.248846m0.082948-73.160632C277.997872 0.165897 87.630921 190.698744 87.796819 425.692021 87.879767 537.423734 131.842505 644.593277 210.311845 724.140948l302.596355 299.859052 301.68392-300.854435c164.818793-166.892507 163.159822-435.894694-3.815634-600.713487C731.477661 44.128635 624.474016 0.082949 512.991148 0z m0 219.398947c80.874848-0.082949 146.570109 65.529364 146.57011 146.404212s-65.529364 146.570109-146.404213 146.57011c-80.874848 0.082949-146.570109-65.529364-146.570109-146.404213v-0.248845c0.497691-80.626002 65.695261-145.823572 146.321264-146.321264" fill="#3F92F6" p-id="5529"></path></svg>

71
src/main.js

@ -0,0 +1,71 @@
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI)
// 适配flex
import '@/common/flexible.js'
import './assets/js/rollSlide.js'
// import './assets/js/tagcloud-2.2.js'
import './utils/mixins'
// 引入全局css
import './assets/fonts/fonts.css'
import './assets/styles/style.scss'
import './icons'
// 按需引入然后注册在vue原型上
import { Message } from 'element-ui'
Vue.prototype.$message = Message
// 馆代码 1201为东西湖馆代码 / 本地测试用FTZN
// Vue.prototype.libcode = 'FTZN'
Vue.prototype.libcode = '1201'
// 全局注册过滤 - 时间
import { parseTime, getFormattedDate } from '@/utils/index.js'
Vue.filter('parseTime', function(time, cFormat) {
return parseTime(time, cFormat)
})
Vue.prototype.getFormattedDate = getFormattedDate
import axios from 'axios'
Vue.prototype.$axios = axios
// 引入echart
import echarts from 'echarts'
Vue.prototype.$echarts = echarts
import scroll from 'vue-seamless-scroll'
Vue.use(scroll)
import {
loading,
borderBox8,
decoration3,
decoration5,
decoration10,
activeRingChart
} from '@jiaminghi/data-view'
Vue.use(loading)
Vue.use(borderBox8)
Vue.use(decoration3)
Vue.use(decoration5)
Vue.use(decoration10)
Vue.use(activeRingChart)
Vue.config.productionTip = false
Vue.component(Message.name, Message)
new Vue({
router,
store,
render: (h) => h(App)
}).$mount('#app')

22
src/router/index.js

@ -0,0 +1,22 @@
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'index',
component: () => import('../views/index.vue'),
meta: {
title: '智慧大屏'
}
}
]
const router = new VueRouter({
mode: 'hash',
routes
})
export default router

15
src/store/index.js

@ -0,0 +1,15 @@
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
},
mutations: {
},
actions: {
},
modules: {
}
})

105
src/utils/index.js

@ -0,0 +1,105 @@
export function debounce(func, wait, immediate) {
let timeout, args, context, timestamp, result
const later = function() {
// 据上一次触发时间间隔
const last = +new Date() - timestamp
// 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
if (last < wait && last > 0) {
timeout = setTimeout(later, wait - last)
} else {
timeout = null
// 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用
if (!immediate) {
result = func.apply(context, args)
if (!timeout) context = args = null
}
}
}
return function(...args) {
context = this
timestamp = +new Date()
const callNow = immediate && !timeout
// 如果延时不存在,重新设定延时
if (!timeout) timeout = setTimeout(later, wait)
if (callNow) {
result = func.apply(context, args)
context = args = null
}
return result
}
}
/**
* Parse the time to string
* @param {(Object|string|number)} time
* @param {string} cFormat
* @returns {string}
*/
export function parseTime(time, cFormat) {
if (arguments.length === 0) {
return null
}
const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
let date
if (typeof time === 'undefined' || time === null || time === 'null') {
return ''
} else if (typeof time === 'object') {
date = time
} else {
if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
time = parseInt(time)
}
if ((typeof time === 'number') && (time.toString().length === 10)) {
time = time * 1000
}
date = new Date(time)
}
const formatObj = {
y: date.getFullYear(),
m: date.getMonth() + 1,
d: date.getDate(),
h: date.getHours(),
i: date.getMinutes(),
s: date.getSeconds(),
a: date.getDay()
}
const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
let value = formatObj[key]
// Note: getDay() returns 0 on Sunday
if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value ] }
if (result.length > 0 && value < 10) {
value = '0' + value
}
return value || 0
})
return time_str
}
// 获取当前日期时间
export function getCurrentTime() {
const yy = new Date().getFullYear()
const mm = new Date().getMonth() + 1
const dd = new Date().getDate()
const hh = new Date().getHours()
const mf = new Date().getMinutes() < 10 ? '0' + new Date().getMinutes() : new Date().getMinutes()
const ss = new Date().getSeconds() < 10 ? '0' + new Date().getSeconds() : new Date().getSeconds()
const time = yy + '年' + mm + '月' + dd + '日 ' + hh + ':' + mf + ':' + ss
return time
}
export function getFormattedDate(date, yearOffset = 0) {
date.setFullYear(date.getFullYear() + yearOffset)
const year = date.getFullYear()
const month = (date.getMonth() + 1).toString().padStart(2, '0')
const day = date.getDate().toString().padStart(2, '0')
return `${year}-${month}-${day}`
}
export function isExternal(path) {
return /^(https?:|mailto:|tel:)/.test(path)
}

162
src/utils/mixins.js

@ -0,0 +1,162 @@
import Vue from 'vue'
Vue.mixin({
methods: {
// 错误
$LoopShowTooltip(chart, chartOption, options) {
const defaultOptions = {
interval: 2000,
loopSeries: false,
seriesIndex: 0,
updateData: null
}
if (!chart || !chartOption) {
return {}
}
let dataIndex = 0 // 数据索引,初始化为-1,是为了判断是否是第一次执行
let seriesIndex = 0 // 系列索引
let timeTicket = 0
const seriesLen = chartOption.series.length // 系列个数
let dataLen = 0 // 某个系列数据个数
let chartType // 系列类型
let first = true
// 不循环series时seriesIndex指定显示tooltip的系列,不指定默认为0,指定多个则默认为第一个
// 循环series时seriesIndex指定循环的series,不指定则从0开始循环所有series,指定单个则相当于不循环,指定多个
// 要不要添加开始series索引和开始的data索引?
if (options) {
options.interval = options.interval || defaultOptions.interval
options.loopSeries = options.loopSeries || defaultOptions.loopSeries
options.seriesIndex = options.seriesIndex || defaultOptions.seriesIndex
options.updateData = options.updateData || defaultOptions.updateData
} else {
options = defaultOptions
}
// 如果设置的seriesIndex无效,则默认为0
if (options.seriesIndex < 0 || options.seriesIndex >= seriesLen) {
seriesIndex = 0
} else {
seriesIndex = options.seriesIndex
}
function autoShowTip() {
function showTip() {
// 判断是否更新数据
if (dataIndex === 0 && !first && typeof options.updateData === 'function') {
options.updateData()
chart.setOption(chartOption)
}
const series = chartOption.series
chartType = series[seriesIndex].type // 系列类型
dataLen = series[seriesIndex].data.length // 某个系列的数据个数
const tipParams = { seriesIndex: seriesIndex }
switch (chartType) {
case 'map':
case 'pie':
case 'chord':
tipParams.name = series[seriesIndex].data[dataIndex].name
break
case 'radar': // 雷达图
tipParams.seriesIndex = seriesIndex
tipParams.dataIndex = dataIndex
break
default:
tipParams.dataIndex = dataIndex
break
}
if (chartType === 'pie' || chartType === 'radar') {
// 取消之前高亮的图形
chart.dispatchAction({
type: 'downplay',
seriesIndex: options.loopSeries ? (seriesIndex === 0 ? seriesLen - 1 : seriesIndex - 1) : seriesIndex,
dataIndex: dataIndex === 0 ? dataLen - 1 : dataIndex - 1
})
// 高亮当前图形
chart.dispatchAction({
type: 'highlight',
seriesIndex: seriesIndex,
dataIndex: dataIndex
})
}
// 显示 tooltip
tipParams.type = 'showTip'
chart.dispatchAction(tipParams)
dataIndex = (dataIndex + 1) % dataLen
if (options.loopSeries && dataIndex === 0 && !first) { // 数据索引归0表示当前系列数据已经循环完
seriesIndex = (seriesIndex + 1) % seriesLen
}
first = false
}
showTip()
// timeTicket = setInterval(showTip, options.interval)
}
// 关闭轮播
function stopAutoShow() {
if (timeTicket) {
clearInterval(timeTicket)
timeTicket = 0
if (chartType === 'pie' || chartType === 'radar') {
// 取消高亮的图形
chart.dispatchAction({
type: 'downplay',
seriesIndex: options.loopSeries ? (seriesIndex === 0 ? seriesLen - 1 : seriesIndex - 1) : seriesIndex,
dataIndex: dataIndex === 0 ? dataLen - 1 : dataIndex - 1
})
}
}
}
const zRender = chart.getZr()
function zRenderMouseMove(param) {
if (param.event) {
// 阻止canvas上的鼠标移动事件冒泡
param.event.cancelBubble = true
}
stopAutoShow()
}
// 离开echarts图时恢复自动轮播
function zRenderGlobalOut() {
if (!timeTicket) {
autoShowTip()
}
}
// 鼠标在echarts图上时停止轮播
chart.on('mousemove', stopAutoShow)
zRender.on('mousemove', zRenderMouseMove)
zRender.on('globalout', zRenderGlobalOut)
autoShowTip()
return {
clearLoop: function() {
if (timeTicket) {
clearInterval(timeTicket)
timeTicket = 0
}
chart.off('mousemove', stopAutoShow)
zRender.off('mousemove', zRenderMouseMove)
zRender.off('globalout', zRenderGlobalOut)
}
}
}
}
})

46
src/utils/request.js

@ -0,0 +1,46 @@
import axios from 'axios'
// import { Message } from 'element-ui'
// 创建axios实例
const service = axios.create({
// baseURL: process.env.NODE_ENV === 'production' ? process.env.VUE_APP_BASE_API : '/', // api 的 base_url
// baseURL: process.env.VUE_APP_BASE_API, // api 的 base_url
timeout: 1000 * 30, // 请求超时时间
headers: {
'Content-Type': 'application/json'
}
})
// request拦截器
service.interceptors.request.use(
config => {
// if (getToken()) {
// config.headers['Authorization'] = getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
// }
switch (config.urlType) {
case 'local':
config.url = (process.env.NODE_ENV === 'production' ? window.g.ApiUrl : process.env.VUE_APP_BASE_API) + config.url
break
case 'interlib':
config.url = (process.env.NODE_ENV === 'production' ? window.g.LibUrl : process.env.VUE_APP_LIB_API) + config.url
break
}
const token = '' // 登录后生成用于识别用户身份,项目不需要直接去掉
config.headers['Authorization'] = token || ''
return config
},
error => {
console.error('error: ', error)
Promise.reject(error)
}
)
// response 拦截器
service.interceptors.response.use(
response => {
return response.data
},
error => {
return Promise.reject(error)
}
)
export default service

55
src/utils/resizeMixins.js

@ -0,0 +1,55 @@
import { debounce } from '@/utils'
export default {
data() {
return {
$_sidebarElm: null,
$_resizeHandler: null
}
},
mounted() {
this.$_resizeHandler = debounce(() => {
if (this.chart) {
this.chart.resize()
}
}, 100)
this.$_initResizeEvent()
this.$_initSidebarResizeEvent()
},
beforeDestroy() {
this.$_destroyResizeEvent()
this.$_destroySidebarResizeEvent()
},
// to fixed bug when cached by keep-alive
// https://github.com/PanJiaChen/vue-element-admin/issues/2116
activated() {
this.$_initResizeEvent()
this.$_initSidebarResizeEvent()
},
deactivated() {
this.$_destroyResizeEvent()
this.$_destroySidebarResizeEvent()
},
methods: {
// use $_ for mixins properties
// https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential
$_initResizeEvent() {
window.addEventListener('resize', this.$_resizeHandler)
},
$_destroyResizeEvent() {
window.removeEventListener('resize', this.$_resizeHandler)
},
$_sidebarResizeHandler(e) {
if (e.propertyName === 'width') {
this.$_resizeHandler()
}
},
$_initSidebarResizeEvent() {
this.$_sidebarElm = document.getElementsByClassName('sidebar-container')[0]
this.$_sidebarElm && this.$_sidebarElm.addEventListener('transitionend', this.$_sidebarResizeHandler)
},
$_destroySidebarResizeEvent() {
this.$_sidebarElm && this.$_sidebarElm.removeEventListener('transitionend', this.$_sidebarResizeHandler)
}
}
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save