-
8.env.production
-
197.eslintrc.js
-
23.gitignore
-
32README.md
-
11babel.config.js
-
57package.json
-
BINpublic/favicon.ico
-
19public/index.html
-
4public/static/config.js
-
16src/App.vue
-
130src/api/inquiryMachine.js
-
BINsrc/assets/fonts/HuXiaoBoNanShenTi.otf
-
BINsrc/assets/fonts/YouSheBiaoTiHei.ttf
-
BINsrc/assets/fonts/ZhenyanGB.ttf
-
19src/assets/fonts/fonts.css
-
627src/assets/iconfont/iconfont.css
-
1src/assets/iconfont/iconfont.js
-
1080src/assets/iconfont/iconfont.json
-
BINsrc/assets/iconfont/iconfont.ttf
-
BINsrc/assets/iconfont/iconfont.woff
-
BINsrc/assets/iconfont/iconfont.woff2
-
BINsrc/assets/images/bg.png
-
BINsrc/assets/images/border.png
-
BINsrc/assets/images/default-img-bg.jpg
-
BINsrc/assets/images/default-img.png
-
BINsrc/assets/images/default-img22.png
-
BINsrc/assets/images/img10.png
-
BINsrc/assets/images/img3.png
-
BINsrc/assets/images/img5.png
-
BINsrc/assets/images/img6.png
-
BINsrc/assets/images/img7.png
-
BINsrc/assets/images/img8.png
-
BINsrc/assets/images/img9.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/shad2.png
-
BINsrc/assets/images/shelf01.png
-
BINsrc/assets/images/shelf02.png
-
BINsrc/assets/images/shelf03.png
-
BINsrc/assets/images/shelf04.png
-
BINsrc/assets/images/shelf05.png
-
BINsrc/assets/images/shelf06.png
-
BINsrc/assets/images/top-bg.png
-
BINsrc/assets/images/top.png
-
BINsrc/assets/logo.png
-
829src/assets/styles/index.scss
-
180src/assets/styles/style.scss
-
147src/common/flexible.js
-
61src/common/scrollMixins.js
-
39src/main.js
-
54src/router/index.js
-
15src/store/index.js
-
92src/utils/index.js
-
55src/utils/request.js
-
26src/utils/resizeMixins.js
-
181src/views/bookList.vue
-
546src/views/girdList.vue
-
163src/views/index.vue
-
344src/views/mixins/index.js
-
195src/views/module/bookDetails.vue
-
337src/views/module/canvasPreview.vue
-
145src/views/module/ranking.vue
-
133src/views/module/search.vue
-
141src/views/module/shelfRanking.vue
-
195src/views/regionsList.vue
-
629src/views/shelfList.vue
-
69vue.config.js
@ -0,0 +1,8 @@ |
|||
ENV = 'production' |
|||
|
|||
# 如果使用 Nginx 代理后端接口,那么此处需要改为 '/',文件查看 Docker 部署篇,Nginx 配置 |
|||
# 接口地址,注意协议,如果你没有配置 ssl,需要将 https 改为 http |
|||
|
|||
VUE_APP_BASE_API = 'http://192.168.3.220:12010' |
|||
# 如果接口是 http 形式, wss 需要改为 ws |
|||
VUE_APP_WS_API = 'ws://192.168.3.220:12011' |
|||
@ -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,32 @@ |
|||
江夏区图书馆自助查询机 |
|||
|
|||
```bash |
|||
# install dependency |
|||
npm install |
|||
|
|||
# develop |
|||
npm run serve |
|||
|
|||
# 构建生产环境 |
|||
npm run build |
|||
|
|||
``` |
|||
```bash |
|||
## 项目结构 |
|||
├── src # 源代码 |
|||
│ ├── api # 所有请求 |
|||
│ ├── assets # 主题 字体等静态资源 |
|||
│ ├── router # 路由 |
|||
│ ├── views # views 所有页面 |
|||
│ │ ├── module |
|||
│ │ ├── index # 首页 |
|||
│ ├── 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,57 @@ |
|||
{ |
|||
"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", |
|||
"fabric": "2.5", |
|||
"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.220:12010' // 配置服务器地址
|
|||
} |
|||
@ -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,130 @@ |
|||
import request from '@/utils/request' |
|||
import qs from 'qs' |
|||
|
|||
// 根据题名著者出版社ISBN查询图书
|
|||
export function FetchFindBooksByQuery(params) { |
|||
return request({ |
|||
url: 'api/queryDeviceAPI/findBooksByQuery' + '?' + qs.stringify(params, { indices: false }), |
|||
method: 'get' |
|||
}) |
|||
} |
|||
|
|||
// 获取热搜词
|
|||
export function FetchFindHotSearch(params) { |
|||
return request({ |
|||
url: 'api/queryDeviceAPI/findHotSearch' + '?' + qs.stringify(params, { indices: false }), |
|||
method: 'get' |
|||
}) |
|||
} |
|||
|
|||
// 初始化盘点概况
|
|||
export function FetchInitStockInfo(params) { |
|||
return request({ |
|||
url: 'api/queryDeviceAPI/initStockInfo' + '?' + qs.stringify(params, { indices: false }), |
|||
method: 'get' |
|||
}) |
|||
} |
|||
|
|||
// 根据机构代码获取楼层列表
|
|||
export function FetchLibraryFloorListByFondsNo(params) { |
|||
return request({ |
|||
url: 'api/queryDeviceAPI/getLibraryFloorListByFondsNo' + '?' + qs.stringify(params, { indices: false }), |
|||
method: 'get' |
|||
}) |
|||
} |
|||
|
|||
// 根据楼层获取区域列表
|
|||
export function FetchRegionListByFloorId(params) { |
|||
return request({ |
|||
url: 'api/queryDeviceAPI/getRegionListByFloorId' + '?' + qs.stringify(params, { indices: false }), |
|||
method: 'get' |
|||
}) |
|||
} |
|||
|
|||
// 根据区域获取书架列表
|
|||
export function FetchShelfListByRegionId(params) { |
|||
return request({ |
|||
url: 'api/queryDeviceAPI/getShelfListByRegionId' + '?' + qs.stringify(params, { indices: false }), |
|||
method: 'get' |
|||
}) |
|||
} |
|||
|
|||
// 书架列表
|
|||
export function FetchBookShelfDetails(params) { |
|||
return request({ |
|||
url: 'api/queryDeviceAPI/getBookShelfDetails' + '?' + qs.stringify(params, { indices: false }), |
|||
method: 'get' |
|||
}) |
|||
} |
|||
|
|||
// 根据书架查看所有层架位
|
|||
export function FetchShelfGridAllByShelfIdText(params) { |
|||
return request({ |
|||
url: 'api/queryDeviceAPI/getShelfGridAllByShelfIdText' + '?' + qs.stringify(params, { indices: false }), |
|||
method: 'get' |
|||
}) |
|||
} |
|||
|
|||
// 根据书架查看所有层架位(参与盘点)
|
|||
export function FetchShelfGridAllByShelfId(params) { |
|||
return request({ |
|||
url: 'api/queryDeviceAPI/getShelfGridAllByShelfId' + '?' + qs.stringify(params, { indices: false }), |
|||
method: 'get' |
|||
}) |
|||
} |
|||
|
|||
// 根据层架位id获取架位图书
|
|||
export function FetchInitBookDetailsByGrids(params) { |
|||
return request({ |
|||
url: 'api/queryDeviceAPI/initBookDetailsByGrids' + '?' + qs.stringify(params, { indices: false }), |
|||
method: 'get' |
|||
}) |
|||
} |
|||
|
|||
// 图书详情
|
|||
export function FetchInitBookDetailsSearchInto(params) { |
|||
return request({ |
|||
url: 'api/queryDeviceAPI/initBookDetailsSearchInto' + '?' + qs.stringify(params, { indices: false }), |
|||
method: 'get' |
|||
}) |
|||
} |
|||
|
|||
// 初始化热门图书
|
|||
export function FetchInitHotBookList(params) { |
|||
return request({ |
|||
url: 'api/queryDeviceAPI/initHotBookList' + '?' + qs.stringify(params, { indices: false }), |
|||
method: 'get' |
|||
}) |
|||
} |
|||
|
|||
// 初始化热门架位
|
|||
export function FetchInitHotShelfList(params) { |
|||
return request({ |
|||
url: 'api/queryDeviceAPI/initHotShelfList' + '?' + qs.stringify(params, { indices: false }), |
|||
method: 'get' |
|||
}) |
|||
} |
|||
|
|||
// 根据bookRecNo查看图书详细信息
|
|||
export function FetchBookDetaisByBookRecNo(params) { |
|||
return request({ |
|||
url: 'api/queryDeviceAPI/getBookDetaisByBookRecNo' + '?' + qs.stringify(params, { indices: false }), |
|||
method: 'get' |
|||
}) |
|||
} |
|||
|
|||
export default { |
|||
FetchFindBooksByQuery, |
|||
FetchInitStockInfo, |
|||
FetchFindHotSearch, |
|||
FetchLibraryFloorListByFondsNo, |
|||
FetchRegionListByFloorId, |
|||
FetchShelfListByRegionId, |
|||
FetchBookShelfDetails, |
|||
FetchShelfGridAllByShelfIdText, |
|||
FetchShelfGridAllByShelfId, |
|||
FetchInitBookDetailsByGrids, |
|||
FetchInitHotBookList, |
|||
FetchInitHotShelfList, |
|||
FetchBookDetaisByBookRecNo |
|||
} |
|||
@ -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,627 @@ |
|||
@font-face { |
|||
font-family: "iconfont"; /* Project id 3966148 */ |
|||
src: url('iconfont.woff2?t=1736498949884') format('woff2'), |
|||
url('iconfont.woff?t=1736498949884') format('woff'), |
|||
url('iconfont.ttf?t=1736498949884') format('truetype'); |
|||
} |
|||
|
|||
.iconfont { |
|||
font-family: "iconfont" !important; |
|||
font-size: 16px; |
|||
font-style: normal; |
|||
-webkit-font-smoothing: antialiased; |
|||
-moz-osx-font-smoothing: grayscale; |
|||
} |
|||
|
|||
.icon-zhongduanjiankong:before { |
|||
content: "\e691"; |
|||
} |
|||
|
|||
.icon-lianjieduankai:before { |
|||
content: "\e600"; |
|||
} |
|||
|
|||
.icon-stop:before { |
|||
content: "\e714"; |
|||
} |
|||
|
|||
.icon-zhuangtai1:before { |
|||
content: "\e690"; |
|||
} |
|||
|
|||
.icon-zhuangtai2:before { |
|||
content: "\e6bc"; |
|||
} |
|||
|
|||
.icon-biaoqian:before { |
|||
content: "\e693"; |
|||
} |
|||
|
|||
.icon-_biaoqian-:before { |
|||
content: "\e68f"; |
|||
} |
|||
|
|||
.icon-shuju:before { |
|||
content: "\e68e"; |
|||
} |
|||
|
|||
.icon-duolouceng:before { |
|||
content: "\e87c"; |
|||
} |
|||
|
|||
.icon-shujia:before { |
|||
content: "\e68c"; |
|||
} |
|||
|
|||
.icon-hangzhengquyuguanli:before { |
|||
content: "\e68d"; |
|||
} |
|||
|
|||
.icon-quyu1:before { |
|||
content: "\e68b"; |
|||
} |
|||
|
|||
.icon-gongsi:before { |
|||
content: "\e689"; |
|||
} |
|||
|
|||
.icon-louceng:before { |
|||
content: "\e68a"; |
|||
} |
|||
|
|||
.icon-wodeshujia:before { |
|||
content: "\e688"; |
|||
} |
|||
|
|||
.icon-ceshi:before { |
|||
content: "\e687"; |
|||
} |
|||
|
|||
.icon-yuanchengkongzhi:before { |
|||
content: "\e7d4"; |
|||
} |
|||
|
|||
.icon-attachment:before { |
|||
content: "\e6a9"; |
|||
} |
|||
|
|||
.icon-zhuti:before { |
|||
content: "\e686"; |
|||
} |
|||
|
|||
.icon-gengduo:before { |
|||
content: "\e670"; |
|||
} |
|||
|
|||
.icon-huoqu:before { |
|||
content: "\e674"; |
|||
} |
|||
|
|||
.icon-dayin:before { |
|||
content: "\e67b"; |
|||
} |
|||
|
|||
.icon-guaqi:before { |
|||
content: "\e67c"; |
|||
} |
|||
|
|||
.icon-dangantongji:before { |
|||
content: "\e685"; |
|||
} |
|||
|
|||
.icon-sulan:before { |
|||
content: "\e63b"; |
|||
} |
|||
|
|||
.icon-jiesuan:before { |
|||
content: "\e649"; |
|||
} |
|||
|
|||
.icon-rengongqueren:before { |
|||
content: "\e659"; |
|||
} |
|||
|
|||
.icon-shengchengpandiandan:before { |
|||
content: "\e663"; |
|||
} |
|||
|
|||
.icon-yijiao:before { |
|||
content: "\e669"; |
|||
} |
|||
|
|||
.icon-shanchu1:before { |
|||
content: "\e66f"; |
|||
} |
|||
|
|||
.icon-jiarujieyueche:before { |
|||
content: "\e67d"; |
|||
} |
|||
|
|||
.icon-liuchengfaqi:before { |
|||
content: "\e67e"; |
|||
} |
|||
|
|||
.icon-cuowu1:before { |
|||
content: "\e67f"; |
|||
} |
|||
|
|||
.icon-danganliyong:before { |
|||
content: "\e680"; |
|||
} |
|||
|
|||
.icon-fou:before { |
|||
content: "\e681"; |
|||
} |
|||
|
|||
.icon-shi:before { |
|||
content: "\e682"; |
|||
} |
|||
|
|||
.icon-dengdai:before { |
|||
content: "\e683"; |
|||
} |
|||
|
|||
.icon-jieyueche-ding:before { |
|||
content: "\e684"; |
|||
} |
|||
|
|||
.icon-ruku:before { |
|||
content: "\e671"; |
|||
} |
|||
|
|||
.icon-yulan:before { |
|||
content: "\e672"; |
|||
} |
|||
|
|||
.icon-chuku:before { |
|||
content: "\e673"; |
|||
} |
|||
|
|||
.icon-mijijia:before { |
|||
content: "\e675"; |
|||
} |
|||
|
|||
.icon-shuaxin:before { |
|||
content: "\e676"; |
|||
} |
|||
|
|||
.icon-bangding:before { |
|||
content: "\e677"; |
|||
} |
|||
|
|||
.icon-quyu:before { |
|||
content: "\e678"; |
|||
} |
|||
|
|||
.icon-shebei:before { |
|||
content: "\e679"; |
|||
} |
|||
|
|||
.icon-danganbaoguan-fanbai:before { |
|||
content: "\e67a"; |
|||
} |
|||
|
|||
.icon-kufang:before { |
|||
content: "\e667"; |
|||
} |
|||
|
|||
.icon-chaihe:before { |
|||
content: "\e668"; |
|||
} |
|||
|
|||
.icon-zishebeiguanli:before { |
|||
content: "\e66a"; |
|||
} |
|||
|
|||
.icon-zidonggengxin:before { |
|||
content: "\e66b"; |
|||
} |
|||
|
|||
.icon-jiebang:before { |
|||
content: "\e66c"; |
|||
} |
|||
|
|||
.icon-you-fanbai:before { |
|||
content: "\e66d"; |
|||
} |
|||
|
|||
.icon-zuo-fanbai:before { |
|||
content: "\e66e"; |
|||
} |
|||
|
|||
.icon-duqu:before { |
|||
content: "\e664"; |
|||
} |
|||
|
|||
.icon-chexiao:before { |
|||
content: "\e665"; |
|||
} |
|||
|
|||
.icon-zhuanghe:before { |
|||
content: "\e666"; |
|||
} |
|||
|
|||
.icon-danganguanli-fanbai:before { |
|||
content: "\e662"; |
|||
} |
|||
|
|||
.icon-gengduo2:before { |
|||
content: "\e661"; |
|||
} |
|||
|
|||
.icon-gengduo1:before { |
|||
content: "\e660"; |
|||
} |
|||
|
|||
.icon-wancheng:before { |
|||
content: "\e65f"; |
|||
} |
|||
|
|||
.icon-zhengque:before { |
|||
content: "\e653"; |
|||
} |
|||
|
|||
.icon-cuowu:before { |
|||
content: "\e654"; |
|||
} |
|||
|
|||
.icon-huifu:before { |
|||
content: "\e655"; |
|||
} |
|||
|
|||
.icon-dian2:before { |
|||
content: "\e656"; |
|||
} |
|||
|
|||
.icon-dian:before { |
|||
content: "\e657"; |
|||
} |
|||
|
|||
.icon-shangchuanchenggong:before { |
|||
content: "\e658"; |
|||
} |
|||
|
|||
.icon-shangchuanshibai:before { |
|||
content: "\e65a"; |
|||
} |
|||
|
|||
.icon-xiaowenjian:before { |
|||
content: "\e65b"; |
|||
} |
|||
|
|||
.icon-bendiguajie:before { |
|||
content: "\e65c"; |
|||
} |
|||
|
|||
.icon-zhongxinjiance:before { |
|||
content: "\e65d"; |
|||
} |
|||
|
|||
.icon-tianjiawenjian:before { |
|||
content: "\e65e"; |
|||
} |
|||
|
|||
.icon-shangchuan2:before { |
|||
content: "\e650"; |
|||
} |
|||
|
|||
.icon-a-1:before { |
|||
content: "\e64f"; |
|||
} |
|||
|
|||
.icon-a-2:before { |
|||
content: "\e651"; |
|||
} |
|||
|
|||
.icon-xiazai:before { |
|||
content: "\e652"; |
|||
} |
|||
|
|||
.icon-zhengli:before { |
|||
content: "\e64e"; |
|||
} |
|||
|
|||
.icon-changgui:before { |
|||
content: "\e64d"; |
|||
} |
|||
|
|||
.icon-yuguidangku:before { |
|||
content: "\e64b"; |
|||
} |
|||
|
|||
.icon-shoujizhengbian:before { |
|||
content: "\e64c"; |
|||
} |
|||
|
|||
.icon-yidong:before { |
|||
content: "\e645"; |
|||
} |
|||
|
|||
.icon-piliangchengjian:before { |
|||
content: "\e646"; |
|||
} |
|||
|
|||
.icon-hebingchengjian:before { |
|||
content: "\e647"; |
|||
} |
|||
|
|||
.icon-danganfenlei:before { |
|||
content: "\e648"; |
|||
} |
|||
|
|||
.icon-fenlei:before { |
|||
content: "\e64a"; |
|||
} |
|||
|
|||
.icon-tupianyulan:before { |
|||
content: "\e644"; |
|||
} |
|||
|
|||
.icon-fabu:before { |
|||
content: "\e643"; |
|||
} |
|||
|
|||
.icon-jihuo:before { |
|||
content: "\e63d"; |
|||
} |
|||
|
|||
.icon-xiala-shouqi:before { |
|||
content: "\e63e"; |
|||
} |
|||
|
|||
.icon-xiala-chakanxinxi:before { |
|||
content: "\e63f"; |
|||
} |
|||
|
|||
.icon-chakan:before { |
|||
content: "\e640"; |
|||
} |
|||
|
|||
.icon-jiazaigengduo:before { |
|||
content: "\e641"; |
|||
} |
|||
|
|||
.icon-quanbuyidu:before { |
|||
content: "\e642"; |
|||
} |
|||
|
|||
.icon-shangchuan:before { |
|||
content: "\e62b"; |
|||
} |
|||
|
|||
.icon-yonghuyouxiang:before { |
|||
content: "\e635"; |
|||
} |
|||
|
|||
.icon-yonghuming:before { |
|||
content: "\e636"; |
|||
} |
|||
|
|||
.icon-suoshubumen:before { |
|||
content: "\e637"; |
|||
} |
|||
|
|||
.icon-suoshuquanzong:before { |
|||
content: "\e638"; |
|||
} |
|||
|
|||
.icon-shoujihaoma:before { |
|||
content: "\e639"; |
|||
} |
|||
|
|||
.icon-yonghujiaose:before { |
|||
content: "\e63a"; |
|||
} |
|||
|
|||
.icon-xingbie:before { |
|||
content: "\e63c"; |
|||
} |
|||
|
|||
.icon-dianzibiao:before { |
|||
content: "\e623"; |
|||
} |
|||
|
|||
.icon-yonghuguanli:before { |
|||
content: "\e624"; |
|||
} |
|||
|
|||
.icon-danganjieshou:before { |
|||
content: "\e625"; |
|||
} |
|||
|
|||
.icon-xitongshezhi2:before { |
|||
content: "\e626"; |
|||
} |
|||
|
|||
.icon-danganguanli:before { |
|||
content: "\e627"; |
|||
} |
|||
|
|||
.icon-yucundangguanli:before { |
|||
content: "\e628"; |
|||
} |
|||
|
|||
.icon-paixu-xia:before { |
|||
content: "\e629"; |
|||
} |
|||
|
|||
.icon-paixu-caozuo:before { |
|||
content: "\e62a"; |
|||
} |
|||
|
|||
.icon-paixu-shang:before { |
|||
content: "\e62c"; |
|||
} |
|||
|
|||
.icon-xinzeng:before { |
|||
content: "\e62d"; |
|||
} |
|||
|
|||
.icon-bianji:before { |
|||
content: "\e62e"; |
|||
} |
|||
|
|||
.icon-shezhi:before { |
|||
content: "\e62f"; |
|||
} |
|||
|
|||
.icon-kuaisushezhi:before { |
|||
content: "\e630"; |
|||
} |
|||
|
|||
.icon-shanchu:before { |
|||
content: "\e631"; |
|||
} |
|||
|
|||
.icon-paixu:before { |
|||
content: "\e632"; |
|||
} |
|||
|
|||
.icon-daochu:before { |
|||
content: "\e633"; |
|||
} |
|||
|
|||
.icon-zhongzhi2:before { |
|||
content: "\e634"; |
|||
} |
|||
|
|||
.icon-rili:before { |
|||
content: "\e604"; |
|||
} |
|||
|
|||
.icon-shouye:before { |
|||
content: "\e605"; |
|||
} |
|||
|
|||
.icon-xitongshezhi:before { |
|||
content: "\e606"; |
|||
} |
|||
|
|||
.icon-shouqi:before { |
|||
content: "\e607"; |
|||
} |
|||
|
|||
.icon-xiala-fanbai:before { |
|||
content: "\e608"; |
|||
} |
|||
|
|||
.icon-xiala:before { |
|||
content: "\e609"; |
|||
} |
|||
|
|||
.icon-zhuangtai:before { |
|||
content: "\e60a"; |
|||
} |
|||
|
|||
.icon-xiaoxi:before { |
|||
content: "\e60b"; |
|||
} |
|||
|
|||
.icon-zhongzhi:before { |
|||
content: "\e60c"; |
|||
} |
|||
|
|||
.icon-xiala-xia:before { |
|||
content: "\e60d"; |
|||
} |
|||
|
|||
.icon-xiala-you:before { |
|||
content: "\e60e"; |
|||
} |
|||
|
|||
.icon-xiala-shang:before { |
|||
content: "\e60f"; |
|||
} |
|||
|
|||
.icon-kuangxuan-jinyong2:before { |
|||
content: "\e610"; |
|||
} |
|||
|
|||
.icon-kuangxuan-xuanze:before { |
|||
content: "\e611"; |
|||
} |
|||
|
|||
.icon-kuangxuan-moren:before { |
|||
content: "\e612"; |
|||
} |
|||
|
|||
.icon-kuangxuan-jinyong1:before { |
|||
content: "\e613"; |
|||
} |
|||
|
|||
.icon-weizhi-copy:before { |
|||
content: "\e7d5"; |
|||
} |
|||
|
|||
.icon-xuanzhong:before { |
|||
content: "\e614"; |
|||
} |
|||
|
|||
.icon-weixuan:before { |
|||
content: "\e615"; |
|||
} |
|||
|
|||
.icon-sousuo:before { |
|||
content: "\e616"; |
|||
} |
|||
|
|||
.icon-guan:before { |
|||
content: "\e617"; |
|||
} |
|||
|
|||
.icon-kai:before { |
|||
content: "\e618"; |
|||
} |
|||
|
|||
.icon-weizhi:before { |
|||
content: "\e619"; |
|||
} |
|||
|
|||
.icon-biaoji:before { |
|||
content: "\e61a"; |
|||
} |
|||
|
|||
.icon-guanbixiao:before { |
|||
content: "\e61b"; |
|||
} |
|||
|
|||
.icon-guanbi:before { |
|||
content: "\e61c"; |
|||
} |
|||
|
|||
.icon-zhuyi-hong:before { |
|||
content: "\e61d"; |
|||
} |
|||
|
|||
.icon-zhuyi-lan:before { |
|||
content: "\e61e"; |
|||
} |
|||
|
|||
.icon-zhuyi-hong-xiao:before { |
|||
content: "\e61f"; |
|||
} |
|||
|
|||
.icon-wenjian-xiao:before { |
|||
content: "\e620"; |
|||
} |
|||
|
|||
.icon-wenjian-da:before { |
|||
content: "\e621"; |
|||
} |
|||
|
|||
.icon-dangan:before { |
|||
content: "\e622"; |
|||
} |
|||
|
|||
.icon-yanzhengma:before { |
|||
content: "\e602"; |
|||
} |
|||
|
|||
.icon-mima:before { |
|||
content: "\e603"; |
|||
} |
|||
|
|||
.icon-zhanghao:before { |
|||
content: "\e601"; |
|||
} |
|||
|
|||
1
src/assets/iconfont/iconfont.js
File diff suppressed because it is too large
View File
1080
src/assets/iconfont/iconfont.json
File diff suppressed because it is too large
View File
|
After Width: 1080 | Height: 1920 | Size: 62 KiB |
|
After Width: 65 | Height: 103 | Size: 180 B |
|
After Width: 591 | Height: 317 | Size: 6.2 KiB |
|
After Width: 440 | Height: 526 | Size: 35 KiB |
|
After Width: 440 | Height: 478 | Size: 37 KiB |
|
After Width: 39 | Height: 38 | Size: 1.9 KiB |
|
After Width: 48 | Height: 13 | Size: 548 B |
|
After Width: 24 | Height: 24 | Size: 619 B |
|
After Width: 24 | Height: 24 | Size: 557 B |
|
After Width: 46 | Height: 50 | Size: 3.4 KiB |
|
After Width: 46 | Height: 50 | Size: 3.6 KiB |
|
After Width: 46 | Height: 50 | Size: 3.6 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: 75 | Height: 444 | Size: 1.2 KiB |
|
After Width: 32 | Height: 441 | Size: 1.4 KiB |
|
After Width: 368 | Height: 441 | Size: 62 KiB |
|
After Width: 97 | Height: 267 | Size: 7.1 KiB |
|
After Width: 256 | Height: 256 | Size: 3.0 KiB |
|
After Width: 97 | Height: 267 | Size: 7.2 KiB |
|
After Width: 97 | Height: 267 | Size: 3.2 KiB |
|
After Width: 1080 | Height: 398 | Size: 40 KiB |
|
After Width: 1920 | Height: 200 | Size: 263 KiB |
|
After Width: 200 | Height: 200 | Size: 6.7 KiB |
@ -0,0 +1,829 @@ |
|||
.content-main{ |
|||
width: calc(100%); |
|||
height: calc(100vh); |
|||
background: url("~@/assets/images/bg.png") left top; |
|||
background-size: 100% 100%; |
|||
} |
|||
.search-main{ |
|||
background-color: #fff; |
|||
border-radius: 8px; |
|||
.search-content{ |
|||
display: flex; |
|||
justify-content: flex-start; |
|||
align-items: center; |
|||
.el-button{ |
|||
height: 56px; |
|||
font-size: 24px; |
|||
border: 1px solid #C6C6E2; |
|||
} |
|||
.input-search{ |
|||
flex: 1; |
|||
display: flex; |
|||
margin: 0 8px; |
|||
border: 1px solid #C6C6E2; |
|||
border-radius: 8px; |
|||
overflow: hidden; |
|||
::v-deep .el-input{ |
|||
flex: 1; |
|||
.el-input__inner{ |
|||
font-size: 20px; |
|||
height: 56px; |
|||
border: none; |
|||
} |
|||
} |
|||
.el-button{ |
|||
display: block; |
|||
padding-left: 48px; |
|||
background: url('~@/assets/images/img5.png') no-repeat 12px center #0348F3; |
|||
background-size: 24px 24px; |
|||
border-radius: 0 8px 8px 0; |
|||
border: none; |
|||
} |
|||
} |
|||
} |
|||
|
|||
.hot-keyword{ |
|||
font-size: 24px; |
|||
p{ |
|||
padding: 16px 0 10px 0; |
|||
} |
|||
.keyword-item{ |
|||
display: flex; |
|||
justify-content: flex-start; |
|||
align-items: center; |
|||
span{ |
|||
display: block; |
|||
padding: 0 12px; |
|||
height: 44px; |
|||
line-height: 44px; |
|||
font-size: 20px; |
|||
background-color: #F9F9FD; |
|||
color: #737475; |
|||
border-radius: 8px; |
|||
margin-right: 12px; |
|||
&.active{ |
|||
background-color: #5A86F4; |
|||
color: #fff; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
.box-style{ |
|||
// margin-top: 20px; |
|||
border-radius: 4px; |
|||
border: 1px solid #EBEEF5; |
|||
background-color: #FFF; |
|||
overflow: hidden; |
|||
color: #303133; |
|||
-webkit-transition: .3s; |
|||
transition: .3s; |
|||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, .1); |
|||
padding: 20px; |
|||
} |
|||
|
|||
// 图书列表 |
|||
.book-content{ |
|||
margin-top: 16px; |
|||
padding: 20px 24px; |
|||
background-color: #fff; |
|||
border-radius: 8px; |
|||
} |
|||
.result{ |
|||
font-size: 16px; |
|||
color: #737475; |
|||
margin-bottom: 10px; |
|||
span{ |
|||
color: #5A86F4; |
|||
} |
|||
} |
|||
.book-all-list{ |
|||
display: flex; |
|||
flex-wrap: wrap; |
|||
justify-content: space-between; |
|||
height: calc(100% - 28px); |
|||
overflow: hidden; |
|||
overflow-y: scroll; |
|||
} |
|||
.book-item{ |
|||
width: calc(100% / 2 - 20px); |
|||
margin: 20px 10px 20px 0; |
|||
} |
|||
.load-data{ |
|||
width: 100%; |
|||
padding: 15px 0; |
|||
text-align: center; |
|||
} |
|||
.book-info{ |
|||
display: flex; |
|||
justify-content: space-between; |
|||
.book-img{ |
|||
display: flex; |
|||
align-items: center; |
|||
width: 160px; |
|||
height: 200px; |
|||
margin-right: 17px; |
|||
// background-color: #f1f1f1; |
|||
overflow: hidden; |
|||
img{ |
|||
display: block; |
|||
width: 100%; |
|||
} |
|||
} |
|||
.book-txt{ |
|||
flex: 1; |
|||
h4{ |
|||
font-size: 28px; |
|||
line-height: 40px; |
|||
} |
|||
div{ |
|||
font-size: 20px; |
|||
height: 32px; |
|||
line-height: 32px; |
|||
margin-top: 8px; |
|||
} |
|||
.book-autor{ |
|||
display: inline-block; |
|||
padding: 0 8px; |
|||
// border: 1px solid #C6C6E2; |
|||
color: #737475; |
|||
border-radius: 4px; |
|||
} |
|||
|
|||
} |
|||
|
|||
.to-book-more{ |
|||
font-size: 20px; |
|||
width: 100px; |
|||
height: 40px; |
|||
line-height: 40px; |
|||
padding: 0 8px; |
|||
color: #fff; |
|||
background-color: #5A86F4; |
|||
border-radius: 4px; |
|||
} |
|||
} |
|||
|
|||
.book-intro{ |
|||
font-size: 20px; |
|||
height: 32px; |
|||
line-height: 32px; |
|||
height: 96px; |
|||
overflow: hidden; |
|||
text-overflow: ellipsis; |
|||
display: -webkit-box; |
|||
-webkit-box-orient: vertical; |
|||
-webkit-line-clamp: 3; |
|||
overflow-y: scroll; |
|||
margin-top: 10px; |
|||
} |
|||
|
|||
.bookList-wrap{ |
|||
display: flex; |
|||
justify-content: space-between; |
|||
margin-top: 16px; |
|||
height: calc(100vh - 418px); |
|||
} |
|||
|
|||
.book-content2{ |
|||
flex: 1; |
|||
margin-left: 20px; |
|||
padding: 20px 24px; |
|||
background-color: #fff; |
|||
border-radius: 8px; |
|||
.book-all-list{ |
|||
display: block; |
|||
} |
|||
.book-item{ |
|||
width: 100%; |
|||
margin: 0 10px 20px 0; |
|||
} |
|||
.book-txt{ |
|||
position: relative; |
|||
} |
|||
} |
|||
|
|||
.bookList-left{ |
|||
width: 310px; |
|||
height: 100%; |
|||
padding: 24px 16px 0 16px; |
|||
background-color: #fff; |
|||
border-radius: 8px; |
|||
overflow: hidden; |
|||
overflow-y: scroll; |
|||
} |
|||
|
|||
.filter-header{ |
|||
position: relative; |
|||
padding-left: 20px; |
|||
font-size: 28px; |
|||
font-weight: 600; |
|||
line-height: 30px; |
|||
&::before{ |
|||
position: absolute; |
|||
left: 0; |
|||
top: 50%; |
|||
content: ""; |
|||
width: 8px; |
|||
height: 26px; |
|||
background-color: #5A86F4; |
|||
transform: translateY(-50%); |
|||
} |
|||
} |
|||
|
|||
.ranking{ |
|||
.el-carousel{ |
|||
margin-top: 14px; |
|||
} |
|||
.ranking-img{ |
|||
display: flex; |
|||
align-items: center; |
|||
width: 140px; |
|||
height: 200px; |
|||
background-color: #f1f1f1; |
|||
overflow: hidden; |
|||
img{ |
|||
display: block; |
|||
width: 100%; |
|||
} |
|||
} |
|||
.ranking-book-detail{ |
|||
.book-info{ |
|||
position: relative; |
|||
padding: 10px 10px 18px 16px; |
|||
background-color: #F9F9FD; |
|||
border: 1px solid #C6C6E2; |
|||
border-radius: 8px; |
|||
h5{ |
|||
font-size: 24px; |
|||
} |
|||
.book-author{ |
|||
padding: 10px 0; |
|||
font-size: 18px; |
|||
color: #FE6902; |
|||
span:first-child{ |
|||
padding-right: 10px; |
|||
border-right: 1px solid #E9E9F4; |
|||
} |
|||
span:last-child{ |
|||
padding-left: 10px; |
|||
} |
|||
} |
|||
.book-intro{ |
|||
opacity: .6; |
|||
} |
|||
.ranking-status{ |
|||
position: absolute; |
|||
right: 10px; |
|||
top: -22px; |
|||
width: 46px; |
|||
height: 50px; |
|||
|
|||
&.num-one{ |
|||
background: url('~@/assets/images/img7.png') no-repeat; |
|||
background-size: 46px 50px; |
|||
} |
|||
&.num-two{ |
|||
background: url('~@/assets/images/img8.png') no-repeat; |
|||
background-size: 46px 50px; |
|||
} |
|||
&.num-three{ |
|||
background: url('~@/assets/images/img9.png') no-repeat; |
|||
background-size: 46px 50px; |
|||
} |
|||
} |
|||
} |
|||
.book-click-num{ |
|||
display: flex; |
|||
justify-content: space-between; |
|||
padding: 6px 6px 6px 16px; |
|||
margin-top: 8px; |
|||
background-color: #F9F9FD; |
|||
border: 1px solid #C6C6E2; |
|||
border-radius: 8px; |
|||
span{ |
|||
display: block; |
|||
font-size: 24px; |
|||
height: 42px; |
|||
line-height: 42px; |
|||
&.click-num{ |
|||
padding-left: 28px; |
|||
font-size: 24px; |
|||
background: url('~@/assets/images/img6.png') no-repeat left center; |
|||
background-size: 24px 24px; |
|||
} |
|||
&.detail-btn{ |
|||
font-size: 20px; |
|||
padding: 0 12px; |
|||
background-color: #5A86F4; |
|||
color: #fff; |
|||
border-radius: 8px; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
.ranking-list-bottom{ |
|||
margin-top: 10px; |
|||
li{ |
|||
display: flex; |
|||
justify-content: space-between; |
|||
align-items: center; |
|||
padding: 24px 0 16px 0; |
|||
border-bottom: 1px solid #C6C6E2; |
|||
font-size: 22px; |
|||
span{ |
|||
display: block; |
|||
margin-right: 30px; |
|||
background: url('~@/assets/images/img3.png') no-repeat center bottom; |
|||
background-size: 48px 13px; |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
.book-place{ |
|||
padding: 0 27px 0 32px; |
|||
background-color: #F8F8FD; |
|||
h4{ |
|||
position: relative; |
|||
padding-left: 18px; |
|||
font-size: 28px; |
|||
line-height: 40px; |
|||
color: #191A1A; |
|||
&::before{ |
|||
position: absolute; |
|||
left: 0; |
|||
top: 50%; |
|||
content: ""; |
|||
width: 7px; |
|||
height: 26px; |
|||
background-color: #191A1A; |
|||
transform: translateY(-50%); |
|||
} |
|||
} |
|||
.book-place-list{ |
|||
li{ |
|||
display: flex; |
|||
justify-content: space-between; |
|||
padding: 14px 0; |
|||
font-size: 25px; |
|||
line-height: 40px; |
|||
border-bottom: 1px solid #C6C6E2; |
|||
span{ |
|||
position: relative; |
|||
width: 57px; |
|||
color: #000; |
|||
&::before{ |
|||
position: absolute; |
|||
bottom: 6px; |
|||
left: 0; |
|||
content: ""; |
|||
width: 16px; |
|||
height: 7px; |
|||
background-color: #5A86F4; |
|||
opacity: .4; |
|||
} |
|||
} |
|||
.book-num{ |
|||
width: 230px; |
|||
} |
|||
.place-detail{ |
|||
flex: 1; |
|||
text-align: right; |
|||
padding-right: 56px; |
|||
color: #000; |
|||
background: url('~@/assets/images/img10.png') no-repeat right center; |
|||
background-size: 39px 38px; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
.book-bottom{ |
|||
position: relative; |
|||
display: flex; |
|||
justify-content: center; |
|||
padding: 24px 0; |
|||
z-index: 999999; |
|||
span{ |
|||
display: block; |
|||
width: 212px; |
|||
height: 57px; |
|||
line-height: 53px; |
|||
font-size: 25px; |
|||
text-align: center; |
|||
background: rgba(90,134,244,0.1); |
|||
border-radius: 29px; |
|||
border: 2px solid #5A86F4; |
|||
color: #5A86F4; |
|||
} |
|||
} |
|||
|
|||
|
|||
|
|||
.positionDialog{ |
|||
.book-detail{ |
|||
position: relative; |
|||
display: flex; |
|||
justify-content: flex-start; |
|||
padding: 10px 30px !important; |
|||
background-color: #F6F8FC; |
|||
li{ |
|||
font-size: 18px; |
|||
line-height: 40px; |
|||
margin-right: 20px; |
|||
font-weight: bold; |
|||
span{ |
|||
display: inline-block; |
|||
text-align: right; |
|||
margin-right: 20px; |
|||
color: #0C0E1E; |
|||
font-weight: normal; |
|||
} |
|||
i{ |
|||
font-style: normal; |
|||
padding: 0 8px; |
|||
} |
|||
} |
|||
} |
|||
.position-content{ |
|||
display: flex; |
|||
justify-content: space-between; |
|||
align-items: flex-start; |
|||
padding: 20px !important; |
|||
h5{ |
|||
font-size: 18px; |
|||
color: #0C0E1E; |
|||
} |
|||
.position-left{ |
|||
width: 500px; |
|||
overflow: hidden; |
|||
::v-deep .venue-preview{ |
|||
height: 500px; |
|||
} |
|||
} |
|||
.position-right{ |
|||
width: 400px; |
|||
margin-left: 20px; |
|||
} |
|||
} |
|||
|
|||
.shelf-top{ |
|||
display: flex; |
|||
justify-content: space-around; |
|||
align-items: center; |
|||
text-align: center; |
|||
margin-top: 30px; |
|||
p{ |
|||
font-size: 16px; |
|||
color: #fff; |
|||
height: 30px; |
|||
line-height: 26px; |
|||
background: url('~@/assets/images/shelf04.png') no-repeat center top; |
|||
background-size: auto 100%; |
|||
} |
|||
} |
|||
|
|||
.data-shelf-row{ |
|||
display: flex; |
|||
flex: 1; |
|||
flex-wrap: wrap; |
|||
text-align: center; |
|||
.data-shelf-cell{ |
|||
position: relative; |
|||
font-size: 16px; |
|||
color: #0C0E1E; |
|||
background: url('~@/assets/images/shelf02.png') repeat-x left top; |
|||
background-size: 20% 100%; |
|||
border-radius: 3px; |
|||
cursor: pointer; |
|||
&::before{ |
|||
content: ""; |
|||
position: absolute; |
|||
left: 0; |
|||
top: 0; |
|||
width: 6px; |
|||
height: 38px; |
|||
background: url('~@/assets/images/shelf01.png') no-repeat left top; |
|||
background-size: 100% 100%; |
|||
} |
|||
&::after{ |
|||
content: ""; |
|||
position: absolute; |
|||
right: -4px; |
|||
top: 0; |
|||
width: 6px; |
|||
height: 38px; |
|||
background: url('~@/assets/images/shelf01.png') no-repeat left top; |
|||
background-size: 100% 100%; |
|||
} |
|||
.cell-name{ |
|||
display: block; |
|||
width: 100%; |
|||
line-height: 38px; |
|||
} |
|||
&.active{ |
|||
color: #fff; |
|||
span{ |
|||
position: relative; |
|||
display: block; |
|||
&::before{ |
|||
position: absolute; |
|||
top: 0; |
|||
left: 6px; |
|||
content: ''; |
|||
width: 98%; |
|||
height: 100%; |
|||
background-color: rgba(255,0,0,.3); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
} |
|||
|
|||
.tooltip-style, |
|||
.popover-external-set { |
|||
width: 250px; |
|||
background:rgba(0,0,0,1); |
|||
color: #fff; |
|||
border-radius: 6px; |
|||
} |
|||
|
|||
.dataScreening-header{ |
|||
display: flex; |
|||
justify-content: space-between; |
|||
align-items: center; |
|||
color: #0C0E1E; |
|||
background-color: #fff; |
|||
margin-bottom: 20px; |
|||
h4{ |
|||
flex: 1; |
|||
} |
|||
.bookshelf-area{ |
|||
text-align: right; |
|||
position: relative; |
|||
display: flex; |
|||
justify-content: flex-start; |
|||
align-items: center; |
|||
padding: 4px 10px; |
|||
a{ |
|||
font-weight: bold; |
|||
font-size: 16px; |
|||
display: block; |
|||
padding: 10px; |
|||
i{ |
|||
margin-right: 10px; |
|||
} |
|||
} |
|||
span{ |
|||
font-size: 14px; |
|||
display: block; |
|||
padding: 0 6px; |
|||
} |
|||
.double-click-btn{ |
|||
position: inherit; |
|||
margin-left: 20px; |
|||
font-weight: normal; |
|||
border: 1px solid #545b65; |
|||
border-radius: 13px; |
|||
line-height: 18px; |
|||
background-color: #e2e9f3; |
|||
} |
|||
} |
|||
} |
|||
|
|||
.shelf-top{ |
|||
display: flex; |
|||
justify-content: space-around; |
|||
align-items: center; |
|||
text-align: center; |
|||
margin-top: 30px; |
|||
p{ |
|||
font-size: 12px; |
|||
color: #fff; |
|||
height: 30px; |
|||
line-height: 26px; |
|||
background: url('~@/assets/images/shelf04.png') no-repeat center top; |
|||
background-size: auto 100%; |
|||
} |
|||
} |
|||
|
|||
.data-shelf-row{ |
|||
display: flex; |
|||
flex: 1; |
|||
flex-wrap: wrap; |
|||
text-align: center; |
|||
.data-shelf-cell{ |
|||
position: relative; |
|||
font-size: 12px; |
|||
color: #0C0E1E; |
|||
background: url('~@/assets/images/shelf02.png') repeat-x left top; |
|||
background-size: 20% 100%; |
|||
border-radius: 3px; |
|||
cursor: pointer; |
|||
&::before{ |
|||
content: ""; |
|||
position: absolute; |
|||
left: 0; |
|||
top: 0; |
|||
width: 6px; |
|||
height: 38px; |
|||
background: url('~@/assets/images/shelf01.png') no-repeat left top; |
|||
background-size: 100% 100%; |
|||
} |
|||
&::after{ |
|||
content: ""; |
|||
position: absolute; |
|||
right: -4px; |
|||
top: 0; |
|||
width: 6px; |
|||
height: 38px; |
|||
background: url('~@/assets/images/shelf01.png') no-repeat left top; |
|||
background-size: 100% 100%; |
|||
} |
|||
.cell-name{ |
|||
display: block; |
|||
width: 100%; |
|||
line-height: 38px; |
|||
} |
|||
&.active{ |
|||
color: #fff; |
|||
span{ |
|||
position: relative; |
|||
display: block; |
|||
&::before{ |
|||
position: absolute; |
|||
top: 0; |
|||
left: 6px; |
|||
content: ''; |
|||
width: 98%; |
|||
height: 100%; |
|||
background-color: rgba(255,0,0,.3); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
.tag-info{ |
|||
display: flex; |
|||
justify-content: flex-start; |
|||
align-items: center; |
|||
position: absolute; |
|||
right: 20px; |
|||
top: 8px; |
|||
p{ |
|||
font-size: 16px; |
|||
font-weight: bold; |
|||
} |
|||
.iconfont{ |
|||
font-size: 16px; |
|||
margin-right: 5px; |
|||
} |
|||
} |
|||
|
|||
.tag-sort{ |
|||
i{ |
|||
color: #0348F3; |
|||
} |
|||
} |
|||
|
|||
.tag-place{ |
|||
i{ |
|||
color: #ED4A41; |
|||
} |
|||
} |
|||
|
|||
.tag-in{ |
|||
i{ |
|||
color: #2ECAAC; |
|||
} |
|||
} |
|||
|
|||
.tag-all{ |
|||
i{ |
|||
color: #0C0E1E; |
|||
} |
|||
} |
|||
|
|||
.tab-content{ |
|||
position: relative; |
|||
background-color: #fff; |
|||
.tab-nav{ |
|||
display: flex; |
|||
justify-content: flex-start; |
|||
font-size: 22px; |
|||
margin: 0 0 18px 0; |
|||
color: #545B65; |
|||
border-bottom: 1px solid #EDEFF3; |
|||
li{ |
|||
margin-right: 60px; |
|||
&.active-tab-nav{ |
|||
padding-bottom: 10px; |
|||
color: #0348F3; |
|||
border-bottom: 3px solid #0348F3; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
//本架图书页面 |
|||
.rack-box{ |
|||
padding: 30px 0 0 0; |
|||
width: 100%; |
|||
.rack-item{ |
|||
position: relative; |
|||
margin-bottom: 30px; |
|||
overflow: hidden; |
|||
.rack-box-list{ |
|||
height: 200px; |
|||
width: 100%; |
|||
overflow: hidden; |
|||
white-space: nowrap; |
|||
background: url('~@/assets/images/shelf02.png') repeat left top; |
|||
background-size: 10% 100%; |
|||
.list-item{ |
|||
display: inline-block; |
|||
border: none; |
|||
width: 42px; |
|||
height: 120px; |
|||
background: url('~@/assets/images/shelf03.png') no-repeat left top; |
|||
background-size: 100% 100%; |
|||
position: relative; |
|||
.book-name{ |
|||
position: absolute; |
|||
left: 15px; |
|||
top: 16px; |
|||
display: block; |
|||
height: 90px; |
|||
font-size: 12px; |
|||
writing-mode:vertical-rl; |
|||
overflow: hidden; |
|||
white-space: nowrap; |
|||
text-overflow: ellipsis; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
.rack-floor{ |
|||
position: absolute; |
|||
left: 0; |
|||
bottom: 2px; |
|||
height: 50px; |
|||
width: 100%; |
|||
display: flex; |
|||
color: #000; |
|||
align-items: center; |
|||
justify-content: space-between; |
|||
padding: 0 40px; |
|||
z-index: 999; |
|||
.icon-l,.icon-r{ |
|||
font-size: 24px; |
|||
} |
|||
} |
|||
} |
|||
|
|||
.change-layer{ |
|||
display: flex; |
|||
justify-content: flex-start; |
|||
padding: 20px 0; |
|||
li{ |
|||
padding: 0 20px; |
|||
height: 42px; |
|||
line-height: 40px; |
|||
margin-right: 10px; |
|||
font-size: 20px; |
|||
border-radius: 7px; |
|||
border: 2px solid #C6C6E2; |
|||
&.active{ |
|||
color: #fff; |
|||
background-color: #0348F3; |
|||
border-color: #0348F3; |
|||
} |
|||
} |
|||
} |
|||
::v-deep .el-carousel{ |
|||
margin: 20px auto; |
|||
} |
|||
.index-ranking{ |
|||
display: flex; |
|||
justify-content: space-between; |
|||
align-items: flex-start; |
|||
margin: 0 44px; |
|||
.box-style{ |
|||
width: 50%; |
|||
&:first-child{ |
|||
margin-right: 20px; |
|||
} |
|||
} |
|||
::v-deep .el-carousel{ |
|||
width: 362px; |
|||
height: 200px; |
|||
} |
|||
} |
|||
@ -0,0 +1,180 @@ |
|||
@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; |
|||
} |
|||
|
|||
|
|||
.tooltip-style, |
|||
.popover-external-set { |
|||
width: 250px; |
|||
background:rgba(0,0,0,1); |
|||
color: #fff; |
|||
border-radius: 6px; |
|||
} |
|||
.tooltip-style{ |
|||
display:none; |
|||
position:absolute; |
|||
} |
|||
|
|||
.popover-external-set { |
|||
position: fixed; |
|||
z-index: 1000; |
|||
} |
|||
|
|||
.tooltip-style, |
|||
.popover-content-set{ |
|||
.tooltip-top{ |
|||
display: flex; |
|||
justify-content: space-between; |
|||
align-items: center; |
|||
font-size: 14px; |
|||
height: 40px; |
|||
line-height: 40px; |
|||
padding: 0 10px; |
|||
border-bottom: 1px solid #fff; |
|||
} |
|||
.tooltip-top span, |
|||
.tooltip-top i{ |
|||
font-size: 12px; |
|||
font-style: normal; |
|||
} |
|||
ul{ |
|||
padding: 10px; |
|||
} |
|||
ul li{ |
|||
display: flex; |
|||
justify-content: flex-start; |
|||
align-items: center; |
|||
line-height: 24px; |
|||
font-style: normal; |
|||
font-size: 12px; |
|||
} |
|||
|
|||
ul li p{ |
|||
width: 60px; |
|||
font-weight: bold; |
|||
text-align: right; |
|||
} |
|||
ul li span, |
|||
ul li em{ |
|||
width: 100px; |
|||
display: block; |
|||
text-align: right; |
|||
font-style: normal; |
|||
} |
|||
ul li i{ |
|||
font-style: normal; |
|||
font-weight: bold; |
|||
padding: 0 10px; |
|||
color: #0348f3; |
|||
} |
|||
ul li span.percentage, |
|||
ul li em.percentage{ |
|||
width: auto; |
|||
} |
|||
|
|||
.tag-item{ |
|||
display: block; |
|||
// width: 50px; |
|||
height: 18px; |
|||
line-height: 16px; |
|||
padding: 0 4px; |
|||
border-radius: 3px; |
|||
font-size: 12px; |
|||
color: #A6ADB6; |
|||
border: 1px solid #E6E8ED; |
|||
background-color: #F3F5F9; |
|||
text-align: center; |
|||
&.tag-sort{ |
|||
color: #FD7359 !important; |
|||
border-color: #FBC0B5 !important; |
|||
background-color: #FCECE9 !important; |
|||
} |
|||
&.tag-place{ |
|||
color: #018BFF !important; |
|||
border-color: #9BD1FF !important; |
|||
background-color: #DCEDFD !important; |
|||
} |
|||
&.tag-all{ |
|||
color: #0C0E1E; |
|||
border-color: #545B65 !important; |
|||
background-color: #E6E8ED !important; |
|||
} |
|||
} |
|||
} |
|||
@ -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,39 @@ |
|||
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 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,54 @@ |
|||
import Vue from 'vue' |
|||
import VueRouter from 'vue-router' |
|||
|
|||
Vue.use(VueRouter) |
|||
|
|||
const routes = [ |
|||
{ |
|||
path: '/', |
|||
name: 'index', |
|||
component: () => import('../views/index.vue'), |
|||
meta: { |
|||
title: '首页' |
|||
} |
|||
}, |
|||
{ |
|||
path: '/regions', |
|||
name: 'regions', |
|||
component: () => import('../views/regionsList.vue'), |
|||
meta: { |
|||
title: '区域' |
|||
} |
|||
}, |
|||
{ |
|||
path: '/shelf', |
|||
name: 'shelf', |
|||
component: () => import('../views/shelfList.vue'), |
|||
meta: { |
|||
title: '书架' |
|||
} |
|||
}, |
|||
{ |
|||
path: '/gird', |
|||
name: 'gird', |
|||
component: () => import('../views/girdList.vue'), |
|||
meta: { |
|||
title: '架位' |
|||
} |
|||
}, |
|||
{ |
|||
path: '/bookList', |
|||
name: 'bookList', |
|||
component: () => import('../views/bookList.vue'), |
|||
meta: { |
|||
title: '图书列表' |
|||
} |
|||
} |
|||
] |
|||
|
|||
const router = new VueRouter({ |
|||
mode: 'hash', |
|||
routes |
|||
}) |
|||
|
|||
export default router |
|||
@ -0,0 +1,15 @@ |
|||
import Vue from 'vue' |
|||
import Vuex from 'vuex' |
|||
|
|||
Vue.use(Vuex) |
|||
|
|||
export default new Vuex.Store({ |
|||
state: { |
|||
}, |
|||
mutations: { |
|||
}, |
|||
actions: { |
|||
}, |
|||
modules: { |
|||
} |
|||
}) |
|||
@ -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 : '/', // 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,181 @@ |
|||
<template> |
|||
<div class="content-main"> |
|||
<Search ref="searchRefs" /> |
|||
<div class="bookList-wrap" style="margin: 30px 44px;"> |
|||
<div class="bookList-left"> |
|||
<Ranking /> |
|||
</div> |
|||
<!-- 图书列表 --> |
|||
<div class="book-content2"> |
|||
<div class="result">检索结果:<span>{{ totalNum }}</span>册</div> |
|||
<div class="book-all-list" @scroll="listenScroll"> |
|||
<div v-for="(item,index) in bookList" :key="index" class="book-item" @click="getBookDetaisByBookRecNo(item)"> |
|||
<div class="book-info"> |
|||
<div class="book-img"> |
|||
<img :src="coverUrl+'/demoRecommend/getBookCover.do?id='+item.id" :onerror="defaultImg" alt=""> |
|||
</div> |
|||
<div class="book-txt"> |
|||
<h4> {{ item.title }} </h4> |
|||
<div class="book-autor"> {{ item.author }} </div> |
|||
<div class="book-publish"> {{ item.publisher }} </div> |
|||
<div class="book-isbn">ISBN:{{ item.isbn }}</div> |
|||
<!-- <div class="book-intro title-item"> {{ item.introduce }} </div> --> |
|||
<div class="to-book-more">查看详情</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div v-if="!hasNextPage" class="load-data">暂无更多数据</div> |
|||
<div v-else class="load-data">加载中...</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<BookDetails ref="bookDetailsRef" /> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import { FetchFindBooksByQuery, FetchBookDetaisByBookRecNo } from '@/api/inquiryMachine' |
|||
import { positionCrud } from './mixins/index.js' |
|||
import Search from './module/search' |
|||
import Ranking from './module/ranking' |
|||
import BookDetails from './module/bookDetails' |
|||
|
|||
export default { |
|||
name: 'BookList', |
|||
components: { |
|||
Search, |
|||
Ranking, |
|||
BookDetails |
|||
}, |
|||
mixins: [positionCrud], |
|||
data() { |
|||
return { |
|||
defaultImg: 'this.src="' + require('@/assets/images/default-img.png') + '"', |
|||
bookList: [], |
|||
coverUrl: null, |
|||
pageIndex: 1, |
|||
pageSize: 10, |
|||
hasNextPage: false, |
|||
totalPages: 0, |
|||
totalNum: 0 |
|||
} |
|||
}, |
|||
computed: { |
|||
}, |
|||
created() { |
|||
}, |
|||
mounted() { |
|||
this.getBookRecommendList() |
|||
}, |
|||
methods: { |
|||
getLocation(row) { |
|||
const parts = [] |
|||
if (row.floorName) { |
|||
parts.push(row.floorName) |
|||
} |
|||
if (row.regionName) { |
|||
parts.push(row.regionName) |
|||
} |
|||
if (row.gridName) { |
|||
parts.push(row.gridName) |
|||
} |
|||
return parts.length > 0 ? parts.join('-') : '-' |
|||
}, |
|||
getBookRecommendList() { |
|||
let params |
|||
if (localStorage.getItem('searchKey')) { |
|||
this.$refs.searchRefs.keyword = localStorage.getItem('searchKey') |
|||
this.$refs.searchRefs.keyWordIndex = parseInt(localStorage.getItem('keyWordIndex')) |
|||
params = { |
|||
'fondsCode': this.libcode, |
|||
'search': localStorage.getItem('searchKey'), |
|||
'page': this.pageIndex - 1, |
|||
'size': this.pageSize |
|||
} |
|||
} else { |
|||
params = { |
|||
'fondsCode': this.libcode, |
|||
'search': this.$refs.searchRefs.keyword, |
|||
'page': this.pageIndex - 1, |
|||
'size': this.pageSize |
|||
} |
|||
} |
|||
FetchFindBooksByQuery(params).then(res => { |
|||
const resData = res.content |
|||
if (resData.length === 0) { |
|||
this.hasNextPage = false |
|||
} else { |
|||
this.hasNextPage = resData.length === this.pageSize |
|||
} |
|||
|
|||
this.totalNum = res.totalElements |
|||
this.totalPages = res.totalPages |
|||
this.bookList = this.bookList.concat(resData) |
|||
// if (this.pageIndex > res.totalPages) { |
|||
// this.hasNextPage = false |
|||
// } |
|||
localStorage.removeItem('searchKey') |
|||
localStorage.removeItem('keyWordIndex') |
|||
}).catch(() => { |
|||
this.$message.error('接口错误') |
|||
}) |
|||
}, |
|||
// 监听滚动 |
|||
listenScroll(e) { |
|||
const ele = e.srcElement ? e.srcElement : e.target |
|||
if (ele.scrollTop + ele.offsetHeight > ele.scrollHeight - 100) { // 监听滚动到div底部 |
|||
this.addMoreData() |
|||
} |
|||
}, |
|||
// 加载更多 |
|||
addMoreData() { |
|||
if (this.hasNextPage) { |
|||
this.getBookRecommendList() |
|||
this.pageIndex++ |
|||
} |
|||
}, |
|||
getBookDetaisByBookRecNo(item) { |
|||
FetchBookDetaisByBookRecNo({ |
|||
'bookRecNo': item.bookRecNo |
|||
}).then(res => { |
|||
this.$refs.bookDetailsRef.getBookRankingDetail(res) |
|||
}).catch(() => { |
|||
this.$message.error('接口错误') |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
@import "~@/assets/styles/index.scss"; |
|||
::v-deep .el-dialog{ |
|||
width: 930px; |
|||
border-radius: 16px; |
|||
background: #F8F8FD; |
|||
box-shadow: 0px 3px 20px 1px rgba(0,0,0,0.05); |
|||
.el-dialog__body{ |
|||
padding: 20px 0 23px 0; |
|||
} |
|||
} |
|||
|
|||
.detail-dialog{ |
|||
::v-deep .el-dialog__header{ |
|||
display: none; |
|||
} |
|||
} |
|||
.dialog-book{ |
|||
padding: 30px; |
|||
font-size: 28px; |
|||
.book-txt{ |
|||
color: #191A1A!important; |
|||
font-size: 30px !important; |
|||
} |
|||
.book-autor{ |
|||
font-size: 24px !important; |
|||
} |
|||
.book-publish{ |
|||
font-size: 28px !important; |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,546 @@ |
|||
<template> |
|||
<div class="content-main"> |
|||
<Search refs="searchRefs" search-type="noList" /> |
|||
<div class="box-style" style="margin: 30px 44px;"> |
|||
<div class="dataScreening-header"> |
|||
<h4 class="filter-header">架位总览</h4> |
|||
<div class="bookshelf-area"> |
|||
<!-- <span class="bookshelf-area">{{ floorName }} - {{ regionName }} - {{ gridRow +'排' }}</span> --> |
|||
<!-- <router-link :to="{ path: '/', query: {floorTabIndex: floorTabIndex }}"> |
|||
{{ floorName }} |
|||
</router-link> |
|||
<span>/</span> |
|||
<router-link :to="{ path: '/regions', query: {regionTabIndex: regionTabIndex }}"> |
|||
{{ regionName }} |
|||
</router-link> |
|||
<span>/</span> |
|||
<router-link :to="{ path: '/shelf', query: {tabIndex: tabIndex }}"> |
|||
{{ gridRow +'排' }} |
|||
</router-link> |
|||
<div class="double-click-btn"><span>点击左侧位置返回</span></div> --> |
|||
<router-link :to="{ path: '/shelf', query: {tabIndex: tabIndex }}"> |
|||
<i class="iconfont icon-huifu" />返回 |
|||
</router-link> |
|||
</div> |
|||
</div> |
|||
<div class="tab-content"> |
|||
<ul class="tab-nav"> |
|||
<li v-for="(item,index) in tabListData" :key="index" class="active-tab-nav">{{ item.name }}<i /></li> |
|||
</ul> |
|||
|
|||
<div v-loading="shelfAllGridDataLoading" class="gird-data-book"> |
|||
<div v-for="(item,index) in shelfAllGridData" :key="index" class="gird-layer"> |
|||
<span class="gird-left-line" /> |
|||
<span class="gird-right-line" /> |
|||
<div class="layer-left"> |
|||
<div class="layer-left-book"> |
|||
<!-- <div |
|||
v-for="(book,i) in item.books" |
|||
:key="i" |
|||
:class="['book-item', { 'red-active' : book.bookStatus === '错架'} ,{ 'blue-active' : book.bookStatus === '错序'}]" |
|||
@touchstart="handleTouchStart(index, i, $event)" |
|||
@touchmove="handleTouchMove(index, i, $event)" |
|||
@touchend="handleTouchEnd(index, i, $event)" |
|||
> |
|||
<span class="book-name">{{ book.bookName }}</span> |
|||
</div> --> |
|||
<!-- @touchstart="handleTouchStart(index, i, book, $event)" --> |
|||
<div :class="['swiper'+index,'rack-box-list']"> |
|||
<div class="swiper-wrapper"> |
|||
<div v-for="book in item.books" :key="book.id" :class="['list-item swiper-slide', { 'red-active' : book.bookStatus === '错架'} ,{ 'blue-active' : book.bookStatus === '错序'}]" @click="getBookDetaisByBookRecNo(book)"> |
|||
<span class="book-name">{{ book.bookName }}</span> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
</div> |
|||
<div class="layer-right-handle"> |
|||
<div class="layer-info-header"> |
|||
<h4>{{ item.gridName }}</h4> |
|||
<!-- <span>2024-11-28 09:46</span> --> |
|||
</div> |
|||
<div class="layer-right-content"> |
|||
<div class="layer-tag-info"> |
|||
<div class="tag-item tag-sort">错序:<i class="iconfont icon-zhuangtai2" /><p>{{ baseStockData.length !==0 && baseStockData[index].errorOrderNum }}</p><span>({{ baseStockData.length !==0 && baseStockData[index].errorOrderProbo }})</span></div> |
|||
<div class="tag-item tag-place">错架:<i class="iconfont icon-zhuangtai2" /><p>{{ baseStockData.length !==0 &&baseStockData[index].errorShelfNum }}</p><span>({{ baseStockData.length !==0 && baseStockData[index].errorShelfProbo }})</span></div> |
|||
<div class="tag-item tag-all">在架:<i class="iconfont icon-zhuangtai2" /><p>{{ baseStockData.length !==0 && baseStockData[index].onShelfNum }}</p></div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<!-- popover --> |
|||
<div |
|||
v-if="popoverIndex !== null" |
|||
class="popover-external-set" |
|||
:style="popoverStyle" |
|||
> |
|||
<div class="popover-content-set"> |
|||
<div class="tooltip-top"> |
|||
<h4>{{ shelfAllGridData[popoverIndex.layer].books[popoverIndex.book].bookName }}</h4> |
|||
<span v-if="shelfAllGridData[popoverIndex.layer].books[popoverIndex.book].bookStatus === '错序'" class="tag-item tag-place">错序</span> |
|||
<span v-if="shelfAllGridData[popoverIndex.layer].books[popoverIndex.book].bookStatus === '错架'" class="tag-item tag-sort">错架</span> |
|||
</div> |
|||
<ul> |
|||
<li><p>索书号</p><em>{{ shelfAllGridData[popoverIndex.layer].books[popoverIndex.book].sortmark }}</em></li> |
|||
<li><p>ISBN</p><em>{{ shelfAllGridData[popoverIndex.layer].books[popoverIndex.book].isbn }}</em></li> |
|||
<li><p>著者</p><em>{{ shelfAllGridData[popoverIndex.layer].books[popoverIndex.book].bookAuthor }}</em></li> |
|||
<li><p>出版社</p><em>{{ shelfAllGridData[popoverIndex.layer].books[popoverIndex.book].bookPublish }}</em></li> |
|||
</ul> |
|||
</div> |
|||
</div> |
|||
|
|||
</div> |
|||
|
|||
<!-- <ul style="display: flex; justify-content: flex-start; padding: 20px; margin-top: 20px;"> |
|||
<li v-for="(item,index) in rackOptions" :key="index" style=" background-color: red; padding: 0 10px; margin-right: 10px;">{{ item.name }}</li> |
|||
</ul> --> |
|||
|
|||
<ul class="change-layer"> |
|||
<li v-for="(item,index) in rackOptions" :key="index" :class="{ 'active': layerVal === index+1 }" @click="changeShelfGetGrid(parseInt(item.name))">{{ item.name }}</li> |
|||
</ul> |
|||
</div> |
|||
</div> |
|||
|
|||
<BookDetails ref="bookDetailsRef" /> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import { FetchShelfGridByShelfIdAndGridShelf, FetchBillByShelfIdAndGridShelf, FetchBookShelfDetails, FetchInitStockInfo, FetchInitBookDetailsByGrids, FetchBookDetaisByBookRecNo } from '@/api/inquiryMachine' |
|||
import { positionCrud } from './mixins/index.js' |
|||
import Search from './module/search' |
|||
import BookDetails from './module/bookDetails' |
|||
import { Swiper } from 'vue-awesome-swiper' |
|||
import 'swiper/swiper-bundle.css' |
|||
|
|||
export default { |
|||
name: 'Index', |
|||
components: { |
|||
Search, |
|||
BookDetails |
|||
}, |
|||
mixins: [positionCrud], |
|||
data() { |
|||
return { |
|||
activeIndex: 0, |
|||
detailVisible: false, |
|||
detailTable: [], |
|||
detailCurrent: {}, |
|||
tabdialogIndex: 0, |
|||
listLoading: false, |
|||
tabIndex: 0, |
|||
floorTabIndex: 0, |
|||
regionTabIndex: 0, |
|||
floorName: null, |
|||
floorId: null, |
|||
regionName: null, |
|||
regionId: null, |
|||
gridRow: null, |
|||
gridShelf: null, |
|||
bookShelfDetails: null, |
|||
booShelfGrid: null, |
|||
shelfAllGridData: [], |
|||
layerNum: 0, |
|||
rackNum: 0, |
|||
bookNum: 46, |
|||
layerVal: null, |
|||
rackOptions: [], |
|||
tabListData: [], |
|||
popoverIndex: null, |
|||
popoverVisible: [], |
|||
popoverStyles: [], |
|||
popoverPosition: { x: 0, y: 0 }, // Popover的位置 |
|||
baseStockData: [], |
|||
shelfAllGridDataLoading: false, |
|||
billNoImg: null, |
|||
bigImg: '' |
|||
} |
|||
}, |
|||
computed: { |
|||
cellStyle: function() { |
|||
const h = '76px' |
|||
const w = '100%/' + this.rackNum |
|||
return { width: `calc(${w} )`, height: `calc(${h})` } |
|||
}, |
|||
popoverStyle() { |
|||
return { |
|||
top: `${this.popoverPosition.y - 300}px`, // 鼠标的Y坐标偏移10px |
|||
left: `${this.popoverPosition.x - 240}px`, // 鼠标的X坐标偏移10px |
|||
position: 'absolute' |
|||
} |
|||
} |
|||
}, |
|||
created() { |
|||
if (localStorage.getItem('dataScreenFloorTableIndex')) { |
|||
this.floorTabIndex = localStorage.getItem('dataScreenFloorTableIndex') |
|||
} |
|||
if (localStorage.getItem('dataScreenRegionTableIndex')) { |
|||
this.regionTabIndex = localStorage.getItem('dataScreenRegionTableIndex') |
|||
} |
|||
if (localStorage.getItem('dataScreenShelf')) { |
|||
const dataScreenShelf = JSON.parse(localStorage.getItem('dataScreenShelf')) |
|||
this.floorName = dataScreenShelf.floorName |
|||
this.regionName = dataScreenShelf.regionName |
|||
this.gridRow = dataScreenShelf.gridRow |
|||
this.gridShelf = dataScreenShelf.gridShelf |
|||
|
|||
if (localStorage.getItem('dataScreenShelfAllGrid')) { |
|||
this.shelfAllGridData = JSON.parse(localStorage.getItem('dataScreenShelfAllGrid')) |
|||
} |
|||
|
|||
// 单面/双面 |
|||
this.tabListData = [{ name: dataScreenShelf.regionName + ' - ' + this.removeAreaPrefix(dataScreenShelf.gridName) }] |
|||
|
|||
this.tabIndex = dataScreenShelf.toward - 1 |
|||
FetchBookShelfDetails({ 'shelfId': dataScreenShelf.shelfId }).then(res => { |
|||
this.layerNum = res.shelfFloor |
|||
this.rackNum = res.shelfShelf |
|||
this.floorId = res.floorId |
|||
this.regionId = res.regionId |
|||
this.bookShelfDetails = res |
|||
|
|||
this.rackOptions = [] |
|||
for (let i = 1; i <= this.rackNum; i++) { |
|||
this.rackOptions.push({ id: i, name: `0${i}架` }) |
|||
} |
|||
this.layerVal = parseInt(this.gridShelf) || '' |
|||
|
|||
this.getInitStockInfo(this.shelfAllGridData) |
|||
|
|||
this.getInitBookDetailsByGrids(this.shelfAllGridData) |
|||
|
|||
// this.getBillByShelfIdAndGridShelf(this.shelfAllGridData) |
|||
this.initSwiper() |
|||
}).catch(() => { |
|||
}) |
|||
} |
|||
}, |
|||
mounted() { |
|||
|
|||
}, |
|||
methods: { |
|||
initSwiper() { |
|||
this.$nextTick(() => { |
|||
this.shelfAllGridData.forEach((el, index) => { |
|||
new Swiper('.swiper' + index, { |
|||
slidesPerView: 'auto', |
|||
slidesPerGroup: 15, |
|||
observer: true |
|||
}) |
|||
}) |
|||
}) |
|||
}, |
|||
removeAreaPrefix(gridNames) { |
|||
const index = gridNames.indexOf('面') |
|||
if (index !== -1) { |
|||
return gridNames.substring(0, index + 1) |
|||
} |
|||
return gridNames |
|||
}, |
|||
|
|||
getBillByShelfIdAndGridShelf(data) { |
|||
const params = { |
|||
'gridShelf': data[0].gridShelf, |
|||
'ShelfId': data[0].shelfId, |
|||
'size': 5 |
|||
} |
|||
FetchBillByShelfIdAndGridShelf(params).then(res => { |
|||
if (res !== null) { |
|||
this.checkDateLine = res.sort((a, b) => { |
|||
return new Date(b.endTime) - new Date(a.endTime) |
|||
}) |
|||
this.billNoImg = this.checkDateLine[0].stockBill |
|||
this.checkDateLine[0].icon = 'el-icon-more' |
|||
this.checkDateLine[0].color = '#0bbd87' |
|||
} else { |
|||
this.checkDateLine = [] |
|||
} |
|||
}).catch(() => { |
|||
}) |
|||
}, |
|||
async getInitStockInfo(data) { |
|||
const promises = data.map(item => { |
|||
const params = { |
|||
'fondsCode': this.libcode, |
|||
'floorId': this.floorId, |
|||
'regionId': this.regionId, |
|||
'shelfId': item.shelfId, |
|||
'gridId': item.id |
|||
} |
|||
return FetchInitStockInfo(params) |
|||
}) |
|||
const results = await Promise.all(promises) |
|||
if (!Array.isArray(this.baseStockData)) { |
|||
this.baseStockData = [] |
|||
} |
|||
this.baseStockData = this.baseStockData.concat(results) |
|||
}, |
|||
getInitBookDetailsByGrids(data) { |
|||
const ids = data.map(item => item.id) |
|||
const params = { |
|||
'grids': ids.join(',') |
|||
} |
|||
FetchInitBookDetailsByGrids(params).then(res => { |
|||
this.shelfAllGridData.forEach((item) => { |
|||
const gridId = item.id |
|||
if (Object.prototype.hasOwnProperty.call(res, gridId)) { |
|||
// item.books = res[gridId] |
|||
this.$set(item, 'books', res[gridId]) |
|||
} |
|||
}) |
|||
}).catch(() => { |
|||
}) |
|||
}, |
|||
handleDetail(item) { |
|||
console.log('item', item) |
|||
this.detailVisible = true |
|||
this.detailTable = item.books |
|||
this.detailCurrent = item |
|||
if (this.detailCurrent.onShelfNum) { |
|||
this.bigImg = `${this.baseApi}/api/fileRelevant/getImg?imgId=/${this.libcode}/${this.billNoImg}/${this.detailCurrent.gridCode}/img_result/result_LSD_compressed.jpg` |
|||
} else { |
|||
this.bigImg = '' |
|||
} |
|||
}, |
|||
// handleTouchStart(item) { |
|||
// // this.isTouching = true |
|||
// // this.showPopover(layerIndex, bookIndex, event) |
|||
|
|||
// // this.$refs.bookDetailsRef.detailShow = true |
|||
// }, |
|||
getBookDetaisByBookRecNo(item) { |
|||
FetchBookDetaisByBookRecNo({ |
|||
'bookRecNo': item.bookRecNo |
|||
}).then(res => { |
|||
this.$refs.bookDetailsRef.getBookRankingDetail(res) |
|||
}).catch(() => { |
|||
this.$message.error('接口错误') |
|||
}) |
|||
}, |
|||
handleTouchMove(layerIndex, bookIndex, event) { |
|||
if (this.isTouching) { |
|||
this.showPopover(layerIndex, bookIndex, event) |
|||
} |
|||
}, |
|||
handleTouchEnd(layerIndex, bookIndex, event) { |
|||
this.isTouching = false |
|||
this.hidePopover() |
|||
}, |
|||
showPopover(layerIndex, bookIndex, event) { |
|||
this.popoverIndex = { layer: layerIndex, book: bookIndex } |
|||
const bookElement = event.target // 获取书籍项元素 |
|||
const rect = bookElement.getBoundingClientRect() // 获取边界 |
|||
if (layerIndex === 0) { |
|||
this.popoverPosition = { |
|||
x: window.scrollX + rect.left + rect.width / 2 - 40, |
|||
y: window.scrollY + rect.top + rect.height |
|||
} |
|||
} else { |
|||
this.popoverPosition = { |
|||
x: window.scrollX + rect.left + rect.width / 2 - 40, |
|||
y: window.scrollY + rect.top + rect.height - 170 |
|||
} |
|||
} |
|||
}, |
|||
hidePopover() { |
|||
this.popoverIndex = null |
|||
}, |
|||
changeShelfGetGrid(val) { |
|||
this.shelfAllGridDataLoading = true |
|||
this.layerVal = val |
|||
const params = { |
|||
'gridShelf': '0' + val, |
|||
'shelfId': this.bookShelfDetails.id, |
|||
'toward': this.bookShelfDetails.toward, |
|||
'floorType': this.bookShelfDetails.floorType |
|||
} |
|||
FetchShelfGridByShelfIdAndGridShelf(params).then(res => { |
|||
this.shelfAllGridData = [] |
|||
this.shelfAllGridData = res |
|||
this.getInitStockInfo(this.shelfAllGridData) |
|||
|
|||
this.getInitBookDetailsByGrids(this.shelfAllGridData) |
|||
|
|||
this.shelfAllGridDataLoading = false |
|||
}).catch(() => { |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
@import "~@/assets/styles/index.scss"; |
|||
.gird-data-book{ |
|||
position: relative; |
|||
// padding: 0 10px; |
|||
// height: 650px; |
|||
// margin-top: 4px; |
|||
// overflow: hidden; |
|||
// overflow-y: scroll; |
|||
} |
|||
|
|||
.gird-layer{ |
|||
position: relative; |
|||
display: flex; |
|||
justify-content: space-between; |
|||
.gird-left-line{ |
|||
position: absolute; |
|||
left: 0; |
|||
top: 0; |
|||
display: block; |
|||
width: 6px; |
|||
height: 130px; |
|||
background: url('~@/assets/images/shelf01.png') no-repeat left top; |
|||
background-size: 100% 100%; |
|||
z-index: 999; |
|||
} |
|||
.gird-right-line{ |
|||
position: absolute; |
|||
right: calc(310px); |
|||
top: 0; |
|||
display: block; |
|||
width: 6px; |
|||
height: 130px; |
|||
background: url('~@/assets/images/shelf01.png') no-repeat left top; |
|||
background-size: 100% 100%; |
|||
z-index: 999; |
|||
} |
|||
.layer-left{ |
|||
width: calc(100% - 300px); |
|||
height: 130px; |
|||
margin-right: 5px; |
|||
padding: 0 0 0 12px; |
|||
background: url('~@/assets/images/shelf02.png') repeat left top; |
|||
background-size: 10% 100%; |
|||
overflow: hidden; |
|||
overflow-x: scroll; |
|||
} |
|||
.layer-left-book{ |
|||
// width: calc(100vw - 655px); |
|||
height: 130px; |
|||
white-space: nowrap; |
|||
.rack-box-list{ |
|||
height: 200px; |
|||
width: 100%; |
|||
overflow: hidden; |
|||
white-space: nowrap; |
|||
} |
|||
.list-item{ |
|||
display: inline-block; |
|||
border: none; |
|||
width: 42px; |
|||
height: 120px; |
|||
background: url('~@/assets/images/shelf03.png') no-repeat left top; |
|||
background-size: 100% 100%; |
|||
position: relative; |
|||
margin-left: -14px; |
|||
margin-top: 10px; |
|||
.book-name{ |
|||
position: absolute; |
|||
left: 12px; |
|||
top: 16px; |
|||
display: block; |
|||
height: 90px; |
|||
font-size: 16px; |
|||
writing-mode:vertical-rl; |
|||
overflow: hidden; |
|||
white-space: nowrap; |
|||
text-overflow: ellipsis; |
|||
} |
|||
&.red-active{ |
|||
background: url('~@/assets/images/shelf05.png') no-repeat left top; |
|||
background-size: 100% 100%; |
|||
} |
|||
&.blue-active{ |
|||
background: url('~@/assets/images/shelf06.png') no-repeat left top; |
|||
background-size: 100% 100%; |
|||
} |
|||
} |
|||
// .book-item{ |
|||
// position: relative; |
|||
// display: inline-block; |
|||
// width: 42px; |
|||
// height: 120px; |
|||
// margin-top: 18px; |
|||
// background: url('~@/assets/images/shelf03.png') no-repeat left top; |
|||
// background-size: 100% 100%; |
|||
// margin-left: -15px; |
|||
// cursor: pointer; |
|||
// span.book-name{ |
|||
// position: absolute; |
|||
// left: 15px; |
|||
// top: 16px; |
|||
// display: block; |
|||
// height: 90px; |
|||
// font-size: 12px; |
|||
// writing-mode:vertical-rl; |
|||
// overflow: hidden; |
|||
// white-space: nowrap; |
|||
// text-overflow: ellipsis; |
|||
// } |
|||
// &.red-active{ |
|||
// background: url('~@/assets/images/shelf05.png') no-repeat left top; |
|||
// background-size: 100% 100%; |
|||
// } |
|||
// &.blue-active{ |
|||
// background: url('~@/assets/images/shelf06.png') no-repeat left top; |
|||
// background-size: 100% 100%; |
|||
// } |
|||
// } |
|||
} |
|||
|
|||
} |
|||
|
|||
.layer-right-handle{ |
|||
width: 300px; |
|||
padding: 0 10px; |
|||
background-color: #E8F2FF; |
|||
margin: 3px 5px; |
|||
border-radius: 6px; |
|||
} |
|||
.layer-info-header{ |
|||
display: flex; |
|||
justify-content: space-between; |
|||
align-items: center; |
|||
line-height: 36px; |
|||
h4{ |
|||
font-size: 20px; |
|||
color: #0c0e1e; |
|||
} |
|||
span{ |
|||
font-size: 12px; |
|||
} |
|||
} |
|||
.layer-right-content{ |
|||
display: flex; |
|||
justify-content: space-between; |
|||
} |
|||
.layer-tag-info{ |
|||
div.tag-item { |
|||
display: flex; |
|||
justify-content: flex-start; |
|||
line-height: 26px; |
|||
font-size: 18px; |
|||
} |
|||
} |
|||
.layer-handle{ |
|||
display: flex; |
|||
flex-direction: column; |
|||
.el-button, |
|||
.el-button--info.is-plain { |
|||
margin-left: 0 !important; |
|||
margin-bottom: 10px; |
|||
padding: 7px 10px !important; |
|||
font-weight: bold !important; |
|||
border-color: #0348f3 !important; |
|||
color: #0348f3 !important; |
|||
} |
|||
.check-btn{ |
|||
color: #fff !important; |
|||
background-color: #0348f3 !important; |
|||
} |
|||
} |
|||
|
|||
</style> |
|||
@ -0,0 +1,163 @@ |
|||
<template> |
|||
<div class="content-main"> |
|||
<Search refs="searchRefs" search-type="noList" /> |
|||
<div class="box-style" style="margin: 30px 44px;"> |
|||
<div class="dataScreening-header"> |
|||
<h4 class="filter-header">图书馆总览</h4> |
|||
</div> |
|||
<div class="home-wrap tab-content"> |
|||
<ul class="tab-nav"> |
|||
<li v-for="(item,index) in floorOptions" :key="index" :class="{ 'active-tab-nav': tabIndex == index }" @click="changeActiveTab(index)">{{ item.floorName }}<i /></li> |
|||
</ul> |
|||
<CanvasPreview ref="previewRefs" v-loading="prewLoading" page-preview="floor" :current-mark-data="currentMarkData" :image-url="imageUrl" /> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="index-ranking"> |
|||
<div class="box-style"> |
|||
<Ranking form-ranking="home" /> |
|||
</div> |
|||
<div class="box-style"> |
|||
<ShelfRanking /> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import { FetchLibraryFloorListByFondsNo, FetchRegionListByFloorId, FetchInitStockInfo } from '@/api/inquiryMachine' |
|||
import CanvasPreview from './module/canvasPreview' |
|||
import { positionCrud } from './mixins/index.js' |
|||
import Search from './module/search' |
|||
import Ranking from './module/ranking' |
|||
import ShelfRanking from './module/shelfRanking' |
|||
import defaultImg from '@/assets/images/default-img-bg.jpg' |
|||
|
|||
export default { |
|||
name: 'Index', |
|||
components: { |
|||
Search, CanvasPreview, Ranking, ShelfRanking |
|||
}, |
|||
mixins: [positionCrud], |
|||
data() { |
|||
return { |
|||
prewLoading: false, |
|||
floorOptions: [], |
|||
tabIndex: 0, |
|||
defaultImg: defaultImg, |
|||
imageUrl: defaultImg, |
|||
imageRegionUrl: defaultImg, |
|||
currentMarkData: null, |
|||
allCoverData: [], |
|||
baseStockDataAllShelf: [] |
|||
} |
|||
}, |
|||
created() { |
|||
this.getFloorList() |
|||
}, |
|||
mounted() { |
|||
|
|||
}, |
|||
methods: { |
|||
getFloorList() { |
|||
FetchLibraryFloorListByFondsNo({ 'fondsCode': this.libcode }).then(res => { |
|||
this.floorOptions = res |
|||
|
|||
this.changeActiveTab(this.tabIndex) |
|||
}).catch(() => { |
|||
this.$message.error('接口错误') |
|||
}) |
|||
}, |
|||
async changeActiveTab(index) { |
|||
const baseUrl = process.env.NODE_ENV === 'production' ? window.g.ApiUrl : process.env.VUE_APP_BASE_API |
|||
this.prewLoading = true |
|||
if (this.$refs.previewRefs.canvasPreview.lowerCanvasEl) { |
|||
this.$refs.previewRefs.canvasPreview.clear() |
|||
this.$refs.previewRefs.canvasPreview.dispose() |
|||
} |
|||
this.allCoverData = [] |
|||
this.tabIndex = index |
|||
const params = { |
|||
'floorId': this.floorOptions[index].id |
|||
} |
|||
try { |
|||
const res = await FetchRegionListByFloorId(params) |
|||
console.log(res) |
|||
this.allCoverData = res |
|||
if (this.floorOptions[index].floorMap) { |
|||
this.imageUrl = baseUrl + '/api/fileRelevant/getImg?imgId=' + this.floorOptions[index].floorMap |
|||
} else { |
|||
this.imageUrl = this.defaultImg |
|||
} |
|||
|
|||
if (this.allCoverData.length !== 0) { |
|||
this.currentMarkData = this.allCoverData[0] |
|||
|
|||
// const signPoint = this.allCoverData.find(item => item.signPoint !== null)?.signPoint |
|||
const imgInfo = JSON.parse(this.allCoverData[0].signPoint).imgInfo |
|||
|
|||
const baseStockDataAllShelf = await this.getInitStockInfo(this.allCoverData) |
|||
const parsedSignPoints = this.allCoverData.map(item => { |
|||
const signPoint = item.signPoint ? JSON.parse(item.signPoint) : null |
|||
return { |
|||
id: item.id, |
|||
name: item.regionName, |
|||
floorName: this.floorOptions[index].floorName, |
|||
floorId: item.floorId, |
|||
pointInfo: signPoint ? signPoint.pointInfo[0].pointInfo : null |
|||
} |
|||
}) |
|||
parsedSignPoints.forEach(parsedItem => { |
|||
const baseStockItem = baseStockDataAllShelf.find(baseItem => baseItem.id === parsedItem.id) |
|||
if (baseStockDataAllShelf) { |
|||
Object.assign(parsedItem, baseStockItem) |
|||
} |
|||
}) |
|||
|
|||
const result = { |
|||
pointInfo: parsedSignPoints, |
|||
imgInfo: imgInfo |
|||
} |
|||
console.log('result', result) |
|||
this.$nextTick(() => { |
|||
this.$refs.previewRefs.initCanvasPreview(result, this.tabIndex) |
|||
}) |
|||
} else { |
|||
this.currentMarkData = {} |
|||
setTimeout(() => { |
|||
this.prewLoading = false |
|||
}, 500) |
|||
} |
|||
} catch (error) { |
|||
console.error(error) |
|||
} |
|||
}, |
|||
async getInitStockInfo(data) { |
|||
const promises = data.map(item => { |
|||
const params = { |
|||
'fondsCode': this.libcode, |
|||
'floorId': this.floorOptions[this.tabIndex].id, |
|||
'regionId': item.id |
|||
} |
|||
return FetchInitStockInfo(params) |
|||
}) |
|||
const results = await Promise.all(promises) |
|||
if (!Array.isArray(this.baseStockDataAllShelf)) { |
|||
this.baseStockDataAllShelf = [] |
|||
} |
|||
// 为每个结果对象添加id字段 |
|||
results.forEach((result, index) => { |
|||
result.id = data[index].id |
|||
}) |
|||
this.baseStockDataAllShelf = this.baseStockDataAllShelf.concat(results) |
|||
return this.baseStockDataAllShelf |
|||
} |
|||
|
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
@import "~@/assets/styles/index.scss"; |
|||
|
|||
</style> |
|||
@ -0,0 +1,344 @@ |
|||
import { FetchShelfGridAllByShelfIdText, FetchBookShelfDetails } from '@/api/inquiryMachine' |
|||
import defaultImg from '@/assets/images/default-img-bg.jpg' |
|||
import { mapGetters } from 'vuex' |
|||
import { fabric } from 'fabric' |
|||
export const positionCrud = { |
|||
mixins: [], |
|||
// 组件共用属性
|
|||
data() { |
|||
return { |
|||
positionVisible: false, |
|||
positionTitle: '图书定位', |
|||
positionContent: {}, |
|||
currentMarkData: null, |
|||
defaultImg: defaultImg, |
|||
imageUrl: defaultImg, |
|||
canvasPreview: {}, |
|||
width: 900, |
|||
height: 600, |
|||
drawWidth: 2, // 笔触宽度
|
|||
booShelfGrid: [], |
|||
layerNum: 0, |
|||
rackNum: 0, |
|||
cellIndex: 0, |
|||
bookShelfDetails: {}, |
|||
getGridShelf: '', |
|||
getGridFloor: '', |
|||
getGridToward: 1 |
|||
} |
|||
}, |
|||
computed: { |
|||
...mapGetters([ |
|||
'user', |
|||
'baseApi' |
|||
]), |
|||
cellStyle: function() { |
|||
const h = '38px' |
|||
let w |
|||
if (this.rackNum === 1) { |
|||
w = '146px' |
|||
} else { |
|||
w = '100%/' + this.rackNum |
|||
} |
|||
return { width: `calc(${w})`, height: `calc(${h})` } |
|||
}, |
|||
rowStyle: function() { |
|||
let w |
|||
if (this.rackNum === 1) { |
|||
w = 146 * this.rackNum + 'px' |
|||
} else { |
|||
w = '100%' |
|||
} |
|||
return { width: `calc(${w})` } |
|||
}, |
|||
reversedRackNum() { |
|||
if (this.booShelfGrid && this.booShelfGrid.length > 0) { |
|||
if (parseInt(this.booShelfGrid[0].gridShelf) === this.rackNum) { |
|||
return Array.from({ length: this.rackNum }, (_, i) => this.rackNum - i).map(x => x.toString()) |
|||
} else { |
|||
return Array.from({ length: this.rackNum }, (_, i) => i + 1).map(x => x.toString()) |
|||
} |
|||
} else { |
|||
return [] |
|||
} |
|||
} |
|||
}, |
|||
// 组件挂载时的共用方法
|
|||
mounted() { |
|||
}, |
|||
// 组件共用方法
|
|||
methods: { |
|||
removeAreaPrefix(gridNames) { |
|||
const index = gridNames.indexOf('面') |
|||
if (index !== -1) { |
|||
return gridNames.substring(index + 1) |
|||
} |
|||
return gridNames |
|||
}, |
|||
handlePosition(row, type) { |
|||
const baseUrl = process.env.NODE_ENV === 'production' ? window.g.ApiUrl : process.env.VUE_APP_BASE_API |
|||
this.booShelfGrid = [] |
|||
this.currentMarkData = {} |
|||
if (this.canvasPreview.lowerCanvasEl) { |
|||
this.canvasPreview.clear() |
|||
this.canvasPreview.dispose() |
|||
} |
|||
this.positionVisible = true |
|||
console.log('type', type) |
|||
let params |
|||
if (type !== 'hot') { |
|||
this.positionTitle = '图书定位 - 《' + row.bookName + '》' |
|||
this.updateParts(row.gridName) |
|||
params = { |
|||
'shelfId': row.actualShelfId |
|||
} |
|||
this.positionContent = row |
|||
} else { |
|||
this.positionTitle = '架位定位' |
|||
params = { |
|||
'shelfId': row.shelf_id |
|||
} |
|||
this.updateParts(row.grid_name) |
|||
} |
|||
|
|||
FetchBookShelfDetails(params).then(res => { |
|||
this.layerNum = res.shelfFloor |
|||
this.rackNum = res.shelfShelf |
|||
this.bookShelfDetails = res |
|||
this.currentMarkData = res |
|||
|
|||
if (row.regionMap) { |
|||
this.imageUrl = baseUrl + '/api/fileRelevant/getImg?imgId=' + row.regionMap |
|||
this.$nextTick(() => { |
|||
const drawinfo = JSON.parse(res.signPoint) |
|||
this.initCanvasPreview(drawinfo, type) |
|||
}) |
|||
} else { |
|||
this.imageUrl = this.defaultImg |
|||
} |
|||
this.getInitShelfGridByShelfId(this.getGridToward) |
|||
}).catch(() => { |
|||
}) |
|||
}, |
|||
updateParts(gridName) { |
|||
const parts = gridName.match(/(\d+)区(\d+)排([A-Za-z])面(\d+)架(\d+)层/) |
|||
if (parts) { |
|||
this.getGridShelf = parts[4] |
|||
this.getGridFloor = parts[5] |
|||
const toward = parts[3] |
|||
if (toward === 'A') { |
|||
this.getGridToward = 1 |
|||
} else if (toward === 'B') { |
|||
this.getGridToward = 2 |
|||
} |
|||
} |
|||
}, |
|||
getInitShelfGridByShelfId(toward) { |
|||
this.listLoading = true |
|||
// rowType 1 单 2 双
|
|||
// toward 1 A面 2 B面
|
|||
// shelfType 1 '始终最左边为第1架(S型排架)'
|
|||
// shelfType 2 'A面最左为第1架(B面最左为最后1架)'
|
|||
// shelfType 3 'B面最左为第1架(A面最左为最后1架)'
|
|||
// floorType 1 '最顶层为第一层(从上至下)'
|
|||
// floorType 2 '最底层为第一层(从下至上)'
|
|||
FetchShelfGridAllByShelfIdText({ 'shelfId': this.bookShelfDetails.id, 'toward': toward }).then(res => { |
|||
const sortFunction = toward === 1 ? { |
|||
1: { 1: 'sortBookshelvesLeftTop', 2: 'sortBookshelvesLeftBottom' }, |
|||
2: { 1: 'sortBookshelvesLeftTop', 2: 'sortBookshelvesLeftBottom' }, |
|||
3: { 1: 'sortBookshelvesRightTop', 2: 'sortBookshelvesRightBottom' } |
|||
} : { |
|||
1: { 1: 'sortBookshelvesLeftTop', 2: 'sortBookshelvesLeftBottom' }, |
|||
2: { 1: 'sortBookshelvesRightTop', 2: 'sortBookshelvesRightBottom' }, |
|||
3: { 1: 'sortBookshelvesLeftTop', 2: 'sortBookshelvesLeftBottom' } |
|||
} |
|||
const shelfType = this.bookShelfDetails.shelfType |
|||
const floorType = this.bookShelfDetails.floorType |
|||
const sortMethod = sortFunction[shelfType][floorType] |
|||
this.booShelfGrid = this[sortMethod](res) |
|||
|
|||
const index = this.booShelfGrid.findIndex((obj) => { |
|||
return obj.gridShelf === this.getGridShelf && obj.gridFloor === this.getGridFloor |
|||
}) |
|||
|
|||
this.cellIndex = index |
|||
setTimeout(() => { |
|||
this.listLoading = false |
|||
}, 1000) |
|||
}).catch(() => { |
|||
}) |
|||
}, |
|||
// 最左为第一架, 最顶层为第一层 从上往下
|
|||
sortBookshelvesLeftTop(data) { |
|||
const sortedData = [] |
|||
const maxFloor = Math.max(...data.map(item => parseInt(item.gridFloor))) |
|||
const maxShelf = Math.max(...data.map(item => parseInt(item.gridShelf.slice(-1)))) |
|||
|
|||
for (let i = 1; i <= maxFloor; i++) { |
|||
for (let j = 1; j <= maxShelf; j++) { |
|||
const currentShelf = data.find(item => parseInt(item.gridFloor) === i && parseInt(item.gridShelf.slice(-1)) === j) |
|||
if (currentShelf) { |
|||
sortedData.push(currentShelf) |
|||
} |
|||
} |
|||
} |
|||
return sortedData |
|||
}, |
|||
// 最右为第一架,最左为最后一架, 最顶层为第一层 从上往下
|
|||
sortBookshelvesRightTop(data) { |
|||
const sortedData = [] |
|||
// 获取最大的楼层数
|
|||
const maxFloor = Math.max(...data.map(item => parseInt(item.gridFloor))) |
|||
const maxShelf = Math.max(...data.map(item => parseInt(item.gridShelf.match(/\d+$/)[0]))) |
|||
for (let i = 1; i <= maxFloor; i++) { |
|||
// 从最大的书架层数开始,向下排序
|
|||
for (let j = maxShelf; j >= 1; j--) { |
|||
const currentShelf = data.find(item => parseInt(item.gridFloor) === i && parseInt(item.gridShelf.match(/\d+$/)[0]) === j) |
|||
if (currentShelf) { |
|||
sortedData.push(currentShelf) |
|||
} |
|||
} |
|||
} |
|||
return sortedData |
|||
}, |
|||
// 最左为第一架, 最底层为第一层 从下往上
|
|||
sortBookshelvesLeftBottom(data) { |
|||
const sortedData = [] |
|||
// 获取最大的楼层数
|
|||
const maxFloor = Math.max(...data.map(item => parseInt(item.gridFloor))) |
|||
// 获取最大的书架层数
|
|||
const maxShelf = Math.max(...data.map(item => parseInt(item.gridShelf.slice(-1)))) |
|||
for (let i = maxFloor; i >= 1; i--) { |
|||
for (let j = 1; j <= maxShelf; j++) { |
|||
const currentShelf = data.find(item => parseInt(item.gridFloor) === i && parseInt(item.gridShelf.slice(-1)) === j) |
|||
if (currentShelf) { |
|||
sortedData.push(currentShelf) |
|||
} |
|||
} |
|||
} |
|||
return sortedData |
|||
}, |
|||
// 最左为最后一架, 最底层为第一层 从下往上
|
|||
sortBookshelvesRightBottom(data) { |
|||
const sortedData = [] |
|||
// 获取最大的楼层数
|
|||
const maxFloor = Math.max(...data.map(item => parseInt(item.gridFloor))) |
|||
const maxShelfPerFloor = data.map(item => parseInt(item.gridShelf.match(/\d+$/)[0])) |
|||
.reduce((acc, curr, index, arr) => { |
|||
const floor = parseInt(data[index].gridFloor) |
|||
if (!acc[floor]) acc[floor] = 1 |
|||
if (acc[floor] < curr) acc[floor] = curr |
|||
return acc |
|||
}, {}) |
|||
// 从最大的楼层开始向下遍历
|
|||
for (let i = maxFloor; i >= 1; i--) { |
|||
// 从最大的书架编号开始向左遍历
|
|||
for (let j = maxShelfPerFloor[i] || 1; j >= 1; j--) { |
|||
const currentShelf = data.find(item => parseInt(item.gridFloor) === i && parseInt(item.gridShelf.match(/\d+$/)[0]) === j) |
|||
if (currentShelf) { |
|||
sortedData.push(currentShelf) |
|||
} |
|||
} |
|||
} |
|||
return sortedData |
|||
}, |
|||
initCanvasPreview(drawinfo, type) { |
|||
console.log('type222', type) |
|||
if (!this.currentMarkData) { |
|||
console.error('currentMarkData is null or undefined') |
|||
return |
|||
} |
|||
let canvasId |
|||
if (type === 'hot') { |
|||
canvasId = `canvasPreview${this.currentMarkData.id}${type}` |
|||
} else { |
|||
canvasId = `canvasPreview${this.currentMarkData.id}` |
|||
} |
|||
|
|||
this.canvasPreview = new fabric.Canvas(canvasId, { |
|||
skipTargetFind: false, |
|||
selectable: false, |
|||
selection: false |
|||
}) |
|||
|
|||
this.$nextTick(() => { |
|||
this.canvasPreview.selectionColor = 'rgba(0,0,0,0.05)' |
|||
this.loadDrawPreview(drawinfo) |
|||
this.canvasPreview.on('mouse:wheel', this.mouse) |
|||
}) |
|||
}, |
|||
// 鼠标滚轮放大缩小
|
|||
mouse(e) { |
|||
if (undefined === e) return |
|||
let zoom = (e.e.deltaY > 0 ? -0.1 : 0.1) + this.canvasPreview.getZoom() |
|||
zoom = Math.max(0.8, zoom) |
|||
// 最小为原来的1/10
|
|||
zoom = Math.min(3, zoom) |
|||
// 最大是原来的3倍
|
|||
const zoomPoint = new fabric.Point(e.e.pageX, e.e.pageY) |
|||
this.canvasPreview.zoomToPoint(zoomPoint, zoom) |
|||
}, |
|||
// 回显详情信息
|
|||
loadDrawPreview(drawinfo) { |
|||
const self = this |
|||
const pointGroup = drawinfo.pointInfo |
|||
const imgInfo = drawinfo.imgInfo |
|||
imgInfo.src = self.imageUrl |
|||
// 加载底图
|
|||
fabric.util.enlivenObjects([imgInfo], objects => { |
|||
objects.forEach(o => { |
|||
o.selectable = false |
|||
o.hasControls = false |
|||
o.centeredScaling = false |
|||
self.canvasPreview.add(o) |
|||
}) |
|||
|
|||
// 处理多边形绘制回显操作
|
|||
pointGroup.forEach(async(item, index) => { |
|||
if (item.pointInfo !== '') { |
|||
const polygon = new fabric.Polygon(item.pointInfo, { |
|||
name: item.name, |
|||
stroke: 'rgba(196, 43, 1, 1)', |
|||
strokeWidth: self.drawWidth, |
|||
fill: 'rgba(196, 43, 1, 1)', |
|||
opacity: 0.5, |
|||
selectable: false, |
|||
hasBorders: false, |
|||
hasControls: false, |
|||
originX: 'left', |
|||
originY: 'top' |
|||
}) |
|||
self.canvasPreview.add(polygon) |
|||
|
|||
polygon.on('mousedown', function(e) { |
|||
console.log('Rect' + (index + 1) + 'clicked', e) |
|||
console.log('e.target.name', e.target.name) |
|||
}) |
|||
|
|||
polygon.on('mouseover', function(e) { |
|||
console.log('e', e) |
|||
console.log('e.target', e.target) |
|||
console.log('e.target.name', e.target.name) |
|||
this.set({ opacity: 0.8, hoverCursor: 'pointer' }) |
|||
self.canvasPreview.renderAll() |
|||
}) |
|||
|
|||
polygon.on('mouseout', function() { |
|||
this.set({ opacity: 0.5 }) |
|||
self.canvasPreview.renderAll() |
|||
}) |
|||
|
|||
// 加载完成后直接对多边形执行zoomToPoint操作
|
|||
const center = polygon.getCenterPoint() |
|||
self.canvasPreview.zoomToPoint({ x: center.x, y: center.y }, 1.4) |
|||
} |
|||
}) |
|||
}) |
|||
self.canvasPreview.renderAll() |
|||
}, |
|||
handleCloseDialog() { |
|||
this.positionVisible = false |
|||
this.detailVisible = false |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,195 @@ |
|||
<template> |
|||
<div> |
|||
<!-- 图书详情dialog --> |
|||
<el-dialog class="detail-dialog" append-to-body :close-on-click-modal="false" :modal-append-to-body="false" :visible.sync="detailShow"> |
|||
<div class="dialog-book"> |
|||
<div class="book-info"> |
|||
<div class="book-img"> |
|||
<img :src="coverUrl+'/demoRecommend/getBookCover.do?id='+detailData.id" :onerror="defaultImg" alt=""> |
|||
</div> |
|||
<div class="book-txt"> |
|||
<h4> {{ detailData.bookBasics.title }} </h4> |
|||
<div class="book-autor"> {{ detailData.bookBasics.author }} </div> |
|||
<div class="book-publish"> {{ detailData.bookBasics.publisher }} </div> |
|||
<div class="book-isbn">ISBN:{{ detailData.bookBasics.isbn }}</div> |
|||
<div class="book-isbn">分类号:{{ detailData.bookBasics.classNo }}</div> |
|||
</div> |
|||
</div> |
|||
<div class="book-intro"> {{ detailData.bookBasics.summary }} </div> |
|||
</div> |
|||
<div class="book-place"> |
|||
<h4>馆藏列表</h4> |
|||
<ul class="book-place-list"> |
|||
<li v-for="(item,index) in detailData.bookDetailsList" :key="index" @click="handlePosition(item)"> |
|||
<span>{{ index+1 }}</span> |
|||
<p class="book-num">{{ item.sortmark }}</p> |
|||
<p class="place-detail"> {{ getLocation(item) }}</p> |
|||
</li> |
|||
</ul> |
|||
</div> |
|||
<div class="book-bottom" @click="handleClosed"> |
|||
<span>关闭</span> |
|||
</div> |
|||
</el-dialog> |
|||
|
|||
<el-dialog class="positionDialog" append-to-body :close-on-click-modal="false" :modal-append-to-body="false" :before-close="handleCloseDialog" :visible="positionVisible" :title="positionTitle"> |
|||
<div class="setting-dialog"> |
|||
<ul class="book-detail"> |
|||
<li><span>所属楼层</span>{{ positionContent.floorName }}</li> |
|||
<li><span>所属区域</span>{{ positionContent.regionName }}</li> |
|||
<li><span>所属书架</span>{{ positionContent.gridName }}</li> |
|||
</ul> |
|||
<div class="position-content"> |
|||
<div class="position-left"> |
|||
<h5>平面图</h5> |
|||
<div class="venue-preview"> |
|||
<div v-show="currentMarkData && currentMarkData.signPoint "> |
|||
<canvas :id="`canvasPreview${currentMarkData && currentMarkData.id}`" :width="width" :height="height" /> |
|||
</div> |
|||
<img v-if="currentMarkData && !currentMarkData.signPoint" :src="imageUrl" :onerror="defaultImg" alt=""> |
|||
<img v-if="!currentMarkData" :src="imageUrl" :onerror="defaultImg" alt=""> |
|||
</div> |
|||
</div> |
|||
<div class="position-right"> |
|||
<h5>书架图</h5> |
|||
<div class="shelf-top" :style="rowStyle"> |
|||
<p v-for="(item,index) in reversedRackNum" :key="index" :style="{width: `calc(${'100%/' + rackNum} - 4px )`}"><span>{{ item + '架' }}</span></p> |
|||
</div> |
|||
<ul class="data-shelf-row" :style="rowStyle"> |
|||
<li |
|||
v-for="(cell,i) in booShelfGrid" |
|||
:key="i" |
|||
:class="{ active: i === cellIndex }" |
|||
class="data-shelf-cell" |
|||
:style="cellStyle" |
|||
> |
|||
<span class="cell-name">{{ removeAreaPrefix(cell.gridName) }}</span> |
|||
</li> |
|||
</ul> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="book-bottom" @click="handleCloseDialog"> |
|||
<span>关闭</span> |
|||
</div> |
|||
</el-dialog> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import { FetchInitBookDetailsSearchInto } from '@/api/inquiryMachine' |
|||
import { positionCrud } from '../mixins/index.js' |
|||
export default { |
|||
name: 'BookDetails', |
|||
mixins: [positionCrud], |
|||
data() { |
|||
return { |
|||
booShelfGrid: [], |
|||
coverUrl: null, |
|||
detailShow: false, |
|||
positionVisible: false, |
|||
positionContent: {}, |
|||
detailData: { |
|||
bookBasics: {}, |
|||
bookDetailsList: [] |
|||
}, |
|||
defaultImg: 'this.src="' + require('@/assets/images/default-img.png') + '"' |
|||
} |
|||
}, |
|||
computed: { |
|||
reversedRackNum() { |
|||
if (this.booShelfGrid && this.booShelfGrid.length > 0) { |
|||
if (parseInt(this.booShelfGrid[0].gridShelf) === this.rackNum) { |
|||
return Array.from({ length: this.rackNum }, (_, i) => this.rackNum - i).map(x => x.toString()) |
|||
} else { |
|||
return Array.from({ length: this.rackNum }, (_, i) => i + 1).map(x => x.toString()) |
|||
} |
|||
} else { |
|||
return [] |
|||
} |
|||
} |
|||
}, |
|||
created() { |
|||
}, |
|||
methods: { |
|||
getLocation(row) { |
|||
const parts = [] |
|||
if (row.floorName) { |
|||
parts.push(row.floorName) |
|||
} |
|||
if (row.regionName) { |
|||
parts.push(row.regionName) |
|||
} |
|||
if (row.gridName) { |
|||
parts.push(row.gridName) |
|||
} |
|||
return parts.length > 0 ? parts.join('-') : '-' |
|||
}, |
|||
getBookRankingDetail(item) { |
|||
this.detailShow = true |
|||
this.detailData = item |
|||
}, |
|||
getBookDetail(item) { |
|||
FetchInitBookDetailsSearchInto({ 'id': item.id }).then((res) => { |
|||
this.detailShow = true |
|||
if (res && Object.keys(res).length !== 0) { |
|||
console.log('res', res) |
|||
this.detailData = res |
|||
} else { |
|||
console.log('res', '111') |
|||
this.detailData = null |
|||
} |
|||
}).catch(() => { |
|||
this.$message.error('接口错误') |
|||
}) |
|||
}, |
|||
handleClosed() { |
|||
this.detailShow = false |
|||
}, |
|||
handleCloseDialog() { |
|||
this.positionVisible = false |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
@import "~@/assets/styles/index.scss"; |
|||
::v-deep .el-dialog{ |
|||
width: 930px; |
|||
border-radius: 16px; |
|||
background: #F8F8FD; |
|||
box-shadow: 0px 3px 20px 1px rgba(0,0,0,0.05); |
|||
.el-dialog__body{ |
|||
padding: 20px 0 23px 0; |
|||
} |
|||
} |
|||
.detail-dialog{ |
|||
::v-deep .el-dialog__header{ |
|||
display: none; |
|||
} |
|||
} |
|||
::v-deep .el-dialog__headerbtn{ |
|||
display: none; |
|||
} |
|||
::v-deep .el-dialog__title{ |
|||
font-weight: bold; |
|||
} |
|||
::v-deep .el-dialog__header{ |
|||
border-bottom: 1px solid #EDEFF3; |
|||
} |
|||
.dialog-book{ |
|||
padding: 30px; |
|||
font-size: 28px; |
|||
.book-txt{ |
|||
color: #191A1A!important; |
|||
font-size: 30px !important; |
|||
} |
|||
.book-autor{ |
|||
font-size: 24px !important; |
|||
} |
|||
.book-publish{ |
|||
font-size: 28px !important; |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,337 @@ |
|||
<template> |
|||
<div class="venue-preview"> |
|||
<!-- v-show="currentMarkData && currentMarkData.signPoint" --> |
|||
<div v-show="currentMarkData && currentMarkData.signPoint"> |
|||
<canvas :id="`canvasPreview${currentMarkData && currentMarkData.id}`" :width="width" :height="height" /> |
|||
</div> |
|||
<img v-if="currentMarkData &&!currentMarkData.signPoint" :src="imageUrl" :onerror="defaultImg" alt=""> |
|||
<div id="tooltip" class="tooltip-style"> |
|||
<!-- <div class="tooltip-top"> |
|||
<h4>区域名称</h4> |
|||
<span class="update-time">2024-11-28 09:46</span> |
|||
</div> |
|||
<ul> |
|||
<li><p>在架</p><span><i>15000</i>册</span></li> |
|||
<li><p>错架</p><span><i>300</i>层</span> <span class="percentage">(2.00%)</span></li> |
|||
<li><p>错序</p><span><i>0</i>层</span><span class="percentage">(0.00%)</span></li> |
|||
</ul> --> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
// import { dataScreeningCrud } from '@/views/visualCheck/mixins/index' |
|||
import defaultImg from '@/assets/images/default-img-bg.jpg' |
|||
import { fabric } from 'fabric' |
|||
import { mapGetters } from 'vuex' |
|||
export default { |
|||
name: 'Mark', |
|||
mixins: [], |
|||
props: { |
|||
currentMarkData: { |
|||
type: Object, |
|||
require: true, |
|||
default: function() { |
|||
return {} |
|||
} |
|||
}, |
|||
imageUrl: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
pagePreview: { |
|||
type: String, |
|||
default: '' |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
defaultImg: defaultImg, |
|||
canvasPreview: {}, |
|||
width: 1200, |
|||
height: 600, |
|||
drawWidth: 2, |
|||
tooltipInfo: null, |
|||
initialDistance: 0, |
|||
initialZoom: 0 |
|||
} |
|||
}, |
|||
computed: { |
|||
...mapGetters([ |
|||
'user', |
|||
'baseApi' |
|||
]) |
|||
}, |
|||
watch: { |
|||
width() { |
|||
this.canvasPreview.setWidth(this.width) |
|||
}, |
|||
height() { |
|||
this.canvasPreview.setHeight(this.height) |
|||
}, |
|||
currentMarkData: { |
|||
handler(newVal, oldVal) { |
|||
// 检查 newVal 是否为 null 或 undefined |
|||
if (!newVal) { |
|||
console.log('newVal - null') |
|||
return |
|||
} |
|||
}, |
|||
deep: true |
|||
}, |
|||
imageUrl(newVal, oldVal) { |
|||
if (newVal !== oldVal) { |
|||
console.log('imageUrl', newVal) |
|||
} |
|||
} |
|||
}, |
|||
mounted() { |
|||
if (this.canvasPreview.lowerCanvasEl) { |
|||
this.canvasPreview.getCanvas().el.addEventListener('touchstart', this.handleTouchStart.bind(this)) |
|||
this.canvasPreview.getCanvas().el.addEventListener('touchmove', this.handleTouchMove.bind(this)) |
|||
this.canvasPreview.getCanvas().el.addEventListener('touchend', this.handleTouchEnd.bind(this)) |
|||
} |
|||
}, |
|||
beforeDestroy() { |
|||
// if (this.canvasPreview) { |
|||
// this.canvasPreview.clear() |
|||
// this.canvasPreview.dispose() |
|||
// } |
|||
}, |
|||
methods: { |
|||
initCanvasPreview(drawinfo, tabIndex) { |
|||
if (!this.currentMarkData) { |
|||
console.error('currentMarkData - null') |
|||
return |
|||
} |
|||
|
|||
const canvasId = `canvasPreview${this.currentMarkData.id}` |
|||
this.canvasPreview = new fabric.Canvas(canvasId, { |
|||
skipTargetFind: false, |
|||
selectable: false, |
|||
selection: false |
|||
}) |
|||
|
|||
this.$nextTick(() => { |
|||
this.canvasPreview.selectionColor = 'rgba(0,0,0,0.05)' |
|||
this.loadDrawPreview(drawinfo, tabIndex) |
|||
// this.canvasPreview.on('mouse:wheel', this.mouse) |
|||
}) |
|||
}, |
|||
// 触摸事件处理函数 |
|||
handleTouchStart(e) { |
|||
if (e.touches.length === 2) { |
|||
const touch1 = e.touches[0] |
|||
const touch2 = e.touches[1] |
|||
this.initialDistance = Math.sqrt((touch2.clientX - touch1.clientX) * (touch2.clientX - touch1.clientX) + (touch2.clientY - touch1.clientY) * (touch2.clientY - touch1.clientY)) |
|||
this.initialZoom = this.canvasPreview.getZoom() |
|||
} |
|||
}, |
|||
handleTouchMove(e) { |
|||
if (e.touches.length === 2) { |
|||
const touch1 = e.touches[0] |
|||
const touch2 = e.touches[1] |
|||
const currentDistance = Math.sqrt((touch2.clientX - touch1.clientX) * (touch2.clientX - touch1.clientX) + (touch2.clientY - touch1.clientY) * (touch2.clientY - touch1.clientY)) |
|||
let newZoom = this.initialZoom * (currentDistance / this.initialDistance) |
|||
newZoom = Math.max(0.8, newZoom) |
|||
newZoom = Math.min(3, newZoom) |
|||
const centerX = (touch1.clientX + touch2.clientX) / 2 |
|||
const centerY = (touch1.clientY + touch2.clientY) / 2 |
|||
const zoomPoint = new fabric.Point(centerX, centerY) |
|||
this.canvasPreview.zoomToPoint(zoomPoint, newZoom) |
|||
} |
|||
}, |
|||
handleTouchEnd() { |
|||
// 触摸结束时可以做一些清理操作,这里暂未用到 |
|||
}, |
|||
// 回显详情信息 |
|||
loadDrawPreview(drawinfo, tabIndex) { |
|||
const self = this |
|||
const pointGroup = drawinfo.pointInfo |
|||
const imgInfo = drawinfo.imgInfo |
|||
imgInfo.src = self.imageUrl |
|||
|
|||
// 加载底图 |
|||
fabric.util.enlivenObjects([imgInfo], objects => { |
|||
objects.forEach(o => { |
|||
o.selectable = false |
|||
o.hasControls = false |
|||
o.centeredScaling = false |
|||
self.canvasPreview.add(o) |
|||
}) |
|||
// 处理多边形绘制回显操作 |
|||
pointGroup.forEach(async(item, index) => { |
|||
console.log('item', item) |
|||
if (item.pointInfo !== '') { |
|||
const polygon = new fabric.Polygon(item.pointInfo, { |
|||
id: item.id, |
|||
name: item.name, |
|||
floorId: item.floorId, |
|||
regionId: item.regionId, |
|||
rowType: item.rowType, |
|||
toward: item.toward, |
|||
floorName: item.floorName, |
|||
regionName: item.regionName, |
|||
shelfFloor: item.shelfFloor, |
|||
shelfShelf: item.shelfShelf, |
|||
errorOrderNum: item.errorOrderNum, |
|||
errorOrderProbo: item.errorOrderProbo, |
|||
errorShelfNum: item.errorShelfNum, |
|||
errorShelfProbo: item.errorShelfProbo, |
|||
onShelfNum: item.onShelfNum, |
|||
stroke: 'rgba(196,43, 1, 1)', |
|||
strokeWidth: self.drawWidth, |
|||
fill: 'rgba(196,43, 1, 1)', |
|||
opacity: 0.5, |
|||
selectable: false, |
|||
hasBorders: false, |
|||
hasControls: false, |
|||
originX: 'left', // 设置原点为左上角 |
|||
originY: 'top' // 设置原点为左上角 |
|||
}) |
|||
self.canvasPreview.add(polygon) |
|||
|
|||
// const lastClickTime = 0 |
|||
// const doubleClickInterval = 300 |
|||
polygon.on('mousedown', function(e) { |
|||
// const currentTime = new Date().getTime() |
|||
// const timeDiff = currentTime - lastClickTime |
|||
|
|||
const toReigonsData = { |
|||
id: e.target.id, |
|||
name: e.target.name, |
|||
floorId: e.target.floorId, |
|||
regionId: e.target.regionId, |
|||
rowType: e.target.rowType, |
|||
toward: e.target.toward, |
|||
regionName: e.target.regionName, |
|||
floorName: e.target.floorName |
|||
} |
|||
console.log('toReigonsData', toReigonsData) |
|||
if (self.pagePreview === 'floor') { |
|||
console.log('toReigonsData', toReigonsData) |
|||
self.handleToRegions(toReigonsData, tabIndex) |
|||
} else if (self.pagePreview === 'region') { |
|||
self.handleToShelfs(toReigonsData, tabIndex) |
|||
} |
|||
|
|||
// if (timeDiff <= doubleClickInterval) { |
|||
// console.log('双击事件', e) |
|||
// lastClickTime = 0 |
|||
// const toReigonsData = { |
|||
// id: e.target.id, |
|||
// name: e.target.name, |
|||
// floorId: e.target.floorId, |
|||
// regionId: e.target.regionId, |
|||
// rowType: e.target.rowType, |
|||
// toward: e.target.toward, |
|||
// regionName: e.target.regionName, |
|||
// floorName: e.target.floorName |
|||
// } |
|||
// console.log('toReigonsData', toReigonsData) |
|||
// if (self.pagePreview === 'floor') { |
|||
// self.handleToRegions(toReigonsData, tabIndex) |
|||
// } else if (self.pagePreview === 'region') { |
|||
// self.handleToShelfs(toReigonsData, tabIndex) |
|||
// } |
|||
// } else { |
|||
// lastClickTime = currentTime |
|||
// } |
|||
}) |
|||
|
|||
// polygon.on('mouseover', function(e) { |
|||
// this.tooltipInfo = { |
|||
// 'id': e.target.id, |
|||
// 'name': e.target.name, |
|||
// 'rowType': e.target.rowType, |
|||
// 'shelfFloor': e.target.shelfFloor, |
|||
// 'shelfShelf': e.target.shelfShelf, |
|||
// 'floorId': e.target.floorId, |
|||
// 'regionId': e.target.regionId, |
|||
// 'errorOrderNum': e.target.errorOrderNum, |
|||
// 'errorOrderProbo': e.target.errorOrderProbo, |
|||
// 'errorShelfNum': e.target.errorShelfNum, |
|||
// 'errorShelfProbo': e.target.errorShelfProbo, |
|||
// 'onShelfNum': e.target.onShelfNum |
|||
// } |
|||
// this.set({ opacity: 0.8, hoverCursor: 'pointer' }) |
|||
// // <span class="update-time">2024-11-28 09:46</span> |
|||
|
|||
// if (self.pagePreview === 'floor') { |
|||
// document.getElementById('tooltip').innerHTML = |
|||
// `<div class="tooltip-top"> |
|||
// <h4>${this.tooltipInfo.name}</h4> |
|||
// </div> |
|||
// <ul> |
|||
// <li><p>在架</p><span><i>${this.tooltipInfo.onShelfNum}</i>册</span></li> |
|||
// <li><p>错架</p><span><i>${this.tooltipInfo.errorShelfNum}</i>册</span> <span class="percentage">(${this.tooltipInfo.errorShelfProbo})</span></li> |
|||
// <li><p>错序</p><span><i>${this.tooltipInfo.errorOrderNum}</i>册</span><span class="percentage">(${this.tooltipInfo.errorOrderProbo})</span></li> |
|||
// </ul>` |
|||
// } else if (self.pagePreview === 'region') { |
|||
// document.getElementById('tooltip').innerHTML = |
|||
// `<div class="tooltip-top"> |
|||
// <h4>书架概况</h4> |
|||
// </div> |
|||
// <ul> |
|||
// <li><p>书架</p><span><i>${this.tooltipInfo.name}</i></span></li> |
|||
// <li><p>规则</p><span><i>${this.tooltipInfo.rowType === 1 ? '单面' : '双面'}${this.tooltipInfo.shelfFloor}*${this.tooltipInfo.shelfShelf}</i></span></li> |
|||
// <li><p>在架</p><span><i>${this.tooltipInfo.onShelfNum}</i>册</span></li> |
|||
// <li><p>错架</p><span><i>${this.tooltipInfo.errorShelfNum}</i>册</span> <span class="percentage">(${this.tooltipInfo.errorShelfProbo})</span></li> |
|||
// <li><p>错序</p><span><i>${this.tooltipInfo.errorOrderNum}</i>册</span><span class="percentage">(${this.tooltipInfo.errorOrderProbo})</span></li> |
|||
// </ul>` |
|||
// } |
|||
|
|||
// // var rectLeft = e.target.left + e.target.width - 100 |
|||
// var rectLeft = e.target.left + e.target.width |
|||
// var rectTop = e.target.top + e.target.height - 40 |
|||
// document.getElementById('tooltip').style.left = rectLeft + 'px' |
|||
// document.getElementById('tooltip').style.top = rectTop + 'px' |
|||
// document.getElementById('tooltip').style.display = 'block' |
|||
// self.canvasPreview.renderAll() |
|||
// }) |
|||
|
|||
// polygon.on('mouseout', function() { |
|||
// this.set({ opacity: 0.5 }) |
|||
// document.getElementById('tooltip').style.display = 'none' |
|||
// self.canvasPreview.renderAll() |
|||
// }) |
|||
} |
|||
}) |
|||
// 计算画布的中心点 |
|||
const centerX = self.canvasPreview.width / 2 |
|||
const centerY = self.canvasPreview.height / 2 |
|||
const centerPoint = new fabric.Point(centerX, centerY) |
|||
|
|||
// 设置画布的缩放比例为最小值并居中显示 |
|||
self.canvasPreview.zoomToPoint(centerPoint, 1) |
|||
self.canvasPreview.renderAll() |
|||
|
|||
setTimeout(() => { |
|||
self.$parent.prewLoading = false |
|||
}, 500) |
|||
}) |
|||
}, |
|||
handleToRegions(data, tabIndex) { |
|||
this.$router.push({ path: '/regions' }) |
|||
localStorage.setItem('dataScreenFloor', JSON.stringify(data)) |
|||
localStorage.setItem('dataScreenFloorTableIndex', tabIndex) |
|||
}, |
|||
handleToShelfs(data, tabIndex) { |
|||
this.$router.push({ path: '/shelf' }) |
|||
localStorage.setItem('dataScreenRegion', JSON.stringify(data)) |
|||
localStorage.setItem('dataScreenRegionTableIndex', tabIndex) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
<style lang="scss" scoped> |
|||
#expImg{ |
|||
display: none; |
|||
} |
|||
.venue-preview{ |
|||
width: 100%; |
|||
background-color: #fff; |
|||
overflow: hidden; |
|||
margin-top: -30px; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,145 @@ |
|||
<template> |
|||
<div class="ranking"> |
|||
<h4 class="filter-header">图书借阅排行榜</h4> |
|||
<el-carousel |
|||
ref="carousel" |
|||
:interval="4000" |
|||
type="card" |
|||
indicator-position="none" |
|||
height="200px" |
|||
@change="carouselChange" |
|||
> |
|||
<el-carousel-item v-for="(item,index) in topThree" :key="index"> |
|||
<div class="ranking-img" @click="getBookDetaisByBookRecNo(item)"> |
|||
<img :src="coverUrl+'/demoRecommend/getBookCover.do?id='+item.id" :onerror="defaultImg" alt=""> |
|||
</div> |
|||
</el-carousel-item> |
|||
</el-carousel> |
|||
<div v-for="(item,i) in topThree" :key="i" class="ranking-book-detail"> |
|||
<div v-if="i === carIndex"> |
|||
<div class="book-info" @click="getBookDetaisByBookRecNo(item)"> |
|||
<h5 class="title-item-only">{{ item.title }}</h5> |
|||
<!-- <div class="book-author" style="display: flex; justify-content: flex-start;"> |
|||
<span class="title-item-only">{{ item.author }}</span> |
|||
<span class="title-item-only">{{ item.publish }}</span> |
|||
</div> --> |
|||
<!-- <p class="book-intro title-item"> |
|||
{{ item.introduce }} |
|||
</p> --> |
|||
<div :class="carClass" /> |
|||
</div> |
|||
<!-- <div class="book-click-num"> |
|||
<span class="click-num">{{ item.clickNum }}次</span> |
|||
<span class="detail-btn" @click="getBookDetail(item)">查看详情</span> |
|||
</div> --> |
|||
</div> |
|||
</div> |
|||
<ul class="ranking-list-bottom other-list"> |
|||
<li v-for="(item,index) in rankingOther" :key="index" @click="getBookDetaisByBookRecNo(item)"> |
|||
<span>{{ 'TOP'+ (index+4) }}</span> |
|||
<p class="title-item-only">{{ item.title }}</p> |
|||
</li> |
|||
</ul> |
|||
|
|||
<BookDetails ref="bookDetailsRef" /> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import { FetchInitHotBookList, FetchBookDetaisByBookRecNo } from '@/api/inquiryMachine' |
|||
import { positionCrud } from '../mixins/index.js' |
|||
import BookDetails from '../module/bookDetails' |
|||
export default { |
|||
name: 'Ranking', |
|||
|
|||
components: { |
|||
BookDetails |
|||
}, |
|||
mixins: [positionCrud], |
|||
props: { |
|||
formRanking: { |
|||
type: String, |
|||
default: '' |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
defaultImg: 'this.src="' + require('@/assets/images/default-img.png') + '"', |
|||
bookList: [], |
|||
coverUrl: null, |
|||
pageIndex: 1, |
|||
pageSize: 10, |
|||
hasNextPage: false, |
|||
totalPages: 0, |
|||
totalNum: 0, |
|||
topThree: [], |
|||
rankingOther: [], |
|||
carIndex: 0 |
|||
} |
|||
}, |
|||
computed: { |
|||
carClass() { |
|||
if (this.carIndex === 0) { |
|||
return 'ranking-status num-one' |
|||
} else if (this.carIndex === 1) { |
|||
return 'ranking-status num-two' |
|||
} else if (this.carIndex === 2) { |
|||
return 'ranking-status num-three' |
|||
} else { |
|||
return 'ranking-status' |
|||
} |
|||
} |
|||
}, |
|||
created() { |
|||
this.getHotBookList() |
|||
}, |
|||
mounted() { |
|||
this.$refs.carousel.$el.addEventListener('current-change', this.carouselChange) |
|||
}, |
|||
methods: { |
|||
getHotBookList() { |
|||
let params |
|||
if (this.formRanking === 'home') { |
|||
params = { |
|||
'fondsCode': this.libcode, |
|||
'size': 5 |
|||
} |
|||
} else { |
|||
params = { |
|||
'fondsCode': this.libcode, |
|||
'size': 10 |
|||
} |
|||
} |
|||
FetchInitHotBookList(params).then(res => { |
|||
this.topThree = res.slice(0, 3) |
|||
if (this.formRanking === 'home') { |
|||
this.rankingOther = res.slice(3, 7) |
|||
} else { |
|||
this.rankingOther = res.slice(3, 10) |
|||
} |
|||
}).catch(() => { |
|||
this.$message.error('接口错误') |
|||
}) |
|||
}, |
|||
getBookDetaisByBookRecNo(item) { |
|||
FetchBookDetaisByBookRecNo({ |
|||
'bookRecNo': item.bookRecNo |
|||
}).then(res => { |
|||
this.$refs.bookDetailsRef.getBookRankingDetail(res) |
|||
}).catch(() => { |
|||
this.$message.error('接口错误') |
|||
}) |
|||
}, |
|||
carouselChange(val) { |
|||
this.carIndex = val |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
@import "~@/assets/styles/index.scss"; |
|||
.other-list{ |
|||
height: 140px; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,133 @@ |
|||
<template> |
|||
<div> |
|||
<div class="search-header-bg" /> |
|||
<el-card class="box-card" style="margin: -220px 44px 0 44px; padding-bottom: 12px;"> |
|||
<h4 style="font-size: 30px; margin-bottom: 24px; text-align: center;">图书检索</h4> |
|||
<div class="search-main"> |
|||
<!-- 搜索栏 --> |
|||
<div class="search-content"> |
|||
<div class="input-search"> |
|||
<el-input |
|||
v-model="keyword" |
|||
placeholder="请输入关键词进行检索" |
|||
/> |
|||
<el-button type="primary" @click="toSearch">搜索</el-button> |
|||
</div> |
|||
<el-button @click="resetSearch">重置</el-button> |
|||
</div> |
|||
<!-- 热门检索 --> |
|||
<div class="hot-keyword"> |
|||
<p style="margin-left: 10px;">热门检索</p> |
|||
<div class="keyword-item"> |
|||
<!-- @click="selectKeyWord(index)" --> |
|||
<span v-for="(item,index) in keywordData" :key="index" :class="{ 'active': keyWordIndex === index }" @click="selectKeyWord(index)">{{ item }}</span> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</el-card> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import { FetchFindHotSearch } from '@/api/inquiryMachine' |
|||
import { positionCrud } from '../mixins/index.js' |
|||
export default { |
|||
name: 'Search', |
|||
mixins: [positionCrud], |
|||
props: { |
|||
searchType: { |
|||
type: String, |
|||
default: '' |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
keyword: '', |
|||
keyWordIndex: null, |
|||
keywordData: [] |
|||
} |
|||
}, |
|||
created() { |
|||
this.getHotSearch() |
|||
}, |
|||
mounted() { |
|||
}, |
|||
methods: { |
|||
getHotSearch() { |
|||
const params = { |
|||
'fondsCode': this.libcode, |
|||
'size': 30 |
|||
} |
|||
FetchFindHotSearch(params).then(res => { |
|||
this.keywordData = res.filter(item => { |
|||
return item !== '' |
|||
}) |
|||
}).catch(() => { |
|||
this.$message.error('接口错误') |
|||
}) |
|||
}, |
|||
resetData() { |
|||
this.$parent.pageIndex = 1 |
|||
this.$parent.hasNextPage = true |
|||
this.keyword = '' |
|||
this.$parent.bookList = [] |
|||
}, |
|||
resetSearch() { |
|||
this.$parent.pageIndex = 1 |
|||
this.$parent.hasNextPage = false |
|||
this.keyword = '' |
|||
this.$parent.bookList = [] |
|||
this.keyWordIndex = null |
|||
console.log('this.totalNum ', this.$parent.totalNum) |
|||
this.$parent.totalNum = 0 |
|||
// this.$parent.addMoreData() |
|||
}, |
|||
toSearch() { |
|||
if (this.keyword) { |
|||
this.keyWordIndex = null |
|||
if (this.searchType === 'noList') { |
|||
localStorage.setItem('searchKey', this.keyword) |
|||
this.$router.push({ path: '/bookList' }) |
|||
} else { |
|||
this.$parent.pageIndex = 1 |
|||
this.$parent.hasNextPage = true |
|||
this.$parent.bookList = [] |
|||
this.$parent.addMoreData() |
|||
} |
|||
} else { |
|||
this.$message.error('请输入检索关键词') |
|||
} |
|||
}, |
|||
selectKeyWord(index) { |
|||
this.resetData() |
|||
if (parseInt(this.keyWordIndex) === index) { |
|||
this.keyWordIndex = null |
|||
} else { |
|||
this.keyWordIndex = index |
|||
this.keyword = this.keywordData[index] |
|||
} |
|||
this.$forceUpdate() |
|||
if (this.searchType === 'noList') { |
|||
localStorage.setItem('searchKey', this.keyword) |
|||
localStorage.setItem('keyWordIndex', this.keyWordIndex) |
|||
this.$router.push({ path: '/bookList' }) |
|||
this.$parent.pageIndex = 1 |
|||
} else { |
|||
this.$parent.pageIndex = 1 |
|||
this.$parent.hasNextPage = true |
|||
this.$parent.bookList = [] |
|||
this.$parent.addMoreData() |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
@import "~@/assets/styles/index.scss"; |
|||
.search-header-bg{ |
|||
height: 298px; |
|||
background: url("~@/assets/images/top-bg.png") no-repeat left top; |
|||
background-size: 100% 100%; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,141 @@ |
|||
<template> |
|||
<div class="ranking"> |
|||
<h4 class="filter-header">热门书架</h4> |
|||
<ul class="ranking-list-bottom shelf-list"> |
|||
<li v-for="(item,index) in shelfHot" :key="index" @click="handleShelfPosition(item)"> |
|||
<span>{{ 'TOP'+ (index+1) }}</span> |
|||
<p class="title-item-only">{{ removeAreaPrefix(item.grid_name) }}</p> |
|||
</li> |
|||
</ul> |
|||
|
|||
<el-dialog class="positionDialog" append-to-body :close-on-click-modal="false" :modal-append-to-body="false" :before-close="handleCloseDialog" :visible="positionVisible" :title="positionTitle"> |
|||
<div class="setting-dialog"> |
|||
<ul class="book-detail"> |
|||
<li><span>所属楼层</span>{{ positionContent.floorName }}</li> |
|||
<li><span>所属区域</span>{{ positionContent.regionName }}</li> |
|||
<li><span>所属书架</span>{{ positionContent.gridName }}</li> |
|||
</ul> |
|||
<div class="position-content"> |
|||
<div class="position-left"> |
|||
<h5>平面图</h5> |
|||
<div class="venue-preview"> |
|||
<div v-show="currentMarkData && currentMarkData.signPoint "> |
|||
<canvas :id="`canvasPreview${currentMarkData && currentMarkData.id}hot`" :width="width" :height="height" /> |
|||
</div> |
|||
<img v-if="currentMarkData && !currentMarkData.signPoint" :src="imageUrl" :onerror="defaultImg" alt=""> |
|||
<img v-if="!currentMarkData" :src="imageUrl" :onerror="defaultImg" alt=""> |
|||
</div> |
|||
</div> |
|||
<div class="position-right"> |
|||
<h5>书架图</h5> |
|||
<div class="shelf-top" :style="rowStyle"> |
|||
<p v-for="(item,index) in reversedRackNum" :key="index" :style="{width: `calc(${'100%/' + rackNum} - 4px )`}"><span>{{ item + '架' }}</span></p> |
|||
</div> |
|||
<ul class="data-shelf-row" :style="rowStyle"> |
|||
<li |
|||
v-for="(cell,i) in booShelfGrid" |
|||
:key="i" |
|||
:class="{ active: i === cellIndex }" |
|||
class="data-shelf-cell" |
|||
:style="cellStyle" |
|||
> |
|||
<span class="cell-name">{{ removeLayerPrefix(cell.gridName) }}</span> |
|||
</li> |
|||
</ul> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="book-bottom" @click="handleCloseDialog"> |
|||
<span>关闭</span> |
|||
</div> |
|||
</el-dialog> |
|||
|
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import { FetchInitHotShelfList } from '@/api/inquiryMachine' |
|||
import { positionCrud } from '../mixins/index.js' |
|||
export default { |
|||
name: 'Ranking', |
|||
components: { |
|||
}, |
|||
mixins: [positionCrud], |
|||
props: { |
|||
}, |
|||
data() { |
|||
return { |
|||
defaultImg: 'this.src="' + require('@/assets/images/default-img.png') + '"', |
|||
shelfHot: [] |
|||
} |
|||
}, |
|||
computed: { |
|||
}, |
|||
created() { |
|||
this.getInitHotShelfList() |
|||
}, |
|||
mounted() { |
|||
}, |
|||
methods: { |
|||
removeLayerPrefix(gridNames) { |
|||
const index = gridNames.indexOf('面') |
|||
if (index !== -1) { |
|||
return gridNames.substring(index + 1) |
|||
} |
|||
return gridNames |
|||
}, |
|||
handleShelfPosition(item) { |
|||
this.positionContent = { |
|||
'floorName': item.floorName, |
|||
'regionName': item.regionName, |
|||
'gridName': item.grid_name |
|||
|
|||
} |
|||
this.handlePosition(item, 'hot') |
|||
}, |
|||
removeAreaPrefix(gridNames) { |
|||
const index = gridNames.indexOf('区') |
|||
if (index !== -1) { |
|||
return gridNames.substring(index + 1) |
|||
} |
|||
return gridNames |
|||
}, |
|||
getInitHotShelfList() { |
|||
const params = { |
|||
'fondsCode': this.libcode, |
|||
'size': 5 |
|||
} |
|||
FetchInitHotShelfList(params).then(res => { |
|||
this.shelfHot = res |
|||
}).catch(() => { |
|||
this.$message.error('接口错误') |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
@import "~@/assets/styles/index.scss"; |
|||
.shelf-list{ |
|||
height: 434px; |
|||
} |
|||
::v-deep .el-dialog{ |
|||
width: 930px; |
|||
border-radius: 16px; |
|||
background: #F8F8FD; |
|||
box-shadow: 0px 3px 20px 1px rgba(0,0,0,0.05); |
|||
.el-dialog__body{ |
|||
padding: 20px 0 23px 0; |
|||
} |
|||
} |
|||
::v-deep .el-dialog__headerbtn{ |
|||
display: none; |
|||
} |
|||
::v-deep .el-dialog__title{ |
|||
font-weight: bold; |
|||
} |
|||
::v-deep .el-dialog__header{ |
|||
border-bottom: 1px solid #EDEFF3; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,195 @@ |
|||
<template> |
|||
<div class="content-main"> |
|||
<Search refs="searchRefs" search-type="noList" /> |
|||
|
|||
<div class="box-style" style="margin: 30px 44px;"> |
|||
<div class="dataScreening-header"> |
|||
<h4 class="filter-header">区域总览</h4> |
|||
<div class="bookshelf-area"> |
|||
<router-link :to="{ path: '/', query: {floorTabIndex: floorTabIndex }}"> |
|||
<i class="iconfont icon-huifu" />返回 |
|||
</router-link> |
|||
<!-- <div class="double-click-btn"><span>点击左侧位置返回</span></div> --> |
|||
</div> |
|||
</div> |
|||
<div class="home-wrap tab-content"> |
|||
<!-- <ul class="fixed-menu"> |
|||
<li v-for="(item,index) in regionOptions" :key="index" :class="{ 'active': tabIndex == index }" @click="changeActiveTab(index)">{{ item.regionName }}<i /></li> |
|||
</ul> --> |
|||
<ul class="tab-nav"> |
|||
<li v-for="(item,index) in regionOptions" :key="index" :class="{ 'active-tab-nav': tabIndex == index }" @click="changeActiveTab(index)">{{ item.regionName }}<i /></li> |
|||
</ul> |
|||
<!-- <div class="total-data"> |
|||
<span>楼层概况</span> |
|||
<p>区域:{{ baseData.regionCount }}</p> |
|||
<p>书架:{{ baseData.shelfCount }}</p> |
|||
<p>摄像头:{{ baseData.deviceCount }}</p> |
|||
</div> --> |
|||
<CanvasPreview ref="previewRefs" v-loading="prewLoading" page-preview="region" :current-mark-data="currentMarkData" :image-url="imageUrl" /> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import { FetchShelfListByRegionId, FetchRegionListByFloorId, FetchInitStockInfo } from '@/api/inquiryMachine' |
|||
import CanvasPreview from './module/canvasPreview' |
|||
import { positionCrud } from './mixins/index.js' |
|||
import Search from './module/search' |
|||
import defaultImg from '@/assets/images/default-img-bg.jpg' |
|||
|
|||
export default { |
|||
name: 'Index', |
|||
components: { |
|||
Search, CanvasPreview |
|||
}, |
|||
mixins: [positionCrud], |
|||
data() { |
|||
return { |
|||
prewLoading: false, |
|||
regionOptions: [], |
|||
floorTabIndex: 0, |
|||
floorId: null, |
|||
floorName: null, |
|||
currentRegionId: null, |
|||
tabIndex: 0, |
|||
defaultImg: defaultImg, |
|||
imageUrl: defaultImg, |
|||
imageRegionUrl: defaultImg, |
|||
currentMarkData: null, |
|||
allCoverData: [], |
|||
baseStockDataAllShelf: [] |
|||
} |
|||
}, |
|||
created() { |
|||
const data = JSON.parse(localStorage.getItem('dataScreenFloor')) |
|||
if (data) { |
|||
this.floorId = data.floorId |
|||
this.floorName = data.floorName |
|||
console.log('this.floorName', this.floorName) |
|||
this.currentRegionId = data.id |
|||
this.getRegionList(this.floorId) |
|||
} |
|||
}, |
|||
mounted() { |
|||
|
|||
}, |
|||
methods: { |
|||
getRegionList(floorId) { |
|||
FetchRegionListByFloorId({ 'floorId': floorId }).then(res => { |
|||
this.regionOptions = res |
|||
|
|||
if (localStorage.getItem('dataScreenFloorTableIndex')) { |
|||
this.floorTabIndex = localStorage.getItem('dataScreenFloorTableIndex') |
|||
} |
|||
|
|||
const item = this.regionOptions.find(element => element.id === this.currentRegionId) |
|||
let index |
|||
if (this.$route.query.regionTabIndex) { |
|||
index = this.$route.query.regionTabIndex |
|||
} else { |
|||
index = item ? this.regionOptions.indexOf(item) : -1 |
|||
} |
|||
console.log('this.regionOptions', this.regionOptions) |
|||
console.log('this.regionOptions', this.regionOptions[index]) |
|||
|
|||
this.tabIndex = index |
|||
this.changeActiveTab(index) |
|||
}).catch(() => { |
|||
this.$message.error('接口错误') |
|||
}) |
|||
}, |
|||
async changeActiveTab(index) { |
|||
const baseUrl = process.env.NODE_ENV === 'production' ? window.g.ApiUrl : process.env.VUE_APP_BASE_API |
|||
this.prewLoading = true |
|||
this.tabIndex = index |
|||
const params = { |
|||
'floorId': this.regionOptions[index].floorId, |
|||
'regionId': this.regionOptions[index].id |
|||
} |
|||
try { |
|||
const res = await FetchShelfListByRegionId(params) |
|||
console.log(res) |
|||
this.allCoverData = res |
|||
if (this.regionOptions[index].regionMap) { |
|||
this.imageUrl = baseUrl + '/api/fileRelevant/getImg?imgId=' + this.regionOptions[index].regionMap |
|||
} else { |
|||
this.imageUrl = this.defaultImg |
|||
} |
|||
|
|||
if (this.allCoverData.length !== 0) { |
|||
this.currentMarkData = this.regionOptions[index] |
|||
const signPoint = this.allCoverData.find(item => item.signPoint !== null)?.signPoint |
|||
const imgInfo = signPoint ? JSON.parse(signPoint).imgInfo : null |
|||
const baseStockDataAllShelf = await this.getInitStockInfo(this.allCoverData) |
|||
const parsedSignPoints = this.allCoverData.map(item => { |
|||
const signPoint = item.signPoint ? JSON.parse(item.signPoint) : null |
|||
return { |
|||
id: item.shelfId, |
|||
name: item.shelfName, |
|||
rowType: item.rowType, |
|||
toward: item.toward, |
|||
floorName: item.floorName, |
|||
regionName: item.regionName, |
|||
shelfFloor: item.shelfFloor, |
|||
shelfShelf: item.shelfShelf, |
|||
floorId: this.regionOptions[index].floorId, |
|||
regionId: this.regionOptions[index].id, |
|||
pointInfo: signPoint ? signPoint.pointInfo[0].pointInfo : null |
|||
} |
|||
}) |
|||
parsedSignPoints.forEach(parsedItem => { |
|||
const baseStockItem = baseStockDataAllShelf.find(baseItem => baseItem.id === parsedItem.id) |
|||
if (baseStockItem) { |
|||
Object.assign(parsedItem, baseStockItem) |
|||
} |
|||
}) |
|||
|
|||
const result = { |
|||
pointInfo: parsedSignPoints, |
|||
imgInfo: imgInfo |
|||
} |
|||
console.log('result', result) |
|||
this.$nextTick(() => { |
|||
this.$refs.previewRefs.initCanvasPreview(result, this.tabIndex) |
|||
}) |
|||
} else { |
|||
this.currentMarkData = {} |
|||
setTimeout(() => { |
|||
this.prewLoading = false |
|||
}, 500) |
|||
} |
|||
} catch (error) { |
|||
console.error(error) |
|||
} |
|||
}, |
|||
async getInitStockInfo(data) { |
|||
const promises = data.map(item => { |
|||
const params = { |
|||
'fondsCode': this.libcode, |
|||
'floorId': this.floorId, |
|||
'regionId': this.regionId, |
|||
'shelfId': item.shelfId |
|||
} |
|||
return FetchInitStockInfo(params) |
|||
}) |
|||
const results = await Promise.all(promises) |
|||
if (!Array.isArray(this.baseStockDataAllShelf)) { |
|||
this.baseStockDataAllShelf = [] |
|||
} |
|||
// 为每个结果对象添加id字段 |
|||
results.forEach((result, index) => { |
|||
result.id = data[index].shelfId |
|||
}) |
|||
this.baseStockDataAllShelf = this.baseStockDataAllShelf.concat(results) |
|||
return this.baseStockDataAllShelf |
|||
} |
|||
|
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
@import "~@/assets/styles/index.scss"; |
|||
|
|||
</style> |
|||
@ -0,0 +1,629 @@ |
|||
<template> |
|||
<div class="content-main"> |
|||
<Search refs="searchRefs" search-type="noList" /> |
|||
|
|||
<div class="box-style" style="margin: 30px 44px;"> |
|||
<div class="dataScreening-header"> |
|||
<h4 class="filter-header">书架总览</h4> |
|||
<div class="bookshelf-area"> |
|||
<!-- <router-link :to="{ path: '/', query: {floorTabIndex: floorTabIndex }}"> |
|||
{{ floorName }} |
|||
</router-link> |
|||
<span>/</span> |
|||
<router-link :to="{ path: '/regions', query: {regionTabIndex: regionTabIndex }}"> |
|||
{{ regionName }} |
|||
</router-link> |
|||
<div class="double-click-btn"><span>点击左侧位置返回</span></div> --> |
|||
<router-link :to="{ path: '/regions', query: {regionTabIndex: regionTabIndex }}"> |
|||
<i class="iconfont icon-huifu" />返回 |
|||
</router-link> |
|||
</div> |
|||
</div> |
|||
<div class="tab-content"> |
|||
<ul class="tab-nav"> |
|||
<li v-for="(item,index) in tabListData" :key="index" :class="{ 'active-tab-nav': tabIndex == index }" @click="changeActiveTab(index)">{{ item.name }}<i /></li> |
|||
</ul> |
|||
<div class="tag-info"> |
|||
<!-- <p class="tag-sort">错序:<i class="iconfont icon-zhuangtai2" /></p> |
|||
<p class="tag-place">错架:<i class="iconfont icon-zhuangtai2" /></p> --> |
|||
<p class="tag-all">在架:<i class="iconfont icon-zhuangtai2" /></p> |
|||
</div> |
|||
<div class="shelf-top" :style="rowStyle"> |
|||
<p v-for="(item,index) in reversedRackNum" :key="index" :style="{width: `calc(142px)`}"><span>{{ item + '架' }}</span></p> |
|||
</div> |
|||
<ul v-loading="listLoading" class="data-shelf-row" :style="rowStyle"> |
|||
<!-- @dblclick="handleCellCurrent(cell,i)" |
|||
@mouseenter="showPopover(i)" |
|||
@mouseleave="hidePopover" |
|||
@touchmove="handleTouchMove(i)" |
|||
@touchstart="handleTouchStart($event, cell,i)" |
|||
@touchend="handleTouchEnd" |
|||
--> |
|||
<li |
|||
v-for="(cell,i) in booShelfGrid" |
|||
:key="i" |
|||
:class="['data-shelf-cell',{'active': isActiveColumn(i)}]" |
|||
:style="cellStyle" |
|||
@click="handleCellCurrent(cell,i)" |
|||
> |
|||
<div class="mask" /> |
|||
<div class="tag-info"> |
|||
<!-- <p class="tag-sort"><i class="iconfont icon-zhuangtai2" />{{ cell.errorOrderNum }}</p> |
|||
<p class="tag-place"><i class="iconfont icon-zhuangtai2" />{{ cell.errorShelfNum }}</p> --> |
|||
<p class="tag-all"><i class="iconfont icon-zhuangtai2" />{{ cell.onShelfNum }}</p> |
|||
</div> |
|||
<el-popover |
|||
v-if="popoverIndex === i" |
|||
ref="popover" |
|||
:visible="popoverVisible[i]" |
|||
width="400" |
|||
:style="popoverStyles[i]" |
|||
trigger="manual" |
|||
> |
|||
<div slot="reference" class="popover-content-set"> |
|||
<div class="tooltip-top"> |
|||
<h4>本架概况</h4> |
|||
<i class="update-time">2024-11-28 09:46</i> |
|||
</div> |
|||
<ul> |
|||
<li><p>架位</p><em class="percentage"><i style="color: #fff;">{{ removeAreaPrefix(cell.gridName) }}</i></em></li> |
|||
<li><p>在架</p><em><i>{{ itemStockData.onShelfNum }}</i>册</em></li> |
|||
<li><p>错架</p><em><i>{{ itemStockData.errorShelfNum }}</i>册</em> <em class="percentage">({{ itemStockData.errorShelfProbo }})</em></li> |
|||
<li><p>错序</p><em><i>{{ itemStockData.errorOrderNum }}</i>册</em><em class="percentage">({{ itemStockData.errorOrderProbo }})</em></li> |
|||
</ul> |
|||
</div> |
|||
</el-popover> |
|||
</li> |
|||
</ul> |
|||
<ul class="change-layer"> |
|||
<li v-for="(item,index) in layerOptions" :key="index" :class="{ 'active': item.name === layerVal.name }" @click="changeShelfGetGrid(item)">{{ item.name }}</li> |
|||
</ul> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import { FetchShelfListByRegionId, FetchShelfGridAllByShelfIdText, FetchBookShelfDetails, FetchInitStockInfo } from '@/api/inquiryMachine' |
|||
import { positionCrud } from './mixins/index.js' |
|||
import Search from './module/search' |
|||
|
|||
export default { |
|||
name: 'Index', |
|||
components: { |
|||
Search |
|||
}, |
|||
mixins: [positionCrud], |
|||
data() { |
|||
return { |
|||
listLoading: false, |
|||
tabIndex: 0, |
|||
floorTabIndex: 0, |
|||
regionTabIndex: 0, |
|||
floorName: null, |
|||
floorId: null, |
|||
regionName: null, |
|||
regionId: null, |
|||
rowType: null, |
|||
bookShelfDetails: {}, |
|||
booShelfGrid: [], |
|||
cellInfo: { |
|||
gridName: null, |
|||
startSortmark: null, |
|||
endSortmark: null, |
|||
cameraId: null |
|||
}, |
|||
callNumVisible: false, |
|||
layerNum: 0, |
|||
rackNum: 0, |
|||
swiperActiveIndex: 0, |
|||
cellIndex: null, |
|||
columnIndex: null, |
|||
layerVal: null, |
|||
layerOptions: [], |
|||
tabListData: [], |
|||
popoverIndex: null, |
|||
popoverVisible: [], |
|||
popoverStyles: [], |
|||
activeColumns: {}, |
|||
itemStockData: {}, |
|||
touchStartTime: null, |
|||
touchStartPosition: null, |
|||
doubleClickTimeout: null |
|||
} |
|||
}, |
|||
computed: { |
|||
cellStyle: function() { |
|||
const h = '76px' |
|||
const w = '118px' |
|||
return { width: `calc(${w} )`, height: `calc(${h})` } |
|||
}, |
|||
rowStyle: function() { |
|||
const w = 118 * this.rackNum + 'px' |
|||
return { width: `calc(${w})` } |
|||
}, |
|||
reversedRackNum() { |
|||
if (this.booShelfGrid && this.booShelfGrid.length > 0) { |
|||
if (parseInt(this.booShelfGrid[0].gridShelf) === this.rackNum) { |
|||
return Array.from({ length: this.rackNum }, (_, i) => this.rackNum - i).map(x => x.toString()) |
|||
} else { |
|||
return Array.from({ length: this.rackNum }, (_, i) => i + 1).map(x => x.toString()) |
|||
} |
|||
} else { |
|||
return [] |
|||
} |
|||
} |
|||
}, |
|||
created() { |
|||
if (localStorage.getItem('dataScreenFloorTableIndex')) { |
|||
this.floorTabIndex = localStorage.getItem('dataScreenFloorTableIndex') |
|||
} |
|||
if (localStorage.getItem('dataScreenRegionTableIndex')) { |
|||
this.regionTabIndex = localStorage.getItem('dataScreenRegionTableIndex') |
|||
} |
|||
if (localStorage.getItem('dataScreenRegion')) { |
|||
const dataScreenRegion = JSON.parse(localStorage.getItem('dataScreenRegion')) |
|||
this.floorName = dataScreenRegion.floorName |
|||
this.floorId = dataScreenRegion.floorId |
|||
this.regionName = dataScreenRegion.regionName |
|||
this.regionId = dataScreenRegion.regionId |
|||
this.rowType = dataScreenRegion.rowType |
|||
|
|||
this.initData(dataScreenRegion) |
|||
|
|||
this.getInitBookShelfList(dataScreenRegion) |
|||
|
|||
this.getInitStockInfo(dataScreenRegion) |
|||
} |
|||
}, |
|||
mounted() { |
|||
|
|||
}, |
|||
methods: { |
|||
changeShelfGetGrid(val) { |
|||
this.layerVal = val |
|||
this.initData(val) |
|||
this.getInitStockInfo(val) |
|||
}, |
|||
initData(data) { |
|||
// 单面/双面 |
|||
this.tabListData = data.rowType === 1 |
|||
? data.toward === 1 |
|||
? [{ name: 'A面' }] |
|||
: [{ name: 'B面' }] |
|||
: [{ name: 'A面' }, { name: 'B面' }] |
|||
|
|||
this.tabIndex = this.$route.query.tabIndex ? this.$route.query.tabIndex : 0 |
|||
|
|||
FetchBookShelfDetails({ 'shelfId': data.id }).then(res => { |
|||
this.layerNum = res.shelfFloor |
|||
this.rackNum = res.shelfShelf |
|||
this.bookShelfDetails = res |
|||
|
|||
if (this.$route.query.tabIndex) { |
|||
this.getInitShelfGridByShelfId(this.bookShelfDetails.id, this.$route.query.tabIndex + 1) |
|||
} else { |
|||
this.getInitShelfGridByShelfId(this.bookShelfDetails.id, this.bookShelfDetails.toward) |
|||
} |
|||
}).catch(() => { |
|||
}) |
|||
}, |
|||
getInitStockInfo(data) { |
|||
const params = { |
|||
'fondsCode': this.libcode, |
|||
'floorId': this.floorId, |
|||
'regionId': this.regionId, |
|||
'shelfId': data.id |
|||
} |
|||
FetchInitStockInfo(params).then(res => { |
|||
this.baseStockData = res |
|||
}).catch(() => { |
|||
}) |
|||
}, |
|||
getInitBookShelfList(data) { |
|||
console.log('data', data) |
|||
const params = { 'floorId': data.floorId, 'regionId': data.regionId } |
|||
FetchShelfListByRegionId(params).then(res => { |
|||
this.layerOptions = res.map(item => { |
|||
return { |
|||
name: item.shelfName, |
|||
id: item.shelfId, |
|||
toward: item.toward, |
|||
rowType: item.rowType |
|||
} |
|||
}) |
|||
this.layerVal = data |
|||
}).catch(() => { |
|||
}) |
|||
}, |
|||
removeAreaPrefix(gridNames) { |
|||
return gridNames.replace(/\d*区|\d*层/g, '') |
|||
}, |
|||
getInitShelfGridByShelfId(shelfId, toward) { |
|||
this.listLoading = true |
|||
// rowType 1 单 2 双 |
|||
// toward 1 A面 2 B面 |
|||
// shelfType 1 '始终最左边为第1架(S型排架)' |
|||
// shelfType 2 'A面最左为第1架(B面最左为最后1架)' |
|||
// shelfType 3 'B面最左为第1架(A面最左为最后1架)' |
|||
// floorType 1 '最顶层为第一层(从上至下)' |
|||
// floorType 2 '最底层为第一层(从下至上)' |
|||
FetchShelfGridAllByShelfIdText({ 'shelfId': shelfId, 'toward': toward }).then(res => { |
|||
console.log('res', res) |
|||
const sortFunction = toward === 1 ? { |
|||
1: { 1: 'sortBookshelvesLeftTop', 2: 'sortBookshelvesLeftBottom' }, |
|||
2: { 1: 'sortBookshelvesLeftTop', 2: 'sortBookshelvesLeftBottom' }, |
|||
3: { 1: 'sortBookshelvesRightTop', 2: 'sortBookshelvesRightBottom' } |
|||
} : { |
|||
1: { 1: 'sortBookshelvesLeftTop', 2: 'sortBookshelvesLeftBottom' }, |
|||
2: { 1: 'sortBookshelvesRightTop', 2: 'sortBookshelvesRightBottom' }, |
|||
3: { 1: 'sortBookshelvesLeftTop', 2: 'sortBookshelvesLeftBottom' } |
|||
} |
|||
const shelfType = this.bookShelfDetails.shelfType |
|||
const floorType = this.bookShelfDetails.floorType |
|||
const sortMethod = sortFunction[shelfType][floorType] |
|||
this.booShelfGrid = this[sortMethod](res) |
|||
|
|||
console.log('this.booShelfGrid', this.booShelfGrid) |
|||
|
|||
this.popoverVisible = Array(this.booShelfGrid.length).fill(false) |
|||
setTimeout(() => { |
|||
this.listLoading = false |
|||
}, 1000) |
|||
}).catch(() => { |
|||
}) |
|||
}, |
|||
// 最左为第一架, 最顶层为第一层 从上往下 |
|||
sortBookshelvesLeftTop(data) { |
|||
const sortedData = [] |
|||
const maxFloor = Math.max(...data.map(item => parseInt(item.gridFloor))) |
|||
const maxShelf = Math.max(...data.map(item => parseInt(item.gridShelf.slice(-1)))) |
|||
|
|||
for (let i = 1; i <= maxFloor; i++) { |
|||
for (let j = 1; j <= maxShelf; j++) { |
|||
const currentShelf = data.find(item => parseInt(item.gridFloor) === i && parseInt(item.gridShelf.slice(-1)) === j) |
|||
if (currentShelf) { |
|||
sortedData.push(currentShelf) |
|||
} |
|||
} |
|||
} |
|||
return sortedData |
|||
}, |
|||
// 最右为第一架,最左为最后一架, 最顶层为第一层 从上往下 |
|||
sortBookshelvesRightTop(data) { |
|||
const sortedData = [] |
|||
// 获取最大的楼层数 |
|||
const maxFloor = Math.max(...data.map(item => parseInt(item.gridFloor))) |
|||
const maxShelf = Math.max(...data.map(item => parseInt(item.gridShelf.match(/\d+$/)[0]))) |
|||
for (let i = 1; i <= maxFloor; i++) { |
|||
// 从最大的书架层数开始,向下排序 |
|||
for (let j = maxShelf; j >= 1; j--) { |
|||
const currentShelf = data.find(item => parseInt(item.gridFloor) === i && parseInt(item.gridShelf.match(/\d+$/)[0]) === j) |
|||
if (currentShelf) { |
|||
sortedData.push(currentShelf) |
|||
} |
|||
} |
|||
} |
|||
return sortedData |
|||
}, |
|||
// 最左为第一架, 最底层为第一层 从下往上 |
|||
sortBookshelvesLeftBottom(data) { |
|||
const sortedData = [] |
|||
// 获取最大的楼层数 |
|||
const maxFloor = Math.max(...data.map(item => parseInt(item.gridFloor))) |
|||
// 获取最大的书架层数 |
|||
const maxShelf = Math.max(...data.map(item => parseInt(item.gridShelf.slice(-1)))) |
|||
for (let i = maxFloor; i >= 1; i--) { |
|||
for (let j = 1; j <= maxShelf; j++) { |
|||
const currentShelf = data.find(item => parseInt(item.gridFloor) === i && parseInt(item.gridShelf.slice(-1)) === j) |
|||
if (currentShelf) { |
|||
sortedData.push(currentShelf) |
|||
} |
|||
} |
|||
} |
|||
return sortedData |
|||
}, |
|||
// 最左为最后一架, 最底层为第一层 从下往上 |
|||
sortBookshelvesRightBottom(data) { |
|||
const sortedData = [] |
|||
// 获取最大的楼层数 |
|||
const maxFloor = Math.max(...data.map(item => parseInt(item.gridFloor))) |
|||
const maxShelfPerFloor = data.map(item => parseInt(item.gridShelf.match(/\d+$/)[0])) |
|||
.reduce((acc, curr, index, arr) => { |
|||
const floor = parseInt(data[index].gridFloor) |
|||
if (!acc[floor]) acc[floor] = 1 |
|||
if (acc[floor] < curr) acc[floor] = curr |
|||
return acc |
|||
}, {}) |
|||
// 从最大的楼层开始向下遍历 |
|||
for (let i = maxFloor; i >= 1; i--) { |
|||
// 从最大的书架编号开始向左遍历 |
|||
for (let j = maxShelfPerFloor[i] || 1; j >= 1; j--) { |
|||
const currentShelf = data.find(item => parseInt(item.gridFloor) === i && parseInt(item.gridShelf.match(/\d+$/)[0]) === j) |
|||
if (currentShelf) { |
|||
sortedData.push(currentShelf) |
|||
} |
|||
} |
|||
} |
|||
return sortedData |
|||
}, |
|||
changeActiveTab(index) { |
|||
this.tabIndex = index |
|||
this.cellIndex = null |
|||
this.getInitShelfGridByShelfId(this.layerVal.id, index + 1) |
|||
}, |
|||
handleCellCurrent(item, index) { |
|||
this.cellIndex = index |
|||
this.cellInfo = { |
|||
id: item.id, |
|||
gridName: item.gridName, |
|||
gridRow: item.gridRow, |
|||
gridShelf: item.gridShelf, |
|||
shelfId: item.shelfId, |
|||
floorName: this.floorName, |
|||
regionName: this.regionName, |
|||
rowType: this.layerVal.rowType, |
|||
toward: item.toward |
|||
} |
|||
this.currentShelfAllGrid = this.booShelfGrid.filter(gird => gird.gridShelf === item.gridShelf) |
|||
this.handleToGrids(this.cellInfo, this.currentShelfAllGrid) |
|||
}, |
|||
handleToGrids(data, currentShelfAllGrid) { |
|||
this.$router.push({ path: '/gird' }) |
|||
if (localStorage.getItem('dataScreenRegion')) { |
|||
const dataScreenRegion = JSON.parse(localStorage.getItem('dataScreenRegion')) |
|||
dataScreenRegion.rowType = this.layerVal.rowType |
|||
dataScreenRegion.toward = this.layerVal.toward |
|||
dataScreenRegion.name = this.layerVal.name |
|||
dataScreenRegion.id = this.layerVal.id |
|||
localStorage.setItem('dataScreenRegion', JSON.stringify(dataScreenRegion)) |
|||
} |
|||
localStorage.setItem('dataScreenShelf', JSON.stringify(data)) |
|||
localStorage.setItem('dataScreenShelfAllGrid', JSON.stringify(currentShelfAllGrid)) |
|||
localStorage.setItem('dataScreenShelfTableIndex', this.tabIndex) |
|||
}, |
|||
showPopover(index) { |
|||
this.popoverIndex = index |
|||
if (!this.popoverVisible[index]) { |
|||
this.$set(this.popoverVisible, index, true) |
|||
} |
|||
|
|||
const lastColumnIndexes = [] |
|||
const secondLastColumnIndexes = [] |
|||
|
|||
for (let i = 0; i < this.booShelfGrid.length; i++) { |
|||
const columnIndex = i % this.rackNum |
|||
// 如果是最后一列(第5列) |
|||
if (this.rackNum !== 1) { |
|||
if (columnIndex === this.rackNum - 1) { |
|||
lastColumnIndexes.push(i) |
|||
// 更新最后一列的样式 |
|||
this.$set(this.popoverStyles, i, { position: 'absolute', left: '-180px', top: '20px' }) |
|||
} |
|||
} else { |
|||
this.$set(this.popoverStyles, i, { position: 'absolute', left: '60px', top: '20px' }) |
|||
} |
|||
|
|||
// 如果是倒数第二列(第4列) |
|||
if (columnIndex === this.rackNum - 2) { |
|||
secondLastColumnIndexes.push(i) |
|||
// 更新倒数第二列的样式 |
|||
// this.$set(this.popoverStyles, i, { position: 'absolute', left: '-20px', top: '20px' }) |
|||
} |
|||
} |
|||
const columnIndex = index % this.rackNum |
|||
this.activeColumns[columnIndex] = true |
|||
|
|||
const params = { |
|||
'fondsCode': this.libcode, |
|||
'floorId': this.floorId, |
|||
'regionId': this.regionId, |
|||
'shelfId': this.bookShelfDetails.id, |
|||
'gridShelf': this.booShelfGrid[columnIndex].gridShelf |
|||
} |
|||
FetchInitStockInfo(params).then(res => { |
|||
this.itemStockData = res |
|||
}).catch(() => { |
|||
}) |
|||
}, |
|||
isActiveColumn(index) { |
|||
const columnIndex = index % this.rackNum |
|||
return this.activeColumns[columnIndex] === true |
|||
}, |
|||
hidePopover() { |
|||
this.activeColumns = {} |
|||
this.popoverIndex = null |
|||
this.popoverVisible.forEach((isVisible, index) => { |
|||
if (isVisible) { |
|||
this.$set(this.popoverVisible, index, false) |
|||
} |
|||
}) |
|||
}, |
|||
handleTouchStart(event, cell, i) { |
|||
let currentPosition |
|||
if (event.touches) { |
|||
currentPosition = event.touches[0] ? event.touches[0].pageX : null |
|||
} |
|||
const currentTime = new Date().getTime() |
|||
// && Math.abs(currentPosition - this.touchStartPosition) < 50 |
|||
if (this.touchStartTime && currentTime - this.touchStartTime < 300) { |
|||
console.log('1111') |
|||
// 满足双击条件 |
|||
clearTimeout(this.doubleClickTimeout) |
|||
this.cellIndex = i |
|||
this.cellInfo = { |
|||
id: cell.id, |
|||
gridName: cell.gridName, |
|||
gridRow: cell.gridRow, |
|||
gridShelf: cell.gridShelf, |
|||
shelfId: cell.shelfId, |
|||
floorName: this.floorName, |
|||
regionName: this.regionName, |
|||
rowType: this.layerVal.rowType, |
|||
toward: cell.toward |
|||
} |
|||
this.currentShelfAllGrid = this.booShelfGrid.filter(gird => gird.gridShelf === cell.gridShelf) |
|||
this.handleToGrids(this.cellInfo, this.currentShelfAllGrid) |
|||
} else { |
|||
console.log('222') |
|||
// 不满足双击条件,可能是单击或其他操作,设置超时 |
|||
this.doubleClickTimeout = setTimeout(() => { |
|||
this.touchStartTime = null |
|||
this.touchStartPosition = null |
|||
}, 300) |
|||
this.touchStartTime = currentTime |
|||
this.touchStartPosition = currentPosition |
|||
|
|||
this.handleTouchMove(i) |
|||
} |
|||
}, |
|||
// 其他方法保持不变 |
|||
handleTouchMove(i) { |
|||
this.popoverIndex = i |
|||
if (!this.popoverVisible[i]) { |
|||
this.$set(this.popoverVisible, i, true) |
|||
} |
|||
|
|||
const lastColumnIndexes = [] |
|||
const secondLastColumnIndexes = [] |
|||
|
|||
for (let i = 0; i < this.booShelfGrid.length; i++) { |
|||
const columnIndex = i % this.rackNum |
|||
// 如果是最后一列(第5列) |
|||
if (this.rackNum !== 1) { |
|||
if (columnIndex === this.rackNum - 1) { |
|||
lastColumnIndexes.push(i) |
|||
// 更新最后一列的样式 |
|||
this.$set(this.popoverStyles, i, { position: 'absolute', left: '-180px', top: '20px' }) |
|||
} |
|||
} else { |
|||
this.$set(this.popoverStyles, i, { position: 'absolute', left: '60px', top: '20px' }) |
|||
} |
|||
|
|||
// 如果是倒数第二列(第4列) |
|||
if (columnIndex === this.rackNum - 2) { |
|||
secondLastColumnIndexes.push(i) |
|||
// 更新倒数第二列的样式 |
|||
// this.$set(this.popoverStyles, i, { position: 'absolute', left: '-20px', top: '20px' }); |
|||
} |
|||
} |
|||
const columnIndex = i % this.rackNum |
|||
this.activeColumns[columnIndex] = true |
|||
console.log('columnIndex', columnIndex) |
|||
console.log(' this.libcode', this.libcode) |
|||
const params = { |
|||
'fondsCode': this.libcode, |
|||
'floorId': this.floorId, |
|||
'regionId': this.regionId, |
|||
'shelfId': this.bookShelfDetails.id, |
|||
'gridShelf': this.booShelfGrid[columnIndex].gridShelf |
|||
} |
|||
FetchInitStockInfo(params).then(res => { |
|||
this.itemStockData = res |
|||
}).catch(() => {}) |
|||
}, |
|||
handleTouchEnd(event) { |
|||
clearTimeout(this.doubleClickTimeout) |
|||
this.activeColumns = {} |
|||
this.popoverIndex = null |
|||
this.popoverVisible.forEach((isVisible, index) => { |
|||
if (isVisible) { |
|||
this.$set(this.popoverVisible, index, false) |
|||
} |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
@import "~@/assets/styles/index.scss"; |
|||
|
|||
.shelf-top{ |
|||
display: flex; |
|||
justify-content: space-around; |
|||
align-items: center; |
|||
text-align: center; |
|||
margin-top: 20px; |
|||
p{ |
|||
font-size: 14px; |
|||
color: #fff; |
|||
height: 36px; |
|||
line-height: 30px; |
|||
background: url('~@/assets/images/shelf04.png') no-repeat center top; |
|||
background-size: auto 100%; |
|||
} |
|||
} |
|||
|
|||
.data-shelf-row{ |
|||
display: flex; |
|||
flex: 1; |
|||
flex-wrap: wrap; |
|||
text-align: center; |
|||
.data-shelf-cell{ |
|||
position: relative; |
|||
font-size: 14px; |
|||
color: #0C0E1E; |
|||
background: url('~@/assets/images/shelf02.png') repeat-x left top; |
|||
background-size: 20% 100%; |
|||
border-radius: 3px; |
|||
cursor: pointer; |
|||
.tag-info{ |
|||
right: 12px; |
|||
top: 44px; |
|||
p{ |
|||
margin-left: 10px; |
|||
} |
|||
} |
|||
&::before{ |
|||
content: ""; |
|||
position: absolute; |
|||
left: 0; |
|||
top: 0; |
|||
width: 6px; |
|||
height: 76px; |
|||
background: url('~@/assets/images/shelf01.png') no-repeat left top; |
|||
background-size: 100% 100%; |
|||
} |
|||
&::after{ |
|||
content: ""; |
|||
position: absolute; |
|||
right: -4px; |
|||
top: 0; |
|||
width: 6px; |
|||
height: 76px; |
|||
background: url('~@/assets/images/shelf01.png') no-repeat left top; |
|||
background-size: 100% 100%; |
|||
} |
|||
.cell-name{ |
|||
display: block; |
|||
width: 100%; |
|||
line-height: 76px; |
|||
} |
|||
&.active{ |
|||
.mask{ |
|||
position: absolute; |
|||
top: 0; |
|||
left: 6px; |
|||
width: 98%; |
|||
height: 100%; |
|||
background-color: rgba(255,0,0,.3); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
::v-deep .data-shelf-row span.el-popover__reference-wrapper{ |
|||
position: absolute !important; |
|||
left: 60% !important; |
|||
top: 48px !important; |
|||
width: 250px; |
|||
// height: 210px; |
|||
background:rgba(0,0,0,1); |
|||
color: #fff; |
|||
border-radius: 6px; |
|||
z-index: 99999999; |
|||
|
|||
} |
|||
|
|||
</style> |
|||
@ -0,0 +1,69 @@ |
|||
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 |
|||
}, |
|||
// host: 'localhost',
|
|||
proxy: { |
|||
'/dxhtsg': { |
|||
target: process.env.VUE_APP_BASE_API, |
|||
changeOrigin: true, |
|||
pathRewrite: { |
|||
'^/dxhtsg': 'dxhtsg' |
|||
} |
|||
}, |
|||
'/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 = '自助查询机' |
|||
return args |
|||
}) |
|||
} |
|||
} |
|||