From 911fb3421b9867a0b27f57dfc0912f33d9e779e8 Mon Sep 17 00:00:00 2001
From: bltcn <blt@tom.com>
Date: 星期四, 23 十一月 2023 17:41:42 +0800
Subject: [PATCH] modify web page (#1122)
---
web-pages/package-lock.json | 84 ++++----
web-pages/src/components/ui-scrollbar/util.js | 120 ++++++++++++
web-pages/package.json | 1
web-pages/src/globalComponents.js | 4
web-pages/src/components/ui-scrollbar/index.vue | 174 +++++++++++++++++
web-pages/src/components/ui-scrollbar/assets/css/index.scss | 72 +++++++
web-pages/src/components/ui-scrollbar/scrollbar-width.js | 29 ++
web-pages/src/components/ui-scrollbar/bar.vue | 104 ++++++++++
web-pages/src/main.js | 4
9 files changed, 544 insertions(+), 48 deletions(-)
diff --git a/web-pages/package-lock.json b/web-pages/package-lock.json
index 74642c4..26fc79a 100644
--- a/web-pages/package-lock.json
+++ b/web-pages/package-lock.json
@@ -2102,27 +2102,6 @@
"whatwg-fetch": "^3.6.2"
},
"dependencies": {
- "@vue/vue-loader-v15": {
- "version": "npm:vue-loader@15.11.1",
- "resolved": "http://27.17.3.62:20000/vue-loader/-/vue-loader-15.11.1.tgz",
- "integrity": "sha512-0iw4VchYLePqJfJu9s62ACWUXeSqM30SQqlIftbYWM3C+jpPcEHKSPUZBLjSF9au4HTHQ/naF6OGnO3Q/qGR3Q==",
- "dev": true,
- "requires": {
- "@vue/component-compiler-utils": "^3.1.0",
- "hash-sum": "^1.0.2",
- "loader-utils": "^1.1.0",
- "vue-hot-reload-api": "^2.3.0",
- "vue-style-loader": "^4.1.0"
- },
- "dependencies": {
- "hash-sum": {
- "version": "1.0.2",
- "resolved": "http://27.17.3.62:20000/hash-sum/-/hash-sum-1.0.2.tgz",
- "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=",
- "dev": true
- }
- }
- },
"debug": {
"version": "4.3.4",
"resolved": "http://27.17.3.62:20000/debug/-/debug-4.3.4.tgz",
@@ -2130,26 +2109,6 @@
"dev": true,
"requires": {
"ms": "2.1.2"
- }
- },
- "json5": {
- "version": "1.0.2",
- "resolved": "http://27.17.3.62:20000/json5/-/json5-1.0.2.tgz",
- "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
- "dev": true,
- "requires": {
- "minimist": "^1.2.0"
- }
- },
- "loader-utils": {
- "version": "1.4.2",
- "resolved": "http://27.17.3.62:20000/loader-utils/-/loader-utils-1.4.2.tgz",
- "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==",
- "dev": true,
- "requires": {
- "big.js": "^5.2.2",
- "emojis-list": "^3.0.0",
- "json5": "^1.0.1"
}
},
"ms": {
@@ -2312,6 +2271,47 @@
"eslint-config-standard": "^16.0.3",
"eslint-import-resolver-node": "^0.3.4",
"eslint-import-resolver-webpack": "^0.13.1"
+ }
+ },
+ "@vue/vue-loader-v15": {
+ "version": "npm:vue-loader@15.11.1",
+ "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.11.1.tgz",
+ "integrity": "sha512-0iw4VchYLePqJfJu9s62ACWUXeSqM30SQqlIftbYWM3C+jpPcEHKSPUZBLjSF9au4HTHQ/naF6OGnO3Q/qGR3Q==",
+ "dev": true,
+ "requires": {
+ "@vue/component-compiler-utils": "^3.1.0",
+ "hash-sum": "^1.0.2",
+ "loader-utils": "^1.1.0",
+ "vue-hot-reload-api": "^2.3.0",
+ "vue-style-loader": "^4.1.0"
+ },
+ "dependencies": {
+ "hash-sum": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz",
+ "integrity": "sha512-fUs4B4L+mlt8/XAtSOGMUO1TXmAelItBPtJG7CyHJfYTdDjwisntGO2JQz7oUsatOY9o68+57eziUVNw/mRHmA==",
+ "dev": true
+ },
+ "json5": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
+ "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
+ "dev": true,
+ "requires": {
+ "minimist": "^1.2.0"
+ }
+ },
+ "loader-utils": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz",
+ "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==",
+ "dev": true,
+ "requires": {
+ "big.js": "^5.2.2",
+ "emojis-list": "^3.0.0",
+ "json5": "^1.0.1"
+ }
+ }
}
},
"@vue/web-component-wrapper": {
@@ -9138,7 +9138,7 @@
},
"vue-hot-reload-api": {
"version": "2.3.4",
- "resolved": "http://27.17.3.62:20000/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz",
+ "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz",
"integrity": "sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog==",
"dev": true
},
diff --git a/web-pages/package.json b/web-pages/package.json
index 10a0124..70a21a1 100644
--- a/web-pages/package.json
+++ b/web-pages/package.json
@@ -14,7 +14,6 @@
"core-js": "3.22.5",
"mockjs": "1.1.0",
"vue": "2.6.14",
- "plugin-component-scrollbar": "1.0.12",
"vue-router": "3.5.3",
"vuex": "3.6.2",
"swiper": "5.4.5",
diff --git a/web-pages/src/components/ui-scrollbar/assets/css/index.scss b/web-pages/src/components/ui-scrollbar/assets/css/index.scss
new file mode 100644
index 0000000..f6693ed
--- /dev/null
+++ b/web-pages/src/components/ui-scrollbar/assets/css/index.scss
@@ -0,0 +1,72 @@
+.ui-scrollbar {
+ overflow: hidden;
+ position: relative;
+
+ &.child-over-width {
+ .ui-scrollbar__view {
+ max-width: 100%;
+ }
+ }
+
+ &:active > .ui-scrollbar__bar,
+ &:focus > .ui-scrollbar__bar,
+ &:hover > .ui-scrollbar__bar {
+ opacity: 1;
+ transition: opacity 0.34s ease-out;
+ }
+}
+
+.ui-scrollbar__wrap {
+ overflow: scroll;
+ height: 100%;
+}
+.ui-scrollbar__view {
+ display: inline-block;
+ vertical-align: middle;
+ min-width: 100%;
+}
+
+.ui-scrollbar__bar {
+ position: absolute;
+ right: 2px;
+ bottom: 2px;
+ z-index: 1;
+ border-radius: 4px;
+ opacity: 0;
+ -webkit-transition: opacity 120ms ease-out;
+ transition: opacity 120ms ease-out;
+
+ &.is-horizontal {
+ height: 6px;
+ left: 2px;
+
+ & > div {
+ height: 100%;
+ }
+ }
+
+ &.is-vertical {
+ width: 6px;
+ top: 2px;
+
+ & > div {
+ width: 100%;
+ }
+ }
+}
+
+.ui-scrollbar__thumb {
+ position: relative;
+ display: block;
+ width: 0;
+ height: 0;
+ cursor: pointer;
+ border-radius: inherit;
+ background-color: rgba(144, 147, 153, 0.3);
+ -webkit-transition: 0.3s background-color;
+ transition: 0.3s background-color;
+
+ &:hover {
+ background-color: hsla(220, 4%, 58%, 0.5);
+ }
+}
diff --git a/web-pages/src/components/ui-scrollbar/bar.vue b/web-pages/src/components/ui-scrollbar/bar.vue
new file mode 100644
index 0000000..8cb3ff3
--- /dev/null
+++ b/web-pages/src/components/ui-scrollbar/bar.vue
@@ -0,0 +1,104 @@
+<script>
+ import { on, off, renderThumbStyle, BAR_MAP } from './util'
+
+ export default {
+ name: 'scrollbar-Bar',
+ props: {
+ vertical: Boolean,
+ size: String,
+ move: Number
+ },
+ computed: {
+ bar () {
+ return BAR_MAP[this.vertical ? 'vertical' : 'horizontal']
+ },
+
+ wrap () {
+ return this.$parent.wrap
+ }
+ },
+ destroyed () {
+ off(document, 'mouseup', this.mouseUpDocumentHandler)
+ },
+ methods: {
+ clickThumbHandler (e) {
+ // prevent click event of right button
+ if (e.ctrlKey || e.button === 2) {
+ return
+ }
+ this.startDrag(e)
+ this[this.bar.axis] =
+ e.currentTarget[this.bar.offset] -
+ (e[this.bar.client] -
+ e.currentTarget.getBoundingClientRect()[this.bar.direction])
+ },
+
+ clickTrackHandler (e) {
+ const offset = Math.abs(
+ e.target.getBoundingClientRect()[this.bar.direction] -
+ e[this.bar.client]
+ )
+ const thumbHalf = this.$refs.thumb[this.bar.offset] / 2
+ const thumbPositionPercentage =
+ ((offset - thumbHalf) * 100) / this.$el[this.bar.offset]
+
+ this.wrap[this.bar.scroll] =
+ (thumbPositionPercentage * this.wrap[this.bar.scrollSize]) /
+ 100
+ },
+
+ startDrag (e) {
+ e.stopImmediatePropagation()
+ this.cursorDown = true
+
+ on(document, 'mousemove', this.mouseMoveDocumentHandler)
+ on(document, 'mouseup', this.mouseUpDocumentHandler)
+ document.onselectstart = () => false
+ },
+
+ mouseMoveDocumentHandler (e) {
+ if (this.cursorDown === false) return
+ const prevPage = this[this.bar.axis]
+
+ if (!prevPage) return
+
+ const offset =
+ (this.$el.getBoundingClientRect()[this.bar.direction] -
+ e[this.bar.client]) *
+ -1
+ const thumbClickPosition =
+ this.$refs.thumb[this.bar.offset] - prevPage
+ const thumbPositionPercentage =
+ ((offset - thumbClickPosition) * 100) /
+ this.$el[this.bar.offset]
+
+ this.wrap[this.bar.scroll] =
+ (thumbPositionPercentage * this.wrap[this.bar.scrollSize]) /
+ 100
+ },
+
+ mouseUpDocumentHandler (e) {
+ this.cursorDown = false
+ this[this.bar.axis] = 0
+ off(document, 'mousemove', this.mouseMoveDocumentHandler)
+ document.onselectstart = null
+ }
+ },
+ render (h) {
+ const { size, move, bar } = this
+ return (
+ <div
+ class={['ui-scrollbar__bar', 'is-' + bar.key]}
+ onMousedown={this.clickTrackHandler}
+ >
+ <div
+ ref="thumb"
+ class="ui-scrollbar__thumb"
+ onMousedown={this.clickThumbHandler}
+ style={renderThumbStyle({ size, move, bar })}
+ ></div>
+ </div>
+ )
+ }
+ }
+</script>
diff --git a/web-pages/src/components/ui-scrollbar/index.vue b/web-pages/src/components/ui-scrollbar/index.vue
new file mode 100644
index 0000000..b42e190
--- /dev/null
+++ b/web-pages/src/components/ui-scrollbar/index.vue
@@ -0,0 +1,174 @@
+
+<script>
+ import { addResizeListener, removeResizeListener, toObject } from './util'
+ import scrollbarWidth from './scrollbar-width'
+ import Bar from './bar.vue'
+ require('./assets/css/index.scss')
+
+ export default {
+ name: 'ui-scrollbar',
+ components: { Bar },
+ props: {
+ native: Boolean,
+ childOverWidth: {
+ type: Boolean,
+ default: true
+ },
+ wrapStyle: {},
+ wrapClass: {},
+ viewClass: {},
+ viewStyle: {},
+ noresize: Boolean, // 濡傛灉 container 灏哄涓嶄細鍙戠敓鍙樺寲锛屾渶濂借缃畠鍙互浼樺寲鎬ц兘
+ tag: {
+ type: String,
+ default: 'div'
+ }
+ },
+
+ data () {
+ return {
+ sizeWidth: '0',
+ sizeHeight: '0',
+ moveX: 0,
+ moveY: 0,
+ scrollbarMiddle: 0
+ }
+ },
+
+ computed: {
+ wrap () {
+ return this.$refs.wrap
+ }
+ },
+
+ mounted () {
+ if (this.native) return
+ this.$nextTick(this.update)
+ !this.noresize && addResizeListener(this.$refs.resize, this.update)
+ !this.noresize && addResizeListener(this.$refs.wrap, this.update)
+ },
+
+ beforeDestroy () {
+ if (this.native) return
+ !this.noresize && removeResizeListener(this.$refs.resize, this.update)
+ !this.noresize && removeResizeListener(this.$refs.wrap, this.update)
+ },
+
+ methods: {
+ handleScroll () {
+ const wrap = this.wrap
+
+ this.moveY = (wrap.scrollTop * 100) / wrap.clientHeight
+ this.moveX = (wrap.scrollLeft * 100) / wrap.clientWidth
+ if (wrap.scrollTop + wrap.clientHeight === wrap.scrollHeight) {
+ this.$emit('scrollbottom')
+ }
+ if (wrap.scrollTop === 0) {
+ this.$emit('scrolltop')
+ }
+ this.$emit('scrollMove', {
+ moveX: wrap.scrollLeft,
+ moveY: wrap.scrollTop,
+ clientX: wrap.clientWidth,
+ clientY: wrap.clientHeight,
+ scrollHeight: wrap.scrollHeight,
+ scrollWidth: wrap.scrollWidth
+ })
+ },
+
+ update () {
+ let heightPercentage = null
+ let widthPercentage = null
+ const wrap = this.wrap
+ if (!wrap) return
+
+ heightPercentage = (wrap.clientHeight * 100) / wrap.scrollHeight
+ widthPercentage = (wrap.clientWidth * 100) / wrap.scrollWidth
+
+ this.sizeHeight = heightPercentage < 100 ? heightPercentage + '%' : ''
+ this.sizeWidth = widthPercentage < 100 ? widthPercentage + '%' : ''
+ },
+ continueScroll (rowNum) {
+ const wrap = this.wrap
+ if (this.scrollbarMiddle === 0) {
+ this.scrollbarMiddle = wrap.scrollTop / 2 + wrap.clientHeight / 2 - wrap.clientHeight / rowNum
+ }
+ wrap.scrollTop = this.scrollbarMiddle
+ }
+ },
+
+ render (h) {
+ const gutter = scrollbarWidth()
+ let style = this.wrapStyle
+
+ if (gutter) {
+ const gutterWith = `-${gutter}px`
+ let gutterStyle = ''
+
+ let overFlowXStr = ''
+ let overflowYStr = ''
+ if (style && style.length > 0) {
+ style.forEach((styleItem) => {
+ if (styleItem['overflow-x'] || styleItem.overflowX) {
+ overFlowXStr = styleItem['overflow-x'] || styleItem.overflowX
+ }
+ if (styleItem['overflow-y'] || styleItem.overflowY) {
+ overflowYStr = styleItem['overflow-y'] || styleItem.overflowY
+ }
+ })
+ }
+
+ if (overFlowXStr === 'hidden') {
+ gutterStyle = `margin-right: ${gutterWith};`
+ } else {
+ gutterStyle = `margin-bottom: ${gutterWith}; margin-right: ${gutterWith};`
+ }
+
+ if (Array.isArray(this.wrapStyle)) {
+ style = toObject(this.wrapStyle)
+ if (overFlowXStr !== 'hidden') {
+ style.marginBottom = gutterWith
+ }
+ if (overflowYStr !== 'hidden') {
+ style.marginRight = gutterWith
+ }
+ } else if (typeof this.wrapStyle === 'string') {
+ style += gutterStyle
+ } else {
+ style = gutterStyle
+ }
+ }
+ const view = h(
+ this.tag,
+ {
+ class: ['ui-scrollbar__view', this.viewClass],
+ style: this.viewStyle,
+ ref: 'resize'
+ },
+ this.$slots.default
+ )
+ const wrap = (
+ <div
+ ref="wrap"
+ style={style}
+ onScroll={this.handleScroll}
+ class={[this.wrapClass, 'ui-scrollbar__wrap', gutter ? '' : 'ui-scrollbar__wrap--hidden-default']}
+ >{[view]}</div>
+ )
+ let nodes
+
+ if (!this.native) {
+ nodes = [
+ wrap,
+ <Bar move={this.moveX} size={this.sizeWidth}></Bar>,
+ <Bar vertical move={this.moveY} size={this.sizeHeight}></Bar>
+ ]
+ } else {
+ nodes = [
+ <div ref="wrap" class={[this.wrapClass, 'ui-scrollbar__wrap']} style={style}>{[view]}</div>
+ ]
+ }
+ return h('div', { class: ['ui-scrollbar', { 'child-over-width': !this.childOverWidth }] }, nodes)
+ }
+ }
+</script>
diff --git a/web-pages/src/components/ui-scrollbar/scrollbar-width.js b/web-pages/src/components/ui-scrollbar/scrollbar-width.js
new file mode 100644
index 0000000..75802ad
--- /dev/null
+++ b/web-pages/src/components/ui-scrollbar/scrollbar-width.js
@@ -0,0 +1,29 @@
+import Vue from 'vue'
+
+let scrollBarWidth
+
+export default function () {
+ if (Vue.prototype.$isServer) return 0
+ if (scrollBarWidth !== undefined) return scrollBarWidth
+
+ const outer = document.createElement('div')
+ outer.className = 'ui-scrollbar__wrap'
+ outer.style.visibility = 'hidden'
+ outer.style.width = '100px'
+ outer.style.position = 'absolute'
+ outer.style.top = '-9999px'
+ document.body.appendChild(outer)
+
+ const widthNoScroll = outer.offsetWidth
+ outer.style.overflow = 'scroll'
+
+ const inner = document.createElement('div')
+ inner.style.width = '100%'
+ outer.appendChild(inner)
+
+ const widthWithScroll = inner.offsetWidth
+ outer.parentNode.removeChild(outer)
+ scrollBarWidth = widthNoScroll - widthWithScroll
+
+ return scrollBarWidth
+};
diff --git a/web-pages/src/components/ui-scrollbar/util.js b/web-pages/src/components/ui-scrollbar/util.js
new file mode 100644
index 0000000..8ba52f3
--- /dev/null
+++ b/web-pages/src/components/ui-scrollbar/util.js
@@ -0,0 +1,120 @@
+import ResizeObserver from 'resize-observer-polyfill'
+
+export const BAR_MAP = {
+ vertical: {
+ offset: 'offsetHeight',
+ scroll: 'scrollTop',
+ scrollSize: 'scrollHeight',
+ size: 'height',
+ key: 'vertical',
+ axis: 'Y',
+ client: 'clientY',
+ direction: 'top'
+ },
+ horizontal: {
+ offset: 'offsetWidth',
+ scroll: 'scrollLeft',
+ scrollSize: 'scrollWidth',
+ size: 'width',
+ key: 'horizontal',
+ axis: 'X',
+ client: 'clientX',
+ direction: 'left'
+ }
+}
+
+export function renderThumbStyle ({ move, size, bar }) {
+ const style = {}
+ const translate = `translate${bar.axis}(${move}%)`
+
+ style[bar.size] = size
+ style.transform = translate
+ style.msTransform = translate
+ style.webkitTransform = translate
+
+ return style
+};
+
+const isServer = typeof window === 'undefined'
+
+/* istanbul ignore next */
+const resizeHandler = function (entries) {
+ for (const entry of entries) {
+ const listeners = entry.target.__resizeListeners__ || []
+ if (listeners.length) {
+ listeners.forEach(fn => {
+ fn()
+ })
+ }
+ }
+}
+
+/* istanbul ignore next */
+export const addResizeListener = function (element, fn) {
+ if (isServer) return
+ if (!element.__resizeListeners__) {
+ element.__resizeListeners__ = []
+ element.__ro__ = new ResizeObserver(resizeHandler)
+ element.__ro__.observe(element)
+ }
+ element.__resizeListeners__.push(fn)
+}
+
+/* istanbul ignore next */
+export const removeResizeListener = function (element, fn) {
+ if (!element || !element.__resizeListeners__) return
+ element.__resizeListeners__.splice(element.__resizeListeners__.indexOf(fn), 1)
+ if (!element.__resizeListeners__.length) {
+ element.__ro__.disconnect()
+ }
+}
+
+function extend (to, _from) {
+ for (const key in _from) {
+ to[key] = _from[key]
+ }
+ return to
+};
+
+export function toObject (arr) {
+ const res = {}
+ for (let i = 0; i < arr.length; i++) {
+ if (arr[i]) {
+ extend(res, arr[i])
+ }
+ }
+ return res
+};
+
+export const on = (function () {
+ if (!isServer && document.addEventListener) {
+ return function (element, event, handler) {
+ if (element && event && handler) {
+ element.addEventListener(event, handler, false)
+ }
+ }
+ } else {
+ return function (element, event, handler) {
+ if (element && event && handler) {
+ element.attachEvent('on' + event, handler)
+ }
+ }
+ }
+})()
+
+/* istanbul ignore next */
+export const off = (function () {
+ if (!isServer && document.removeEventListener) {
+ return function (element, event, handler) {
+ if (element && event) {
+ element.removeEventListener(event, handler, false)
+ }
+ }
+ } else {
+ return function (element, event, handler) {
+ if (element && event) {
+ element.detachEvent('on' + event, handler)
+ }
+ }
+ }
+})()
diff --git a/web-pages/src/globalComponents.js b/web-pages/src/globalComponents.js
index 4b7b1ed..53fb12d 100644
--- a/web-pages/src/globalComponents.js
+++ b/web-pages/src/globalComponents.js
@@ -1,9 +1,11 @@
// 缁勪欢
import uiJessibuca from '@/components/ui-jessibuca/index.vue'
+import uiScrollbar from '@/components/ui-scrollbar/index.vue'
const components = {
// 缁勪欢
- uiJessibuca
+ uiJessibuca,
+ uiScrollbar
}
const install = function (Vue, opts = {}) {
diff --git a/web-pages/src/main.js b/web-pages/src/main.js
index 617c1ba..9f215bf 100644
--- a/web-pages/src/main.js
+++ b/web-pages/src/main.js
@@ -10,8 +10,6 @@
// 椤圭洰鏈湴鍏ㄥ眬鏂规硶
import globalFunctions from './globalFunctions'
-import pluginComponentScrollbar from 'plugin-component-scrollbar'
-
// 绗笁鏂圭粍浠�
// ant-design-vue 缁勪欢 鎸夐渶鍔犺浇
import { ConfigProvider, Input } from 'ant-design-vue'
@@ -21,8 +19,6 @@
Vue.use(ConfigProvider)
Vue.use(Input)
-
-Vue.use(pluginComponentScrollbar)
const axiosInstance = Axios.create({
timeout: 60000
--
Gitblit v1.9.1