-
9.env.development
-
9.env.production
-
197.eslintrc.js
-
23.gitignore
-
37README.md
-
11babel.config.js
-
56package.json
-
BINpublic/favicon.ico
-
19public/index.html
-
4public/static/config.js
-
16src/App.vue
-
84src/api/inquiryMachine.js
-
BINsrc/assets/404_images/404.png
-
BINsrc/assets/404_images/404_cloud.png
-
BINsrc/assets/fonts/HuXiaoBoNanShenTi.otf
-
BINsrc/assets/fonts/YouSheBiaoTiHei.ttf
-
BINsrc/assets/fonts/ZhenyanGB.ttf
-
19src/assets/fonts/fonts.css
-
80src/assets/iconfont/iconfont.css
-
1src/assets/iconfont/iconfont.js
-
121src/assets/iconfont/iconfont.json
-
51src/assets/iconfont/iconfont.svg
-
BINsrc/assets/iconfont/iconfont.ttf
-
BINsrc/assets/iconfont/iconfont.woff
-
BINsrc/assets/iconfont/iconfont.woff2
-
BINsrc/assets/images/default-img.png
-
BINsrc/assets/images/empty.png
-
BINsrc/assets/images/index/320 180 down.png
-
BINsrc/assets/images/index/320 180 up.png
-
BINsrc/assets/images/index/400 620 left.png
-
BINsrc/assets/images/index/400 620 right.png
-
BINsrc/assets/images/index/760 180 down.png
-
BINsrc/assets/images/index/760 180 up.png
-
BINsrc/assets/images/index/activities.png
-
BINsrc/assets/images/index/bg.png
-
BINsrc/assets/images/index/brief.png
-
BINsrc/assets/images/index/digital.png
-
BINsrc/assets/images/index/guide.png
-
BINsrc/assets/images/index/logo.png
-
BINsrc/assets/images/index/newbook.png
-
BINsrc/assets/images/index/search.png
-
BINsrc/assets/images/index/title.png
-
BINsrc/assets/images/list-title.png
-
BINsrc/assets/images/local-bg.png
-
BINsrc/assets/images/top.png
-
BINsrc/assets/logo.png
-
87src/assets/styles/index.scss
-
209src/assets/styles/quillEditor.css
-
80src/assets/styles/style.scss
-
147src/common/flexible.js
-
61src/common/scrollMixins.js
-
41src/main.js
-
98src/router/index.js
-
48src/store/column.js
-
13src/store/index.js
-
92src/utils/index.js
-
55src/utils/request.js
-
26src/utils/resizeMixins.js
-
90src/views/columnLayout.vue
-
173src/views/columnListMix.vue
-
93src/views/columnListMixDetail.vue
-
64src/views/imgTxtDetail.vue
-
293src/views/index.vue
-
174src/views/menu.vue
-
228src/views/module/bookDetails.vue
-
434src/views/module/waterfall.vue
-
282src/views/newBookRecommend.vue
-
158src/views/old.vue
-
342src/views/waterfallFlow.vue
-
160src/views/waterfallFlow2.vue
-
61vue.config.js
@ -0,0 +1,9 @@ |
|||
ENV = 'development' |
|||
|
|||
# 接口地址 |
|||
|
|||
# 许镇-本地服地址 |
|||
VUE_APP_BASE_API = 'http://192.168.99.72:14000' |
|||
|
|||
# 是否启用 babel-plugin-dynamic-import-node插件 |
|||
VUE_CLI_BABEL_TRANSPILE_MODULES = true |
|||
@ -0,0 +1,9 @@ |
|||
ENV = 'production' |
|||
|
|||
# 如果使用 Nginx 代理后端接口,那么此处需要改为 '/',文件查看 Docker 部署篇,Nginx 配置 |
|||
# 接口地址,注意协议,如果你没有配置 ssl,需要将 https 改为 http |
|||
# VUE_APP_BASE_API = 'https://openapitest.aiyxlib.com' |
|||
VUE_APP_BASE_API = 'http://172.22.0.23:8080' |
|||
# VUE_APP_BASE_API = 'http://127.0.0.1:8080' |
|||
# 如果接口是 http 形式, wss 需要改为 ws |
|||
VUE_APP_WS_API = 'ws://192.168.99.107:7071' |
|||
@ -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': 2, |
|||
'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'] |
|||
} |
|||
} |
|||
@ -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 |
|||
@ -0,0 +1,37 @@ |
|||
自助查询机 |
|||
|
|||
```bash |
|||
# install dependency |
|||
npm install |
|||
|
|||
# develop |
|||
npm run serve |
|||
|
|||
# 构建生产环境 |
|||
npm run build |
|||
|
|||
``` |
|||
```bash |
|||
## 项目结构 |
|||
├── src # 源代码 |
|||
│ ├── api # 所有请求 |
|||
│ ├── assets # 主题 字体等静态资源 |
|||
│ ├── router # 路由 |
|||
│ ├── views # views 所有页面 |
|||
│ │ ├── module |
|||
│ │ │ ├── bookDetails.vue # 书籍详情 |
|||
│ │ ├── activityDetail # 活动详情 |
|||
│ │ ├── activityFeed # 活动资讯list |
|||
│ │ ├── digitalResource # 数字资源 |
|||
│ │ ├── libraryIntroduction # 图书馆简介 |
|||
│ │ ├── newBookRecommend # 新书推荐 |
|||
│ ├── App.vue # 入口页面 |
|||
│ ├── main.js # 入口文件 加载组件 初始化等 注意:Vue.prototype.libcode使用 |
|||
├── .env.xxx # 环境变量配置 |
|||
├── .eslintrc.js # eslint 配置项 |
|||
├── .babelrc # babel-loader 配置 |
|||
├── .travis.yml # 自动化CI配置 |
|||
├── vue.config.js # vue-cli 配置 |
|||
├── postcss.config.js # postcss 配置 |
|||
└── package.json # package.json |
|||
``` |
|||
@ -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' |
|||
] |
|||
} |
|||
@ -0,0 +1,56 @@ |
|||
{ |
|||
"name": "intelligence-inquiry-machine", |
|||
"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": "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.9", |
|||
"swiper": "^8.4.2", |
|||
"vue": "^2.6.11", |
|||
"vue-awesome": "^4.0.2", |
|||
"vue-awesome-swiper": "^3.1.3", |
|||
"vue-router": "^3.1.5", |
|||
"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", |
|||
"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" |
|||
] |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
<!DOCTYPE html> |
|||
<html lang="en"> |
|||
<head> |
|||
<meta charset="utf-8"> |
|||
<meta name="referrer" content="no-referrer"> |
|||
<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> |
|||
@ -0,0 +1,4 @@ |
|||
window.g = { |
|||
AXIOS_TIMEOUT: 10000, |
|||
ApiUrl: 'http://192.168.3.5:8080' // 配置服务器地址
|
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
<template> |
|||
<div id="app"> |
|||
<router-view /> |
|||
</div> |
|||
</template> |
|||
|
|||
<style lang="scss"> |
|||
body { |
|||
margin: 0; |
|||
} |
|||
#app { |
|||
font-family: Avenir, Helvetica, Arial, sans-serif; |
|||
-webkit-font-smoothing: antialiased; |
|||
-moz-osx-font-smoothing: grayscale; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,84 @@ |
|||
import request from '@/utils/request' |
|||
import qs from 'qs' |
|||
|
|||
// 查询机栏目管理详情
|
|||
export function FetchQueryTopicDetails(params) { |
|||
return request({ |
|||
url: '/api/queryMachine/getQueryMenuDetails', |
|||
method: 'get', |
|||
params: params |
|||
}) |
|||
} |
|||
|
|||
// 根据栏目id获取内容
|
|||
export function FetchInitQueryTopicContext(params) { |
|||
return request({ |
|||
url: '/api/queryMachine/initQueryTopicContext', |
|||
method: 'get', |
|||
params: params |
|||
}) |
|||
} |
|||
|
|||
// 新书推荐
|
|||
export function FetchNewBook(params) { |
|||
return request({ |
|||
url: '/api/screenSetting/getNewBook' + '?' + qs.stringify(params, { indices: false }), |
|||
method: 'get' |
|||
}) |
|||
} |
|||
|
|||
// 通过isbn获取图书详细信息
|
|||
export function FetchMarcByISBN(params) { |
|||
return request({ |
|||
url: '/api/screenSetting/marcByISBN' + '?' + qs.stringify(params, { indices: false }), |
|||
method: 'get' |
|||
}) |
|||
} |
|||
|
|||
// 数字资源
|
|||
export function initNumberResoures(params) { |
|||
return request({ |
|||
url: '/dxhtsg/initNumberResoures', |
|||
method: 'get', |
|||
params: params |
|||
}) |
|||
} |
|||
|
|||
// 新书推荐
|
|||
export function FetchNewBookRecommend(params) { |
|||
return request({ |
|||
url: '/dxhtsg/newBookRecommend', |
|||
method: 'get', |
|||
params: params |
|||
}) |
|||
} |
|||
|
|||
// 通过isbn获取图书封面
|
|||
export function FetchCoverByISBN(params) { |
|||
return request({ |
|||
url: '/dxhtsg/getCoverByISBN', |
|||
method: 'get', |
|||
params: params |
|||
// responseType: 'blob'
|
|||
}) |
|||
} |
|||
|
|||
// 图书详情
|
|||
export function getBookDetailsByISBN(params) { |
|||
return request({ |
|||
url: '/api/bookBasice/getBookBasiceByISBN', |
|||
method: 'get', |
|||
params: params |
|||
}) |
|||
} |
|||
|
|||
export default { |
|||
FetchQueryTopicDetails, |
|||
FetchInitQueryTopicContext, |
|||
FetchNewBook, |
|||
FetchMarcByISBN, |
|||
FetchNewBookRecommend, |
|||
FetchCoverByISBN, |
|||
initNumberResoures, |
|||
getBookDetailsByISBN |
|||
} |
|||
|
After Width: 1014 | Height: 556 | Size: 96 KiB |
|
After Width: 152 | Height: 138 | Size: 4.7 KiB |
@ -0,0 +1,19 @@ |
|||
@font-face { |
|||
font-family: "ZhenyanGB"; |
|||
src: url('ZhenyanGB.ttf'); |
|||
font-weight: normal; |
|||
font-style: normal; |
|||
} |
|||
|
|||
@font-face { |
|||
font-family: "YouSheBiaoTiHei"; |
|||
src: url('YouSheBiaoTiHei.ttf'); |
|||
font-weight: normal; |
|||
font-style: normal; |
|||
} |
|||
@font-face { |
|||
font-family: "HuXiaoBoNanShenTi"; |
|||
src: url('HuXiaoBoNanShenTi.otf'); |
|||
font-weight: normal; |
|||
font-style: normal; |
|||
} |
|||
@ -0,0 +1,80 @@ |
|||
@font-face { |
|||
font-family: "iconfont"; /* Project id 3646564 */ |
|||
src: url('iconfont.woff2?t=1664428017869') format('woff2'), |
|||
url('iconfont.woff?t=1664428017869') format('woff'), |
|||
url('iconfont.ttf?t=1664428017869') format('truetype'), |
|||
url('iconfont.svg?t=1664428017869#iconfont') format('svg'); |
|||
} |
|||
|
|||
.iconfont { |
|||
font-family: "iconfont" !important; |
|||
font-size: 16px; |
|||
font-style: normal; |
|||
-webkit-font-smoothing: antialiased; |
|||
-moz-osx-font-smoothing: grayscale; |
|||
} |
|||
|
|||
.icon-weizhi:before { |
|||
content: "\e639"; |
|||
} |
|||
|
|||
.icon-youhua:before { |
|||
content: "\e635"; |
|||
} |
|||
|
|||
.icon-zuohua:before { |
|||
content: "\e638"; |
|||
} |
|||
|
|||
.icon-a-no21:before { |
|||
content: "\e636"; |
|||
} |
|||
|
|||
.icon-a-21:before { |
|||
content: "\e637"; |
|||
} |
|||
|
|||
.icon-jianpan:before { |
|||
content: "\e634"; |
|||
} |
|||
|
|||
.icon-guanbi:before { |
|||
content: "\e630"; |
|||
} |
|||
|
|||
.icon-zuo:before { |
|||
content: "\e631"; |
|||
} |
|||
|
|||
.icon-benjiatushu:before { |
|||
content: "\e632"; |
|||
} |
|||
|
|||
.icon-remen:before { |
|||
content: "\e633"; |
|||
} |
|||
|
|||
.icon-you:before { |
|||
content: "\e62f"; |
|||
} |
|||
|
|||
.icon-tongzhi:before { |
|||
content: "\e628"; |
|||
} |
|||
|
|||
.icon-a-no3:before { |
|||
content: "\e629"; |
|||
} |
|||
|
|||
.icon-a-no1:before { |
|||
content: "\e62b"; |
|||
} |
|||
|
|||
.icon-a-3:before { |
|||
content: "\e62d"; |
|||
} |
|||
|
|||
.icon-a-1:before { |
|||
content: "\e62e"; |
|||
} |
|||
|
|||
1
src/assets/iconfont/iconfont.js
File diff suppressed because it is too large
View File
@ -0,0 +1,121 @@ |
|||
{ |
|||
"id": "3646564", |
|||
"name": "东西湖图书馆", |
|||
"font_family": "iconfont", |
|||
"css_prefix_text": "icon-", |
|||
"description": "", |
|||
"glyphs": [ |
|||
{ |
|||
"icon_id": "32102019", |
|||
"name": "位置", |
|||
"font_class": "weizhi", |
|||
"unicode": "e639", |
|||
"unicode_decimal": 58937 |
|||
}, |
|||
{ |
|||
"icon_id": "31966175", |
|||
"name": "右滑", |
|||
"font_class": "youhua", |
|||
"unicode": "e635", |
|||
"unicode_decimal": 58933 |
|||
}, |
|||
{ |
|||
"icon_id": "31966176", |
|||
"name": "左滑", |
|||
"font_class": "zuohua", |
|||
"unicode": "e638", |
|||
"unicode_decimal": 58936 |
|||
}, |
|||
{ |
|||
"icon_id": "31879702", |
|||
"name": "no.2", |
|||
"font_class": "a-no21", |
|||
"unicode": "e636", |
|||
"unicode_decimal": 58934 |
|||
}, |
|||
{ |
|||
"icon_id": "31879708", |
|||
"name": "2", |
|||
"font_class": "a-21", |
|||
"unicode": "e637", |
|||
"unicode_decimal": 58935 |
|||
}, |
|||
{ |
|||
"icon_id": "31879044", |
|||
"name": "键盘", |
|||
"font_class": "jianpan", |
|||
"unicode": "e634", |
|||
"unicode_decimal": 58932 |
|||
}, |
|||
{ |
|||
"icon_id": "31859389", |
|||
"name": "关闭", |
|||
"font_class": "guanbi", |
|||
"unicode": "e630", |
|||
"unicode_decimal": 58928 |
|||
}, |
|||
{ |
|||
"icon_id": "31859390", |
|||
"name": "左", |
|||
"font_class": "zuo", |
|||
"unicode": "e631", |
|||
"unicode_decimal": 58929 |
|||
}, |
|||
{ |
|||
"icon_id": "31859393", |
|||
"name": "本架图书", |
|||
"font_class": "benjiatushu", |
|||
"unicode": "e632", |
|||
"unicode_decimal": 58930 |
|||
}, |
|||
{ |
|||
"icon_id": "31859394", |
|||
"name": "热门", |
|||
"font_class": "remen", |
|||
"unicode": "e633", |
|||
"unicode_decimal": 58931 |
|||
}, |
|||
{ |
|||
"icon_id": "31859388", |
|||
"name": "右", |
|||
"font_class": "you", |
|||
"unicode": "e62f", |
|||
"unicode_decimal": 58927 |
|||
}, |
|||
{ |
|||
"icon_id": "31804863", |
|||
"name": "通知", |
|||
"font_class": "tongzhi", |
|||
"unicode": "e628", |
|||
"unicode_decimal": 58920 |
|||
}, |
|||
{ |
|||
"icon_id": "31804864", |
|||
"name": "no.3", |
|||
"font_class": "a-no3", |
|||
"unicode": "e629", |
|||
"unicode_decimal": 58921 |
|||
}, |
|||
{ |
|||
"icon_id": "31804866", |
|||
"name": "no.1", |
|||
"font_class": "a-no1", |
|||
"unicode": "e62b", |
|||
"unicode_decimal": 58923 |
|||
}, |
|||
{ |
|||
"icon_id": "31804868", |
|||
"name": "3", |
|||
"font_class": "a-3", |
|||
"unicode": "e62d", |
|||
"unicode_decimal": 58925 |
|||
}, |
|||
{ |
|||
"icon_id": "31804869", |
|||
"name": "1", |
|||
"font_class": "a-1", |
|||
"unicode": "e62e", |
|||
"unicode_decimal": 58926 |
|||
} |
|||
] |
|||
} |
|||
51
src/assets/iconfont/iconfont.svg
File diff suppressed because it is too large
View File
|
After Width: 440 | Height: 526 | Size: 51 KiB |
|
After Width: 200 | Height: 200 | Size: 6.0 KiB |
|
After Width: 324 | Height: 184 | Size: 24 KiB |
|
After Width: 324 | Height: 184 | Size: 26 KiB |
|
After Width: 404 | Height: 624 | Size: 60 KiB |
|
After Width: 404 | Height: 624 | Size: 33 KiB |
|
After Width: 764 | Height: 184 | Size: 31 KiB |
|
After Width: 764 | Height: 184 | Size: 28 KiB |
|
After Width: 215 | Height: 201 | Size: 8.2 KiB |
|
After Width: 1920 | Height: 1080 | Size: 680 KiB |
|
After Width: 234 | Height: 201 | Size: 8.1 KiB |
|
After Width: 245 | Height: 200 | Size: 11 KiB |
|
After Width: 153 | Height: 200 | Size: 8.6 KiB |
|
After Width: 675 | Height: 90 | Size: 12 KiB |
|
After Width: 225 | Height: 200 | Size: 8.7 KiB |
|
After Width: 240 | Height: 201 | Size: 9.9 KiB |
|
After Width: 445 | Height: 111 | Size: 11 KiB |
|
After Width: 494 | Height: 76 | Size: 15 KiB |
|
After Width: 83 | Height: 346 | Size: 6.5 KiB |
|
After Width: 1920 | Height: 200 | Size: 263 KiB |
|
After Width: 200 | Height: 200 | Size: 6.7 KiB |
@ -0,0 +1,87 @@ |
|||
#screen-container { |
|||
width: 100%; |
|||
height: 100vh; |
|||
padding: 0 0.175rem; |
|||
font-size: 0.25rem; |
|||
line-height: 0.35rem; |
|||
color: #fff; |
|||
background-color: #010326; |
|||
overflow: hidden; |
|||
} |
|||
|
|||
.content-main{ |
|||
display: flex; |
|||
justify-content: space-between; |
|||
height: 880px; |
|||
background: #F4F4F4; |
|||
overflow: hidden; |
|||
} |
|||
|
|||
.introduction-main { |
|||
padding: 30px 40px; |
|||
.nav-menu { |
|||
background: #ffffff; |
|||
width: 300px; |
|||
ul { |
|||
margin-top: 30px; |
|||
li { |
|||
height: 90px; |
|||
font-size: 30px; |
|||
font-family: Source Han Sans CN-Regular, Source Han Sans CN; |
|||
font-weight: 400; |
|||
line-height: 90px; |
|||
text-align: center; |
|||
margin-bottom: 20px; |
|||
&:hover { |
|||
background: #e4e4e4; |
|||
} |
|||
&.is-active { |
|||
background: linear-gradient( |
|||
318deg, |
|||
#38b8d9 0%, |
|||
#5394f1 45%, |
|||
#a0a9ef 100% |
|||
); |
|||
color: #ffffff; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
.introduction-info { |
|||
margin-left: 30px; |
|||
background: #ffffff; |
|||
width: 1510px; |
|||
padding: 20px; |
|||
overflow-y: auto; |
|||
.info-title { |
|||
height: 100px; |
|||
text-align: center; |
|||
font-size: 38px; |
|||
font-family: Source Han Sans CN-Regular, Source Han Sans CN; |
|||
font-weight: 400; |
|||
color: #333333; |
|||
line-height: 100px; |
|||
} |
|||
.info-img { |
|||
background: url("~@/assets/images/top.png") no-repeat center -5px; |
|||
} |
|||
} |
|||
} |
|||
.activity-list li { |
|||
height: 90px; |
|||
margin: 0 40px; |
|||
border-bottom: 1px solid #d9d9d9; |
|||
font-size: 30px; |
|||
line-height: 90px; |
|||
padding: 0 20px; |
|||
span.date { |
|||
float: right; |
|||
} |
|||
.activity-title { |
|||
white-space: nowrap; |
|||
overflow: hidden; |
|||
text-overflow: ellipsis; |
|||
width: calc(100% - 282px); |
|||
display: inline-block; |
|||
} |
|||
} |
|||
@ -0,0 +1,209 @@ |
|||
.ql-align-center{ |
|||
text-align: center; |
|||
} |
|||
|
|||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=SimHei]::before, |
|||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=SimHei]::before { |
|||
content: "黑体"; |
|||
font-family: "SimHei"; |
|||
} |
|||
|
|||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Microsoft-YaHei]::before, |
|||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Microsoft-YaHei]::before { |
|||
content: "微软雅黑"; |
|||
font-family: "Microsoft YaHei"; |
|||
} |
|||
|
|||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=KaiTi]::before, |
|||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=KaiTi]::before { |
|||
content: "楷体"; |
|||
font-family: "KaiTi"; |
|||
} |
|||
|
|||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=FangSong]::before, |
|||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=FangSong]::before { |
|||
content: "仿宋"; |
|||
font-family: "FangSong"; |
|||
} |
|||
|
|||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Arial]::before, |
|||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Arial]::before { |
|||
content: "Arial"; |
|||
font-family: "Arial"; |
|||
} |
|||
|
|||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Times-New-Roman]::before, |
|||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Times-New-Roman]::before { |
|||
content: "Times New Roman"; |
|||
font-family: "Times New Roman"; |
|||
} |
|||
|
|||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=sans-serif]::before, |
|||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=sans-serif]::before { |
|||
content: "sans-serif"; |
|||
font-family: "sans-serif"; |
|||
} |
|||
|
|||
.ql-font-SimSun { |
|||
font-family: "SimSun"; |
|||
} |
|||
|
|||
.ql-font-SimHei { |
|||
font-family: "SimHei"; |
|||
} |
|||
|
|||
.ql-font-Microsoft-YaHei { |
|||
font-family: "Microsoft YaHei"; |
|||
} |
|||
|
|||
.ql-font-KaiTi { |
|||
font-family: "KaiTi"; |
|||
} |
|||
|
|||
.ql-font-FangSong { |
|||
font-family: "FangSong"; |
|||
} |
|||
|
|||
.ql-font-Arial { |
|||
font-family: "Arial"; |
|||
} |
|||
|
|||
.ql-font-Times-New-Roman { |
|||
font-family: "Times New Roman"; |
|||
} |
|||
|
|||
.ql-font-sans-serif { |
|||
font-family: "sans-serif"; |
|||
} |
|||
|
|||
/* 字号设置 */ |
|||
/* 默认字号 */ |
|||
.ql-snow .ql-picker.ql-size .ql-picker-label::before, |
|||
.ql-snow .ql-picker.ql-size .ql-picker-item::before { |
|||
content: "12px"; |
|||
} |
|||
|
|||
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="12px"]::before{ |
|||
content: "12px"; |
|||
font-size: 14px; |
|||
} |
|||
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="14px"]::before{ |
|||
content: "14px"; |
|||
font-size: 14px; |
|||
} |
|||
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="16px"]::before{ |
|||
content: "16px"; |
|||
font-size: 14px; |
|||
} |
|||
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="18px"]::before{ |
|||
content: "18px"; |
|||
font-size: 14px; |
|||
} |
|||
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="20px"]::before{ |
|||
content: "20px"; |
|||
font-size: 14px; |
|||
} |
|||
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="22px"]::before{ |
|||
content: "22px"; |
|||
font-size: 14px; |
|||
} |
|||
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="26px"]::before{ |
|||
content: "26px"; |
|||
font-size: 14px; |
|||
} |
|||
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="28px"]::before{ |
|||
content: "28px"; |
|||
font-size: 14px; |
|||
} |
|||
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="30px"]::before{ |
|||
content: "30px"; |
|||
font-size: 14px; |
|||
} |
|||
|
|||
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="12px"]::before { |
|||
content: "12px"; |
|||
font-size: 12px; |
|||
} |
|||
|
|||
.ql-size-12px { |
|||
font-size: 12px; |
|||
} |
|||
|
|||
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="14px"]::before { |
|||
content: "14px"; |
|||
font-size: 14px; |
|||
} |
|||
|
|||
.ql-size-14px { |
|||
font-size: 14px; |
|||
} |
|||
|
|||
|
|||
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="16px"]::before { |
|||
content: "16px"; |
|||
font-size: 16px; |
|||
} |
|||
|
|||
.ql-size-16px { |
|||
font-size: 16px; |
|||
} |
|||
|
|||
|
|||
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="18px"]::before { |
|||
content: "18px"; |
|||
font-size: 18px; |
|||
} |
|||
|
|||
.ql-size-18px { |
|||
font-size: 18px; |
|||
} |
|||
|
|||
|
|||
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="20px"]::before { |
|||
content: "20px"; |
|||
font-size: 20px; |
|||
} |
|||
|
|||
.ql-size-20px { |
|||
font-size: 20px; |
|||
} |
|||
|
|||
|
|||
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="22px"]::before { |
|||
content: "22px"; |
|||
font-size: 22px; |
|||
} |
|||
|
|||
.ql-size-22px { |
|||
font-size: 22px; |
|||
} |
|||
|
|||
|
|||
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="26px"]::before { |
|||
content: "26px"; |
|||
font-size: 26px; |
|||
} |
|||
|
|||
.ql-size-26px { |
|||
font-size: 26px; |
|||
} |
|||
|
|||
|
|||
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="28px"]::before { |
|||
content: "28px"; |
|||
font-size: 28px; |
|||
} |
|||
|
|||
.ql-size-28px { |
|||
font-size: 28px; |
|||
} |
|||
|
|||
|
|||
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="30px"]::before { |
|||
content: "30px"; |
|||
font-size: 30px; |
|||
} |
|||
|
|||
.ql-size-30px { |
|||
font-size: 30px; |
|||
} |
|||
@ -0,0 +1,80 @@ |
|||
@import '~@/assets/iconfont/iconfont.css'; |
|||
|
|||
// 全局样式 |
|||
* { |
|||
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; |
|||
} |
|||
} |
|||
|
|||
.clearfix { |
|||
&::after { |
|||
content: ""; |
|||
display: table; |
|||
height: 0; |
|||
line-height: 0; |
|||
visibility: hidden; |
|||
clear: both; |
|||
} |
|||
} |
|||
|
|||
/**滚动条的宽度*/ |
|||
::-webkit-scrollbar { |
|||
width: 10px; |
|||
height: 10px; |
|||
} |
|||
|
|||
//滚动条的滑块 |
|||
::-webkit-scrollbar-thumb { |
|||
background-color: #44A9E4; |
|||
border-radius: 5px; |
|||
} |
|||
|
|||
.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; |
|||
} |
|||
@ -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'] = {})) |
|||
@ -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 |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,41 @@ |
|||
import Vue from 'vue' |
|||
import App from './App.vue' |
|||
import router from './router' |
|||
import store from './store' |
|||
|
|||
// 适配flex
|
|||
import '@/common/flexible.js' |
|||
|
|||
// 引入全局css
|
|||
import './assets/styles/style.scss' |
|||
import './assets/iconfont/iconfont.js' |
|||
import './assets/fonts/fonts.css' |
|||
import './assets/styles/quillEditor.css' |
|||
|
|||
import ElementUI from 'element-ui' |
|||
import 'element-ui/lib/theme-chalk/index.css' |
|||
Vue.use(ElementUI) |
|||
|
|||
import axios from 'axios' |
|||
Vue.prototype.$axios = axios |
|||
|
|||
// 馆代码 1501 江夏图书馆 1201 东西湖图书馆 FTZN 本地
|
|||
// Vue.prototype.libcode = 'FTZN'
|
|||
// Vue.prototype.libcode = '1501'
|
|||
|
|||
import { parseTime } from '@/utils/index.js' |
|||
Vue.filter('parseTime', function(time, cFormat) { |
|||
return parseTime(time, cFormat) |
|||
}) |
|||
|
|||
// 引入echart
|
|||
import echarts from 'echarts' |
|||
Vue.prototype.$echarts = echarts |
|||
|
|||
Vue.config.productionTip = false |
|||
|
|||
new Vue({ |
|||
router, |
|||
store, |
|||
render: (h) => h(App) |
|||
}).$mount('#app') |
|||
@ -0,0 +1,98 @@ |
|||
import Vue from 'vue' |
|||
import VueRouter from 'vue-router' |
|||
import ColumnLayout from '@/views/columnLayout' |
|||
import ColumnListMix from '@/views/columnListMix' |
|||
import ColumnListMixDetail from '@/views/columnListMixDetail' |
|||
|
|||
Vue.use(VueRouter) |
|||
|
|||
const routes = [ |
|||
{ |
|||
path: '/', |
|||
name: 'index', |
|||
component: () => import('@/views/index.vue'), |
|||
meta: { |
|||
title: '首页' |
|||
} |
|||
}, |
|||
{ |
|||
path: '/NewBookRecommend', |
|||
name: 'NewBookRecommend', |
|||
component: () => import('@/views/newBookRecommend.vue'), |
|||
meta: { |
|||
title: '新书推荐' |
|||
} |
|||
}, |
|||
// {
|
|||
// path: '/DigitalResource',
|
|||
// name: 'DigitalResource',
|
|||
// component: () => import('@/views/digitalResource.vue'),
|
|||
// meta: {
|
|||
// title: '数字资源'
|
|||
// }
|
|||
// },
|
|||
// {
|
|||
// path: '/LibraryIntroduction',
|
|||
// name: 'LibraryIntroduction',
|
|||
// component: () => import('@/views/libraryIntroduction.vue'),
|
|||
// meta: {
|
|||
// title: '图书馆简介'
|
|||
// }
|
|||
// },
|
|||
// {
|
|||
// path: '/ActivityFeed',
|
|||
// name: 'ActivityFeed',
|
|||
// component: () => import('@/views/activityFeed.vue'),
|
|||
// meta: {
|
|||
// title: '活动咨询'
|
|||
// }
|
|||
// },
|
|||
// {
|
|||
// path: '/ActivityDetail',
|
|||
// name: 'ActivityDetail',
|
|||
// component: () => import('@/views/activityDetail.vue'),
|
|||
// meta: {
|
|||
// title: '活动详情'
|
|||
// }
|
|||
// },
|
|||
{ |
|||
path: '/menu', |
|||
name: 'menu', |
|||
component: () => import('@/views/menu.vue') |
|||
}, |
|||
{ |
|||
path: '/imgTxtDetail', |
|||
name: 'imgTxtDetail', |
|||
component: () => import('@/views/imgTxtDetail.vue') |
|||
}, |
|||
{ |
|||
path: '/column', |
|||
name: 'ColumnLayout', |
|||
component: ColumnLayout, |
|||
redirect: '/column/list', |
|||
children: [ |
|||
{ |
|||
path: 'list', |
|||
name: 'ColumnListMix', |
|||
component: ColumnListMix |
|||
}, |
|||
{ |
|||
path: 'detail', |
|||
name: 'ColumnListMixDetail', |
|||
component: ColumnListMixDetail |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
path: '/waterfallFlow', |
|||
name: 'waterfallFlow', |
|||
component: () => import('@/views/waterfallFlow.vue') |
|||
} |
|||
] |
|||
|
|||
const router = new VueRouter({ |
|||
mode: 'hash', |
|||
routes |
|||
}) |
|||
|
|||
export default router |
|||
@ -0,0 +1,48 @@ |
|||
|
|||
// 初始状态
|
|||
const state = { |
|||
tabList: [], |
|||
libcode: '', |
|||
selectMenuIndex: 0 |
|||
} |
|||
|
|||
// mutations
|
|||
const mutations = { |
|||
// 设置专栏数据
|
|||
setColumnData(state, payload) { |
|||
state.tabList = payload.tabList || [] |
|||
state.libcode = payload.libcode || '' |
|||
state.selectMenuIndex = payload.selectMenuIndex || 0 |
|||
}, |
|||
|
|||
// 更新选中的菜单索引
|
|||
setSelectMenuIndex(state, index) { |
|||
state.selectMenuIndex = index |
|||
} |
|||
} |
|||
|
|||
// actions
|
|||
const actions = { |
|||
updateColumnData({ commit }, data) { |
|||
commit('setColumnData', data) |
|||
}, |
|||
|
|||
updateSelectIndex({ commit }, index) { |
|||
commit('setSelectMenuIndex', index) |
|||
} |
|||
} |
|||
|
|||
// getters
|
|||
const getters = { |
|||
getTabList: state => state.tabList, |
|||
getLibcode: state => state.libcode, |
|||
getSelectIndex: state => state.selectMenuIndex |
|||
} |
|||
|
|||
export default { |
|||
namespaced: true, |
|||
state, |
|||
mutations, |
|||
actions, |
|||
getters |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
import Vue from 'vue' |
|||
import Vuex from 'vuex' |
|||
import column from './column' |
|||
|
|||
Vue.use(Vuex) |
|||
|
|||
// 创建并导出store实例
|
|||
export default new Vuex.Store({ |
|||
modules: { |
|||
column // 注册column模块
|
|||
} |
|||
}) |
|||
|
|||
@ -0,0 +1,92 @@ |
|||
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 |
|||
} |
|||
} |
|||
|
|||
// 获取当前日期时间
|
|||
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 |
|||
} |
|||
|
|||
/** |
|||
* 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 |
|||
} |
|||
@ -0,0 +1,55 @@ |
|||
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.NODE_ENV === 'production' ? window.g.ApiUrl : 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 请根据实际情况自行修改
|
|||
// }
|
|||
const token = '' |
|||
config.headers['Authorization'] = token || '' |
|||
return config |
|||
}, |
|||
error => { |
|||
console.error('error: ', error) |
|||
Promise.reject(error) |
|||
} |
|||
) |
|||
|
|||
// response 拦截器
|
|||
service.interceptors.response.use( |
|||
response => { |
|||
const errorMsg = response.data.errMsg |
|||
if (response.status === 200) { |
|||
// console.log(response.data.data)
|
|||
if (response.data instanceof Blob) { |
|||
return response.data |
|||
} else if (response.data.data) { |
|||
return response.data.data |
|||
} else { |
|||
return response.data |
|||
} |
|||
} else { |
|||
Message.error({ |
|||
message: errorMsg, |
|||
duration: 5000 |
|||
}) |
|||
Promise.reject() |
|||
} |
|||
}, |
|||
error => { |
|||
return Promise.reject(error) |
|||
} |
|||
) |
|||
export default service |
|||
@ -0,0 +1,26 @@ |
|||
// 混入代码 resize-mixins.js
|
|||
import { debounce } from '@/utils/index' |
|||
const resizeChartMethod = '$__resizeChartMethod' |
|||
|
|||
export default { |
|||
data() { |
|||
// 在组件内部将图表init的引用映射到chart属性上
|
|||
return { |
|||
chart: null |
|||
} |
|||
}, |
|||
created() { |
|||
window.addEventListener('resize', this[resizeChartMethod], false) |
|||
}, |
|||
beforeDestroy() { |
|||
window.removeEventListener('reisze', this[resizeChartMethod]) |
|||
}, |
|||
methods: { |
|||
// 通过lodash的防抖函数来控制resize的频率
|
|||
[resizeChartMethod]: debounce(function() { |
|||
if (this.chart) { |
|||
this.chart.resize() |
|||
} |
|||
}, 100) |
|||
} |
|||
} |
|||
@ -0,0 +1,90 @@ |
|||
<template> |
|||
<div class="content-main introduction-main"> |
|||
<div class="nav-menu"> |
|||
<ul> |
|||
<li |
|||
v-for="(item,index) in tabList" |
|||
:key="index" |
|||
:class="{ 'is-active': selectMenuIndex === index }" |
|||
@click="selectMenuChange(item, index)" |
|||
> |
|||
{{ item.title }} |
|||
</li> |
|||
</ul> |
|||
</div> |
|||
<div class="introduction-info"> |
|||
<router-view /> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import { FetchQueryTopicDetails } from '@/api/inquiryMachine' |
|||
export default { |
|||
name: 'ColumnLayout', |
|||
data() { |
|||
return { |
|||
libcode: '', |
|||
tabList: [], |
|||
selectMenuIndex: 0 |
|||
} |
|||
}, |
|||
created() { |
|||
const savedIndex = localStorage.getItem('selectIndex') |
|||
if (savedIndex !== null) { |
|||
this.selectMenuIndex = parseInt(savedIndex) |
|||
} |
|||
this.getQueryTopicDetails() |
|||
}, |
|||
methods: { |
|||
getQueryTopicDetails() { |
|||
const params = { 'id': this.$route.query.menuId } |
|||
FetchQueryTopicDetails(params).then(res => { |
|||
console.log('接口返回数据:', res) |
|||
if (res && res.queryTopicList && res.queryTopicList.length > 0) { |
|||
this.tabList = res.queryTopicList |
|||
this.libcode = res.queryMenu.libcode |
|||
// this.$store.commit |
|||
this.$store.commit('column/setColumnData', { |
|||
tabList: this.tabList, |
|||
libcode: this.libcode, |
|||
selectMenuIndex: this.selectMenuIndex |
|||
}) |
|||
console.log('Vuex设置成功:', this.$store.state.column.tabList) |
|||
} else { |
|||
console.error('接口返回的queryTopicList为空或格式错误') |
|||
} |
|||
}).catch(err => { |
|||
console.error('接口请求失败:', err) |
|||
this.$message.error('接口错误') |
|||
}) |
|||
}, |
|||
selectMenuChange(item, index) { |
|||
this.selectMenuIndex = index |
|||
localStorage.setItem('selectIndex', index) |
|||
this.$store.commit('column/setSelectMenuIndex', index) |
|||
const targetRoute = { |
|||
name: 'ColumnListMix', |
|||
query: this.$route.query |
|||
} |
|||
const currentRoute = this.$router.currentRoute |
|||
if (currentRoute.name === targetRoute.name && |
|||
JSON.stringify(currentRoute.query) === JSON.stringify(targetRoute.query)) { |
|||
if (this.$children.length > 0) { |
|||
this.$children[0].getInitQueryTopicContext(item) |
|||
} |
|||
return |
|||
} |
|||
this.$router.push(targetRoute).then(() => { |
|||
if (this.$children.length > 0) { |
|||
this.$children[0].getInitQueryTopicContext(item) |
|||
} |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
@import "~@/assets/styles/index.scss"; |
|||
</style> |
|||
@ -0,0 +1,173 @@ |
|||
<template> |
|||
<div style="height:calc(100%);"> |
|||
<div v-if="detailData && tabList[selectMenuIndex].type ===1" class="new-detial-info"> |
|||
<h2 class="detail-title">{{ detailData.overTitle }}</h2> |
|||
<div class="detail-date">发布时间:{{ detailData.create_time }}</div> |
|||
<div class="detail-content" v-html="detailData.introHtml" /> |
|||
|
|||
</div> |
|||
<ul v-else-if="infoList.length !== 0 && (tabList[selectMenuIndex].type ===2 || tabList[selectMenuIndex]===3)" class="activity-list"> |
|||
<li v-for="(item,index) in infoList" :key="index" @click="toDetail(item)"> |
|||
<div class="activity-title">{{ item.overTitle?item.overTitle:'' }}</div> |
|||
<span class="date">{{ item.create_time }}</span> |
|||
</li> |
|||
</ul> |
|||
<Waterfall |
|||
v-else-if="infoList.length !== 0 && tabList[selectMenuIndex].type ===4" |
|||
:list="infoList" |
|||
:columns="columns" |
|||
:loading="loading" |
|||
:placeholder="placeholderImg" |
|||
:total-items="totalItems" |
|||
@scroll-end="loadMoreData" |
|||
/> |
|||
<div v-else style="height:calc(100%);display: flex; flex-direction: column; justify-content:center ; align-items: center;"> |
|||
<img style="display: block;" src="~@/assets/images/empty.png"> |
|||
<p style="font-size: 30px;">暂无相关数据</p> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import Waterfall from './module/waterfall.vue' |
|||
import { mapState } from 'vuex' |
|||
import { FetchInitQueryTopicContext } from '@/api/inquiryMachine' |
|||
export default { |
|||
name: 'ColumnListMix', |
|||
components: { |
|||
Waterfall |
|||
}, |
|||
data() { |
|||
return { |
|||
detailData: {}, |
|||
infoList: [], |
|||
columns: 2, |
|||
dataList: [], |
|||
loading: false, |
|||
currentPage: 0, |
|||
pageSize: 10, |
|||
totalItems: 0, |
|||
placeholderImg: require('@/assets/images/default-img.png') |
|||
} |
|||
}, |
|||
computed: { |
|||
...mapState('column', ['tabList', 'libcode', 'selectMenuIndex']) |
|||
}, |
|||
watch: { |
|||
$route: { |
|||
handler() { |
|||
console.log('当前Vuex中的tabList:', this.$store.state.column.tabList) |
|||
if (this.tabList.length > 0) { |
|||
this.getInitQueryTopicContext(this.tabList[this.selectMenuIndex]) |
|||
} else { |
|||
const timer = setTimeout(() => { |
|||
if (this.tabList.length > 0) { |
|||
this.getInitQueryTopicContext(this.tabList[this.selectMenuIndex]) |
|||
} else { |
|||
console.log('重试后tabList仍为空') |
|||
} |
|||
clearTimeout(timer) |
|||
}, 500) |
|||
} |
|||
}, |
|||
immediate: true |
|||
} |
|||
}, |
|||
methods: { |
|||
getInitQueryTopicContext(result) { |
|||
console.log(result.type) |
|||
const params = { |
|||
'page': this.currentPage, |
|||
'size': this.pageSize, |
|||
'libcode': this.libcode, |
|||
'topicId': result.id, |
|||
'topicType': result.type |
|||
} |
|||
FetchInitQueryTopicContext(params).then(res => { |
|||
if (res.totalElements) { |
|||
this.totalItems = res.totalElements |
|||
} |
|||
const linkSrc = process.env.NODE_ENV === 'production' |
|||
? window.g.ApiUrl |
|||
: process.env.VUE_APP_BASE_API |
|||
|
|||
if (res && res.content.length > 0) { |
|||
if (result.type === 4) { |
|||
const formattedData = res.content.map(item => ({ |
|||
id: item.id || `item-${Date.now()}-${Math.random()}`, |
|||
type: 'image', |
|||
title: item.overTitle || '无标题', |
|||
image: item.imgUrl ? `${linkSrc}/api/fileRelevant/getImg?imgType=2&imgId=${item.imgUrl}` : this.placeholderImg, |
|||
linkUrl: item.linkUrl || '#' |
|||
})) |
|||
|
|||
this.infoList = [...this.infoList, ...formattedData] |
|||
} else if (result.type === 1) { |
|||
this.detailData = res.content[0] |
|||
} else { |
|||
this.infoList = res.content |
|||
} |
|||
} else { |
|||
this.infoList = [] |
|||
} |
|||
}).catch(() => { |
|||
this.$message.error('接口错误') |
|||
}) |
|||
}, |
|||
loadMoreData() { |
|||
if (this.dataList.length >= this.totalItems) { |
|||
return |
|||
} |
|||
if (this.loading) return |
|||
|
|||
this.currentPage++ |
|||
this.getInitQueryTopicContext(this.tabList[this.selectMenuIndex]) |
|||
}, |
|||
|
|||
isAllDataLoaded() { |
|||
if (this.totalItems > 0) { |
|||
return this.dataList.length >= this.totalItems |
|||
} |
|||
return this.currentPage > 0 && this.dataList.length % this.pageSize !== 0 |
|||
}, |
|||
toDetail(item) { |
|||
// itemId: item.id |
|||
this.$router.push({ |
|||
name: 'ColumnListMixDetail', |
|||
query: { |
|||
...this.$route.query |
|||
} |
|||
}) |
|||
localStorage.setItem('columnListMixDetail', JSON.stringify(item)) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
@import "~@/assets/styles/index.scss"; |
|||
.detail-title{ |
|||
font-size: 32px; |
|||
font-family: Source Han Sans CN-Regular, Source Han Sans CN; |
|||
font-weight: 400; |
|||
color: #333333; |
|||
line-height: 100px; |
|||
text-align: center; |
|||
} |
|||
.detail-date{ |
|||
text-align: center; |
|||
margin-bottom: 20px; |
|||
} |
|||
.detail-content{ |
|||
::v-deep p{ |
|||
span{ |
|||
display: block !important; |
|||
text-indent:2em !important; |
|||
} |
|||
img{ |
|||
display: block; |
|||
margin: 10px auto; |
|||
} |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,93 @@ |
|||
<template> |
|||
<div class="detail-content"> |
|||
<div v-if="detailData" class="detail-info"> |
|||
<h2 class="detail-title">{{ detailData.overTitle }}</h2> |
|||
<div class="detail-date">发布时间:{{ detailData.create_time }}</div> |
|||
<div class="detail-content" v-html="detailData.introHtml" /> |
|||
</div> |
|||
|
|||
<div v-else-if="loading"> |
|||
<p>加载中...</p> |
|||
</div> |
|||
|
|||
<div v-else> |
|||
<p>加载详情失败</p> |
|||
<button @click="reloadDetail">重新加载</button> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
name: 'ColumnListMixDetail', |
|||
data() { |
|||
return { |
|||
detailData: null, |
|||
loading: true |
|||
} |
|||
}, |
|||
created() { |
|||
this.loadDetailData() |
|||
}, |
|||
methods: { |
|||
loadDetailData() { |
|||
this.loading = true |
|||
|
|||
const storedData = localStorage.getItem('columnListMixDetail') |
|||
if (storedData) { |
|||
this.detailData = JSON.parse(storedData) |
|||
this.loading = false |
|||
return |
|||
} |
|||
// 方式2: 如果需要从接口重新获取(推荐) |
|||
// const itemId = this.$route.query.itemId |
|||
// if (itemId) { |
|||
// FetchTopicDetail({ id: itemId }).then(res => { |
|||
// this.detailData = res.data |
|||
// }).catch(err => { |
|||
// console.error('获取详情失败', err) |
|||
// }).finally(() => { |
|||
// this.loading = false |
|||
// }) |
|||
// } else { |
|||
// this.loading = false |
|||
// } |
|||
}, |
|||
// 重新加载详情 |
|||
reloadDetail() { |
|||
this.loadDetailData() |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
@import "~@/assets/styles/index.scss"; |
|||
.detail-info{ |
|||
.detail-title{ |
|||
font-size: 32px; |
|||
font-family: Source Han Sans CN-Regular, Source Han Sans CN; |
|||
font-weight: 400; |
|||
color: #333333; |
|||
line-height: 100px; |
|||
text-align: center; |
|||
} |
|||
.detail-date{ |
|||
text-align: center; |
|||
margin-bottom: 20px; |
|||
} |
|||
.detail-content{ |
|||
::v-deep p{ |
|||
span{ |
|||
display: block !important; |
|||
text-indent:2em !important; |
|||
} |
|||
img{ |
|||
display: block; |
|||
margin: 10px auto; |
|||
} |
|||
} |
|||
} |
|||
|
|||
} |
|||
</style> |
|||
@ -0,0 +1,64 @@ |
|||
<template> |
|||
<div class="content-main introduction-main"> |
|||
<div class="new-detial-info" v-html="rawHtml" /> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import { FetchQueryTopicDetails, FetchInitQueryTopicContext } from '@/api/inquiryMachine' |
|||
export default { |
|||
name: 'ImgTxtDetail', |
|||
data() { |
|||
return { |
|||
rawHtml: '' |
|||
} |
|||
}, |
|||
created() { |
|||
this.getQueryTopicDetails() |
|||
}, |
|||
methods: { |
|||
getQueryTopicDetails() { |
|||
const params = { |
|||
'id': this.$route.query.menuId |
|||
} |
|||
FetchQueryTopicDetails(params).then(res => { |
|||
console.log(res) |
|||
if (res && res.queryTopicList.length > 0) { |
|||
this.getInitQueryTopicContext(res) |
|||
} |
|||
}).catch(() => { |
|||
this.$message.error('接口错误') |
|||
}) |
|||
}, |
|||
getInitQueryTopicContext(result) { |
|||
const params = { |
|||
'page': 0, |
|||
'size': 10, |
|||
'libcode': result.queryMenu.libcode, |
|||
'topicId': result.queryTopicList[0].id, |
|||
'topicType': result.queryTopicList[0].type |
|||
} |
|||
FetchInitQueryTopicContext(params).then(res => { |
|||
console.log(res) |
|||
if (res && res.content.length > 0) { |
|||
this.rawHtml = res.content[0].introHtml |
|||
} else { |
|||
this.rawHtml = '暂无数据' |
|||
} |
|||
}).catch(() => { |
|||
this.$message.error('接口错误') |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
@import "~@/assets/styles/index.scss"; |
|||
.new-detial-info { |
|||
background: #ffffff; |
|||
width: 100%; |
|||
padding: 20px; |
|||
overflow-y: auto; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,293 @@ |
|||
<template> |
|||
<div v-if="pageError" class="wscn-http404-container"> |
|||
<div class="wscn-http404"> |
|||
<div class="pic-404"> |
|||
<img class="pic-404__parent" src="@/assets/404_images/404.png" alt="404"> |
|||
<img class="pic-404__child left" src="@/assets/404_images/404_cloud.png" alt="404"> |
|||
<img class="pic-404__child mid" src="@/assets/404_images/404_cloud.png" alt="404"> |
|||
<img class="pic-404__child right" src="@/assets/404_images/404_cloud.png" alt="404"> |
|||
</div> |
|||
<div class="bullshit"> |
|||
<div class="bullshit__oops">OOPS!</div> |
|||
<div class="bullshit__headline">{{ message }}</div> |
|||
<div class="bullshit__info">请检查您输入的网址是否正确</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import { FetchQueryTopicDetails } from '@/api/inquiryMachine' |
|||
export default { |
|||
name: 'Home', |
|||
data() { |
|||
return { |
|||
pageError: false |
|||
} |
|||
}, |
|||
computed: { |
|||
message() { |
|||
return '暂未查到相关页面......' |
|||
} |
|||
}, |
|||
created() { |
|||
console.log('this.router.path', this.$route.query) |
|||
this.getQueryTopicDetails() |
|||
}, |
|||
methods: { |
|||
getQueryTopicDetails() { |
|||
const params = { |
|||
'id': this.$route.query.menuId |
|||
} |
|||
FetchQueryTopicDetails(params).then(res => { |
|||
this.pageError = false |
|||
console.log(res) |
|||
// res.queryTopicList[0].type = 1 // 图文详情 |
|||
// res.queryTopicList[0].type = 2 // 文字列表 - 图文详情 |
|||
// res.queryTopicList[0].type = 3 // 图文列表 - 图文详情 |
|||
// res.queryTopicList[0].type = 4 // 图文列表 - 外部跳转 |
|||
|
|||
// res.queryMenu.type = 1 // 菜单 |
|||
// res.queryMenu.type = 2 && res.queryTopicList.length === 1 && res.queryTopicList[0].type==1 // 即进入imgTxtDetail页面 |
|||
// res.queryMenu.type = 3 && res.queryTopicList.length >0 // 即进入columnListMix页面 |
|||
// res.queryMenu.type = 4 // 即直接进入newBookRecommend页面 |
|||
localStorage.setItem('menuId', res.queryMenu.id) |
|||
localStorage.setItem('menuInfo', JSON.stringify(res)) |
|||
|
|||
// 根据不同条件跳转不同页面 |
|||
if (res.queryMenu.type === 1) { |
|||
// 带菜单页面 |
|||
this.$router.push({ |
|||
path: '/menu', |
|||
query: { 'menuId': res.queryMenu.id } |
|||
}) |
|||
} else if (res.queryMenu.type === 2 && res.queryTopicList.length === 1 && res.queryTopicList[0].type === 1) { |
|||
// 进入不带栏目得纯图文详情页面 |
|||
// , 'topicId': res.queryTopicList[0].id |
|||
this.$router.push({ |
|||
path: '/imgTxtDetail', |
|||
query: { 'menuId': res.queryMenu.id } |
|||
}) |
|||
} else if (res.queryMenu.type === 3 && res.queryTopicList.length > 1) { |
|||
// 进入columnListMix页面 |
|||
this.$router.push({ |
|||
path: '/column', |
|||
query: { 'menuId': res.queryMenu.id } |
|||
}) |
|||
} else if (res.queryMenu.type === 3 && res.queryTopicList.length === 1 && res.queryTopicList[0].type === 4) { |
|||
// 进入waterfallFlow页面 |
|||
this.$router.push({ |
|||
path: '/waterfallFlow', |
|||
query: { 'menuId': res.queryMenu.id } |
|||
}) |
|||
} else if (res.queryMenu.type === 4) { |
|||
// 进入newBookRecommend页面 |
|||
this.$router.push({ |
|||
path: '/newBookRecommend', |
|||
query: { 'menuId': res.queryMenu.id, 'libcode': res.queryMenu.libcode } |
|||
}) |
|||
} |
|||
}).catch(() => { |
|||
// this.$message.error('接口错误') |
|||
this.pageError = true |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
@import "~@/assets/styles/index.scss"; |
|||
.wscn-http404-container{ |
|||
transform: translate(-50%,-50%); |
|||
position: absolute; |
|||
top: 40%; |
|||
left: 50%; |
|||
} |
|||
.wscn-http404 { |
|||
position: relative; |
|||
width: 1200px; |
|||
padding: 0 50px; |
|||
overflow: hidden; |
|||
.pic-404 { |
|||
position: relative; |
|||
float: left; |
|||
width: 600px; |
|||
overflow: hidden; |
|||
&__parent { |
|||
width: 100%; |
|||
} |
|||
&__child { |
|||
position: absolute; |
|||
&.left { |
|||
width: 80px; |
|||
top: 17px; |
|||
left: 220px; |
|||
opacity: 0; |
|||
animation-name: cloudLeft; |
|||
animation-duration: 2s; |
|||
animation-timing-function: linear; |
|||
animation-fill-mode: forwards; |
|||
animation-delay: 1s; |
|||
} |
|||
&.mid { |
|||
width: 46px; |
|||
top: 10px; |
|||
left: 420px; |
|||
opacity: 0; |
|||
animation-name: cloudMid; |
|||
animation-duration: 2s; |
|||
animation-timing-function: linear; |
|||
animation-fill-mode: forwards; |
|||
animation-delay: 1.2s; |
|||
} |
|||
&.right { |
|||
width: 62px; |
|||
top: 100px; |
|||
left: 500px; |
|||
opacity: 0; |
|||
animation-name: cloudRight; |
|||
animation-duration: 2s; |
|||
animation-timing-function: linear; |
|||
animation-fill-mode: forwards; |
|||
animation-delay: 1s; |
|||
} |
|||
@keyframes cloudLeft { |
|||
0% { |
|||
top: 17px; |
|||
left: 220px; |
|||
opacity: 0; |
|||
} |
|||
20% { |
|||
top: 33px; |
|||
left: 188px; |
|||
opacity: 1; |
|||
} |
|||
80% { |
|||
top: 81px; |
|||
left: 92px; |
|||
opacity: 1; |
|||
} |
|||
100% { |
|||
top: 97px; |
|||
left: 60px; |
|||
opacity: 0; |
|||
} |
|||
} |
|||
@keyframes cloudMid { |
|||
0% { |
|||
top: 10px; |
|||
left: 420px; |
|||
opacity: 0; |
|||
} |
|||
20% { |
|||
top: 40px; |
|||
left: 360px; |
|||
opacity: 1; |
|||
} |
|||
70% { |
|||
top: 130px; |
|||
left: 180px; |
|||
opacity: 1; |
|||
} |
|||
100% { |
|||
top: 160px; |
|||
left: 120px; |
|||
opacity: 0; |
|||
} |
|||
} |
|||
@keyframes cloudRight { |
|||
0% { |
|||
top: 100px; |
|||
left: 500px; |
|||
opacity: 0; |
|||
} |
|||
20% { |
|||
top: 120px; |
|||
left: 460px; |
|||
opacity: 1; |
|||
} |
|||
80% { |
|||
top: 180px; |
|||
left: 340px; |
|||
opacity: 1; |
|||
} |
|||
100% { |
|||
top: 200px; |
|||
left: 300px; |
|||
opacity: 0; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
.bullshit { |
|||
position: relative; |
|||
float: left; |
|||
width: 300px; |
|||
padding: 30px 0; |
|||
overflow: hidden; |
|||
&__oops { |
|||
font-size: 32px; |
|||
font-weight: bold; |
|||
line-height: 40px; |
|||
color: #1482f0; |
|||
opacity: 0; |
|||
margin-bottom: 20px; |
|||
animation-name: slideUp; |
|||
animation-duration: 0.5s; |
|||
animation-fill-mode: forwards; |
|||
} |
|||
&__headline { |
|||
font-size: 20px; |
|||
line-height: 24px; |
|||
color: #222; |
|||
font-weight: bold; |
|||
opacity: 0; |
|||
margin-bottom: 10px; |
|||
animation-name: slideUp; |
|||
animation-duration: 0.5s; |
|||
animation-delay: 0.1s; |
|||
animation-fill-mode: forwards; |
|||
} |
|||
&__info { |
|||
font-size: 13px; |
|||
line-height: 21px; |
|||
color: grey; |
|||
opacity: 0; |
|||
margin-bottom: 30px; |
|||
animation-name: slideUp; |
|||
animation-duration: 0.5s; |
|||
animation-delay: 0.2s; |
|||
animation-fill-mode: forwards; |
|||
} |
|||
&__return-home { |
|||
display: block; |
|||
float: left; |
|||
width: 110px; |
|||
height: 36px; |
|||
background: #1482f0; |
|||
border-radius: 100px; |
|||
text-align: center; |
|||
color: #ffffff; |
|||
opacity: 0; |
|||
font-size: 14px; |
|||
line-height: 36px; |
|||
cursor: pointer; |
|||
animation-name: slideUp; |
|||
animation-duration: 0.5s; |
|||
animation-delay: 0.3s; |
|||
animation-fill-mode: forwards; |
|||
} |
|||
@keyframes slideUp { |
|||
0% { |
|||
transform: translateY(60px); |
|||
opacity: 0; |
|||
} |
|||
100% { |
|||
transform: translateY(0); |
|||
opacity: 1; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,174 @@ |
|||
<template> |
|||
<!-- 活动咨询 --> |
|||
<div class="content-main introduction-main"> |
|||
<div class="nav-menu"> |
|||
<ul> |
|||
<li |
|||
v-for="(item,index) in tabList" |
|||
:key="index" |
|||
:class="{ 'is-active': selectMenuIndex === index }" |
|||
@click="selectMenuChange(item, index)" |
|||
> |
|||
{{ item.title }} |
|||
</li> |
|||
</ul> |
|||
</div> |
|||
<div class="introduction-info"> |
|||
<ul v-if="rightColumnTab.length !== 0" class="menu-tab-list"> |
|||
<li |
|||
v-for="(item,index) in rightColumnTab" |
|||
:key="item.id" |
|||
:class="{ 'active': columeIndex === index }" |
|||
@click="handleColumnClick(item, index)" |
|||
> |
|||
{{ item.title }} |
|||
</li> |
|||
</ul> |
|||
<div style="height: calc(100% - 60px);"> |
|||
<ul v-if="infoList.length !== 0" class="activity-list"> |
|||
<li v-for="item in infoList" :key="item.id" @click="toDetail(item)"> |
|||
<div class="activity-title">{{ item.overTitle?item.overTitle:'' }}</div> |
|||
<span class="date">{{ item.create_time }}</span> |
|||
</li> |
|||
</ul> |
|||
<div v-else style="height:calc(100%);display: flex; flex-direction: column; justify-content:center ; align-items: center;"> |
|||
<img style="display: block;" src="~@/assets/images/empty.png"> |
|||
<p style="font-size: 30px;">暂无相关数据</p> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import { FetchQueryTopicDetails, FetchInitQueryTopicContext } from '@/api/inquiryMachine' |
|||
export default { |
|||
name: 'ActivityFeed', |
|||
data() { |
|||
return { |
|||
libcode: '', |
|||
tabList: [], |
|||
selectMenuIndex: 0, |
|||
rightColumnTab: [], |
|||
columeIndex: 0, |
|||
infoList: [] |
|||
} |
|||
}, |
|||
created() { |
|||
this.getQueryTopicDetails() |
|||
}, |
|||
methods: { |
|||
getQueryTopicDetails() { |
|||
const params = { 'id': this.$route.query.menuId } |
|||
FetchQueryTopicDetails(params).then(res => { |
|||
console.log('接口返回数据:', res) |
|||
if (res && res.queryMenu) { |
|||
this.tabList = res.queryMenu.children |
|||
this.libcode = res.queryMenu.libcode |
|||
this.rightColumnTab = [] |
|||
this.tabList.forEach(childMenu => { |
|||
if (childMenu.queryMenuTopics && childMenu.queryMenuTopics.length > 0) { |
|||
childMenu.queryMenuTopics.forEach(menuTopic => { |
|||
if (menuTopic.queryTopic) { |
|||
this.rightColumnTab.push(menuTopic.queryTopic) |
|||
} |
|||
}) |
|||
} |
|||
}) |
|||
|
|||
if (this.rightColumnTab.length > 0) { |
|||
this.columeIndex = 0 // 默认选中第一个 |
|||
const defaultTopic = this.rightColumnTab[0] // 获取默认选中的queryTopic |
|||
this.getInitQueryTopicContext(defaultTopic) // 传入默认topic请求数据 |
|||
} |
|||
} else { |
|||
this.tabList = [] |
|||
this.rightColumnTab = [] |
|||
this.infoList = [] |
|||
} |
|||
}).catch(err => { |
|||
console.error('接口请求失败:', err) |
|||
this.$message.error('接口错误') |
|||
this.rightColumnTab = [] |
|||
this.infoList = [] |
|||
}) |
|||
}, |
|||
getInitQueryTopicContext(currentTopic) { |
|||
const params = { |
|||
'page': 0, |
|||
'size': 10, |
|||
'libcode': this.libcode, |
|||
'topicId': currentTopic.id, // 传当前选中queryTopic的id(原代码传result.id错误) |
|||
'topicType': currentTopic.type // 传当前选中queryTopic的type(原代码传result.type错误) |
|||
} |
|||
FetchInitQueryTopicContext(params).then(res => { |
|||
if (res && res.content.length > 0) { |
|||
this.infoList = res.content |
|||
} else { |
|||
this.infoList = [] // 无数据时清空列表 |
|||
} |
|||
}).catch(() => { |
|||
this.$message.error('接口错误') |
|||
this.infoList = [] |
|||
}) |
|||
}, |
|||
handleColumnClick(currentTopic, index) { |
|||
this.columeIndex = index // 更新选中索引 |
|||
this.getInitQueryTopicContext(currentTopic) // 传入当前topic请求数据 |
|||
}, |
|||
selectMenuChange(childMenu, index) { |
|||
this.selectMenuIndex = index |
|||
this.rightColumnTab = [] |
|||
if (childMenu.queryMenuTopics && childMenu.queryMenuTopics.length > 0) { |
|||
childMenu.queryMenuTopics.forEach(menuTopic => { |
|||
if (menuTopic.queryTopic) { |
|||
this.rightColumnTab.push(menuTopic.queryTopic) |
|||
} |
|||
}) |
|||
if (this.rightColumnTab.length > 0) { |
|||
this.columeIndex = 0 |
|||
this.getInitQueryTopicContext(this.rightColumnTab[0]) |
|||
} else { |
|||
this.infoList = [] |
|||
} |
|||
} else { |
|||
this.rightColumnTab = [] |
|||
this.infoList = [] |
|||
} |
|||
}, |
|||
toDetail(item) { |
|||
this.$router.push('/ActivityDetail') |
|||
localStorage.setItem('selectIndex', JSON.stringify(this.selectMenuIndex)) |
|||
localStorage.setItem('activityDetail', JSON.stringify(item)) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
@import "~@/assets/styles/index.scss"; |
|||
.menu-tab-list{ |
|||
display: flex; |
|||
justify-content: flex-start; |
|||
font-size: 26px; |
|||
// padding: 10px 0; |
|||
border-bottom: 2px solid #D9D9D9; |
|||
li{ |
|||
padding: 10px 20px; |
|||
margin-right: 20px; |
|||
&.active{ |
|||
position: relative; |
|||
color:#5394F1; |
|||
&::before{ |
|||
position: absolute; |
|||
bottom: -2px; |
|||
left: 0; |
|||
content: ''; |
|||
width: 100%; |
|||
height: 2px; |
|||
background-color: #5394F1; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,228 @@ |
|||
<template> |
|||
<div> |
|||
<el-dialog |
|||
title="图书详情" |
|||
:visible.sync="dialogVisible" |
|||
width="60%" |
|||
> |
|||
<!-- :before-close="handleClose" --> |
|||
<div class="dialog-setting"> |
|||
<div class="book-details-box"> |
|||
<div class="book-details"> |
|||
<div class="book-cover"> |
|||
<img :src="bookData.imgPath ? bookData.imgPath : ''" :onerror="defaultImg"> |
|||
</div> |
|||
<div class="book-desc"> |
|||
<h3>{{ bookData.title }}</h3> |
|||
<p class="book-from">作者:{{ bookData.author }}</p> |
|||
<p v-if="bookData.publisher" class="book-from">出版社:{{ bookData.publisher }}</p> |
|||
<p class="book-brief"> 简介:{{ bookData.summary }}</p> |
|||
</div> |
|||
</div> |
|||
<div class="book-local"> |
|||
<!-- <span v-if="bookData.bookPlace">所在位置:{{ bookData.bookPlace }}</span> --> |
|||
<!-- 待定:热门图书/新书推荐跳转到 场馆导航操作 --> |
|||
<!-- <span v-else>所在位置</span> --> |
|||
<div class="local-title"> |
|||
所在位置 |
|||
</div> |
|||
<ul class="local-list"> |
|||
<template v-if="!bookData.places || bookData.places.length === 0"> |
|||
<li class="local-none"> |
|||
<span>当前图书暂未查到位置信息</span> |
|||
</li> |
|||
</template> |
|||
<template v-else> |
|||
<li |
|||
v-for="(item, index) in bookData.places" |
|||
:key="index" |
|||
class="local-list-info" |
|||
@click="toBookNav(index)" |
|||
> |
|||
<svg class="icon svg-icon" aria-hidden="true"> |
|||
<use xlink:href="#icon-weizhi" /> |
|||
</svg> |
|||
<span>{{ item.shelfName }}</span> |
|||
</li> |
|||
</template> |
|||
</ul> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</el-dialog> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
name: 'BookDetails', |
|||
data() { |
|||
return { |
|||
dialogVisible: false, |
|||
bookData: {}, |
|||
defaultImg: 'this.src="' + require('@/assets/images/default-img.png') + '"' |
|||
} |
|||
}, |
|||
created() { |
|||
}, |
|||
methods: { |
|||
toBookNav(index) { |
|||
const linkSrc = process.env.VUE_APP_BASE_API |
|||
window.location.href = linkSrc + '/anchoring/goNavigation.do?libcode=1201&barcode=' + this.bookData.places[index].barcode |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
::v-deep .el-dialog{ |
|||
position: fixed; |
|||
top: 50%; |
|||
left: 50%; |
|||
margin-top: 0 !important; |
|||
transform: translate(-50%,-50%); |
|||
border-radius: 24px; |
|||
.el-dialog__body{ |
|||
padding: 0 40px 40px 40px ; |
|||
z-index: 999; |
|||
} |
|||
} |
|||
::v-deep .el-dialog__header{ |
|||
text-align: center; |
|||
padding-top:0 ; |
|||
padding-bottom:4px ; |
|||
.el-dialog__title{ |
|||
display: inline-block; |
|||
font-family: "ZhenyanGB"; |
|||
font-size: 40px; |
|||
width: 494px; |
|||
height: 76px; |
|||
line-height: 76px; |
|||
background: url('~@/assets/images/list-title.png') no-repeat 0 0; |
|||
} |
|||
} |
|||
::v-deep .el-dialog__headerbtn{ |
|||
background-color: #3F92F6; |
|||
width: 40px; |
|||
height: 40px; |
|||
border-radius: 50%; |
|||
.el-dialog__close{ |
|||
color: #fff; |
|||
font-size: 30px; |
|||
} |
|||
} |
|||
.book-details-box{ |
|||
.book-details{ |
|||
display: flex; |
|||
justify-content: space-between; |
|||
padding: 30px 0; |
|||
.book-cover{ |
|||
width: 318px; |
|||
height: 382px; |
|||
margin-right: 40px; |
|||
img{ |
|||
width: 100%; |
|||
height: 100%; |
|||
} |
|||
} |
|||
.book-desc{ |
|||
flex: 1; |
|||
color: #333; |
|||
overflow: hidden; |
|||
h3{ |
|||
font-size: 40px; |
|||
font-weight: normal; |
|||
} |
|||
.book-from{ |
|||
width: 100%; |
|||
font-size: 30px; |
|||
} |
|||
h3,.book-from{ |
|||
text-overflow: -o-ellipsis-lastline; |
|||
overflow: hidden; |
|||
text-overflow: ellipsis; |
|||
display: -webkit-box; |
|||
-webkit-line-clamp: 2; |
|||
line-clamp: 2; |
|||
-webkit-box-orient: vertical; |
|||
margin-bottom: 20px; |
|||
} |
|||
.book-brief{ |
|||
font-size: 24px; |
|||
margin-bottom: 20px; |
|||
text-overflow: -o-ellipsis-lastline; |
|||
overflow: hidden; |
|||
text-overflow: ellipsis; |
|||
display: -webkit-box; |
|||
-webkit-line-clamp: 4; |
|||
line-clamp: 4; |
|||
-webkit-box-orient: vertical; |
|||
} |
|||
} |
|||
} |
|||
// .book-local{ |
|||
// border: 1px solid #3F92F6; |
|||
// background: #D0E0F9; |
|||
// border-radius: 52px; |
|||
// height: 64px; |
|||
// line-height: 64px; |
|||
// text-align: center; |
|||
// font-size: 30px; |
|||
// color: #333; |
|||
// overflow: hidden; |
|||
// white-space: nowrap; |
|||
// text-overflow: ellipsis; |
|||
// } |
|||
.book-local { |
|||
height: 343px; |
|||
color: #333; |
|||
display: flex; |
|||
// border-radius: 52px; |
|||
// line-height: 64px; |
|||
// text-align: center; |
|||
// font-size: 30px; |
|||
// overflow: hidden; |
|||
// white-space: nowrap; |
|||
// text-overflow: ellipsis; |
|||
.local-title { |
|||
width: 83px; |
|||
height: 100%; |
|||
background: url("~@/assets/images/local-bg.png") no-repeat; |
|||
writing-mode: vertical-rl; |
|||
text-align: center; |
|||
line-height: 83px; |
|||
font-size: 30px; |
|||
color: #fff; |
|||
} |
|||
.local-list { |
|||
flex: 1; |
|||
border: 1px solid #3f92f6; |
|||
border-left: none; |
|||
background: #d0e0f9; |
|||
overflow: hidden; |
|||
overflow-y: auto; |
|||
position: relative; |
|||
font-size: 26px; |
|||
.local-list-info { |
|||
height: 56px; |
|||
line-height: 56px; |
|||
background-color: #fff; |
|||
// margin-right: 8px; |
|||
margin-bottom: 15px; |
|||
padding-left: 13px; |
|||
span { |
|||
margin-left: 19px; |
|||
} |
|||
} |
|||
.local-none { |
|||
width: 100%; |
|||
text-align: center; |
|||
position: absolute; |
|||
// left: 50%; |
|||
top: 50%; |
|||
transform: translateY(-50%); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,434 @@ |
|||
<template> |
|||
<!-- 参考 https://blog.csdn.net/weixin_44198965/article/details/147831036 --> |
|||
<div class="waterfall-container"> |
|||
<!-- 列容器 --> |
|||
<div ref="columnWrapper" class="waterfall-column-wrapper"> |
|||
<!-- 瀑布流项 --> |
|||
<div |
|||
v-for="(item, index) in renderedList" |
|||
:key="item.id || index" |
|||
v-lazy-load="item.image || item.cover" |
|||
class="waterfall-item" |
|||
> |
|||
<!-- 图片类型 --> |
|||
<div v-if="item.type === 'image'" class="item-content" @click="jump(item.linkUrl)"> |
|||
<img |
|||
:src="placeholder" |
|||
:alt="item.title || '图片'" |
|||
class="item-image" |
|||
> |
|||
<div v-if="item.title" class="item-title">{{ item.title }}</div> |
|||
</div> |
|||
|
|||
<!-- 视频类型 --> |
|||
<div v-else-if="item.type === 'video'" class="item-content"> |
|||
<video |
|||
:poster="placeholder" |
|||
controls |
|||
class="item-video" |
|||
> |
|||
<source :src="item.videoUrl" type="video/mp4"> |
|||
</video> |
|||
<div v-if="item.title" class="item-title">{{ item.title }}</div> |
|||
</div> |
|||
|
|||
<!-- 图文类型 --> |
|||
<div v-else class="item-content"> |
|||
<img |
|||
v-if="item.image" |
|||
:src="placeholder" |
|||
:alt="item.title || '图文'" |
|||
class="item-image" |
|||
> |
|||
<div v-if="item.title" class="item-title">{{ item.title }}</div> |
|||
<div v-if="item.desc" class="item-desc">{{ item.desc }}</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<!-- 加载状态 --> |
|||
<div v-if="loading" class="loading-more"> |
|||
加载中... |
|||
</div> |
|||
<div v-if="isComplete && renderedList.length > 0" class="load-complete"> |
|||
没有更多内容了 |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
name: 'Waterfall', |
|||
|
|||
directives: { |
|||
lazyLoad: { |
|||
inserted(el, binding, vnode) { |
|||
const observer = new IntersectionObserver((entries) => { |
|||
entries.forEach(entry => { |
|||
if (entry.isIntersecting) { |
|||
const img = el.tagName === 'IMG' ? el : el.querySelector('img') |
|||
if (img) { |
|||
img.src = binding.value |
|||
// 图片加载完成后重新布局 |
|||
img.onload = () => { |
|||
vnode.context.layoutItems() |
|||
} |
|||
// 图片加载错误处理 |
|||
img.onerror = () => { |
|||
if (vnode.context.placeholder) { |
|||
img.src = vnode.context.placeholder |
|||
} |
|||
} |
|||
} |
|||
observer.unobserve(el) |
|||
} |
|||
}) |
|||
}, { |
|||
rootMargin: '0px 0px 100px 0px' // 提前100px加载 |
|||
}) |
|||
|
|||
observer.observe(el) |
|||
|
|||
el._observer = observer |
|||
}, |
|||
unbind(el) { |
|||
if (el._observer) { |
|||
el._observer.disconnect() |
|||
} |
|||
} |
|||
} |
|||
}, |
|||
|
|||
// 定义组件props |
|||
props: { |
|||
// 数据源数组 |
|||
list: { |
|||
type: Array, |
|||
required: true, |
|||
default: () => [] |
|||
}, |
|||
// 列数配置 |
|||
columns: { |
|||
type: Number, |
|||
default: 2, |
|||
validator: function(value) { |
|||
return value >= 1 && value <= 5 // 限制列数在1-5之间 |
|||
} |
|||
}, |
|||
// 列间距 |
|||
gap: { |
|||
type: Number, |
|||
default: 10 |
|||
}, |
|||
// 是否开启懒加载 |
|||
lazyLoad: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
// 触底加载的阈值(距离底部多少像素触发加载) |
|||
loadThreshold: { |
|||
type: Number, |
|||
default: 100 |
|||
}, |
|||
// 图片加载时的占位图 |
|||
placeholder: { |
|||
type: String, |
|||
default: '改成你的图片' |
|||
}, |
|||
totalItems: { |
|||
type: Number, |
|||
default: 0 |
|||
} |
|||
}, |
|||
|
|||
data() { |
|||
return { |
|||
waterfallRef: null, // 瀑布流容器引用 |
|||
columnHeights: [], // 每列当前高度数组 |
|||
columnWrapperRef: null, // 列容器引用 |
|||
loading: false, // 加载状态 |
|||
isComplete: false, // 是否已加载全部数据 |
|||
renderedList: [], // 已渲染的数据列表 |
|||
pageSize: 20, // 每次加载的数据量 |
|||
currentPage: 1 // 当前页码 |
|||
} |
|||
}, |
|||
|
|||
computed: { |
|||
// 计算列宽度(根据容器宽度和列数计算) |
|||
columnWidth() { |
|||
if (!this.waterfallRef) return 0 |
|||
const containerWidth = this.waterfallRef.clientWidth |
|||
return (containerWidth - (this.columns - 1) * this.gap) / this.columns |
|||
} |
|||
}, |
|||
|
|||
watch: { |
|||
// 监听列数变化 |
|||
columns(newVal, oldVal) { |
|||
if (newVal !== oldVal) { |
|||
this.resetLayout() |
|||
} |
|||
}, |
|||
|
|||
// 监听数据源变化 |
|||
list: { |
|||
handler(newList) { |
|||
this.renderedList = newList // 直接同步父组件数据(无需分页切片) |
|||
this.$nextTick(() => this.layoutItems()) |
|||
}, |
|||
deep: true |
|||
} |
|||
}, |
|||
|
|||
mounted() { |
|||
this.scrollContainer = this.$el |
|||
this.waterfallRef = this.$el |
|||
this.columnWrapperRef = this.$el.querySelector('.waterfall-column-wrapper') |
|||
|
|||
this.resetLayout() |
|||
if (this.lazyLoad) { |
|||
this.scrollContainer.addEventListener('scroll', this.handleScroll) |
|||
} |
|||
window.addEventListener('resize', this.handleResize) |
|||
}, |
|||
|
|||
beforeDestroy() { |
|||
if (this.lazyLoad && this.scrollContainer) { |
|||
this.scrollContainer.removeEventListener('scroll', this.handleScroll) |
|||
} |
|||
window.removeEventListener('resize', this.handleResize) |
|||
}, |
|||
|
|||
methods: { |
|||
// 初始化列高度数组 |
|||
initColumnHeights() { |
|||
this.columnHeights = new Array(this.columns).fill(0) |
|||
}, |
|||
|
|||
// 初始化渲染数据 |
|||
initRenderList() { |
|||
this.renderedList = this.list.slice(0, this.pageSize) |
|||
this.currentPage = 1 |
|||
this.isComplete = this.renderedList.length >= this.list.length |
|||
}, |
|||
|
|||
// 重置瀑布流布局 |
|||
resetLayout() { |
|||
this.initColumnHeights() |
|||
this.initRenderList() |
|||
this.$nextTick(() => { |
|||
this.layoutItems() |
|||
}) |
|||
}, |
|||
|
|||
// 瀑布流布局算法 |
|||
layoutItems() { |
|||
if (!this.columnWrapperRef || !this.waterfallRef) return |
|||
|
|||
// 获取所有子元素 |
|||
const items = this.columnWrapperRef.children |
|||
if (!items || items.length === 0) return |
|||
|
|||
// 初始化列高度 |
|||
this.initColumnHeights() |
|||
|
|||
// 临时列高度副本用于计算 |
|||
const tempColumnHeights = [...this.columnHeights] |
|||
|
|||
// 遍历所有子元素进行布局 |
|||
Array.from(items).forEach((item, index) => { |
|||
// 找到当前最短的列 |
|||
const minHeight = Math.min(...tempColumnHeights) |
|||
const columnIndex = tempColumnHeights.indexOf(minHeight) |
|||
|
|||
// 计算位置 |
|||
const left = columnIndex * (this.columnWidth + this.gap) |
|||
const top = minHeight |
|||
|
|||
// 应用样式 |
|||
item.style.position = 'absolute' |
|||
item.style.width = `${this.columnWidth}px` |
|||
item.style.left = `${left}px` |
|||
item.style.top = `${top}px` |
|||
item.style.transition = 'all 0.3s ease' |
|||
|
|||
// 更新列高度 |
|||
tempColumnHeights[columnIndex] += item.clientHeight + this.gap |
|||
}) |
|||
|
|||
// 更新列高度 |
|||
this.columnHeights = tempColumnHeights |
|||
|
|||
// 设置容器高度 |
|||
const maxHeight = Math.max(...tempColumnHeights) |
|||
this.columnWrapperRef.style.height = `${maxHeight}px` |
|||
}, |
|||
|
|||
// 滚动事件处理 |
|||
// handleScroll() { |
|||
// if (this.loading || this.isComplete) return |
|||
|
|||
// const scrollTop = document.documentElement.scrollTop || document.body.scrollTop |
|||
// const windowHeight = window.innerHeight |
|||
// const scrollHeight = document.documentElement.scrollHeight |
|||
|
|||
// // 判断是否触底 |
|||
// if (scrollTop + windowHeight >= scrollHeight - this.loadThreshold) { |
|||
// this.loadMore() |
|||
// } |
|||
// }, |
|||
|
|||
handleScroll() { |
|||
if (this.loading || (this.totalItems > 0 && this.renderedList.length >= this.totalItems)) { |
|||
return |
|||
} |
|||
|
|||
// 获取滚动容器(父组件的.content-main) |
|||
const scrollContainer = this.$parent.$el.querySelector('.content-main') || window |
|||
let scrollTop, clientHeight, scrollHeight |
|||
|
|||
if (scrollContainer === window) { |
|||
scrollTop = document.documentElement.scrollTop || document.body.scrollTop |
|||
clientHeight = window.innerHeight |
|||
scrollHeight = document.documentElement.scrollHeight |
|||
} else { |
|||
// 关键:用滚动容器的实际尺寸计算(避免父组件padding影响) |
|||
scrollTop = scrollContainer.scrollTop |
|||
clientHeight = scrollContainer.clientHeight |
|||
scrollHeight = scrollContainer.scrollHeight |
|||
} |
|||
|
|||
// 触底阈值:距离底部100px时触发加载(可调整) |
|||
if (scrollTop + clientHeight >= scrollHeight - this.loadThreshold) { |
|||
this.$emit('scroll-end') // 触发父组件的loadMoreData |
|||
console.log('触发加载更多') |
|||
} |
|||
}, |
|||
|
|||
// 加载更多数据 |
|||
loadMore() { |
|||
if (this.loading || this.isComplete) return |
|||
|
|||
this.loading = true |
|||
|
|||
// 模拟异步加载 |
|||
setTimeout(() => { |
|||
try { |
|||
const nextPage = this.currentPage + 1 |
|||
const startIndex = (nextPage - 1) * this.pageSize |
|||
const endIndex = nextPage * this.pageSize |
|||
|
|||
if (startIndex >= this.list.length) { |
|||
this.isComplete = true |
|||
return |
|||
} |
|||
|
|||
const newItems = this.list.slice(startIndex, endIndex) |
|||
this.renderedList = [...this.renderedList, ...newItems] |
|||
this.currentPage = nextPage |
|||
|
|||
// 检查是否已加载全部数据 |
|||
if (endIndex >= this.list.length) { |
|||
this.isComplete = true |
|||
} |
|||
|
|||
// 等待DOM更新后重新布局 |
|||
this.$nextTick(() => { |
|||
this.layoutItems() |
|||
}) |
|||
} catch (error) { |
|||
console.error('加载更多数据失败:', error) |
|||
} finally { |
|||
this.loading = false |
|||
} |
|||
}, 500) |
|||
}, |
|||
jump(url) { |
|||
window.location.href = url |
|||
}, |
|||
// 响应式处理窗口大小变化 |
|||
handleResize() { |
|||
this.resetLayout() |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.waterfall-container { |
|||
position: relative; |
|||
width: calc(100%); |
|||
height: 800px; |
|||
overflow: hidden; |
|||
overflow-y: auto; |
|||
} |
|||
|
|||
.waterfall-column-wrapper { |
|||
position: relative; |
|||
width: 100%; |
|||
|
|||
} |
|||
|
|||
.waterfall-item { |
|||
margin-bottom: 10px; |
|||
break-inside: avoid; |
|||
box-sizing: border-box; |
|||
background: #fff; |
|||
border-radius: 8px; |
|||
overflow: hidden; |
|||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); |
|||
transition: all 0.3s ease; |
|||
} |
|||
|
|||
.waterfall-item:hover { |
|||
transform: translateY(-5px); |
|||
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); |
|||
} |
|||
|
|||
.item-content { |
|||
padding: 12px; |
|||
} |
|||
|
|||
.item-image, .item-video { |
|||
width: 100%; |
|||
border-radius: 4px; |
|||
display: block; |
|||
background: #f5f5f5; |
|||
} |
|||
|
|||
.item-video { |
|||
aspect-ratio: 9/16; |
|||
object-fit: cover; |
|||
} |
|||
|
|||
.item-title { |
|||
margin-top: 8px; |
|||
font-size: 24px; |
|||
line-height: 1.4; |
|||
color: #333; |
|||
font-weight: bold; |
|||
display: -webkit-box; |
|||
-webkit-line-clamp: 2; |
|||
-webkit-box-orient: vertical; |
|||
overflow: hidden; |
|||
} |
|||
|
|||
.item-desc { |
|||
margin-top: 6px; |
|||
font-size: 12px; |
|||
color: #666; |
|||
line-height: 1.4; |
|||
display: -webkit-box; |
|||
-webkit-line-clamp: 3; |
|||
-webkit-box-orient: vertical; |
|||
overflow: hidden; |
|||
} |
|||
|
|||
.loading-more, .load-complete { |
|||
text-align: center; |
|||
padding: 20px 0; |
|||
color: #999; |
|||
font-size: 14px; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,282 @@ |
|||
<template> |
|||
<!-- 新书推荐 --> |
|||
<div class="content-main new-main"> |
|||
<div class="swiper-container"> |
|||
<div class="swiper-wrapper new-book-list"> |
|||
<div v-for="(item,index) in rankingList" :key="index" class="swiper-slide" @click="handleDetails(index)"> |
|||
<div class="book-list-item"> |
|||
<div class="book-img"> |
|||
<img :src="item.imgPath" :onerror="defaultImg"> |
|||
</div> |
|||
<div class="book-info"> |
|||
<h4 class="title-item">{{ item.name }}</h4> |
|||
<p>作者:{{ item.author }}</p> |
|||
<p>出版社:{{ item.publisher }}</p> |
|||
<p>出版年份:{{ item.publisherdate }}</p> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="icon iconfont prev-btn"> |
|||
<svg class="icon svg-icon" aria-hidden="true"> |
|||
<use xlink:href="#icon-zuohua" /> |
|||
</svg> |
|||
</div> |
|||
<div class="icon iconfont next-btn"> |
|||
<svg class="icon svg-icon" aria-hidden="true"> |
|||
<use xlink:href="#icon-youhua" /> |
|||
</svg> |
|||
</div> |
|||
</div> |
|||
<BookDetails ref="detailDom" /> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import { Swiper } from 'vue-awesome-swiper' |
|||
import 'swiper/swiper-bundle.css' |
|||
// import { FetchNewBookRecommend, FetchCoverByISBN, getBookDetailsByISBN } from '@/api/inquiryMachine' |
|||
import { FetchNewBook, FetchMarcByISBN, getBookDetailsByISBN } from '@/api/inquiryMachine' |
|||
import BookDetails from './module/bookDetails.vue' |
|||
export default { |
|||
name: 'NewBookRecommend', |
|||
components: { |
|||
BookDetails |
|||
}, |
|||
data() { |
|||
return { |
|||
defaultImg: 'this.src="' + require('@/assets/images/default-img.png') + '"', |
|||
coverUrl: null, |
|||
rankingList: [] |
|||
} |
|||
}, |
|||
created() { |
|||
this.getNewBook() |
|||
}, |
|||
mounted() { |
|||
}, |
|||
methods: { |
|||
initSwiper() { |
|||
this.$nextTick(() => { |
|||
new Swiper('.swiper-container', { |
|||
touchEventsTarget: '.swiper-container', |
|||
slidesPerView: 5, |
|||
spaceBetween: 20, |
|||
centeredSlides: true, |
|||
observer: true, |
|||
// loop: true, |
|||
centeredSlidesBounds: true, |
|||
watchSlidesVisibility: true, |
|||
navigation: { |
|||
nextEl: '.next-btn', |
|||
prevEl: '.prev-btn' |
|||
} |
|||
// on: { |
|||
// click: function() { |
|||
// alert(this.clickedIndex) |
|||
// } |
|||
// } |
|||
}) |
|||
}) |
|||
}, |
|||
|
|||
getNewBook() { |
|||
console.log('this.$route.query.libcode', this.$route.query.libcode) |
|||
const params = { |
|||
'libcode': this.$route.query.libcode, |
|||
'size': 40 |
|||
} |
|||
FetchNewBook(params).then(res => { |
|||
// 图片地址格式 http://192.168.99.67:8080/downloadFile/qytsg/ae281b90-b100-4541-9379-3e104854652c.png |
|||
// 图片地址格式 http://192.168.99.72:14000/api/fileRelevant/getImg?imgType=2&imgId=c964bcab-ec82-43f0-8653-04d930d7da4a |
|||
const linkSrc = process.env.NODE_ENV === 'production' ? window.g.ApiUrl : process.env.VUE_APP_BASE_API |
|||
console.log('res.data', res) |
|||
this.rankingList = res.map(item => { |
|||
if (item.imgPath) { |
|||
item.imgPath = linkSrc + '/api/fileRelevant/getImg?imgType=2&imgId=' + item.imgPath |
|||
return Promise.resolve(item) |
|||
} else { |
|||
const params = { |
|||
'sIsbn': item.isbn |
|||
} |
|||
return FetchMarcByISBN(params).then(response => { |
|||
const result = JSON.parse(response.data)[0] |
|||
if (result.srcurl) { |
|||
item.imgPath = result.srcurl |
|||
return item |
|||
} else if (result.img) { |
|||
item.imgPath = 'data:image/png;base64,' + result.img |
|||
return item |
|||
} else { |
|||
return null |
|||
} |
|||
}) |
|||
} |
|||
}) |
|||
Promise.all(this.rankingList).then(results => { |
|||
this.rankingList = results.filter(item => item !== null) |
|||
this.initSwiper() |
|||
}) |
|||
|
|||
console.log('this.rankingList', this.rankingList) |
|||
}) |
|||
}, |
|||
// getBookList() { |
|||
// const linkSrc = process.env.NODE_ENV === 'production' ? window.g.ApiUrl : process.env.VUE_APP_BASE_API |
|||
// const params = { |
|||
// libcode: this.libcode, |
|||
// pageNo: 1, |
|||
// pageSize: 10 |
|||
// } |
|||
// FetchNewBookRecommend(params).then(res => { |
|||
// console.log(res) |
|||
// this.rankingList = res.newbookList.map((item, index) => { |
|||
// if (item.nbImgPath) { |
|||
// item.cover = linkSrc + '/downloadFile' + item.nbImgPath |
|||
// } else { |
|||
// item.cover = null |
|||
// } |
|||
// return item |
|||
// }) |
|||
// this.initSwiper() |
|||
// }).catch(() => { |
|||
// this.$message.error('接口错误') |
|||
// }) |
|||
// }, |
|||
// getCoverByISBN(isbn, item) { |
|||
// const params = { |
|||
// isbn: isbn |
|||
// } |
|||
// FetchCoverByISBN(params).then((res) => { |
|||
// // item.cover = window.URL.createObjectURL(res) |
|||
// item.cover = res |
|||
// this.rankingList.push(item) |
|||
// this.initSwiper() |
|||
// }) |
|||
// }, |
|||
// 详情 |
|||
handleDetails(index) { |
|||
const params = { |
|||
isbn: this.rankingList[index].isbn.replace(/\-/g, '') |
|||
} |
|||
getBookDetailsByISBN(params).then(res => { |
|||
const linkSrc = process.env.NODE_ENV === 'production' ? window.g.ApiUrl : process.env.VUE_APP_BASE_API |
|||
res.imgPath = linkSrc + '/api/fileRelevant/getImg?imgType=2&imgId=' + res.bookCover |
|||
this.$refs.detailDom.bookData = res |
|||
|
|||
this.$refs.detailDom.dialogVisible = true |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
@import "~@/assets/styles/index.scss"; |
|||
.new-main{ |
|||
position: relative; |
|||
padding: 0 50px; |
|||
} |
|||
.new-book-list{ |
|||
color: #333; |
|||
.book-list-item{ |
|||
width: 100%; |
|||
box-shadow: 0px 0px 20px 1px #D2D2D2; |
|||
border-radius: 2px 2px 2px 2px; |
|||
} |
|||
.book-img{ |
|||
height: 6.575rem; |
|||
display: flex; |
|||
align-items: center; |
|||
overflow: hidden; |
|||
img{ |
|||
display: block; |
|||
width: 100%; |
|||
// height: 100%; |
|||
} |
|||
} |
|||
.book-info{ |
|||
padding: 10px 20px; |
|||
h4{ |
|||
font-weight: normal; |
|||
margin-bottom: 20px; |
|||
} |
|||
p{ |
|||
margin-bottom: 10px; |
|||
} |
|||
} |
|||
} |
|||
|
|||
.icon{ |
|||
height: 1.1em; |
|||
} |
|||
.prev-btn, |
|||
.next-btn{ |
|||
position: absolute; |
|||
bottom: 60px; |
|||
font-size: 60px; |
|||
// color: #71C09E; |
|||
z-index: 999; |
|||
} |
|||
|
|||
.prev-btn{ |
|||
left: 100px; |
|||
} |
|||
|
|||
.next-btn{ |
|||
right: 100px; |
|||
} |
|||
|
|||
.swiper-container { |
|||
width: 100%; |
|||
height: 100%; |
|||
overflow: hidden; |
|||
} |
|||
.swiper-slide { |
|||
display: -webkit-box; |
|||
display: -ms-flexbox; |
|||
display: -webkit-flex; |
|||
display: flex; |
|||
-webkit-box-pack: center; |
|||
-ms-flex-pack: center; |
|||
-webkit-justify-content: center; |
|||
justify-content: center; |
|||
-webkit-box-align: center; |
|||
-ms-flex-align: center; |
|||
-webkit-align-items: center; |
|||
align-items: center; |
|||
transition: 300ms; |
|||
transform: scale(0.84); |
|||
.book-info{ |
|||
line-height: 20px; |
|||
font-size: 16px; |
|||
h4{ |
|||
font-size: 20px; |
|||
} |
|||
} |
|||
} |
|||
|
|||
.swiper-slide.swiper-slide-prev, |
|||
.swiper-slide.swiper-slide-next { |
|||
font-size: 28px; |
|||
transform: scale(0.9); |
|||
.book-info{ |
|||
line-height: 28px; |
|||
font-size: 22px; |
|||
h4{ |
|||
font-size: 28px; |
|||
} |
|||
} |
|||
} |
|||
|
|||
.swiper-slide-active,.swiper-slide-duplicate-active { |
|||
transform: scaleX(1); |
|||
.book-info{ |
|||
line-height: 40px; |
|||
font-size: 28px; |
|||
h4{ |
|||
font-size: 40px; |
|||
} |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,158 @@ |
|||
<template> |
|||
<!-- 数字资源 --> |
|||
<div class="content-main"> |
|||
<div class="swiper mySwiper"> |
|||
<div class="swiper-wrapper"> |
|||
<div v-for="(item,index) in swiperListTemp" :key="index" class="swiper-slide img-module"> |
|||
<div v-for="(cell,i) in item" :key="i" :class="{'item-big': i % 4 === 0 || i % 4 === 3, 'item-small': i % 4 === 1 || i % 4 === 2, 'main-item': true}" @click="jump(cell.linkUrl)"> |
|||
<img :src="cell.image" :alt="cell.overTitle || '图片'"> |
|||
<div class="title"> |
|||
{{ cell.overTitle }} |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import { Swiper } from 'vue-awesome-swiper' |
|||
import 'swiper/swiper-bundle.css' |
|||
import { FetchQueryTopicDetails, FetchInitQueryTopicContext } from '@/api/inquiryMachine' |
|||
|
|||
export default { |
|||
name: 'WaterfallFlow', |
|||
data() { |
|||
return { |
|||
rankingList: [] |
|||
} |
|||
}, |
|||
computed: { |
|||
swiperListTemp() { |
|||
let index = 0 |
|||
const count = 4 |
|||
const arrTemp = [] |
|||
const experts = this.rankingList |
|||
for (let i = 0; i < this.rankingList.length; i++) { |
|||
index = parseInt(i / count) |
|||
if (arrTemp.length <= index) { |
|||
arrTemp.push([]) |
|||
} |
|||
arrTemp[index].push(experts[i]) |
|||
} |
|||
return arrTemp |
|||
} |
|||
}, |
|||
created() { |
|||
this.getQueryTopicDetails() |
|||
}, |
|||
mounted() { |
|||
this.initSwiper() |
|||
}, |
|||
methods: { |
|||
initSwiper() { |
|||
this.$nextTick(() => { |
|||
new Swiper('.swiper', {}) |
|||
}) |
|||
}, |
|||
getQueryTopicDetails() { |
|||
const params = { |
|||
'id': this.$route.query.menuId |
|||
} |
|||
FetchQueryTopicDetails(params).then(res => { |
|||
console.log(res) |
|||
if (res && res.queryTopicList.length > 0) { |
|||
this.getInitQueryTopicContext(res) |
|||
} |
|||
}).catch(() => { |
|||
this.$message.error('接口错误') |
|||
}) |
|||
}, |
|||
getInitQueryTopicContext(result) { |
|||
const params = { |
|||
'page': 0, |
|||
'size': 10, |
|||
'libcode': result.queryMenu.libcode, |
|||
'topicId': result.queryTopicList[0].id, |
|||
'topicType': result.queryTopicList[0].type |
|||
} |
|||
FetchInitQueryTopicContext(params).then(res => { |
|||
const linkSrc = process.env.NODE_ENV === 'production' |
|||
? window.g.ApiUrl |
|||
: process.env.VUE_APP_BASE_API |
|||
|
|||
if (res && res.content && res.content.length > 0) { |
|||
this.rankingList = res.content.map(item => { |
|||
if (item && item.imgUrl) { |
|||
return { |
|||
...item, |
|||
image: `${linkSrc}/api/fileRelevant/getImg?imgType=2&imgId=${item.imgUrl}` |
|||
} |
|||
} |
|||
return { |
|||
...item, |
|||
image: null |
|||
} |
|||
}) |
|||
} else { |
|||
this.rankingList = [] |
|||
} |
|||
}).catch(() => { |
|||
this.$message.error('接口错误') |
|||
}) |
|||
}, |
|||
jump(url) { |
|||
window.location.href = url |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
@import "~@/assets/styles/index.scss"; |
|||
.img-module { |
|||
width: 100%; |
|||
height: 100%; |
|||
padding: 40px; |
|||
display: flex; |
|||
flex-wrap: wrap; |
|||
align-items: center; |
|||
justify-content: space-between; |
|||
align-content: space-between; |
|||
.main-item { |
|||
position: relative; |
|||
img { |
|||
width: 100%; |
|||
height: 100%; |
|||
border-radius: 30px; |
|||
} |
|||
.title { |
|||
position: absolute; |
|||
left: 50%; |
|||
top: 50%; |
|||
transform: translate(-50%, -50%); |
|||
font-family: "HuXiaoBoNanShenTi"; |
|||
font-size: 80px; |
|||
color: #333; |
|||
overflow: hidden; |
|||
text-overflow: ellipsis; |
|||
display: -webkit-box; |
|||
-webkit-line-clamp: 3; |
|||
line-clamp: 3; |
|||
-webkit-box-orient: vertical; |
|||
} |
|||
} |
|||
.item-big { |
|||
width: 1000px; |
|||
height: 390px; |
|||
} |
|||
.item-small { |
|||
width: 800px; |
|||
height: 310px; |
|||
.title { |
|||
font-size: 64px; |
|||
} |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,342 @@ |
|||
<template> |
|||
<!-- 数字资源 --> |
|||
<div class="content-main"> |
|||
<div class="swiper mySwiper"> |
|||
<div class="swiper-wrapper"> |
|||
<!-- 每个swiper-slide包含4个项目 --> |
|||
<div v-for="(group, groupIndex) in swiperGroups" :key="groupIndex" class="swiper-slide"> |
|||
<div class="img-module"> |
|||
<div |
|||
v-for="(cell, i) in group" |
|||
:key="i" |
|||
:class="{'item-big': i % 4 === 0 || i % 4 === 3, 'item-small': i % 4 === 1 || i % 4 === 2, 'main-item': true}" |
|||
@click="jump(cell.linkUrl)" |
|||
> |
|||
<img v-if="cell.image" :src="cell.image" :alt="cell.overTitle || '图片'"> |
|||
<div v-else class="placeholder" /> |
|||
<div class="title"> |
|||
{{ cell.overTitle }} |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<!-- Swiper导航按钮 --> |
|||
<div class="swiper-button-prev" /> |
|||
<div class="swiper-button-next" /> |
|||
</div> |
|||
|
|||
<!-- 加载更多按钮 --> |
|||
<div class="load-more" @click="loadMore"> |
|||
<span v-if="isLoading">加载中...</span> |
|||
<span v-else-if="hasMore">加载更多</span> |
|||
<!-- <span v-else>没有更多数据了</span> --> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import { Swiper } from 'vue-awesome-swiper' |
|||
import 'swiper/swiper-bundle.css' |
|||
import { FetchQueryTopicDetails, FetchInitQueryTopicContext } from '@/api/inquiryMachine' |
|||
|
|||
export default { |
|||
name: 'WaterfallFlow', |
|||
components: { |
|||
}, |
|||
data() { |
|||
return { |
|||
rankingList: [], |
|||
swiperInstance: null, |
|||
pageParams: { |
|||
page: 0, |
|||
size: 100, |
|||
libcode: '', |
|||
topicId: '', |
|||
topicType: '' |
|||
}, |
|||
|
|||
hasMore: true, |
|||
isLoading: false |
|||
} |
|||
}, |
|||
computed: { |
|||
// 将数据分成每组4个的数组,保持原始样式结构 |
|||
swiperGroups() { |
|||
const groups = [] |
|||
const itemsPerGroup = 4 |
|||
|
|||
for (let i = 0; i < this.rankingList.length; i += itemsPerGroup) { |
|||
// 从当前索引开始,截取4个元素作为一组 |
|||
groups.push(this.rankingList.slice(i, i + itemsPerGroup)) |
|||
} |
|||
|
|||
return groups |
|||
} |
|||
}, |
|||
created() { |
|||
this.getQueryTopicDetails() |
|||
}, |
|||
mounted() { |
|||
// 监听数据变化,更新Swiper |
|||
this.$watch('swiperGroups', (newVal) => { |
|||
if (newVal.length > 0) { |
|||
this.initSwiper() |
|||
} |
|||
}, { immediate: false }) |
|||
}, |
|||
methods: { |
|||
initSwiper() { |
|||
this.$nextTick(() => { |
|||
if (this.swiperInstance) { |
|||
this.swiperInstance.destroy(true, true) |
|||
} |
|||
|
|||
// 创建新实例,保持横向滑动效果 |
|||
this.swiperInstance = new Swiper('.mySwiper', { |
|||
direction: 'horizontal', |
|||
slidesPerView: 1, // 每次显示一个组 |
|||
speed: 500, |
|||
loop: false, |
|||
navigation: { |
|||
nextEl: '.swiper-button-next', |
|||
prevEl: '.swiper-button-prev' |
|||
}, |
|||
pagination: { |
|||
el: '.swiper-pagination', |
|||
clickable: true, |
|||
renderBullet: function(index, className) { |
|||
return `<span class="${className}">${index + 1}</span>` |
|||
} |
|||
}, |
|||
observer: true, |
|||
observeParents: true |
|||
}) |
|||
}) |
|||
}, |
|||
|
|||
getQueryTopicDetails() { |
|||
const params = { |
|||
'id': this.$route.query.menuId |
|||
} |
|||
|
|||
FetchQueryTopicDetails(params).then(res => { |
|||
console.log('主题详情:', res) |
|||
if (res && res.queryTopicList && res.queryTopicList.length > 0) { |
|||
this.pageParams.libcode = res.queryMenu.libcode |
|||
this.pageParams.topicId = res.queryTopicList[0].id |
|||
this.pageParams.topicType = res.queryTopicList[0].type |
|||
|
|||
this.loadMore() |
|||
} else { |
|||
this.hasMore = false |
|||
} |
|||
}).catch(() => { |
|||
this.$message.error('获取主题详情失败') |
|||
this.hasMore = false |
|||
}) |
|||
}, |
|||
|
|||
loadMore() { |
|||
if (this.isLoading || !this.hasMore) return |
|||
|
|||
this.isLoading = true |
|||
|
|||
const params = { |
|||
page: this.pageParams.page, |
|||
size: this.pageParams.size, |
|||
libcode: this.pageParams.libcode, |
|||
topicId: this.pageParams.topicId, |
|||
topicType: this.pageParams.topicType |
|||
} |
|||
|
|||
FetchInitQueryTopicContext(params).then(res => { |
|||
console.log('获取数据:', res) |
|||
|
|||
if (res && res.content && res.content.length > 0) { |
|||
const linkSrc = process.env.NODE_ENV === 'production' |
|||
? window.g.ApiUrl |
|||
: process.env.VUE_APP_BASE_API |
|||
|
|||
const newItems = res.content.map(item => ({ |
|||
...item, |
|||
image: item.imgUrl ? `${linkSrc}/api/fileRelevant/getImg?imgType=2&imgId=${item.imgUrl}` : null |
|||
})) |
|||
|
|||
this.rankingList = [...this.rankingList, ...newItems] |
|||
|
|||
this.hasMore = newItems.length >= this.pageParams.size |
|||
|
|||
this.pageParams.page++ |
|||
} else { |
|||
this.hasMore = false |
|||
} |
|||
}).catch(() => { |
|||
this.$message.error('获取数据失败') |
|||
}).finally(() => { |
|||
this.isLoading = false |
|||
}) |
|||
}, |
|||
|
|||
jump(url) { |
|||
if (url) { |
|||
window.location.href = url |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
@import "~@/assets/styles/index.scss"; |
|||
// 保持原始样式不变 |
|||
.img-module { |
|||
width: 100%; |
|||
height: 100%; |
|||
padding: 40px; |
|||
display: flex; |
|||
flex-wrap: wrap; |
|||
align-items: center; |
|||
justify-content: space-between; |
|||
align-content: space-between; |
|||
|
|||
.main-item { |
|||
position: relative; |
|||
cursor: pointer; |
|||
transition: transform 0.3s ease; |
|||
|
|||
&:hover { |
|||
transform: translateY(-5px); |
|||
} |
|||
|
|||
img { |
|||
width: 100%; |
|||
height: 100%; |
|||
border-radius: 30px; |
|||
object-fit: cover; |
|||
} |
|||
|
|||
.placeholder { |
|||
width: 100%; |
|||
height: 100%; |
|||
background-color: #f5f5f5; |
|||
border-radius: 30px; |
|||
} |
|||
|
|||
.title { |
|||
position: absolute; |
|||
left: 50%; |
|||
top: 50%; |
|||
transform: translate(-50%, -50%); |
|||
font-family: "HuXiaoBoNanShenTi"; |
|||
font-size: 80px; |
|||
color: #333; |
|||
overflow: hidden; |
|||
text-overflow: ellipsis; |
|||
display: -webkit-box; |
|||
-webkit-line-clamp: 3; |
|||
line-clamp: 3; |
|||
-webkit-box-orient: vertical; |
|||
text-shadow: 0 2px 4px rgba(255, 255, 255, 0.8); |
|||
padding: 0 20px; |
|||
text-align: center; |
|||
} |
|||
} |
|||
|
|||
.item-big { |
|||
width: 1000px; |
|||
height: 390px; |
|||
} |
|||
|
|||
.item-small { |
|||
width: 800px; |
|||
height: 310px; |
|||
|
|||
.title { |
|||
font-size: 64px; |
|||
} |
|||
} |
|||
} |
|||
|
|||
// 加载更多按钮样式 |
|||
.load-more { |
|||
position: fixed; |
|||
bottom: 20px; |
|||
left: 0; |
|||
width: 100%; |
|||
text-align: center; |
|||
padding: 30px 0; |
|||
font-size: 18px; |
|||
color: #666; |
|||
z-index: 9999; |
|||
cursor: pointer; |
|||
transition: color 0.3s; |
|||
|
|||
&:hover { |
|||
color: #007bff; |
|||
} |
|||
} |
|||
|
|||
// Swiper导航按钮样式 |
|||
.swiper-button-prev, |
|||
.swiper-button-next { |
|||
width: 50px; |
|||
height: 50px; |
|||
background-color: rgba(255, 255, 255, 0.8); |
|||
border-radius: 50%; |
|||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); |
|||
|
|||
&::after { |
|||
font-size: 20px; |
|||
color: #333; |
|||
} |
|||
} |
|||
|
|||
.swiper-button-prev { |
|||
left: 10px; |
|||
} |
|||
|
|||
.swiper-button-next { |
|||
right: 10px; |
|||
} |
|||
|
|||
.swiper-pagination { |
|||
bottom: 0; |
|||
|
|||
.swiper-pagination-bullet { |
|||
width: 12px; |
|||
height: 12px; |
|||
margin: 0 6px; |
|||
background-color: #ddd; |
|||
|
|||
&.swiper-pagination-bullet-active { |
|||
background-color: #007bff; |
|||
width: 30px; |
|||
border-radius: 6px; |
|||
} |
|||
} |
|||
} |
|||
|
|||
@media (max-width: 1920px) { |
|||
.item-big { |
|||
width: calc(50% - 20px); |
|||
height: auto; |
|||
} |
|||
|
|||
.item-small { |
|||
width: calc(25% - 20px); |
|||
height: auto; |
|||
} |
|||
} |
|||
|
|||
@media (max-width: 1200px) { |
|||
.main-item .title { |
|||
font-size: 60px; |
|||
} |
|||
|
|||
.item-small .title { |
|||
font-size: 48px; |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,160 @@ |
|||
<template> |
|||
<div class="content-main" style="padding: 40px;"> |
|||
<waterfall |
|||
:list="dataList" |
|||
:columns="columns" |
|||
:loading="loading" |
|||
:placeholder="placeholderImg" |
|||
:total-items="totalItems" |
|||
@scroll-end="loadMoreData" |
|||
/> |
|||
</div> |
|||
<!-- <div class="controls"> |
|||
<button :class="{ active: columns === 2 }" @click="columns = 2">2列</button> |
|||
<button :class="{ active: columns === 3 }" @click="columns = 3">3列</button> |
|||
<button :class="{ active: columns === 4 }" @click="columns = 4">4列</button> |
|||
</div> --> |
|||
</template> |
|||
|
|||
<script> |
|||
import Waterfall from './module/waterfall.vue' |
|||
import { FetchQueryTopicDetails, FetchInitQueryTopicContext } from '@/api/inquiryMachine' |
|||
|
|||
export default { |
|||
components: { |
|||
Waterfall |
|||
}, |
|||
|
|||
data() { |
|||
return { |
|||
columns: 2, |
|||
dataList: [], |
|||
loading: false, |
|||
currentPage: 0, |
|||
pageSize: 10, |
|||
totalItems: 0, |
|||
topicInfo: null, |
|||
placeholderImg: require('@/assets/images/default-img.png') |
|||
} |
|||
}, |
|||
|
|||
created() { |
|||
this.getQueryTopicDetails() |
|||
}, |
|||
|
|||
methods: { |
|||
getQueryTopicDetails() { |
|||
this.loading = true |
|||
const params = { |
|||
'id': this.$route.query.menuId |
|||
} |
|||
FetchQueryTopicDetails(params).then(res => { |
|||
console.log('主题详情数据:', res) |
|||
if (res && res.queryTopicList && res.queryTopicList.length > 0) { |
|||
this.topicInfo = res |
|||
this.currentPage = 0 |
|||
this.getInitQueryTopicContext() |
|||
} else { |
|||
this.$message.warning('未找到相关主题数据') |
|||
this.loading = false |
|||
} |
|||
}).catch(() => { |
|||
this.$message.error('获取主题详情失败') |
|||
this.loading = false |
|||
}) |
|||
}, |
|||
|
|||
// 获取主题内容 |
|||
getInitQueryTopicContext() { |
|||
if (!this.topicInfo) return |
|||
|
|||
this.loading = true |
|||
const params = { |
|||
'page': this.currentPage, |
|||
'size': this.pageSize, |
|||
'libcode': this.topicInfo.queryMenu.libcode, |
|||
'topicId': this.topicInfo.queryTopicList[0].id, |
|||
'topicType': this.topicInfo.queryTopicList[0].type |
|||
} |
|||
|
|||
FetchInitQueryTopicContext(params).then(res => { |
|||
this.loading = false |
|||
// console.log('res.totalElements', res.totalElements) |
|||
if (res.totalElements) { |
|||
this.totalItems = res.totalElements |
|||
} |
|||
|
|||
const linkSrc = process.env.NODE_ENV === 'production' |
|||
? window.g.ApiUrl |
|||
: process.env.VUE_APP_BASE_API |
|||
|
|||
if (res && res.content && res.content.length > 0) { |
|||
const formattedData = res.content.map(item => ({ |
|||
id: item.id || `item-${Date.now()}-${Math.random()}`, |
|||
type: 'image', |
|||
title: item.overTitle || '无标题', |
|||
image: item.imgUrl ? `${linkSrc}/api/fileRelevant/getImg?imgType=2&imgId=${item.imgUrl}` : this.placeholderImg, |
|||
linkUrl: item.linkUrl || '#' |
|||
})) |
|||
|
|||
this.dataList = [...this.dataList, ...formattedData] |
|||
// console.log(`第${this.currentPage + 1}页加载后总条数:`, this.dataList.length) |
|||
} else { |
|||
this.totalItems = this.dataList.length |
|||
} |
|||
}).catch(() => { |
|||
this.$message.error('获取主题内容失败') |
|||
this.loading = false |
|||
}) |
|||
}, |
|||
|
|||
// 加载更多数据 |
|||
loadMoreData() { |
|||
if (this.dataList.length >= this.totalItems) { |
|||
// console.log('已加载全部5条数据') |
|||
return |
|||
} |
|||
if (this.loading) return |
|||
|
|||
this.currentPage++ |
|||
// console.log('开始加载第', this.currentPage + 1, '页') |
|||
this.getInitQueryTopicContext() |
|||
}, |
|||
|
|||
isAllDataLoaded() { |
|||
if (this.totalItems > 0) { |
|||
return this.dataList.length >= this.totalItems |
|||
} |
|||
return this.currentPage > 0 && this.dataList.length % this.pageSize !== 0 |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
@import "~@/assets/styles/index.scss"; |
|||
// .controls { |
|||
// margin-bottom: 20px; |
|||
// display: flex; |
|||
// gap: 10px; |
|||
// padding: 0 16px; |
|||
// } |
|||
|
|||
// .controls button { |
|||
// padding: 8px 16px; |
|||
// background: #f0f0f0; |
|||
// border: none; |
|||
// border-radius: 4px; |
|||
// cursor: pointer; |
|||
// transition: all 0.2s ease; |
|||
// } |
|||
|
|||
// .controls button:hover { |
|||
// background: #e0e0e0; |
|||
// } |
|||
|
|||
// .controls button.active { |
|||
// background: #ff2442; |
|||
// color: white; |
|||
// } |
|||
</style> |
|||
@ -0,0 +1,61 @@ |
|||
const path = require('path') |
|||
const resolve = dir => { |
|||
return path.join(__dirname, dir) |
|||
} |
|||
const name = '自助查询机' |
|||
module.exports = { |
|||
publicPath: process.env.NODE_ENV === 'development' ? '/' : './', |
|||
outputDir: 'dist', |
|||
assetsDir: 'static', |
|||
lintOnSave: process.env.NODE_ENV === 'development', |
|||
productionSourceMap: false, |
|||
devServer: { |
|||
port: 3000, |
|||
open: true, |
|||
overlay: { |
|||
warnings: false, |
|||
errors: true |
|||
}, |
|||
proxy: { |
|||
'/api': { |
|||
target: process.env.VUE_APP_BASE_API, |
|||
changeOrigin: true, |
|||
pathRewrite: { |
|||
'^/api': 'api' |
|||
} |
|||
}, |
|||
'/auth': { |
|||
target: process.env.VUE_APP_BASE_API, |
|||
changeOrigin: true, |
|||
pathRewrite: { |
|||
'^/auth': 'auth' |
|||
} |
|||
} |
|||
} |
|||
}, |
|||
configureWebpack: { |
|||
name: name, |
|||
resolve: { |
|||
alias: { |
|||
'@': resolve('src') |
|||
} |
|||
}, |
|||
performance: { |
|||
hints: 'warning', |
|||
// 入口起点的最大体积
|
|||
maxEntrypointSize: 50000000, |
|||
// 生成文件的最大体积
|
|||
maxAssetSize: 30000000 |
|||
} |
|||
}, |
|||
chainWebpack: config => { |
|||
config.resolve |
|||
.alias.set('_c', resolve('src/components')) |
|||
|
|||
config.plugin('html') |
|||
.tap(args => { |
|||
args[0].title = name |
|||
return args |
|||
}) |
|||
} |
|||
} |
|||