@neatui/nuxt 1.5.4 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/components/form/Checkbox.vue +61 -46
- package/src/components/form/CheckboxGroup.vue +74 -0
- package/src/components/form/CheckboxItem.vue +87 -0
- package/src/components/form/DateView@v3.vue +38 -19
- package/src/components/form/Input@v3.vue +2 -25
- package/src/components/form/InputNumber.vue +2 -4
- package/src/components/form/{Textarea@v2.vue → Textarea.vue} +1 -3
- package/src/components/form/index.ts +4 -2
- package/src/components/loader/FormLoader/{FormLoader@v2.vue → FormLoader.vue} +3 -1
- package/src/components/loader/index.ts +1 -1
- package/src/components/form/DateRangePicker@v2.vue.backup +0 -224
- package/src/components/form/Input.vue.backup +0 -230
- package/src/components/form/MoreSelect.vue.backup +0 -144
- package/src/components/form/SearchSelect.vue.backup +0 -194
- package/src/components/form/TextArea.vue +0 -193
- package/src/components/form/date.ts +0 -321
- package/src/components/loader/FormLoader/FormLoader@v3.vue.backup +0 -399
- package/src/components/loader/FormLoader/FormRender@v3.vue.backup +0 -4
- package/src/components/loader/FormLoader@v1/FormLoader.vue +0 -506
- package/src/components/loader/FormLoader@v1/FormRender.vue +0 -302
|
@@ -1,194 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div :ui-form="`@a type:select sz:${sz}`" :ui-form-open="state.show ? 'show' : ''">
|
|
3
|
-
<IFollowView ref="ifollow" tipBoxClass="ny-sm nx-no" tipBoxStyle="min-width: 100%" @onshow="onshow" @onhide="onhide">
|
|
4
|
-
<Input
|
|
5
|
-
v-bind="{ placeholder, rules, theme, sz, co, block, ready, type, tips, disabled, readonly: true, clearable: false, verify, prefix, suffix, interacted }"
|
|
6
|
-
v-model="state.selectd.label"
|
|
7
|
-
:interacted="interacted"
|
|
8
|
-
>
|
|
9
|
-
<template #suffix><i ui-form-select=""></i></template>
|
|
10
|
-
</Input>
|
|
11
|
-
<template #tips v-if="!readonly || !disabled">
|
|
12
|
-
<div v-if="search" class="ny-sm nx-sl">
|
|
13
|
-
<Input v-model="state.search" sz="s">
|
|
14
|
-
<template #suffix>
|
|
15
|
-
<i ui-form-search="" class="co-note"></i>
|
|
16
|
-
</template>
|
|
17
|
-
</Input>
|
|
18
|
-
</div>
|
|
19
|
-
<ul v-if="props.options?.length" ui-scroll=":y s" class="nx-sm lh-ml" style="min-width: 100%; max-height: 16em">
|
|
20
|
-
<li class="ux-hover nx-sm r-ss nowrap" :class="item.value === state.selectd?.value ? 'co-main' : ''" v-for="(item, idx) of state.filter" :key="idx" @click="select(item)">
|
|
21
|
-
{{ item.label || item }}
|
|
22
|
-
</li>
|
|
23
|
-
</ul>
|
|
24
|
-
<div v-else class="w-full ny-ms" ui-flex="col cm" v-html="spare"></div>
|
|
25
|
-
<ul class="nx-sm lh-ml" v-if="tools">
|
|
26
|
-
<li class="my-ss"><div class="o-mm" ui-line="@a"></div></li>
|
|
27
|
-
<li ui-flex="row xm">
|
|
28
|
-
<div class="co-main">
|
|
29
|
-
<p class="nx-sm r-ss nowrap">
|
|
30
|
-
<span>{{ state.filter?.length || 0 }}个可选项</span>
|
|
31
|
-
</p>
|
|
32
|
-
</div>
|
|
33
|
-
<div>
|
|
34
|
-
<button v-show="state.selectd?.value" class="co-risk" ui-btn="@a none s" @click="remove">清空</button>
|
|
35
|
-
</div>
|
|
36
|
-
</li>
|
|
37
|
-
</ul>
|
|
38
|
-
</template>
|
|
39
|
-
</IFollowView>
|
|
40
|
-
</div>
|
|
41
|
-
</template>
|
|
42
|
-
|
|
43
|
-
<script setup lang="ts">
|
|
44
|
-
import { reactive, ref, computed } from 'vue';
|
|
45
|
-
import { Input } from '../form';
|
|
46
|
-
import { IFollowView } from '../basic';
|
|
47
|
-
const ifollow: any = ref(null);
|
|
48
|
-
|
|
49
|
-
const emits = defineEmits(['update:modelValue', 'change', 'onshow', 'onhide']);
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* 入参说明
|
|
53
|
-
* modelValue 值
|
|
54
|
-
* options 枚举列表
|
|
55
|
-
* tools 是否显示工具栏
|
|
56
|
-
* spare 空闲兜底内容
|
|
57
|
-
* search 是否启用搜索框
|
|
58
|
-
* pagination 是否启用分页
|
|
59
|
-
* refresh 是否显示刷新
|
|
60
|
-
*
|
|
61
|
-
* ---------------------------
|
|
62
|
-
* theme 主题
|
|
63
|
-
* sz 尺寸
|
|
64
|
-
* co 颜色
|
|
65
|
-
* block 撑满
|
|
66
|
-
* ready 准备就绪
|
|
67
|
-
* type 类型
|
|
68
|
-
* tips 提示文案
|
|
69
|
-
* placeholder 内容占位
|
|
70
|
-
* maxlength 最大长度
|
|
71
|
-
* minlength 最小长度
|
|
72
|
-
* disabled 是否禁用
|
|
73
|
-
* readonly 是否只读
|
|
74
|
-
* clearable 是否显示清除按钮
|
|
75
|
-
* rules 校验规则
|
|
76
|
-
* verify 是否是示校验图标
|
|
77
|
-
* prefix 前缀内容
|
|
78
|
-
* suffix 后缀内容
|
|
79
|
-
* interacted 用户是否交互
|
|
80
|
-
*/
|
|
81
|
-
|
|
82
|
-
// 类型
|
|
83
|
-
interface Props {
|
|
84
|
-
modelValue?: string | number;
|
|
85
|
-
options: Array<object>;
|
|
86
|
-
tools?: boolean;
|
|
87
|
-
spare?: string;
|
|
88
|
-
search?: boolean;
|
|
89
|
-
pagination?: boolean;
|
|
90
|
-
refresh?: boolean;
|
|
91
|
-
|
|
92
|
-
// Input
|
|
93
|
-
placeholder?: string;
|
|
94
|
-
rules?: Array<object>;
|
|
95
|
-
theme?: string;
|
|
96
|
-
sz?: '' | 'xs' | 's' | 'm' | 'l' | 'xl';
|
|
97
|
-
co?: string;
|
|
98
|
-
block?: boolean;
|
|
99
|
-
ready?: boolean;
|
|
100
|
-
type?: string;
|
|
101
|
-
tips?: string;
|
|
102
|
-
maxlength?: null | number;
|
|
103
|
-
minlength?: null | number;
|
|
104
|
-
disabled?: boolean;
|
|
105
|
-
readonly?: boolean;
|
|
106
|
-
clearable?: boolean;
|
|
107
|
-
verify?: boolean;
|
|
108
|
-
prefix?: Array<any>;
|
|
109
|
-
suffix?: Array<any>;
|
|
110
|
-
interacted?: boolean;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// 入参
|
|
114
|
-
const props: any = withDefaults(defineProps<Props>(), {
|
|
115
|
-
modelValue: '',
|
|
116
|
-
options: () => [],
|
|
117
|
-
tools: true,
|
|
118
|
-
spare: '当前没有可选项',
|
|
119
|
-
search: true,
|
|
120
|
-
pagination: false,
|
|
121
|
-
refresh: false,
|
|
122
|
-
|
|
123
|
-
// INPUT
|
|
124
|
-
placeholder: '',
|
|
125
|
-
rules: () => [],
|
|
126
|
-
theme: '@a',
|
|
127
|
-
sz: '',
|
|
128
|
-
co: '',
|
|
129
|
-
block: true,
|
|
130
|
-
ready: false,
|
|
131
|
-
type: 'text',
|
|
132
|
-
tips: '',
|
|
133
|
-
maxlength: null,
|
|
134
|
-
minlength: null,
|
|
135
|
-
disabled: false,
|
|
136
|
-
readonly: false,
|
|
137
|
-
clearable: false,
|
|
138
|
-
verify: false,
|
|
139
|
-
prefix: () => [],
|
|
140
|
-
suffix: () => [],
|
|
141
|
-
interacted: false
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
const change = ({ value = '' }: any = {}) => {
|
|
145
|
-
emits('update:modelValue', value);
|
|
146
|
-
emits('change', value);
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
const state = reactive({
|
|
150
|
-
show: 0,
|
|
151
|
-
search: '',
|
|
152
|
-
selectd: computed(() => {
|
|
153
|
-
return props.options.find((option: any) => `${option.value}` === `${props.modelValue}`) || {};
|
|
154
|
-
}),
|
|
155
|
-
filter: computed(() => {
|
|
156
|
-
if (state.search) {
|
|
157
|
-
return props.options?.filter((item: any) => {
|
|
158
|
-
return item.label?.includes(state.search);
|
|
159
|
-
});
|
|
160
|
-
} else {
|
|
161
|
-
return props.options;
|
|
162
|
-
}
|
|
163
|
-
})
|
|
164
|
-
});
|
|
165
|
-
// 选择
|
|
166
|
-
const select = (item: any = {}) => {
|
|
167
|
-
change(item);
|
|
168
|
-
ifollow.value.cancel();
|
|
169
|
-
};
|
|
170
|
-
// 清空
|
|
171
|
-
const remove = () => {
|
|
172
|
-
change({});
|
|
173
|
-
ifollow.value.cancel();
|
|
174
|
-
};
|
|
175
|
-
// 取消
|
|
176
|
-
const cancel = () => {
|
|
177
|
-
ifollow.value.cancel();
|
|
178
|
-
};
|
|
179
|
-
// 显示
|
|
180
|
-
const onshow = () => {
|
|
181
|
-
emits('onshow', state.selectd);
|
|
182
|
-
};
|
|
183
|
-
// 折叠
|
|
184
|
-
const onhide = () => {
|
|
185
|
-
emits('onhide', state.selectd);
|
|
186
|
-
};
|
|
187
|
-
|
|
188
|
-
defineExpose({
|
|
189
|
-
select,
|
|
190
|
-
remove,
|
|
191
|
-
change,
|
|
192
|
-
cancel
|
|
193
|
-
});
|
|
194
|
-
</script>
|
|
@@ -1,193 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div
|
|
3
|
-
:ui-form="`${theme} sz:${sz} ${state.co} type:textarea ${block ? ' :block' : ''} ${disabled ? 'disabled' : ''} ${readonly ? 'readonly' : ''}`"
|
|
4
|
-
@click="emits('click', $event)"
|
|
5
|
-
>
|
|
6
|
-
<div v-if="ready" :ui-form-tips="state.ontips">{{ state.tips }}</div>
|
|
7
|
-
<slot>
|
|
8
|
-
<textarea
|
|
9
|
-
ref="el"
|
|
10
|
-
:rows="rows"
|
|
11
|
-
v-model="mv"
|
|
12
|
-
:type="type"
|
|
13
|
-
:placeholder="placeholder"
|
|
14
|
-
:readonly="readonly || disabled"
|
|
15
|
-
@focus="emits('focus', $event)"
|
|
16
|
-
@input="emits('input', $event)"
|
|
17
|
-
@change="emits('change', $event)"
|
|
18
|
-
@blur="emits('blur', $event)"
|
|
19
|
-
ui-scroll=":y"
|
|
20
|
-
dir="auto"
|
|
21
|
-
></textarea>
|
|
22
|
-
</slot>
|
|
23
|
-
<i v-if="ready && verify" :ui-form-verify="state.verify"></i>
|
|
24
|
-
</div>
|
|
25
|
-
</template>
|
|
26
|
-
|
|
27
|
-
<script setup lang="ts">
|
|
28
|
-
import { ref, watch, computed, onMounted, PropType, nextTick } from 'vue';
|
|
29
|
-
|
|
30
|
-
const emits = defineEmits(['update:modelValue', 'click', 'blur', 'focus', 'change', 'input', 'clear']);
|
|
31
|
-
const props = defineProps({
|
|
32
|
-
theme: { type: String, default: '@a' },
|
|
33
|
-
sz: { type: String, default: '' },
|
|
34
|
-
co: { type: String, default: '' },
|
|
35
|
-
block: { type: Boolean, default: true },
|
|
36
|
-
// 值
|
|
37
|
-
modelValue: {
|
|
38
|
-
type: [String, Number],
|
|
39
|
-
default: '',
|
|
40
|
-
},
|
|
41
|
-
// 类型
|
|
42
|
-
type: {
|
|
43
|
-
type: String,
|
|
44
|
-
default: 'text',
|
|
45
|
-
},
|
|
46
|
-
// 提示文案
|
|
47
|
-
tips: {
|
|
48
|
-
type: String,
|
|
49
|
-
default: '',
|
|
50
|
-
},
|
|
51
|
-
// 内容占位
|
|
52
|
-
placeholder: {
|
|
53
|
-
type: String,
|
|
54
|
-
default: '',
|
|
55
|
-
},
|
|
56
|
-
// 最大长度
|
|
57
|
-
maxLength: {
|
|
58
|
-
type: Number,
|
|
59
|
-
default: null,
|
|
60
|
-
},
|
|
61
|
-
// 最小长度
|
|
62
|
-
minLength: {
|
|
63
|
-
type: Number,
|
|
64
|
-
default: null,
|
|
65
|
-
},
|
|
66
|
-
// 最小长度
|
|
67
|
-
autoHeight: {
|
|
68
|
-
type: Boolean,
|
|
69
|
-
default: false,
|
|
70
|
-
},
|
|
71
|
-
// 是否禁用
|
|
72
|
-
disabled: {
|
|
73
|
-
type: Boolean,
|
|
74
|
-
default: false,
|
|
75
|
-
},
|
|
76
|
-
// 是否中读
|
|
77
|
-
readonly: {
|
|
78
|
-
type: Boolean,
|
|
79
|
-
default: false,
|
|
80
|
-
},
|
|
81
|
-
// 是否显示清除按钮
|
|
82
|
-
clearable: {
|
|
83
|
-
type: Boolean,
|
|
84
|
-
default: true,
|
|
85
|
-
},
|
|
86
|
-
// 校验规则
|
|
87
|
-
rules: {
|
|
88
|
-
type: Array,
|
|
89
|
-
default: () => [],
|
|
90
|
-
},
|
|
91
|
-
// 是否是示校验图标
|
|
92
|
-
verify: {
|
|
93
|
-
type: Boolean,
|
|
94
|
-
default: false,
|
|
95
|
-
},
|
|
96
|
-
prefix: {
|
|
97
|
-
type: Array as PropType<any[]>,
|
|
98
|
-
default: () => [],
|
|
99
|
-
},
|
|
100
|
-
suffix: {
|
|
101
|
-
type: Array as PropType<any[]>,
|
|
102
|
-
default: () => [],
|
|
103
|
-
},
|
|
104
|
-
rows: {
|
|
105
|
-
type: Number,
|
|
106
|
-
default: 3,
|
|
107
|
-
},
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
const ready: any = ref(0);
|
|
111
|
-
const state: any = computed(() => {
|
|
112
|
-
if (ready.value) {
|
|
113
|
-
// 提示文案
|
|
114
|
-
let tips = '';
|
|
115
|
-
// 错误类型
|
|
116
|
-
let type = '';
|
|
117
|
-
// 验证结果
|
|
118
|
-
let verify = '';
|
|
119
|
-
if (props.modelValue) {
|
|
120
|
-
// 有值
|
|
121
|
-
const res: any = props.rules?.some((rule: any) => {
|
|
122
|
-
const yes = rule.validator && !rule.validator(props.modelValue);
|
|
123
|
-
tips = rule.msg;
|
|
124
|
-
type = rule.type;
|
|
125
|
-
return yes;
|
|
126
|
-
});
|
|
127
|
-
verify = res ? 'no' : 'ok';
|
|
128
|
-
} else {
|
|
129
|
-
// 无值
|
|
130
|
-
const res: any = props.rules?.some((rule: any) => {
|
|
131
|
-
tips = rule.msg;
|
|
132
|
-
type = rule.type;
|
|
133
|
-
return rule.required;
|
|
134
|
-
});
|
|
135
|
-
verify = res ? 'no' : '';
|
|
136
|
-
}
|
|
137
|
-
if (verify !== 'no' && props.tips) {
|
|
138
|
-
tips = props.tips;
|
|
139
|
-
}
|
|
140
|
-
// 是否显示提示
|
|
141
|
-
const ontips = verify === 'no' && tips ? 'show' : '';
|
|
142
|
-
// 状态颜色
|
|
143
|
-
const co = verify === 'no' ? 'co:' + type : props.co ? 'co:' + props.co : '';
|
|
144
|
-
return { tips, ontips, verify, co };
|
|
145
|
-
} else {
|
|
146
|
-
return {};
|
|
147
|
-
}
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
// 自动高度
|
|
151
|
-
const el: any = ref(null);
|
|
152
|
-
const fAutoHeight = () => {
|
|
153
|
-
nextTick(() => {
|
|
154
|
-
if (props.autoHeight) {
|
|
155
|
-
el.value.style.height = 'auto';
|
|
156
|
-
el.value.style.height = el.value.scrollHeight + 1 + 'px';
|
|
157
|
-
}
|
|
158
|
-
});
|
|
159
|
-
};
|
|
160
|
-
|
|
161
|
-
const mv: any = ref(props.modelValue);
|
|
162
|
-
watch(
|
|
163
|
-
() => props.modelValue,
|
|
164
|
-
(v: any) => {
|
|
165
|
-
mv.value = v;
|
|
166
|
-
},
|
|
167
|
-
{ deep: true, immediate: true },
|
|
168
|
-
);
|
|
169
|
-
|
|
170
|
-
watch(
|
|
171
|
-
() => mv.value,
|
|
172
|
-
(v: any) => {
|
|
173
|
-
let value = v;
|
|
174
|
-
if (typeof props.maxLength === 'number' && !isNaN(props.maxLength)) {
|
|
175
|
-
value = value.slice(0, props.maxLength);
|
|
176
|
-
mv.value = value;
|
|
177
|
-
}
|
|
178
|
-
emits('update:modelValue', value);
|
|
179
|
-
|
|
180
|
-
// 自动高度
|
|
181
|
-
fAutoHeight();
|
|
182
|
-
},
|
|
183
|
-
{ deep: true },
|
|
184
|
-
);
|
|
185
|
-
|
|
186
|
-
onMounted(() => {
|
|
187
|
-
setTimeout(() => {
|
|
188
|
-
ready.value = 1;
|
|
189
|
-
}, 300);
|
|
190
|
-
// 自动高度
|
|
191
|
-
fAutoHeight();
|
|
192
|
-
});
|
|
193
|
-
</script>
|
|
@@ -1,321 +0,0 @@
|
|
|
1
|
-
import { isDate, isDateString, isNumber, isString } from './type';
|
|
2
|
-
import { numfill } from './number';
|
|
3
|
-
|
|
4
|
-
interface UpdateParam {
|
|
5
|
-
y?: number;
|
|
6
|
-
m?: number;
|
|
7
|
-
d?: number;
|
|
8
|
-
h?: number;
|
|
9
|
-
n?: number;
|
|
10
|
-
s?: number;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
interface CalendarParam {
|
|
14
|
-
group?: boolean;
|
|
15
|
-
value?: Array<string>;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export default class IDate {
|
|
19
|
-
source: any = '';
|
|
20
|
-
attr: any;
|
|
21
|
-
lang: any;
|
|
22
|
-
date: any;
|
|
23
|
-
time: any;
|
|
24
|
-
year: any;
|
|
25
|
-
month: any;
|
|
26
|
-
days: number;
|
|
27
|
-
valid: boolean;
|
|
28
|
-
constructor(lang: any = 'zh') {
|
|
29
|
-
this.lang = lang;
|
|
30
|
-
this.days = 0;
|
|
31
|
-
this.valid = false;
|
|
32
|
-
}
|
|
33
|
-
// 生成日期
|
|
34
|
-
create(obj?: any, opts: any = {}) {
|
|
35
|
-
const zone = opts.zone || '';
|
|
36
|
-
|
|
37
|
-
// 统一预处理:如果是字符串就先把-替换成/,解决iOS兼容性
|
|
38
|
-
if (isString(obj)) {
|
|
39
|
-
obj = obj.replace(/-/g, '/');
|
|
40
|
-
|
|
41
|
-
// 明确格式处理
|
|
42
|
-
if (opts.format) {
|
|
43
|
-
const [a1, a2, a3] = obj.split(/[-/]/).map((i: any) => i.length);
|
|
44
|
-
const [b1, b2, b3] = opts.format?.split(/[-/]/).map((i: any) => i.length);
|
|
45
|
-
if (a1 === b1 && a2 === b2 && a3 === b3) {
|
|
46
|
-
obj = `${a1 || '01'}/${a2 || '01'}/${a3 || '01'}`;
|
|
47
|
-
} else {
|
|
48
|
-
console.warn(`${obj} is not a valid date`);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// 不合法日期是否应该抛出错误?
|
|
54
|
-
if (!isDate(obj) && !isDateString(obj)) {
|
|
55
|
-
console.log(53, obj);
|
|
56
|
-
console.warn(`${obj} is not a valid date`);
|
|
57
|
-
} else {
|
|
58
|
-
this.valid = true;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
function utc(obj: any) {
|
|
62
|
-
if (!isString(obj)) {
|
|
63
|
-
return new Date();
|
|
64
|
-
}
|
|
65
|
-
const parts = obj.split(/[-/]/).map(Number);
|
|
66
|
-
const [year, month, day] = parts;
|
|
67
|
-
return new Date(Date.UTC(year, month - 1, day));
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// 如果是10位时间戳
|
|
71
|
-
if (isNumber(obj)) {
|
|
72
|
-
const _len = obj?.toString()?.length;
|
|
73
|
-
if (_len === 10) {
|
|
74
|
-
obj = obj * 1000;
|
|
75
|
-
} else if (_len === 11) {
|
|
76
|
-
obj = obj * 100;
|
|
77
|
-
} else if (_len === 12) {
|
|
78
|
-
obj = obj * 10;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
// 判断是否有入参
|
|
82
|
-
if (obj === undefined) {
|
|
83
|
-
obj = new Date();
|
|
84
|
-
}
|
|
85
|
-
// 判断是否是日期
|
|
86
|
-
if (obj) {
|
|
87
|
-
this.source = obj;
|
|
88
|
-
const date = isDate(obj) ? obj : isDateString(obj) ? (isString(obj) ? (zone === 'utc' ? utc(obj) : new Date(obj)) : new Date(obj)) : new Date();
|
|
89
|
-
|
|
90
|
-
this.date = date;
|
|
91
|
-
const cnWeek = ['日', '一', '二', '三', '四', '五', '六'];
|
|
92
|
-
this.time = date.getTime();
|
|
93
|
-
|
|
94
|
-
this.attr = {
|
|
95
|
-
time: date.getTime(),
|
|
96
|
-
year: date.getFullYear(),
|
|
97
|
-
YYYY: date.getFullYear(),
|
|
98
|
-
yyyy: date.getFullYear(),
|
|
99
|
-
YY: `${date.getFullYear()}`.slice(-2),
|
|
100
|
-
yy: `${date.getFullYear()}`.slice(-2),
|
|
101
|
-
Y: date.getFullYear(),
|
|
102
|
-
y: date.getFullYear(),
|
|
103
|
-
month: date.getMonth() + 1,
|
|
104
|
-
MM: numfill(date.getMonth() + 1),
|
|
105
|
-
M: date.getMonth() + 1,
|
|
106
|
-
DD: numfill(date.getDate()),
|
|
107
|
-
dd: numfill(date.getDate()),
|
|
108
|
-
D: date.getDate(),
|
|
109
|
-
date: date.getDate(),
|
|
110
|
-
d: date.getDate(),
|
|
111
|
-
H: date.getHours(),
|
|
112
|
-
h: date.getHours() > 12 ? date.getHours() - 12 : date.getHours(),
|
|
113
|
-
HH: numfill(date.getHours()),
|
|
114
|
-
hh: numfill(date.getHours()),
|
|
115
|
-
mm: numfill(date.getMinutes()),
|
|
116
|
-
m: date.getMinutes(),
|
|
117
|
-
ss: numfill(date.getSeconds()),
|
|
118
|
-
s: date.getSeconds(),
|
|
119
|
-
w: date.getDay(),
|
|
120
|
-
W: cnWeek[date.getDay()],
|
|
121
|
-
};
|
|
122
|
-
// 本月天数
|
|
123
|
-
this.days = new Date(this.attr.y, this.attr.M, 0).getDate();
|
|
124
|
-
}
|
|
125
|
-
return this;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// 日期格式
|
|
129
|
-
format(format = 'YYYY-MM-DD') {
|
|
130
|
-
if (this.date) {
|
|
131
|
-
return format.replace(/(YYYY|yyyy|YY|yy|MM|M|DD|dd|D|d|HH|hh|H|h|mm|m|ss|s|w)/g, (_: any, key: any) => this.attr[key]);
|
|
132
|
-
} else {
|
|
133
|
-
return this.source;
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// 时间更新
|
|
138
|
-
update(obj: UpdateParam) {
|
|
139
|
-
if (this.date) {
|
|
140
|
-
const { y = 0, m = 0, d = 0, h = 0, n = 0, s = 0 }: any = obj || {};
|
|
141
|
-
if (y) {
|
|
142
|
-
this.date.setFullYear(this.date.getFullYear() + y);
|
|
143
|
-
}
|
|
144
|
-
if (m) {
|
|
145
|
-
this.date.setMonth(this.date.getMonth() + m);
|
|
146
|
-
}
|
|
147
|
-
if (d) {
|
|
148
|
-
this.date.setDate(this.date.getDate() + d);
|
|
149
|
-
}
|
|
150
|
-
if (h) {
|
|
151
|
-
this.date.setHours(this.date.getHours() + h);
|
|
152
|
-
}
|
|
153
|
-
if (n) {
|
|
154
|
-
this.date.setMinutes(this.date.getMinutes() + n);
|
|
155
|
-
}
|
|
156
|
-
if (s) {
|
|
157
|
-
this.date.setSeconds(this.date.getSeconds() + s);
|
|
158
|
-
}
|
|
159
|
-
this.create(this.date);
|
|
160
|
-
}
|
|
161
|
-
return this;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// 人性化
|
|
165
|
-
humanized(words: any = {}) {
|
|
166
|
-
if (this.date) {
|
|
167
|
-
const now = new Date();
|
|
168
|
-
const diff = now.getTime() - this.date.getTime();
|
|
169
|
-
const minute = 60 * 1000;
|
|
170
|
-
const hour = 60 * minute;
|
|
171
|
-
const day = 24 * hour;
|
|
172
|
-
const week = 7 * day;
|
|
173
|
-
const month = 30 * day;
|
|
174
|
-
const year = 365 * day;
|
|
175
|
-
|
|
176
|
-
const {
|
|
177
|
-
NOW = 'Just now',
|
|
178
|
-
MIN = ' minute ago',
|
|
179
|
-
HRS = ' hour ago',
|
|
180
|
-
DAY = ' day ago',
|
|
181
|
-
WKS = ' week ago',
|
|
182
|
-
MON = ' month ago',
|
|
183
|
-
YRS = ' year ago',
|
|
184
|
-
MINS = ' minutes ago',
|
|
185
|
-
HRSS = ' hours ago',
|
|
186
|
-
DAYS = ' days ago',
|
|
187
|
-
WKSS = ' weeks ago',
|
|
188
|
-
MONS = ' months ago',
|
|
189
|
-
YRSS = ' years ago',
|
|
190
|
-
}: any = words || {};
|
|
191
|
-
|
|
192
|
-
if (diff < minute) {
|
|
193
|
-
return NOW;
|
|
194
|
-
} else if (diff < hour) {
|
|
195
|
-
const minutes = Math.floor(diff / minute);
|
|
196
|
-
return `${minutes}${minutes > 1 ? MINS : MIN}`;
|
|
197
|
-
} else if (diff < day) {
|
|
198
|
-
const hours = Math.floor(diff / hour);
|
|
199
|
-
return `${hours}${hours > 1 ? HRSS : HRS}`;
|
|
200
|
-
} else if (diff < week) {
|
|
201
|
-
const days = Math.floor(diff / day);
|
|
202
|
-
return `${days}${days > 1 ? DAYS : DAY}`;
|
|
203
|
-
} else if (diff < month) {
|
|
204
|
-
const weeks = Math.floor(diff / week);
|
|
205
|
-
return `${weeks}${weeks > 1 ? WKSS : WKS}`;
|
|
206
|
-
} else if (diff < year) {
|
|
207
|
-
const months = Math.floor(diff / month);
|
|
208
|
-
return `${months}${months > 1 ? MONS : MON}`;
|
|
209
|
-
} else {
|
|
210
|
-
const years = Math.floor(diff / year);
|
|
211
|
-
return `${years}${years > 1 ? YRSS : YRS}`;
|
|
212
|
-
}
|
|
213
|
-
} else {
|
|
214
|
-
return this.source;
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
// 日历
|
|
219
|
-
calendar(param: CalendarParam = {}) {
|
|
220
|
-
if (!this.date) {
|
|
221
|
-
this.create(new Date());
|
|
222
|
-
}
|
|
223
|
-
const { group = false, value = [] }: any = param;
|
|
224
|
-
const values: any = value
|
|
225
|
-
.filter((day: any) => {
|
|
226
|
-
return day && isDateString(day);
|
|
227
|
-
})
|
|
228
|
-
.sort((a: any, b: any) => {
|
|
229
|
-
return idate(a).time - idate(b).time;
|
|
230
|
-
})
|
|
231
|
-
.map((day: any) => idate(day).format('YYYY-MM-DD'));
|
|
232
|
-
|
|
233
|
-
// 年
|
|
234
|
-
const y: any = this.date?.getFullYear();
|
|
235
|
-
// 月
|
|
236
|
-
const m: any = this.date?.getMonth() + 1;
|
|
237
|
-
// 本月第一天星期几
|
|
238
|
-
const w = new Date(y, m - 1, 1).getDay();
|
|
239
|
-
// 当前月份一共几天
|
|
240
|
-
const days = new Date(y, m, 0).getDate();
|
|
241
|
-
|
|
242
|
-
// 当前
|
|
243
|
-
const curr = new Date();
|
|
244
|
-
const curr_y = curr.getFullYear();
|
|
245
|
-
const curr_m = curr.getMonth() + 1;
|
|
246
|
-
const curr_d = curr.getDate();
|
|
247
|
-
|
|
248
|
-
// 上月
|
|
249
|
-
const last = new Date(y, m - 1, 0);
|
|
250
|
-
const last_y = last.getFullYear();
|
|
251
|
-
const last_m = last.getMonth() + 1;
|
|
252
|
-
let prevdays = last.getDate();
|
|
253
|
-
|
|
254
|
-
// 下月
|
|
255
|
-
const next = new Date(y, m + 1, 0);
|
|
256
|
-
const next_y = next.getFullYear();
|
|
257
|
-
const next_m = next.getMonth() + 1;
|
|
258
|
-
const _calendar: any = [];
|
|
259
|
-
|
|
260
|
-
// 上月的日期
|
|
261
|
-
for (let i = 0; i < w; i++) {
|
|
262
|
-
_calendar.unshift({
|
|
263
|
-
date: `${last_y}-${numfill(last_m)}-${numfill(prevdays)}`,
|
|
264
|
-
day: prevdays,
|
|
265
|
-
isLastMonth: true,
|
|
266
|
-
});
|
|
267
|
-
prevdays = prevdays - 1;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
// 本月的日期
|
|
271
|
-
for (let d = 1; d <= days; d++) {
|
|
272
|
-
_calendar.push({
|
|
273
|
-
date: `${y}-${numfill(m)}-${numfill(d)}`,
|
|
274
|
-
day: d,
|
|
275
|
-
today: curr_y === y && curr_m === m && curr_d === d,
|
|
276
|
-
isCurrMonth: true,
|
|
277
|
-
});
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
// 下月的日期
|
|
281
|
-
for (let i = 1; _calendar.length < 42; i++) {
|
|
282
|
-
const _i = i;
|
|
283
|
-
_calendar.push({
|
|
284
|
-
date: `${next_y}-${numfill(next_m)}-${numfill(_i)}`,
|
|
285
|
-
day: _i,
|
|
286
|
-
isNextMonth: true,
|
|
287
|
-
});
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
let calendar = _calendar.map((item: any) => {
|
|
291
|
-
const _idx = values.indexOf(idate(item.date).format('YYYY-MM-DD'));
|
|
292
|
-
// 判断是否在选
|
|
293
|
-
if (_idx !== -1) {
|
|
294
|
-
if (item.isCurrMonth) {
|
|
295
|
-
item.selected = true;
|
|
296
|
-
}
|
|
297
|
-
if (_idx === 0) {
|
|
298
|
-
item.sta = true;
|
|
299
|
-
}
|
|
300
|
-
if (_idx === values.length - 1) {
|
|
301
|
-
item.end = true;
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
// 判断是否在范围内
|
|
305
|
-
if (values.length > 1) {
|
|
306
|
-
if (item.isCurrMonth && idate(item.date).time >= idate(values[0]).time && idate(item.date).time <= idate(values[values.length - 1]).time) {
|
|
307
|
-
item.range = true;
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
return item;
|
|
311
|
-
});
|
|
312
|
-
// 是否按周分组
|
|
313
|
-
if (group) {
|
|
314
|
-
calendar = Array.from({ length: Math.ceil(_calendar.length / 7) }, (_v, index) => _calendar.slice(index * 7, index * 7 + 7));
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
return calendar;
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
export const idate = (obj?: any) => new IDate().create(obj);
|