1
This commit is contained in:
@@ -0,0 +1,670 @@
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<!-- @vue-docgen-ignore-next-line -->
|
||||
<script module="xfs" lang="wxs" src="./xfs.wxs"></script>
|
||||
<!-- #endif -->
|
||||
<script lang="ts">
|
||||
import { getUid, checkIsCssUnit } from '../../core/util/xCoreUtil.uts'
|
||||
import { getDefaultColor } from '../../core/util/xCoreColorUtil.uts'
|
||||
import { SlotsType } from 'vue'
|
||||
import { xConfig } from "../../config/xConfig.uts"
|
||||
|
||||
type POSITION_TYPE_XY = {
|
||||
x : number,
|
||||
y : number
|
||||
}
|
||||
|
||||
/**
|
||||
* @name 左滑菜单 xSwitchSlider
|
||||
* @description 常用于对话聊天,订单列表等一些隐藏式按钮设计场景。如果子菜单无法定宽或者被挤夺请写style:flex-shrink: 0;避免。
|
||||
* @page /pages/index/switch-slider
|
||||
* @category 反馈组件
|
||||
* @constant 平台兼容
|
||||
* | Harmony | H5 | andriod | IOS | 小程序 | UTS | UNIAPP-X SDK | version |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| ☑ | ☑ | ☑️ | ☑️ | ☑️ | ☑️ | 4.76+ | 1.1.18 |
|
||||
*/
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
opened: false,
|
||||
startX: 0,
|
||||
startY: 0,
|
||||
slideX: 0,
|
||||
_x: 0,
|
||||
_y: 0,
|
||||
_tempPop_x:0,
|
||||
_tempPop_y:0,
|
||||
dirs: "right",
|
||||
id: "xSwitchSilder" + getUid(),
|
||||
idMenuRight: "xSwitchSilderItems" + getUid(),
|
||||
isMove: false,
|
||||
dateTime: 0,
|
||||
diffX: 0,
|
||||
isSwiper:'none'
|
||||
}
|
||||
},
|
||||
emits: [
|
||||
/**
|
||||
* 提供这个函数是因为如果你把此组件套在了scroll中
|
||||
* 你在ios端根本 无法去阻止 底部的scrollview的滚动,这大概官方是解决不了的
|
||||
* 冒泡 事件。我只能绕开。
|
||||
* 此函数会发现是否禁用你外部滚动的指示。
|
||||
*/
|
||||
"disabledScrollChange",
|
||||
/**
|
||||
* 活动区域被点击时触发。
|
||||
*/
|
||||
"click",
|
||||
/**
|
||||
* 打开菜单时触发
|
||||
*/
|
||||
"open",
|
||||
/**
|
||||
* 关闭时触发
|
||||
*/
|
||||
"close",
|
||||
/**
|
||||
* 触摸开始
|
||||
*/
|
||||
"start",
|
||||
/**
|
||||
* 触摸结束
|
||||
*/
|
||||
"end",
|
||||
/**
|
||||
* 触摸中
|
||||
*/
|
||||
"move",
|
||||
/**
|
||||
* 等同v-model:status
|
||||
*/
|
||||
"update:status"
|
||||
],
|
||||
slots: Object as SlotsType<{
|
||||
default : {
|
||||
status : boolean
|
||||
},
|
||||
menu : {
|
||||
status : boolean
|
||||
}
|
||||
}>,
|
||||
props: {
|
||||
|
||||
/**
|
||||
* 被拖动层的自定义样式
|
||||
*/
|
||||
custonmStyle: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
/**
|
||||
* 菜单容器层自定义样式
|
||||
*/
|
||||
custonmMenuStyle: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
/**
|
||||
* 宽度
|
||||
*/
|
||||
width: {
|
||||
type: String,
|
||||
default: "100%"
|
||||
},
|
||||
/**
|
||||
* 高度,单位随意
|
||||
*/
|
||||
height: {
|
||||
type: String,
|
||||
default: "50"
|
||||
},
|
||||
/**
|
||||
* 是否禁用
|
||||
*/
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
/**
|
||||
* 当滑动时小于此值,会回弹到原位。
|
||||
*/
|
||||
threshold: {
|
||||
type: Number,
|
||||
default: 15
|
||||
},
|
||||
/**
|
||||
* 当打开或者松开时的动画时间
|
||||
*/
|
||||
duration: {
|
||||
type: Number,
|
||||
default: 450
|
||||
},
|
||||
/**
|
||||
* 当前打开状态
|
||||
*/
|
||||
status: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
/**
|
||||
* 下边线的颜色
|
||||
*/
|
||||
borderColor:{
|
||||
type:String,
|
||||
default:"#f5f5f5"
|
||||
},
|
||||
/**
|
||||
* 下边线暗黑的颜色,如果不提供,取全局borderDarkColor
|
||||
*/
|
||||
borderDarkColor:{
|
||||
type:String,
|
||||
default:""
|
||||
},
|
||||
/**
|
||||
* 让拖动层内容失去响应,会导致顶层里面的内容无法触发事件响应
|
||||
* 但好处是:拖动更流畅,没有断断续续。请自行根据场景打开和关闭。
|
||||
* false关闭让内容响应事件,true让内容失去响应。
|
||||
*/
|
||||
eventNone:{
|
||||
type:Boolean,
|
||||
default:true
|
||||
}
|
||||
|
||||
},
|
||||
computed: {
|
||||
_height() : string {
|
||||
return checkIsCssUnit(this.height, xConfig.unit)
|
||||
},
|
||||
_disabled() : boolean {
|
||||
return this.disabled
|
||||
},
|
||||
_custonmStyle() : string {
|
||||
return this.custonmStyle
|
||||
},
|
||||
_custonmMenuStyle() : string {
|
||||
return this.custonmStyle
|
||||
},
|
||||
|
||||
_borderColor() : string {
|
||||
if (xConfig.dark == 'dark'&&this.borderDarkColor=='') return getDefaultColor(xConfig.borderDarkColor)
|
||||
if (xConfig.dark == 'dark'&&this.borderDarkColor!='') return getDefaultColor(this.borderDarkColor)
|
||||
return getDefaultColor(this.borderColor)
|
||||
},
|
||||
_animationFun() : string {
|
||||
return xConfig.animationFun
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
status(newval : boolean) {
|
||||
if (newval == this.opened) return;
|
||||
if (this.status) {
|
||||
this.open()
|
||||
} else {
|
||||
this.close()
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
|
||||
this.getNodeInfo();
|
||||
},
|
||||
methods: {
|
||||
// #ifdef MP-WEIXIN
|
||||
setOpts(opts){
|
||||
if(opts?.isMove!=null){
|
||||
this.isMove = opts.isMove;
|
||||
}
|
||||
if(opts?.opened!=null){
|
||||
this.opened = opts.opened;
|
||||
}
|
||||
if(opts?.isSwiper!=null){
|
||||
this.isSwiper = opts.isSwiper;
|
||||
}
|
||||
|
||||
},
|
||||
callEmits(args){
|
||||
if(!args.name) return;
|
||||
if(args.args!=null&&args.args!=undefined){
|
||||
this.$emit(args.name,args.args)
|
||||
}else{
|
||||
this.$emit(args.name)
|
||||
if(args.name=='open'|| args.name=='close'){
|
||||
this.$emit("update:status", args.name=='open')
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
// #endif
|
||||
resetMoveData() {
|
||||
this.startX = 0;
|
||||
this.startY = 0;
|
||||
let ele = this.$refs['xSwitchSilder'] as UniElement
|
||||
ele.style.setProperty("transition-duration", '0ms')
|
||||
},
|
||||
getNodeInfo() {
|
||||
uni.createSelectorQuery().in(this)
|
||||
.select(".xSwitchSilderItems")
|
||||
.boundingClientRect().exec((ret) => {
|
||||
let el = uni.getElementById(this.id as string) as UniElement|null
|
||||
let nodeinfo = ret[0] as NodeInfo
|
||||
let width = nodeinfo.width as number
|
||||
if (this.status&&el!=null) {
|
||||
this.opened = false;
|
||||
this.dirs = "left"
|
||||
el.style.setProperty("transition-duration", this.duration.toString() + 'ms')
|
||||
el.style.setProperty("left", '-' + width.toString() + 'px')
|
||||
this.slideX = -width;
|
||||
}
|
||||
})
|
||||
},
|
||||
getMenuRightwidth() : number {
|
||||
let idMenuRight = this.$refs['xSwitchSilderItems'] as UniElement
|
||||
let menurightWidth = idMenuRight.getBoundingClientRect().width;
|
||||
return menurightWidth
|
||||
},
|
||||
eventTransform_start(evt : POSITION_TYPE_XY) {
|
||||
this.diffX = 0
|
||||
this.dateTime = new Date().getTime()
|
||||
this.resetMoveData();
|
||||
if (this._disabled) return;
|
||||
this.startX = evt.x - this.slideX;
|
||||
this._x = evt.x
|
||||
this._y = evt.y
|
||||
this.startY = evt.y;
|
||||
this.isMove = true;
|
||||
},
|
||||
eventTransform_move(evt : POSITION_TYPE_XY) {
|
||||
let el = this.$refs['xSwitchSilder'] as UniElement|null;
|
||||
if(el==null) return;
|
||||
let x = evt.x - this.startX;
|
||||
let realleftdom = el.style.getPropertyValue("left") as string | null
|
||||
let leftpos = parseInt(realleftdom == null ? '0' : realleftdom)
|
||||
if (isNaN(leftpos)) {
|
||||
leftpos = 0
|
||||
}
|
||||
let menuwidth = this.getMenuRightwidth()
|
||||
let diffX = evt.x - this._x;
|
||||
this._x = evt.x
|
||||
|
||||
if (leftpos > 0) {
|
||||
x = 0
|
||||
} else if (leftpos < -menuwidth) {
|
||||
x = -menuwidth
|
||||
}
|
||||
|
||||
x = Math.min(0, x)
|
||||
x = Math.max(-menuwidth, x)
|
||||
|
||||
this.slideX = x;
|
||||
|
||||
if (Math.abs(x) > this.threshold) {
|
||||
if (diffX > 0) {
|
||||
this.dirs = "right"
|
||||
} else {
|
||||
this.dirs = "left"
|
||||
}
|
||||
}
|
||||
if (leftpos >= -menuwidth && leftpos <= 0 && Math.abs(diffX) > 0) {
|
||||
el.style.setProperty("left", x + 'px')
|
||||
}
|
||||
this.diffX = diffX;
|
||||
},
|
||||
mStart(evt : UniTouchEvent) {
|
||||
/**
|
||||
* 触发时触发
|
||||
*/
|
||||
this.$emit("start")
|
||||
this.dateTime = Date.now()
|
||||
let event = evt.changedTouches[0];
|
||||
this._tempPop_x = event.clientX
|
||||
this._tempPop_y = event.clientY
|
||||
this.resetMoveData();
|
||||
if (this._disabled) return;
|
||||
this.isMove = true;
|
||||
this.isSwiper = 'none';
|
||||
this.eventTransform_start({ x: event.clientX, y: event.clientY } as POSITION_TYPE_XY)
|
||||
},
|
||||
mMove(evt : UniTouchEvent) {
|
||||
/**
|
||||
* 触摸中时触发
|
||||
*/
|
||||
this.$emit("move")
|
||||
let event = evt.changedTouches[0]
|
||||
if (this._disabled) return;
|
||||
|
||||
// 如果y距离大于x距离就允许滑动页面,否则左滑组件。
|
||||
let y = Math.abs(event.clientY - this._tempPop_y)
|
||||
let x = Math.abs(event.clientX - this._tempPop_x)
|
||||
// 判断是否有明显的方向
|
||||
const hasDirection = Math.max(x, y) > 10
|
||||
// 判断是否为水平方向
|
||||
const isHorizontal = x > y
|
||||
|
||||
if (hasDirection && this.isSwiper == 'none') {
|
||||
if (isHorizontal) {
|
||||
// 水平滑动,启用左滑并阻止页面滚动
|
||||
this.isSwiper = 'swiper'
|
||||
evt.preventDefault()
|
||||
evt.stopPropagation()
|
||||
} else {
|
||||
// 垂直滑动,禁用左滑
|
||||
this.isSwiper = 'off'
|
||||
}
|
||||
}
|
||||
|
||||
// 只有在启用左滑状态下才执行滑动
|
||||
if (this.isSwiper == 'swiper') {
|
||||
this.eventTransform_move({ x: event.clientX, y: event.clientY } as POSITION_TYPE_XY)
|
||||
}
|
||||
},
|
||||
mEnd(evt : UniTouchEvent) {
|
||||
|
||||
/**
|
||||
* 触摸结束时触发
|
||||
*/
|
||||
this.$emit("end")
|
||||
let diffdate = Date.now() -this.dateTime
|
||||
let diffx = evt.changedTouches[0].clientX - this._tempPop_x
|
||||
let diffy = evt.changedTouches[0].clientY - this._tempPop_y
|
||||
if(Math.abs(diffx) == Math.abs(diffy) && diffx==0 && diffdate>50&&diffdate<=250){
|
||||
this.mClick()
|
||||
}
|
||||
|
||||
|
||||
let el = this.$refs['xSwitchSilder'] as UniElement | null;
|
||||
let idMenuRight = this.$refs['xSwitchSilderItems'] as UniElement|null
|
||||
if(el==null||idMenuRight==null) return;
|
||||
this.isMove = false;
|
||||
if (this._disabled||this.isSwiper=='off'){
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
let menuwidth = idMenuRight.getBoundingClientRect().width
|
||||
el.style.setProperty("transition-duration", this.duration.toString() + 'ms')
|
||||
if (this.dirs == 'left') {
|
||||
|
||||
this.slideX = -menuwidth;
|
||||
el.style.setProperty("left", (-menuwidth).toString() + 'px')
|
||||
this.opened = true;
|
||||
/**
|
||||
* 打开菜单时触发
|
||||
*/
|
||||
this.$emit("open")
|
||||
|
||||
} else if (this.dirs == 'right') {
|
||||
el.style.setProperty("left", '0px')
|
||||
this.slideX = 0
|
||||
this.opened = false;
|
||||
/**
|
||||
* 关闭时触发
|
||||
*/
|
||||
this.$emit("close")
|
||||
}
|
||||
},
|
||||
onAniEnd() {
|
||||
// #ifdef APP||WEB
|
||||
if (this.dirs == 'left') {
|
||||
/** 等同v-model:status **/
|
||||
this.$emit("update:status", true)
|
||||
this.isMove = false;
|
||||
}
|
||||
if (this.dirs == 'right') {
|
||||
/** 等同v-model:status **/
|
||||
this.$emit("update:status", false)
|
||||
this.isMove = false;
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
mClick() {
|
||||
|
||||
/**
|
||||
* 活动区域被点击时触发。
|
||||
*/
|
||||
this.$emit("click")
|
||||
},
|
||||
// #ifdef WEB
|
||||
mmStart(evt : UniMouseEvent) {
|
||||
window.xSwitchSliderId = this.id
|
||||
/**
|
||||
* 触发时触发
|
||||
*/
|
||||
this.$emit("start")
|
||||
|
||||
this.dateTime = Date.now()
|
||||
this.resetMoveData();
|
||||
this._tempPop_x = evt.clientX;
|
||||
this._tempPop_y = evt.clientY;
|
||||
if (this._disabled) return;
|
||||
this.isSwiper = 'none';
|
||||
this.isMove = true;
|
||||
this.eventTransform_start({ x: evt.clientX, y: evt.clientY } as POSITION_TYPE_XY)
|
||||
},
|
||||
mmMove(evt : UniMouseEvent) {
|
||||
if(window.xSwitchSliderId != this.id) return;
|
||||
/**
|
||||
* 触摸中时触发
|
||||
*/
|
||||
this.$emit("move")
|
||||
if (this._disabled||!this.isMove) return;
|
||||
|
||||
// 如果y距离大于x距离就允许滑动页面,否则左滑组件。
|
||||
let y = Math.abs(evt.clientY - this._tempPop_y)
|
||||
let x = Math.abs(evt.clientX - this._tempPop_x)
|
||||
// 判断是否有明显的方向
|
||||
const hasDirection = Math.max(x, y) > 10
|
||||
// 判断是否为水平方向
|
||||
const isHorizontal = x > y
|
||||
|
||||
if (hasDirection && this.isSwiper == 'none') {
|
||||
if (isHorizontal) {
|
||||
// 水平滑动,启用左滑并阻止页面滚动
|
||||
this.isSwiper = 'swiper'
|
||||
evt.preventDefault()
|
||||
evt.stopPropagation()
|
||||
|
||||
} else {
|
||||
// 垂直滑动,禁用左滑
|
||||
this.isSwiper = 'off'
|
||||
}
|
||||
}
|
||||
|
||||
if (this.isSwiper == 'swiper') {
|
||||
this.eventTransform_move({ x: evt.clientX, y: evt.clientY } as POSITION_TYPE_XY)
|
||||
}
|
||||
},
|
||||
mmEnd(evt:UniMouseEvent) {
|
||||
if(window.xSwitchSliderId != this.id||!this.isMove) return;
|
||||
/**
|
||||
* 触摸结束时触发
|
||||
*/
|
||||
this.$emit("end")
|
||||
let diffdate = Date.now() -this.dateTime
|
||||
let diffx = evt.clientX - this._tempPop_x
|
||||
let diffy = evt.clientY - this._tempPop_y
|
||||
if(Math.abs(diffx) == Math.abs(diffy) && diffx==0 && diffdate>50&&diffdate<=250){
|
||||
this.mClick()
|
||||
}
|
||||
|
||||
let el = this.$refs['xSwitchSilder'] as UniElement
|
||||
let idMenuRight = this.$refs['xSwitchSilderItems'] as UniElement
|
||||
this.isMove = false;
|
||||
|
||||
if (this._disabled||this.isSwiper == 'off') return;
|
||||
|
||||
let menuwidth = idMenuRight!.getBoundingClientRect().width
|
||||
el!.style.setProperty("transition-duration", this.duration.toString() + 'ms')
|
||||
if (this.dirs == 'left') {
|
||||
|
||||
this.slideX = -menuwidth;
|
||||
el!.style.setProperty("left", (-menuwidth).toString() + 'px')
|
||||
this.opened = true;
|
||||
/**
|
||||
* 打开菜单时触发
|
||||
*/
|
||||
this.$emit("open")
|
||||
|
||||
} else if (this.dirs == 'right') {
|
||||
el!.style.setProperty("left", '0px')
|
||||
this.slideX = 0
|
||||
this.opened = false;
|
||||
/**
|
||||
* 关闭时触发
|
||||
*/
|
||||
this.$emit("close")
|
||||
}
|
||||
},
|
||||
// #endif
|
||||
/**
|
||||
* 打开
|
||||
* @public
|
||||
*/
|
||||
open() {
|
||||
this.opened = true;
|
||||
this.dirs = "left"
|
||||
// #ifdef APP||WEB
|
||||
let menuwidth = this.getMenuRightwidth()
|
||||
let el = this.$refs['xSwitchSilder'] as UniElement|null;
|
||||
if(el==null) return;
|
||||
el.style.setProperty("transition-duration", this.duration.toString() + 'ms')
|
||||
el.style.setProperty("left", '-' + menuwidth.toString() + 'px')
|
||||
this.slideX = -menuwidth;
|
||||
// #endif
|
||||
},
|
||||
/**
|
||||
* 关闭
|
||||
* @public
|
||||
*/
|
||||
close() {
|
||||
this.opened = false;
|
||||
this.dirs = "right"
|
||||
|
||||
// #ifdef APP||WEB
|
||||
let el = this.$refs['xSwitchSilder'] as UniElement|null;
|
||||
if(el!=null){
|
||||
el.style.setProperty("transition-duration", this.duration.toString() + 'ms')
|
||||
el.style.setProperty("left", '0px')
|
||||
}
|
||||
// #endif
|
||||
this.slideX = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<view>
|
||||
<view
|
||||
class="xSwitchSilder" :style="{minHeight:_height}">
|
||||
<view
|
||||
|
||||
|
||||
<!-- #ifdef APP||WEB -->
|
||||
@touchstart="mStart"
|
||||
@touchmove="mMove"
|
||||
@touchend="mEnd"
|
||||
@touchcancel="mEnd"
|
||||
<!-- #endif -->
|
||||
|
||||
|
||||
<!-- #ifdef WEB -->
|
||||
@mousedown="mmStart"
|
||||
@mousemove="mmMove"
|
||||
@mouseup="mmEnd"
|
||||
@mouseleave="mmEnd"
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
@touchstart="xfs.mStart"
|
||||
@touchmove="xfs.mMove"
|
||||
@touchend="xfs.mEnd"
|
||||
@touchcancel="xfs.mEnd"
|
||||
:data-opts="{
|
||||
disabled:_disabled,
|
||||
slideX:slideX,
|
||||
duration:duration,
|
||||
animationFun:_animationFun,
|
||||
opened:opened,
|
||||
threshold:threshold
|
||||
}"
|
||||
:change:prop="xfs.propObserver"
|
||||
:prop="opened"
|
||||
<!-- #endif -->
|
||||
|
||||
:id="id" ref="xSwitchSilder"
|
||||
:style="[{'transition-timing-function':_animationFun},_custonmStyle]"
|
||||
class="xSwitchSilderWrap "
|
||||
@transitionend="onAniEnd">
|
||||
<view :class="[eventNone?'noEventBySwitchSlider':'']" class="" style="width: 100%;height: 100%;">
|
||||
<!--
|
||||
@slot 默认插槽,你的顶层布局可以在这里。 由于vue 的diff机制,去掉5ms的延迟。内容层会失去事件响应。请通过组件的@click
|
||||
-->
|
||||
<slot></slot>
|
||||
</view>
|
||||
</view>
|
||||
<view class="xSwitchSilderItemsWrap">
|
||||
<view ref="xSwitchSilderItems" :id="idMenuRight" class="xSwitchSilderItems" :style="_custonmMenuStyle">
|
||||
<!--
|
||||
@slot 菜单插槽
|
||||
@prop {boolean} status - 当前打开的状态
|
||||
-->
|
||||
<slot name="menu" :status="opened"></slot>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view :style="{backgroundColor:_borderColor,height:'1px'}"></view>
|
||||
</view>
|
||||
</template>
|
||||
<style>
|
||||
.noEventBySwitchSlider {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.xSwitchSilder {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
/* #ifdef WEB */
|
||||
cursor: grab;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
/* #ifdef WEB */
|
||||
.xSwitchSilder:active {
|
||||
cursor: grabbing;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
.xSwitchSilderWrap {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 2;
|
||||
right: 0px;
|
||||
transition-property: left;
|
||||
transition-duration: 0ms;
|
||||
}
|
||||
|
||||
.xSwitchSilderItemsWrap {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.xSwitchSilderItems {
|
||||
flex-shrink: 0;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
/* #ifdef WEB */
|
||||
cursor: pointer;
|
||||
/* #endif */
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user