qiaopengfei #12
|
@ -1,11 +1,20 @@
|
|||
import Vue from 'vue'
|
||||
import App from '../src/App.vue'
|
||||
|
||||
|
||||
//基于element组件封装,引入element组件库
|
||||
import { Input, Select } from 'element-ui';
|
||||
import { Input, Select, Option, OptionGroup, DatePicker, Tabs, TabPane, Pagination, Dialog, Button } from 'element-ui';
|
||||
import 'element-ui/lib/theme-chalk/index.css';
|
||||
Vue.use(Input);
|
||||
Vue.use(Select);
|
||||
Vue.use(OptionGroup);
|
||||
Vue.use(Option);
|
||||
Vue.use(DatePicker);
|
||||
Vue.use(Tabs);
|
||||
Vue.use(TabPane);
|
||||
Vue.use(Pagination)
|
||||
Vue.use(Dialog)
|
||||
Vue.use(Button)
|
||||
|
||||
// 导入组件库
|
||||
import erp_element_ui from '../packages'
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
import agDatePicker from './src'
|
||||
|
||||
// 为组件提供 install 安装方法,供按需引入
|
||||
agDatePicker.install = function (Vue) {
|
||||
Vue.component(agDatePicker.name, agDatePicker)
|
||||
}
|
||||
|
||||
// 导出组件
|
||||
export default agDatePicker
|
|
@ -0,0 +1,145 @@
|
|||
<template>
|
||||
<el-date-picker
|
||||
class="ag-date-picker"
|
||||
v-model="dateArr"
|
||||
v-bind="attrs"
|
||||
v-on="inputListeners"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* agDatePicker 时间选择器
|
||||
*/
|
||||
import isEmpty from "../../../src/utils/isEmpty";
|
||||
|
||||
export default {
|
||||
name: "agDatePicker",
|
||||
props: {
|
||||
value: {
|
||||
type: Array,
|
||||
default: () => [null, null],
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dateArr: [null, null],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
attrs() {
|
||||
return {
|
||||
size: "small",
|
||||
type: "daterange",
|
||||
format: "yyyy/MM/dd",
|
||||
"value-format": "yyyy-MM-dd",
|
||||
"start-placeholder": "开始日期",
|
||||
"end-placeholder": "结束日期",
|
||||
"range-separator": "-",
|
||||
"picker-options": {
|
||||
disabledDate(time) {
|
||||
return (
|
||||
time.getTime() >
|
||||
new Date(new Date().toLocaleDateString()).getTime() +
|
||||
24 * 60 * 60 * 1000 -
|
||||
1
|
||||
);
|
||||
},
|
||||
shortcuts: [
|
||||
{
|
||||
text: "本月",
|
||||
onClick(picker) {
|
||||
const end =
|
||||
new Date(new Date().toLocaleDateString()).getTime() +
|
||||
24 * 60 * 60 * 1000 -
|
||||
1;
|
||||
const time = new Date();
|
||||
time.setDate(1);
|
||||
time.setHours(0);
|
||||
time.setSeconds(0);
|
||||
time.setMinutes(0);
|
||||
var start = time.getTime();
|
||||
picker.$emit("pick", [start, end]);
|
||||
},
|
||||
},
|
||||
{
|
||||
text: "近一个月",
|
||||
onClick(picker) {
|
||||
const end = new Date();
|
||||
const start = new Date();
|
||||
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
|
||||
picker.$emit("pick", [start, end]);
|
||||
},
|
||||
},
|
||||
{
|
||||
text: "近三个月",
|
||||
onClick(picker) {
|
||||
const end = new Date();
|
||||
const start = new Date();
|
||||
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
|
||||
picker.$emit("pick", [start, end]);
|
||||
},
|
||||
},
|
||||
{
|
||||
text: "近六个月",
|
||||
onClick(picker) {
|
||||
const end = new Date();
|
||||
const start = new Date();
|
||||
start.setTime(start.getTime() - 3600 * 1000 * 24 * 180);
|
||||
picker.$emit("pick", [start, end]);
|
||||
},
|
||||
},
|
||||
{
|
||||
text: "最近一年",
|
||||
onClick(picker) {
|
||||
const end = new Date();
|
||||
const start = new Date();
|
||||
start.setTime(start.getTime() - 3600 * 1000 * 24 * 360);
|
||||
picker.$emit("pick", [start, end]);
|
||||
},
|
||||
},
|
||||
],
|
||||
}, //多选日期
|
||||
...this.$attrs,
|
||||
};
|
||||
},
|
||||
// 所有父级事件
|
||||
inputListeners() {
|
||||
return Object.assign({}, this.$listeners, {
|
||||
input: (value) => {
|
||||
let date1 = "";
|
||||
let date2 = "";
|
||||
|
||||
if (!isEmpty(value) && value.length === 2 && value[0] && value[1]) {
|
||||
date1 = `${value[0]} 00:00:00`;
|
||||
date2 = `${value[1]} 23:59:59`;
|
||||
}
|
||||
this.$emit("input", [date1, date2]);
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
value: {
|
||||
handler(newVal) {
|
||||
if (!Array.isArray(newVal)) {
|
||||
throw new Error("agDatePicker date请传入数组");
|
||||
}
|
||||
|
||||
let [date1, date2] = newVal;
|
||||
if (!this.dateArr) {
|
||||
this.dateArr = [date1 || "", date2 || ""];
|
||||
return;
|
||||
}
|
||||
this.$set(this.dateArr, 0, date1 || "");
|
||||
this.$set(this.dateArr, 1, date2 || "");
|
||||
},
|
||||
immediate: true,
|
||||
deep: true,
|
||||
},
|
||||
},
|
||||
methods: {},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
|
@ -0,0 +1,9 @@
|
|||
import agDialog from './src'
|
||||
|
||||
// 为组件提供 install 安装方法,供按需引入
|
||||
agDialog.install = function (Vue) {
|
||||
Vue.component(agDialog.name, agDialog)
|
||||
}
|
||||
|
||||
// 导出组件
|
||||
export default agDialog
|
|
@ -0,0 +1,91 @@
|
|||
<template>
|
||||
<el-dialog
|
||||
class="ag-dialog"
|
||||
:title="$slots.title ? '' : title"
|
||||
:visible.sync="show"
|
||||
:custom="custom"
|
||||
v-bind="attrs"
|
||||
v-on="$listeners"
|
||||
>
|
||||
<!-- 有写弹窗头部则采用输入的 -->
|
||||
<template v-if="$slots.title">
|
||||
<span slot="title">
|
||||
<slot name="title" />
|
||||
</span>
|
||||
</template>
|
||||
<!-- 弹窗内容区域 -->
|
||||
<slot />
|
||||
<!-- 默认底部 -->
|
||||
<template v-if="!$slots.footer && custom">
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button class="btn" size="small" @click="cancel">取消</el-button>
|
||||
<el-button class="btn sure" size="small" type="primary" @click="submit"
|
||||
>确定</el-button
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
<!-- 弹窗底部区域,可自定义 -->
|
||||
<template v-if="$slots.footer">
|
||||
<span slot="footer">
|
||||
<slot name="footer" />
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
//没有输入slot=title的时候,就使用自定义的shot=title
|
||||
export default {
|
||||
name: "agDialog",
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
custom: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
attrs() {
|
||||
return {
|
||||
width: "30%",
|
||||
top: "15vh",
|
||||
boolean: "dialog",
|
||||
"show-close": false,
|
||||
"append-to-body": true,
|
||||
"modal-append-to-body": true,
|
||||
"destroy-on-close": true,
|
||||
...this.$attrs,
|
||||
};
|
||||
},
|
||||
show: {
|
||||
get() {
|
||||
return this.visible;
|
||||
},
|
||||
set(val) {
|
||||
this.$emit("update:visible", val); // visible 改变的时候通知父组件
|
||||
},
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
methods: {
|
||||
cancel() {
|
||||
this.$emit("cancel");
|
||||
},
|
||||
submit() {
|
||||
this.$emit("submit");
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped >
|
||||
</style>
|
|
@ -68,5 +68,7 @@ export default {
|
|||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
<style lang="scss" scoped>
|
||||
@import url("~@/static/index.scss");
|
||||
</style>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
import agNumberRange from './src'
|
||||
|
||||
// 为组件提供 install 安装方法,供按需引入
|
||||
agNumberRange.install = function (Vue) {
|
||||
Vue.component(agNumberRange.name, agNumberRange)
|
||||
}
|
||||
|
||||
// 导出组件
|
||||
export default agNumberRange
|
|
@ -0,0 +1,118 @@
|
|||
<template>
|
||||
<div class="ag-number-range">
|
||||
<el-input
|
||||
:style="{ width: width + 'px' }"
|
||||
:size="size"
|
||||
v-model="startValue"
|
||||
@input="handleStartInput"
|
||||
@blur="handleInputBlur"
|
||||
></el-input>
|
||||
<span class="separator">{{ rangeSeparator }}</span>
|
||||
<el-input
|
||||
:style="{ width: width + 'px' }"
|
||||
:size="size"
|
||||
v-model="endValue"
|
||||
@input="handleEndInput"
|
||||
@blur="handleInputBlur"
|
||||
></el-input>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* NumberRange
|
||||
* 数值范围
|
||||
*/
|
||||
export default {
|
||||
name: "agNumberRange",
|
||||
|
||||
model: {
|
||||
prop: "value",
|
||||
event: "change",
|
||||
},
|
||||
|
||||
props: {
|
||||
// 绑定的value
|
||||
value: {
|
||||
type: Array,
|
||||
default: function () {
|
||||
return [];
|
||||
},
|
||||
},
|
||||
|
||||
// 分隔符
|
||||
rangeSeparator: {
|
||||
type: String,
|
||||
default: "-",
|
||||
},
|
||||
|
||||
// 输入框宽度
|
||||
width: {
|
||||
type: [Number, String],
|
||||
default: "50",
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default: "small",
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 开始数值
|
||||
startValue: "",
|
||||
// 结束数值
|
||||
endValue: "",
|
||||
};
|
||||
},
|
||||
comments: {
|
||||
|
||||
},
|
||||
watch: {
|
||||
value(newValue) {
|
||||
if (Array.isArray(newValue)) {
|
||||
this.startValue = newValue[0];
|
||||
this.endValue = newValue[1];
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* 输入框失去焦点
|
||||
* @emit change
|
||||
*/
|
||||
handleInputBlur() {
|
||||
this.$emit("change", [this.startValue, this.endValue]);
|
||||
},
|
||||
|
||||
/**
|
||||
* 监听start值
|
||||
* @param e 当前值
|
||||
*/
|
||||
handleStartInput(e) {
|
||||
this.startValue = this.formatValue(e);
|
||||
},
|
||||
|
||||
/**
|
||||
* 监听end值
|
||||
* @param e 当前值
|
||||
*/
|
||||
handleEndInput(e) {
|
||||
this.endValue = this.formatValue(e);
|
||||
},
|
||||
|
||||
/**
|
||||
* 格式化输入, 只能输入数字 和 .
|
||||
* @param v
|
||||
* @return {*}
|
||||
*/
|
||||
formatValue(v) {
|
||||
const reg = /[^\d|.]/g;
|
||||
return v.replace(reg, "");
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
|
@ -0,0 +1,9 @@
|
|||
import agPagination from './src'
|
||||
|
||||
// 为组件提供 install 安装方法,供按需引入
|
||||
agPagination.install = function (Vue) {
|
||||
Vue.component(agPagination.name, agPagination)
|
||||
}
|
||||
|
||||
// 导出组件
|
||||
export default agPagination
|
|
@ -0,0 +1,36 @@
|
|||
<template>
|
||||
<el-pagination class="ag-pagination" v-bind="attrs" v-on="$listeners">
|
||||
</el-pagination>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: "agPagination",
|
||||
props: {
|
||||
tabsData: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
return [];
|
||||
},
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
computed: {
|
||||
attrs() {
|
||||
return {
|
||||
total: 0,
|
||||
"page-size": 20,
|
||||
"current-page": 1,
|
||||
"page-sizes": [20, 50, 100, 200],
|
||||
layout: "total, sizes, prev, pager, next, jumper",
|
||||
...this.$attrs,
|
||||
};
|
||||
},
|
||||
},
|
||||
methods: {},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
</style>
|
|
@ -2,23 +2,22 @@
|
|||
<el-select
|
||||
class="ag_select"
|
||||
:style="{ width }"
|
||||
:value="value"
|
||||
:size="size"
|
||||
v-on="inputListeners"
|
||||
v-bind="attrs"
|
||||
v-on="inputListeners"
|
||||
>
|
||||
<slot />
|
||||
<slot name="prefix" slot="prefix" />
|
||||
<slot name="empty" slot="empty" />
|
||||
<el-option
|
||||
v-for="(item, index) in options"
|
||||
:key="index"
|
||||
v-for="item in options"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
></el-option>
|
||||
<!-- <slot name="options" slot="options" /> -->
|
||||
</el-select>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import cloneDeep from "../../../src/utils/cloneDeep";
|
||||
export default {
|
||||
name: "agSelect",
|
||||
props: {
|
||||
|
@ -26,29 +25,25 @@ export default {
|
|||
type: String,
|
||||
default: "",
|
||||
},
|
||||
value: {
|
||||
type: String,
|
||||
default: "",
|
||||
options: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
return [];
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default: "small",
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
model: "",
|
||||
options: [],
|
||||
};
|
||||
return {};
|
||||
},
|
||||
computed: {
|
||||
attrs() {
|
||||
if (this.$attrs["remote-method"]) {
|
||||
let obj = cloneDeep(this.$attrs);
|
||||
Reflect.deleteProperty(obj, "remote-method");
|
||||
return { ...obj, clearable: true, filterable: true, remote: true };
|
||||
}
|
||||
return false;
|
||||
return {
|
||||
size: "small",
|
||||
remote: true,
|
||||
clearable: true,
|
||||
filterable: true,
|
||||
...this.$attrs,
|
||||
};
|
||||
},
|
||||
// 所有父级事件
|
||||
inputListeners() {
|
||||
|
@ -76,26 +71,7 @@ export default {
|
|||
);
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
value: {
|
||||
immediate: true,
|
||||
handler(newVal) {
|
||||
this.removeMethod(newVal);
|
||||
this.model = newVal;
|
||||
},
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
async removeMethod(keywords) {
|
||||
if (this.$attrs["remote-method"]) {
|
||||
let opts = await this.$attrs["remote-method"](keywords);
|
||||
this.options = opts;
|
||||
}
|
||||
},
|
||||
handleChange(value) {
|
||||
this.$emit("input", value);
|
||||
},
|
||||
},
|
||||
methods: {},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
import agTabs from './src'
|
||||
|
||||
// 为组件提供 install 安装方法,供按需引入
|
||||
agTabs.install = function (Vue) {
|
||||
Vue.component(agTabs.name, agTabs)
|
||||
}
|
||||
|
||||
// 导出组件
|
||||
export default agTabs
|
|
@ -0,0 +1,43 @@
|
|||
<template>
|
||||
<el-tabs class="ag-tabs" v-bind="$attrs" v-on="$listeners">
|
||||
<slot v-if="!tabsData.length" name="default" />
|
||||
<el-tab-pane
|
||||
v-else
|
||||
v-for="(item, index) in tabsData"
|
||||
:key="index"
|
||||
:name="item.name"
|
||||
:lazy="item.lazy || false"
|
||||
:disabled="item.disabled || false"
|
||||
:closable="item.closable || false"
|
||||
>
|
||||
<template #label>
|
||||
<span>
|
||||
{{ item.label }}
|
||||
<i :class="item.icon"></i>
|
||||
<span v-if="item.remark" class="remark">{{ item.remark }}</span>
|
||||
</span>
|
||||
</template>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: "agTabs",
|
||||
props: {
|
||||
tabsData: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
return [];
|
||||
},
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
computed: {},
|
||||
methods: {},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
</style>
|
162
src/App.vue
162
src/App.vue
|
@ -1,39 +1,157 @@
|
|||
<template>
|
||||
<div>
|
||||
<agSelect ref="ref_Pedestal" :value="value" @input="changeInput">
|
||||
</agSelect>
|
||||
<el-button type="text" @click="abb = true">点击打开 Dialog</el-button>
|
||||
<agTabs ref="ref_Pedestal" :visible.sync="abb">
|
||||
<!-- <span slot="footer">房价大降分类数据</span> -->
|
||||
</agTabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import agSelect from "../packages/agSelect/src/index";
|
||||
import agTabs from "../packages/agDialog/src/index.vue";
|
||||
export default {
|
||||
components: { agSelect },
|
||||
components: { agTabs },
|
||||
data() {
|
||||
return {
|
||||
value: "",
|
||||
options: [{
|
||||
value: '选项1',
|
||||
label: '黄金糕'
|
||||
}, {
|
||||
value: '选项2',
|
||||
label: '双皮奶'
|
||||
}, {
|
||||
value: '选项3',
|
||||
label: '蚵仔煎'
|
||||
}, {
|
||||
value: '选项4',
|
||||
label: '龙须面'
|
||||
}, {
|
||||
value: '选项5',
|
||||
label: '北京烤鸭'
|
||||
}],
|
||||
options: [
|
||||
{
|
||||
label: "热门城市",
|
||||
options: [
|
||||
{
|
||||
value: "Shanghai",
|
||||
label: "上海",
|
||||
},
|
||||
{
|
||||
value: "Beijing",
|
||||
label: "北京",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "城市名",
|
||||
options: [
|
||||
{
|
||||
value: "Chengdu",
|
||||
label: "成都",
|
||||
},
|
||||
{
|
||||
value: "Shenzhen",
|
||||
label: "深圳",
|
||||
},
|
||||
{
|
||||
value: "Guangzhou",
|
||||
label: "广州",
|
||||
},
|
||||
{
|
||||
value: "Dalian",
|
||||
label: "大连",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
pickerOptions: {
|
||||
shortcuts: [
|
||||
{
|
||||
text: "最近一周",
|
||||
onClick(picker) {
|
||||
const end = new Date();
|
||||
const start = new Date();
|
||||
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
|
||||
picker.$emit("pick", [start, end]);
|
||||
},
|
||||
},
|
||||
{
|
||||
text: "最近一个月",
|
||||
onClick(picker) {
|
||||
const end = new Date();
|
||||
const start = new Date();
|
||||
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
|
||||
picker.$emit("pick", [start, end]);
|
||||
},
|
||||
},
|
||||
{
|
||||
text: "最近三个月",
|
||||
onClick(picker) {
|
||||
const end = new Date();
|
||||
const start = new Date();
|
||||
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
|
||||
picker.$emit("pick", [start, end]);
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
tabsData: [
|
||||
{
|
||||
label: "全部",
|
||||
icon: "el-icon-phone",
|
||||
disabled: true,
|
||||
remark: "99",
|
||||
name: "0",
|
||||
total: 0,
|
||||
},
|
||||
{
|
||||
label: "全部",
|
||||
icon: "el-icon-phone",
|
||||
remark: "99",
|
||||
name: "100",
|
||||
total: 0,
|
||||
},
|
||||
{
|
||||
label: "全部",
|
||||
icon: "el-icon-phone",
|
||||
remark: "99",
|
||||
name: "2",
|
||||
total: 0,
|
||||
},
|
||||
{
|
||||
label: "全部",
|
||||
icon: "el-icon-phone",
|
||||
remark: "99",
|
||||
name: "3",
|
||||
total: 0,
|
||||
},
|
||||
{
|
||||
label: "全部",
|
||||
icon: "el-icon-phone",
|
||||
remark: "99",
|
||||
name: "4",
|
||||
total: 0,
|
||||
},
|
||||
],
|
||||
abb: false,
|
||||
innerVisible: false,
|
||||
// options: [
|
||||
// {
|
||||
// value: "选项1",
|
||||
// label: "黄金糕",
|
||||
// },
|
||||
// {
|
||||
// value: "选项2",
|
||||
// label: "双皮奶",
|
||||
// },
|
||||
// {
|
||||
// value: "选项3",
|
||||
// label: "蚵仔煎",
|
||||
// },
|
||||
// {
|
||||
// value: "选项4",
|
||||
// label: "龙须面",
|
||||
// },
|
||||
// {
|
||||
// value: "选项5",
|
||||
// label: "北京烤鸭",
|
||||
// },
|
||||
// ],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
changeInput() {
|
||||
// console.log(this.value);
|
||||
handleClick() {
|
||||
console.log(1111);
|
||||
},
|
||||
handleSizeChange() {},
|
||||
handleCurrentChange() {},
|
||||
handleClose() {},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -0,0 +1,267 @@
|
|||
// 当超过n行时,显示省略号
|
||||
@mixin elln($n) {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: $n;
|
||||
}
|
||||
// 清除浮动
|
||||
.clearfix {
|
||||
& after {
|
||||
display: table;
|
||||
clear: both;
|
||||
content: "";
|
||||
}
|
||||
}
|
||||
// 垂直居中 未知父元素高度 父元素需position: relative;
|
||||
@mixin cj1 {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
@mixin cj2 {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
-ms-transform: translateY(-50%); /* IE 9 */
|
||||
-moz-transform: translateY(-50%); /* Firefox */
|
||||
-webkit-transform: translateY(-50%); /* Safari 和 Chrome */
|
||||
-o-transform: translateY(-50%); /* Opera */
|
||||
}
|
||||
|
||||
@mixin cjf {
|
||||
display: flex; /*谷歌,火狐等新版本*/
|
||||
display: -webkit-box; /*安卓低版本*/
|
||||
display: -moz-box; /*火狐低版本*/
|
||||
display: -ms-flexbox; /*IE版本*/
|
||||
display: -webkit-flex; /*谷歌*/
|
||||
align-items: center;
|
||||
-webkit-box-align: center;
|
||||
-moz-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
-webkit-align-items: center;
|
||||
}
|
||||
|
||||
@mixin sj1 {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: auto;
|
||||
}
|
||||
@mixin sj2 {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
-ms-transform: translateX(-50%); /* IE 9 */
|
||||
-moz-transform: translateX(-50%); /* Firefox */
|
||||
-webkit-transform: translateX(-50%); /* Safari 和 Chrome */
|
||||
-o-transform: translateX(-50%); /* Opera */
|
||||
}
|
||||
@mixin sjf {
|
||||
display: flex; /*谷歌,火狐等新版本*/
|
||||
display: -webkit-box; /*安卓低版本*/
|
||||
display: -moz-box; /*火狐低版本*/
|
||||
display: -ms-flexbox; /*IE版本*/
|
||||
display: -webkit-flex; /*谷歌*/
|
||||
justify-content: center;
|
||||
-webkit-box-pack: center;
|
||||
-moz-box-pack: center;
|
||||
-ms-flex-pack: center;
|
||||
-webkit-justify-content: center;
|
||||
}
|
||||
|
||||
// 清除默认样式开始
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
}
|
||||
html,
|
||||
body,
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6,
|
||||
div,
|
||||
dl,
|
||||
dt,
|
||||
dd,
|
||||
ul,
|
||||
ol,
|
||||
li,
|
||||
p,
|
||||
blockquote,
|
||||
pre,
|
||||
hr,
|
||||
figure,
|
||||
table,
|
||||
caption,
|
||||
th,
|
||||
td,
|
||||
form,
|
||||
fieldset,
|
||||
legend,
|
||||
input,
|
||||
button,
|
||||
textarea,
|
||||
menu {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
header,
|
||||
footer,
|
||||
section,
|
||||
article,
|
||||
aside,
|
||||
nav,
|
||||
hgroup,
|
||||
address,
|
||||
figure,
|
||||
figcaption,
|
||||
menu,
|
||||
details {
|
||||
display: block;
|
||||
}
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
caption,
|
||||
th {
|
||||
text-align: left;
|
||||
font-weight: normal;
|
||||
}
|
||||
html,
|
||||
body,
|
||||
fieldset,
|
||||
img,
|
||||
iframe,
|
||||
abbr {
|
||||
border: 0;
|
||||
}
|
||||
i,
|
||||
cite,
|
||||
em,
|
||||
var,
|
||||
address,
|
||||
dfn {
|
||||
font-style: normal;
|
||||
}
|
||||
[hidefocus],
|
||||
summary {
|
||||
outline: 0;
|
||||
}
|
||||
li {
|
||||
list-style: none;
|
||||
}
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6,
|
||||
small {
|
||||
font-size: 100%;
|
||||
}
|
||||
sup,
|
||||
sub {
|
||||
font-size: 83%;
|
||||
}
|
||||
pre,
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-family: inherit;
|
||||
}
|
||||
q:before,
|
||||
q:after {
|
||||
content: none;
|
||||
}
|
||||
textarea {
|
||||
overflow: auto;
|
||||
resize: none;
|
||||
}
|
||||
label,
|
||||
summary {
|
||||
cursor: default;
|
||||
}
|
||||
a,
|
||||
button {
|
||||
cursor: pointer;
|
||||
}
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6,
|
||||
em,
|
||||
strong,
|
||||
b {
|
||||
font-weight: bold;
|
||||
}
|
||||
del,
|
||||
ins,
|
||||
u,
|
||||
s,
|
||||
a,
|
||||
a:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
body,
|
||||
textarea,
|
||||
input,
|
||||
button,
|
||||
select,
|
||||
keygen,
|
||||
legend {
|
||||
font: 12px/1.14 Microsoft YaHei, arial, \5b8b\4f53;
|
||||
color: #333;
|
||||
outline: 0;
|
||||
}
|
||||
body {
|
||||
background: #fff;
|
||||
}
|
||||
a,
|
||||
a:hover {
|
||||
color: #333;
|
||||
}
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
// 清除默认样式结束
|
||||
// 滚动条美化
|
||||
@media screen and (min-width: 768px) {
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 9px;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
border-radius: 5px;
|
||||
background-color: #C1C1C1;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background-color: #A8A8A8;
|
||||
}
|
||||
|
||||
/* 小型尺寸 */
|
||||
.mini-bar::-webkit-scrollbar {
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
}
|
||||
|
||||
.mini-bar::-webkit-scrollbar-thumb {
|
||||
border-radius: 3px;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
export default function isEmpty(value) {
|
||||
// 首先,检查null和undefined
|
||||
if (value == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 检查数字、字符串和布尔值(非空字符串、非零数字和非false值被视为非空)
|
||||
if (typeof value === 'number' || typeof value === 'string' || typeof value === 'boolean') {
|
||||
return !value;
|
||||
}
|
||||
|
||||
// 检查对象、数组和函数
|
||||
if (typeof value === 'object' || typeof value === 'function') {
|
||||
// 使用Object.keys()来获取对象自身的所有属性键组成的数组
|
||||
// 然后检查这个数组的长度是否为0
|
||||
// 注意:对于数组和函数,这同样适用,因为它们在JavaScript中也是对象
|
||||
return Object.keys(value).length === 0;
|
||||
}
|
||||
|
||||
// 如果以上条件都不满足,那么可能是一个特殊的对象(如RegExp, Date等)
|
||||
// 在这里,我们假设这些都不是“空”的,除非你有特定的需求来处理它们
|
||||
// 但按照lodash的`_.isEmpty`的逻辑,这些通常被视为非空
|
||||
return false;
|
||||
}
|
Loading…
Reference in New Issue