qiaopengfei #12
|
@ -2,10 +2,13 @@ import Vue from 'vue'
|
|||
import App from '../src/App.vue'
|
||||
|
||||
//基于element组件封装,引入element组件库
|
||||
import { Input, Select } from 'element-ui';
|
||||
import { Input, Select, Option, OptionGroup, DatePicker } 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);
|
||||
|
||||
// 导入组件库
|
||||
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,141 @@
|
|||
<template>
|
||||
<el-date-picker
|
||||
class="ag-date-picker"
|
||||
v-model="dateArr"
|
||||
v-bind="attrs"
|
||||
@change="dataChange"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* agDatePicker 时间选择器
|
||||
*/
|
||||
import isEmpty from "../../../src/utils/isEmpty";
|
||||
|
||||
export default {
|
||||
name: "agDatePicker",
|
||||
props: {
|
||||
value: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dateArr: ["", ""],
|
||||
};
|
||||
},
|
||||
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,
|
||||
};
|
||||
},
|
||||
},
|
||||
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: {
|
||||
dataChange(val) {
|
||||
let date1 = "";
|
||||
let date2 = "";
|
||||
|
||||
if (!isEmpty(val) && val.length === 2 && val[0] && val[1]) {
|
||||
date1 = `${val[0]} 00:00:00`;
|
||||
date2 = `${val[1]} 23:59:59`;
|
||||
}
|
||||
this.$emit("input", [date1, date2]);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></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>
|
|
@ -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: "",
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default: "small",
|
||||
options: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
return [];
|
||||
},
|
||||
},
|
||||
},
|
||||
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,23 @@
|
|||
<template>
|
||||
<el-tabs class="ag-tabs" v-on="$listeners" v-bind="attrs"> </el-tabs>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "agTabs",
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
computed: {
|
||||
attrs() {
|
||||
return {
|
||||
...this.$attrs,
|
||||
};
|
||||
},
|
||||
},
|
||||
methods: {},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang='scss'>
|
||||
</style>
|
115
src/App.vue
115
src/App.vue
|
@ -1,33 +1,106 @@
|
|||
<template>
|
||||
<div>
|
||||
<agSelect ref="ref_Pedestal" :value="value" @input="changeInput">
|
||||
</agSelect>
|
||||
<agDatePicker ref="ref_Pedestal" v-model="value" @blur="changeInput" >
|
||||
</agDatePicker>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import agSelect from "../packages/agSelect/src/index";
|
||||
import agDatePicker from "../packages/agDatePicker/src/index.vue";
|
||||
export default {
|
||||
components: { agSelect },
|
||||
components: { agDatePicker },
|
||||
data() {
|
||||
return {
|
||||
value: "",
|
||||
options: [{
|
||||
value: '选项1',
|
||||
label: '黄金糕'
|
||||
}, {
|
||||
value: '选项2',
|
||||
label: '双皮奶'
|
||||
}, {
|
||||
value: '选项3',
|
||||
label: '蚵仔煎'
|
||||
}, {
|
||||
value: '选项4',
|
||||
label: '龙须面'
|
||||
}, {
|
||||
value: '选项5',
|
||||
label: '北京烤鸭'
|
||||
}],
|
||||
value: [],
|
||||
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]);
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
// options: [
|
||||
// {
|
||||
// value: "选项1",
|
||||
// label: "黄金糕",
|
||||
// },
|
||||
// {
|
||||
// value: "选项2",
|
||||
// label: "双皮奶",
|
||||
// },
|
||||
// {
|
||||
// value: "选项3",
|
||||
// label: "蚵仔煎",
|
||||
// },
|
||||
// {
|
||||
// value: "选项4",
|
||||
// label: "龙须面",
|
||||
// },
|
||||
// {
|
||||
// value: "选项5",
|
||||
// label: "北京烤鸭",
|
||||
// },
|
||||
// ],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
|
|
|
@ -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