[TOC]
## 全局工具
* 新建目录`/src/utils`
### 新建文件`/src/utils/util.js`
```javascript
export function timeFix() {
const time = new Date()
const hour = time.getHours()
return hour < 9 ? '早上好' : hour <= 11 ? '上午好' : hour <= 13 ? '中午好' : hour < 20 ? '下午好' : '晚上好'
}
export function welcome() {
const arr = ['休息一会儿吧', '准备吃什么呢?', '要不要打一把 王者荣耀', '我猜你可能累了']
const index = Math.floor(Math.random() * arr.length)
return arr[index]
}
/**
* 触发 window.resize
*/
export function triggerWindowResizeEvent() {
const event = document.createEvent('HTMLEvents')
event.initEvent('resize', true, true)
event.eventType = 'message'
window.dispatchEvent(event)
}
export function handleScrollHeader(callback) {
let timer = 0
let beforeScrollTop = window.pageYOffset
callback = callback || function () {
}
window.addEventListener(
'scroll',
event => {
clearTimeout(timer)
timer = setTimeout(() => {
let direction = 'up'
const afterScrollTop = window.pageYOffset
const delta = afterScrollTop - beforeScrollTop
if (delta === 0) {
return false
}
direction = delta > 0 ? 'down' : 'up'
callback(direction)
beforeScrollTop = afterScrollTop
}, 50)
},
false
)
}
export function isIE() {
const bw = window.navigator.userAgent
const compare = (s) => bw.indexOf(s) >= 0
const ie11 = (() => 'ActiveXObject' in window)()
return compare('MSIE') || ie11
}
/**
* Remove loading animate
* @param id parent element id or class
* @param timeout
*/
export function removeLoadingAnimate(id = '', timeout = 1500) {
if (id === '') {
return
}
setTimeout(() => {
document.body.removeChild(document.getElementById(id))
}, timeout)
}
// 节流
// 思路: 第一次先设定一个变量true,
// 第二次执行这个函数时,会判断变量是否true,
// 是则返回。当第一次的定时器执行完函数最后会设定变量为flase。
// 那么下次判断变量时则为flase,函数会依次运行。
export function throttle(fn, delay = 100) {
// 首先设定一个变量,在没有执行我们的定时器时为null
var timer = null
return function () {
// 当我们发现这个定时器存在时,则表示定时器已经在运行中,需要返回
if (timer) return
timer = setTimeout(() => {
fn.apply(this, arguments)
timer = null
}, delay)
}
}
// 防抖
// 首次运行时把定时器赋值给一个变量, 第二次执行时,
// 如果间隔没超过定时器设定的时间则会清除掉定时器,
// 重新设定定时器, 依次反复, 当我们停止下来时,
// 没有执行清除定时器, 超过一定时间后触发回调函数。
export function debounce(fun, delay) {
return function (args) {
// 获取函数的作用域和变量
const that = this
const _args = args
// 每次事件被触发,都会清除当前的timeer,然后重写设置超时调用
clearTimeout(fun.id)
fun.id = setTimeout(function () {
fun.call(that, _args)
}, delay)
}
}
/**
* 判断是否为空对象
* @param {*} object 源对象
*/
export function isEmptyObject(object) {
return Object.keys(object).length === 0
}
/**
* 判断是否为对象
* @param {*} object
*/
export function isObject(object) {
return Object.prototype.toString.call(object) === '[object Object]'
}
/**
* 判断是否为对象
* @param {*} array
*/
export function isArray(array) {
return Object.prototype.toString.call(array) === '[object Array]'
}
/**
* 判断是否为空
* @param {*} object 源对象
*/
export function isEmpty(value) {
if (isArray(value)) {
return value.length === 0
}
if (isObject(value)) {
return isEmptyObject(value)
}
return !value
}
/**
* 判断是否在数组中
* @param {*} search
* @param {*} array
*/
export function inArray(search, array) {
return array.includes(search)
}
/**
* 获取指定天数的日期
* @param day
* @returns {string}
*/
export function getDateByDay(day) {
var today = new Date()
var targetdaySeconds = today.getTime() + 1000 * 60 * 60 * 24 * day
today.setTime(targetdaySeconds) // 注意,这行是关键代码
return today.getFullYear() + '-' + zeroFillLeft(today.getMonth() + 1) + '-' + zeroFillLeft(today.getDate())
}
/**
* 左侧补0
* @param value
* @returns {*}
*/
export function zeroFillLeft(value) {
return (value.toString().length === 1) ? ('0' + value) : value
}
/**
* 批量给指定对象赋值
* @param obj obj 指定的对象,一般为vue实例
* @param obj assignment 赋值的元素 { a: '123' }
*/
export function assignment(obj, assignment) {
Object.keys(assignment).forEach(key => {
obj[key] = assignment[key]
})
}
```
## 全局样式
### 新建文件`/src/utils/util.less`
```less
.textOverflow() {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
word-break: break-all;
}
.textOverflowMulti(@line: 2, @bg: #fff) {
position: relative;
max-height: @line * 1.5em;
margin-right: -1em;
padding-right: 1em;
overflow: hidden;
line-height: 1.5em;
text-align: justify;
&::before {
position: absolute;
right: 14px;
bottom: 0;
padding: 0 1px;
background: @bg;
content: '...';
}
&::after {
position: absolute;
right: 14px;
width: 1em;
height: 1em;
margin-top: 0.2em;
background: white;
content: '';
}
}
// 文字超出隐藏(一行)
// 需要设置文字容器的宽度
.oneline-hide {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
word-break: break-all;
}
// 文字超出隐藏(两行)
// 需要设置文字容器的宽度
.twoline-hide {
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
white-space: normal;
}
// 动画
@keyframes fadenum {
/*设置内容由显示变为隐藏*/
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
/* 浮动 */
.clearfix() {
zoom: 1;
&::before,
&::after {
display: table;
content: ' ';
}
&::after {
clear: both;
height: 0;
font-size: 0;
visibility: hidden;
}
}
.fl-l {
float: left;
}
.fl-r {
float: right;
}
/* flex布局 */
.flex {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
}
.flex-box {
flex: 1;
}
.flex-dir-row {
flex-direction: row;
}
.flex-dir-column {
-webkit-box-orient: vertical;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
}
.flex-x-center {
-webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
}
.flex-x-between {
-webkit-box-pack: justify;
-webkit-justify-content: space-between;
-ms-flex-pack: justify;
justify-content: space-between;
}
.flex-x-around {
justify-content: space-around;
}
.flex-x-end {
-webkit-box-pack: end;
-ms-flex-pack: end;
-webkit-justify-content: flex-end;
justify-content: flex-end;
}
.flex-y-center {
-webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
}
/* 全局函数 */
.hiden {
display: none;
}
// 手型指针
.cur-p {
cursor: pointer;
user-select: none;
}
// 外边距
.mt-5 {
margin-top: 5px;
}
.mt-10 {
margin-top: 10px;
}
.mt-15 {
margin-top: 20px;
}
.mt-20 {
margin-top: 20px !important;
}
.mt-30 {
margin-top: 30px;
}
.mt-40 {
margin-top: 40px;
}
.mt-50 {
margin-top: 50px;
}
.mb-0 {
margin-bottom: 0 !important;
}
.mb-5 {
margin-bottom: 5px !important;
}
.mb-10 {
margin-bottom: 10px;
}
.mb-15 {
margin-bottom: 15px;
}
.ml-5 {
margin-left: 5px;
}
.ml-10 {
margin-left: 10px;
}
.mr-5 {
margin-right: 5px;
}
.mr-10 {
margin-right: 10px;
}
.mr-20 {
margin-right: 20px;
}
.mlr-2 {
margin-left: 2px;
margin-right: 2px;
}
.mtb-2 {
margin-top: 2px;
margin-bottom: 2px;
}
// 文字颜色
.c-p {
color: #1890ff !important;
}
.c-muted-1 {
color: #7b7b7b;
}
// 字体大小
.f-12 {
font-size: 12px;
}
.f-13 {
font-size: 13px;
}
.f-w-b {
font-weight: bold;
}
// 删除线
.f-through {
text-decoration: line-through;
}
```
### 新建文件`/src/global.less`
```less
@import './utils/utils.less';
// 滚动条样式
::-webkit-scrollbar {
width: 6px;
height: 6px;
}
::-webkit-scrollbar-thumb {
border-radius: 10px;
background-color: #bdbdbd;
-webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, .3);
}
html,
body,
#app,
#root {
height: 100%;
}
iframe {
border: 0;
}
p {
// margin: 0 !important
margin: 0
}
.colorWeak {
filter: invert(80%);
}
.ant-layout.layout-basic {
height: 100vh;
min-height: 100vh;
}
canvas {
display: block;
}
body {
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
ul,
ol {
list-style: none;
}
// 数据列表 样式
.table-alert {
margin-bottom: 16px;
}
// 数据列表 操作
.table-operator {
margin-bottom: 18px;
.search-btn {
margin-right: 8px;
}
}
// 数据列表 搜索条件
.table-page-search-wrapper {
.ant-form-inline {
.ant-form-item {
display: flex;
margin-bottom: 24px;
margin-right: 0;
.ant-form-item-control-wrapper {
flex: 1 1;
display: inline-block;
vertical-align: middle;
}
> .ant-form-item-label {
line-height: 32px;
padding-right: 8px;
width: auto;
}
.ant-form-item-control {
height: 32px;
line-height: 32px;
}
}
}
.table-page-search-submitButtons {
display: block;
margin-bottom: 24px;
white-space: nowrap;
}
}
// 内容页card组件标题
.card-title {
font-size: 16px;
margin-bottom: 16px;
color: rgba(0, 0, 0, 0.75);
}
// 图标按钮样式
.ant-btn > .anticon + span,
.ant-btn > span + .anticon {
margin-left: 5px;
}
// 表单
.ant-form {
.ant-form-explain,
.ant-form-extra {
font-size: 13px;
}
.form-item-help {
font-size: 12px;
// line-height: 2;
line-height: 1.5;
padding-top: 4px;
min-height: 22px;
margin-top: -2px;
transition: color 0.3s cubic-bezier(0.215, 0.61, 0.355, 1);
a {
margin: 0 3px;
}
p.extra,
small {
color: rgba(0, 0, 0, 0.45);
font-size: 13px !important;
}
p.extra {
margin-bottom: 5px;
}
}
}
// 级联选择器
.ant-cascader-menu {
height: 225px;
}
// 分割线
.ant-divider {
margin: 30px 0 !important;
.ant-divider-inner-text {
font-size: 13px;
color: rgba(0, 0, 0, 0.61);
}
}
.ant-divider-horizontal.ant-divider-with-text-left::before {
width: 5%;
}
//# 兼容外部样式
// ueditor
.edui-default {
.edui-editor {
// z-index: 2 !important;
font-size: 14px;
line-height: normal;
border-radius: 0;
-webkit-border-radius: 0;
-moz-border-radius: 0;
pre {
overflow: unset;
}
}
.edui-editor-toolbarboxouter {
box-shadow: unset;
background-image: linear-gradient(to bottom, #ffffff, #fbfbfb);
}
.edui-editor-toolbarbox {
box-shadow: unset;
}
// 自定义图片按钮
.edui-for-image-button .edui-icon {
background-position: -380px 0px;
}
}
// ## 自定义模块 ##
.ant-table {
// 操作栏 项目间距
.actions > a {
margin-right: 8px;
&:last-child {
margin-right: 0;
}
}
}
// 搜索表单
.search-form {
margin-bottom: 5px;
.ant-form-item {
margin-bottom: 10px;
}
.ant-form-item-control-wrapper {
min-width: 220px;
}
.search-btn {
.ant-form-item-control-wrapper {
width: auto;
min-width: auto;
}
}
}
// 列表页-操作按钮组
.row-item-tab {
& > button {
margin-right: 5px;
}
}
// 无边框的modal
.ant-modal-root {
&.noborder {
.ant-modal-header {
border-bottom: none;
}
.ant-modal-footer {
border-top: none;
}
.ant-modal-body {
padding: 5px 24px 15px 24px;
}
}
}
// 表格不允许换行
.ant-table {
td,
th {
white-space: nowrap;
}
}
// Alert 警告提示 (banner)
.ant-alert-banner {
margin-bottom: 15px;
padding-left: 40px;
.ant-alert-message {
font-size: 13px;
}
// 黄色警告
&.ant-alert-warning {
background-color: #fffcee;
border: 1px solid #fff0c1;
}
// 标题+描述
&.ant-alert-with-description {
padding-left: 55px;
.ant-alert-icon {
font-size: 18px;
top: 16px;
left: 25px;
}
.ant-alert-message {
font-size: 14px;
margin-bottom: 6px;
// margin-bottom: 0;
}
.ant-alert-description {
font-size: 12.3px;
}
}
}
```
## 在`/src/main.js`中引入全局样式
```javascript
import './global.less`
```