ct-component-plus 0.0.1
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/README.md +3 -0
- package/package.json +37 -0
- package/packages/components/button/index.js +9 -0
- package/packages/components/button/src/button.vue +172 -0
- package/packages/components/cascader/index.js +8 -0
- package/packages/components/cascader/src/cascader.vue +224 -0
- package/packages/components/cascader/src/ct-cascader.vue +261 -0
- package/packages/components/cascader/src/index.js +51 -0
- package/packages/components/checkbox/index.js +8 -0
- package/packages/components/checkbox/src/checkbox.vue +48 -0
- package/packages/components/checkbox/src/index.js +13 -0
- package/packages/components/date-picker/index.js +9 -0
- package/packages/components/date-picker/src/clear-icon.vue +3 -0
- package/packages/components/date-picker/src/date-icon.vue +3 -0
- package/packages/components/date-picker/src/date-picker.vue +77 -0
- package/packages/components/date-picker/src/index.js +34 -0
- package/packages/components/dialog/index.js +9 -0
- package/packages/components/dialog/src/dialog.vue +104 -0
- package/packages/components/empty/index.js +9 -0
- package/packages/components/empty/src/empty.vue +98 -0
- package/packages/components/index.js +71 -0
- package/packages/components/input/index.js +8 -0
- package/packages/components/input/src/index.js +14 -0
- package/packages/components/input/src/input.vue +107 -0
- package/packages/components/input-range/index.js +8 -0
- package/packages/components/input-range/src/index.js +30 -0
- package/packages/components/input-range/src/input-range.vue +234 -0
- package/packages/components/menu/index.js +8 -0
- package/packages/components/menu/src/assets/plus_line.svg +1 -0
- package/packages/components/menu/src/item.vue +47 -0
- package/packages/components/menu/src/link.vue +29 -0
- package/packages/components/menu/src/logo.vue +26 -0
- package/packages/components/menu/src/menu-item.vue +104 -0
- package/packages/components/menu/src/menu.vue +192 -0
- package/packages/components/menu/src/utils/index.js +5 -0
- package/packages/components/message/icon/ErrorIcon.vue +25 -0
- package/packages/components/message/icon/InfoIcon.vue +25 -0
- package/packages/components/message/icon/SuccessIcon.vue +25 -0
- package/packages/components/message/icon/WarningIcon.vue +25 -0
- package/packages/components/message/index.js +9 -0
- package/packages/components/message/src/method.js +55 -0
- package/packages/components/message-box/index.js +8 -0
- package/packages/components/message-box/src/message-box.vue +108 -0
- package/packages/components/pagination/index.js +8 -0
- package/packages/components/pagination/src/pagination.vue +37 -0
- package/packages/components/radio/index.js +8 -0
- package/packages/components/radio/src/index.js +13 -0
- package/packages/components/radio/src/radio.vue +48 -0
- package/packages/components/search-box/index.js +25 -0
- package/packages/components/search-box/src/index.js +30 -0
- package/packages/components/search-box/src/search-box.vue +240 -0
- package/packages/components/search-box/src/slot.vue +5 -0
- package/packages/components/select/index.js +8 -0
- package/packages/components/select/src/arrow-down.vue +3 -0
- package/packages/components/select/src/clear-icon.vue +3 -0
- package/packages/components/select/src/empty.vue +14 -0
- package/packages/components/select/src/index.js +52 -0
- package/packages/components/select/src/select.vue +331 -0
- package/packages/components/table/index.js +8 -0
- package/packages/components/table/src/TableSort.vue +179 -0
- package/packages/components/table/src/index.js +47 -0
- package/packages/components/table/src/table.vue +249 -0
- package/packages/components/tabs/index.js +8 -0
- package/packages/components/tabs/src/tabs.vue +226 -0
- package/packages/components/year-select/index.js +8 -0
- package/packages/components/year-select/src/index.js +45 -0
- package/packages/components/year-select/src/year-select.vue +274 -0
- package/packages/constants/aria.ts +17 -0
- package/packages/constants/index.ts +1 -0
- package/packages/directives/click-outside/index.ts +118 -0
- package/packages/directives/index.js +1 -0
- package/packages/echarts/bar/index.js +64 -0
- package/packages/echarts/base.js +96 -0
- package/packages/echarts/line/index.js +107 -0
- package/packages/hooks/index.js +6 -0
- package/packages/hooks/use-buried/index.js +47 -0
- package/packages/hooks/use-checked-all/index.js +37 -0
- package/packages/hooks/use-echarts/index.js +2 -0
- package/packages/hooks/use-echarts/use-bar/index.js +67 -0
- package/packages/hooks/use-echarts/use-line/index.js +83 -0
- package/packages/hooks/use-namespace/index.js +66 -0
- package/packages/hooks/use-search-component/index.js +29 -0
- package/packages/style/element.less +600 -0
- package/packages/style/init.less +114 -0
- package/packages/utils/index.js +2 -0
- package/packages/utils/operate.js +78 -0
- package/packages/utils/types.js +35 -0
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<el-tooltip
|
|
3
|
+
ref="tooltipRef"
|
|
4
|
+
:visible="popperVisible"
|
|
5
|
+
:teleported="teleported"
|
|
6
|
+
:popper-class="[nsCascader.e('dropdown'), popperClass]"
|
|
7
|
+
:popper-options="popperOptions"
|
|
8
|
+
:fallback-placements="fallbackPlacements"
|
|
9
|
+
:stop-popper-mouse-event="false"
|
|
10
|
+
:gpu-acceleration="false"
|
|
11
|
+
placement="bottom-start"
|
|
12
|
+
transition="el-cascader-zoom-in-top"
|
|
13
|
+
effect="light"
|
|
14
|
+
pure
|
|
15
|
+
persistent
|
|
16
|
+
@hide="hideSuggestionPanel"
|
|
17
|
+
>
|
|
18
|
+
<template #default>
|
|
19
|
+
<div
|
|
20
|
+
v-clickoutside:[contentRef]="() => togglePopperVisible(false)"
|
|
21
|
+
:class="cascaderKls"
|
|
22
|
+
:style="cascaderStyle"
|
|
23
|
+
@click="() => togglePopperVisible(readonly ? undefined : true)"
|
|
24
|
+
@keydown="handleKeyDown"
|
|
25
|
+
@mouseenter="inputHover = true"
|
|
26
|
+
@mouseleave="inputHover = false"
|
|
27
|
+
>
|
|
28
|
+
<el-input
|
|
29
|
+
ref="input"
|
|
30
|
+
v-model="inputValue"
|
|
31
|
+
:placeholder="currentPlaceholder"
|
|
32
|
+
:readonly="readonly"
|
|
33
|
+
:disabled="isDisabled"
|
|
34
|
+
:validate-event="false"
|
|
35
|
+
:class="inputClass"
|
|
36
|
+
:tabindex="multiple && filterable && !isDisabled ? -1 : undefined"
|
|
37
|
+
@compositionstart="handleComposition"
|
|
38
|
+
@compositionupdate="handleComposition"
|
|
39
|
+
@compositionend="handleComposition"
|
|
40
|
+
@focus="handleFocus"
|
|
41
|
+
@blur="handleBlur"
|
|
42
|
+
@input="handleInput"
|
|
43
|
+
>
|
|
44
|
+
</el-input>
|
|
45
|
+
</div>
|
|
46
|
+
</template>
|
|
47
|
+
<template #content>
|
|
48
|
+
<el-cascader-panel
|
|
49
|
+
v-show="!filtering"
|
|
50
|
+
ref="cascaderPanelRef"
|
|
51
|
+
v-model="checkedValue"
|
|
52
|
+
:options="options"
|
|
53
|
+
:props="props.props"
|
|
54
|
+
:border="false"
|
|
55
|
+
:render-label="$slots.default"
|
|
56
|
+
@expand-change="handleExpandChange"
|
|
57
|
+
@close="$nextTick(() => togglePopperVisible(false))"
|
|
58
|
+
/>
|
|
59
|
+
</template>
|
|
60
|
+
</el-tooltip>
|
|
61
|
+
</template>
|
|
62
|
+
|
|
63
|
+
<script setup>
|
|
64
|
+
import { onMounted, computed, nextTick, ref, useAttrs } from "vue";
|
|
65
|
+
import { cascaderEmits, cascaderProps } from "./index";
|
|
66
|
+
import { useNamespace, useBuriedParams } from "../../../hooks";
|
|
67
|
+
import { ClickOutside as vClickoutside } from "../../../directives";
|
|
68
|
+
import { EVENT_CODE } from "../../../constants";
|
|
69
|
+
const props = defineProps(cascaderProps);
|
|
70
|
+
const emit = defineEmits(cascaderEmits);
|
|
71
|
+
const attrs = useAttrs();
|
|
72
|
+
|
|
73
|
+
const nsCascader = useNamespace("cascader");
|
|
74
|
+
|
|
75
|
+
const inputPlaceholder = computed(() => props.placeholder || "请选择");
|
|
76
|
+
const isDisabled = computed(() => props.disabled);
|
|
77
|
+
const multiple = computed(() => !!props.props.multiple);
|
|
78
|
+
const readonly = computed(() => !props.filterable || multiple.value);
|
|
79
|
+
const tooltipRef = ref(null);
|
|
80
|
+
const popperVisible = ref(false);
|
|
81
|
+
const popperOptions = {
|
|
82
|
+
modifiers: [
|
|
83
|
+
{
|
|
84
|
+
name: "arrowPosition",
|
|
85
|
+
enabled: true,
|
|
86
|
+
phase: "main",
|
|
87
|
+
fn: ({ state }) => {
|
|
88
|
+
const { modifiersData, placement } = state;
|
|
89
|
+
if (["right", "left", "bottom", "top"].includes(placement)) return;
|
|
90
|
+
modifiersData.arrow.x = 35;
|
|
91
|
+
},
|
|
92
|
+
requires: ["arrow"],
|
|
93
|
+
},
|
|
94
|
+
],
|
|
95
|
+
};
|
|
96
|
+
const fallbackPlacements = [
|
|
97
|
+
"bottom-start",
|
|
98
|
+
"bottom",
|
|
99
|
+
"top-start",
|
|
100
|
+
"top",
|
|
101
|
+
"right",
|
|
102
|
+
"left",
|
|
103
|
+
];
|
|
104
|
+
|
|
105
|
+
const isOnComposition = ref(false);
|
|
106
|
+
const contentRef = computed(() => {
|
|
107
|
+
return tooltipRef.value
|
|
108
|
+
? tooltipRef.value.popperRef
|
|
109
|
+
? tooltipRef.value.popperRef.contentRef
|
|
110
|
+
: ""
|
|
111
|
+
: "";
|
|
112
|
+
});
|
|
113
|
+
const cascaderKls = computed(() => {
|
|
114
|
+
return [
|
|
115
|
+
"el-cascader",
|
|
116
|
+
nsCascader.b(),
|
|
117
|
+
nsCascader.is("disabled", isDisabled.value),
|
|
118
|
+
attrs.class,
|
|
119
|
+
];
|
|
120
|
+
});
|
|
121
|
+
const cascaderStyle = computed(() => {
|
|
122
|
+
return attrs.style;
|
|
123
|
+
});
|
|
124
|
+
const inputClass = computed(() => {
|
|
125
|
+
return nsCascader.is("focus", popperVisible.value);
|
|
126
|
+
});
|
|
127
|
+
const input = ref(null);
|
|
128
|
+
const inputHover = ref(false);
|
|
129
|
+
const filtering = ref(false);
|
|
130
|
+
const inputValue = ref("");
|
|
131
|
+
const currentPlaceholder = computed(() => {
|
|
132
|
+
return isOnComposition.value ? "" : inputPlaceholder.value;
|
|
133
|
+
});
|
|
134
|
+
const checkedNodes = computed(() => cascaderPanelRef.value?.checkedNodes || []);
|
|
135
|
+
const cascaderPanelRef = ref(null);
|
|
136
|
+
const presentText = computed(() => {
|
|
137
|
+
const { showAllLevels, separator } = props;
|
|
138
|
+
const nodes = checkedNodes.value;
|
|
139
|
+
return nodes.length
|
|
140
|
+
? multiple.value
|
|
141
|
+
? ""
|
|
142
|
+
: nodes[0].calcText(showAllLevels, separator)
|
|
143
|
+
: "";
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
const suggestionPanel = ref(null);
|
|
147
|
+
const checkedValue = computed({
|
|
148
|
+
get() {
|
|
149
|
+
return props.modelValue;
|
|
150
|
+
},
|
|
151
|
+
set(val) {
|
|
152
|
+
emit("update:modelValue", val);
|
|
153
|
+
emit("change", val);
|
|
154
|
+
},
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
const handleExpandChange = (value) => {
|
|
158
|
+
updatePopperPosition();
|
|
159
|
+
emit("expandChange", value);
|
|
160
|
+
};
|
|
161
|
+
const handleFocus = (e) => {
|
|
162
|
+
emit("focus", e);
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
const handleBlur = (e) => {
|
|
166
|
+
emit("blur", e);
|
|
167
|
+
};
|
|
168
|
+
const handleInput = (val, e) => {
|
|
169
|
+
!popperVisible.value && togglePopperVisible(true);
|
|
170
|
+
|
|
171
|
+
if (e?.isComposing) return;
|
|
172
|
+
};
|
|
173
|
+
const handleComposition = (event) => {
|
|
174
|
+
const text = event.target?.value;
|
|
175
|
+
if (event.type === "compositionend") {
|
|
176
|
+
isOnComposition.value = false;
|
|
177
|
+
nextTick(() => handleInput(text));
|
|
178
|
+
} else {
|
|
179
|
+
isOnComposition.value = true;
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
const handleKeyDown = (e) => {
|
|
183
|
+
if (isOnComposition.value) return;
|
|
184
|
+
|
|
185
|
+
switch (e.code) {
|
|
186
|
+
case EVENT_CODE.enter:
|
|
187
|
+
togglePopperVisible();
|
|
188
|
+
break;
|
|
189
|
+
case EVENT_CODE.down:
|
|
190
|
+
togglePopperVisible(true);
|
|
191
|
+
nextTick(focusFirstNode);
|
|
192
|
+
e.preventDefault();
|
|
193
|
+
break;
|
|
194
|
+
case EVENT_CODE.esc:
|
|
195
|
+
if (popperVisible.value === true) {
|
|
196
|
+
e.preventDefault();
|
|
197
|
+
e.stopPropagation();
|
|
198
|
+
togglePopperVisible(false);
|
|
199
|
+
}
|
|
200
|
+
break;
|
|
201
|
+
case EVENT_CODE.tab:
|
|
202
|
+
togglePopperVisible(false);
|
|
203
|
+
break;
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
const focusFirstNode = () => {
|
|
207
|
+
let firstNode = null;
|
|
208
|
+
|
|
209
|
+
if (filtering.value && suggestionPanel.value) {
|
|
210
|
+
firstNode = suggestionPanel.value.$el.querySelector(
|
|
211
|
+
".el-cascader__suggestion-item"
|
|
212
|
+
);
|
|
213
|
+
} else {
|
|
214
|
+
firstNode = cascaderPanelRef.value?.$el.querySelector(
|
|
215
|
+
'.el-cascader-node[tabindex="-1"]'
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (firstNode) {
|
|
220
|
+
firstNode.focus();
|
|
221
|
+
!filtering.value && firstNode.click();
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
const togglePopperVisible = (visible) => {
|
|
225
|
+
if (isDisabled.value) return;
|
|
226
|
+
|
|
227
|
+
visible = visible ?? !popperVisible.value;
|
|
228
|
+
|
|
229
|
+
if (visible !== popperVisible.value) {
|
|
230
|
+
popperVisible.value = visible;
|
|
231
|
+
input.value?.input?.setAttribute("aria-expanded", `${visible}`);
|
|
232
|
+
|
|
233
|
+
if (visible) {
|
|
234
|
+
updatePopperPosition();
|
|
235
|
+
nextTick(cascaderPanelRef.value?.scrollToExpandingNode);
|
|
236
|
+
} else if (props.filterable) {
|
|
237
|
+
syncPresentTextValue();
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
emit("visibleChange", visible);
|
|
241
|
+
}
|
|
242
|
+
};
|
|
243
|
+
const syncPresentTextValue = () => {
|
|
244
|
+
const { value } = presentText;
|
|
245
|
+
inputValue.value = value;
|
|
246
|
+
searchInputValue.value = value;
|
|
247
|
+
};
|
|
248
|
+
const updatePopperPosition = () => {
|
|
249
|
+
nextTick(() => {
|
|
250
|
+
tooltipRef.value?.updatePopper();
|
|
251
|
+
});
|
|
252
|
+
};
|
|
253
|
+
const hideSuggestionPanel = () => {
|
|
254
|
+
filtering.value = false;
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
useBuriedParams(props, emit);
|
|
258
|
+
onMounted(() => {});
|
|
259
|
+
</script>
|
|
260
|
+
<style lang='less'>
|
|
261
|
+
</style>
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { buriedParamsKey, searchComponentProps } from '../../../hooks';
|
|
2
|
+
|
|
3
|
+
export const cascaderEmits = [
|
|
4
|
+
"update:modelValue",
|
|
5
|
+
buriedParamsKey,
|
|
6
|
+
];
|
|
7
|
+
export const cascaderProps = {
|
|
8
|
+
...searchComponentProps,
|
|
9
|
+
modelValue: [String, Number, Array],
|
|
10
|
+
multiple: Boolean,
|
|
11
|
+
options: {
|
|
12
|
+
type: Array,
|
|
13
|
+
default() {
|
|
14
|
+
return []
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
props: {
|
|
18
|
+
type: Object,
|
|
19
|
+
default() {
|
|
20
|
+
return {}
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
disabled: Boolean,
|
|
24
|
+
showAllLevels: {
|
|
25
|
+
type: Boolean,
|
|
26
|
+
default: false
|
|
27
|
+
},
|
|
28
|
+
separator: {
|
|
29
|
+
type: String,
|
|
30
|
+
default: '/',
|
|
31
|
+
},
|
|
32
|
+
separatorMultiple: {
|
|
33
|
+
type: String,
|
|
34
|
+
default: '、',
|
|
35
|
+
},
|
|
36
|
+
filterable: Boolean,
|
|
37
|
+
clearable: {
|
|
38
|
+
type: Boolean,
|
|
39
|
+
default: true
|
|
40
|
+
},
|
|
41
|
+
popperClass: String,
|
|
42
|
+
api: String,
|
|
43
|
+
serviceMethod: String,
|
|
44
|
+
serviceParams: Object,
|
|
45
|
+
mapObj: {
|
|
46
|
+
type: Object,
|
|
47
|
+
default() {
|
|
48
|
+
return {}
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<el-checkbox-group :class="[ns.b()]" v-model="showValue" ref="checkboxRef">
|
|
3
|
+
<el-checkbox
|
|
4
|
+
:class="[ns.e('item')]"
|
|
5
|
+
v-for="item in optionList"
|
|
6
|
+
:key="item.value"
|
|
7
|
+
:label="item.value"
|
|
8
|
+
:disabled="item.disabled"
|
|
9
|
+
>{{ item.label }}</el-checkbox
|
|
10
|
+
>
|
|
11
|
+
</el-checkbox-group>
|
|
12
|
+
</template>
|
|
13
|
+
|
|
14
|
+
<script setup>
|
|
15
|
+
import { computed, onMounted, ref } from "vue";
|
|
16
|
+
import { useNamespace, useBuriedParams } from "../../../hooks";
|
|
17
|
+
import { checkboxEmits, checkboxProps } from "./index";
|
|
18
|
+
const props = defineProps(checkboxProps);
|
|
19
|
+
const emit = defineEmits(checkboxEmits);
|
|
20
|
+
|
|
21
|
+
const ns = useNamespace("checkbox");
|
|
22
|
+
const checkboxRef = ref(null);
|
|
23
|
+
const showValue = computed({
|
|
24
|
+
get() {
|
|
25
|
+
return props.modelValue;
|
|
26
|
+
},
|
|
27
|
+
set(newValue) {
|
|
28
|
+
emit("update:modelValue", newValue);
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
const optionList = computed(() => {
|
|
32
|
+
return props.options;
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
useBuriedParams(props, emit, {
|
|
36
|
+
getContent: (value) => {
|
|
37
|
+
const item = optionList.value.find((item) => item.value === value);
|
|
38
|
+
return item ? item.label : "";
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
defineExpose({
|
|
43
|
+
ref: checkboxRef,
|
|
44
|
+
});
|
|
45
|
+
onMounted(() => {});
|
|
46
|
+
</script>
|
|
47
|
+
<style lang='less'>
|
|
48
|
+
</style>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { buriedParamsKey, searchComponentProps } from '../../../hooks';
|
|
2
|
+
|
|
3
|
+
export const checkboxEmits = ["update:modelValue", buriedParamsKey];
|
|
4
|
+
export const checkboxProps = {
|
|
5
|
+
...searchComponentProps,
|
|
6
|
+
modelValue: Array,
|
|
7
|
+
options: {
|
|
8
|
+
type: Array,
|
|
9
|
+
default() {
|
|
10
|
+
return []
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import CtDatePicker from './src/date-picker.vue';
|
|
2
|
+
|
|
3
|
+
/* istanbul ignore next */
|
|
4
|
+
CtDatePicker.install = function (Vue) {
|
|
5
|
+
// TODO 这里D组件名是这这里写死的,不是使用CtdatePicker.name的形式,因为setup里面不可以直接什么组件的name属性,故而这里没有这个属性,后续可以考虑使用defineOptions(需要安装unplugin-vue-macros插件)
|
|
6
|
+
Vue.component('CtDatePicker', CtDatePicker);
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export default CtDatePicker;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<el-date-picker
|
|
3
|
+
:class="[ns.b()]"
|
|
4
|
+
v-model="showValue"
|
|
5
|
+
:value-format="valueFormat"
|
|
6
|
+
:range-separator="rangeSeparator"
|
|
7
|
+
:clear-icon="clearIcon"
|
|
8
|
+
:prefix-icon="prefixIcon"
|
|
9
|
+
:unlink-panels="unlinkPanels"
|
|
10
|
+
v-bind="rawAttr"
|
|
11
|
+
>
|
|
12
|
+
<template #default="cell">
|
|
13
|
+
<slot v-bind="cell"></slot>
|
|
14
|
+
</template>
|
|
15
|
+
</el-date-picker>
|
|
16
|
+
</template>
|
|
17
|
+
|
|
18
|
+
<script setup>
|
|
19
|
+
import { computed, onMounted, useAttrs } from "vue";
|
|
20
|
+
import { useNamespace, useBuriedParams } from "../../../hooks";
|
|
21
|
+
import { isFunction, isArray } from "../../../utils";
|
|
22
|
+
import { datePickerEmits, datePickerProps } from "./index";
|
|
23
|
+
const props = defineProps(datePickerProps);
|
|
24
|
+
const emit = defineEmits(datePickerEmits);
|
|
25
|
+
const attr = useAttrs();
|
|
26
|
+
const ns = useNamespace("date-picker");
|
|
27
|
+
|
|
28
|
+
const showValue = computed({
|
|
29
|
+
get() {
|
|
30
|
+
return props.modelValue;
|
|
31
|
+
},
|
|
32
|
+
set(newValue) {
|
|
33
|
+
let val = newValue;
|
|
34
|
+
const defaultCount = 24 * 60 * 60 * 1000 - 1000;
|
|
35
|
+
try {
|
|
36
|
+
if (props.valueFormat === "x") {
|
|
37
|
+
if (isFunction(props.addTimestamp)) {
|
|
38
|
+
val = props.addTimestamp(val);
|
|
39
|
+
} else if (isArray(val)) {
|
|
40
|
+
if (isArray(props.addTimestamp)) {
|
|
41
|
+
console.log(val);
|
|
42
|
+
val = val.map((item, index) => {
|
|
43
|
+
if (!item) return item;
|
|
44
|
+
return +props.addTimestamp[index] + item;
|
|
45
|
+
});
|
|
46
|
+
} else {
|
|
47
|
+
if (attr.type !== "dates") {
|
|
48
|
+
val[1] = val[1] ? val[1] + defaultCount : val[1];
|
|
49
|
+
} else {
|
|
50
|
+
val.forEach((item) => item + defaultCount);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
} else if (val) {
|
|
54
|
+
val = val + (props.addTimestamp || defaultCount);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
} catch (error) {
|
|
58
|
+
console.error(error);
|
|
59
|
+
}
|
|
60
|
+
emit("update:modelValue", val);
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
useBuriedParams(props, emit, {
|
|
64
|
+
getContent: (val) => {
|
|
65
|
+
if (!val) return "";
|
|
66
|
+
try {
|
|
67
|
+
return new Date(val).toLocaleString();
|
|
68
|
+
} catch (error) {
|
|
69
|
+
console.error(error);
|
|
70
|
+
return val;
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
onMounted(() => {});
|
|
75
|
+
</script>
|
|
76
|
+
<style lang='less'>
|
|
77
|
+
</style>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { buriedParamsKey, searchComponentProps } from '../../../hooks';
|
|
2
|
+
import clearIcon from './clear-icon.vue';
|
|
3
|
+
import dateIcon from './date-icon.vue';
|
|
4
|
+
|
|
5
|
+
export const datePickerEmits = ["update:modelValue", buriedParamsKey];
|
|
6
|
+
export const datePickerProps = {
|
|
7
|
+
...searchComponentProps,
|
|
8
|
+
modelValue: [Date, Number, String, Array],
|
|
9
|
+
valueFormat: {
|
|
10
|
+
type: String,
|
|
11
|
+
default: 'x'
|
|
12
|
+
},
|
|
13
|
+
addTimestamp: [Number, String, Array, Function],
|
|
14
|
+
rangeSeparator: {
|
|
15
|
+
type: String,
|
|
16
|
+
default: '至',
|
|
17
|
+
},
|
|
18
|
+
clearIcon: {
|
|
19
|
+
type: [String, Object],
|
|
20
|
+
default() {
|
|
21
|
+
return clearIcon
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
prefixIcon: {
|
|
25
|
+
type: [String, Object],
|
|
26
|
+
default() {
|
|
27
|
+
return dateIcon
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
unlinkPanels: {
|
|
31
|
+
type: Boolean,
|
|
32
|
+
default: true
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import CtDialog from './src/dialog.vue';
|
|
2
|
+
|
|
3
|
+
/* istanbul ignore next */
|
|
4
|
+
CtDialog.install = function (Vue) {
|
|
5
|
+
// TODO 这里的组件名是这这里写死的,不是使用CtButton.name的形式,因为setup里面不可以直接什么组件的name属性,故而这里没有这个属性,后续可以考虑使用defineOptions(需要安装unplugin-vue-macros插件)
|
|
6
|
+
Vue.component('CtDialog', CtDialog);
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export default CtDialog;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<el-dialog
|
|
3
|
+
:class="[ns.b()]"
|
|
4
|
+
v-model="dialogVisible"
|
|
5
|
+
:title="title"
|
|
6
|
+
:width="width"
|
|
7
|
+
:show-close="false"
|
|
8
|
+
v-bind="$attrs"
|
|
9
|
+
>
|
|
10
|
+
<template #header="{ close, titleId, titleClass }">
|
|
11
|
+
<div :id="titleId" :class="[titleClass, ns.e('title')]">{{ title }}</div>
|
|
12
|
+
<ct-icon
|
|
13
|
+
:class="ns.e('close-btn')"
|
|
14
|
+
name="close_line"
|
|
15
|
+
size="16"
|
|
16
|
+
color="#d9dee7"
|
|
17
|
+
@click="close"
|
|
18
|
+
></ct-icon>
|
|
19
|
+
</template>
|
|
20
|
+
<slot></slot>
|
|
21
|
+
<template #footer>
|
|
22
|
+
<div :class="ns.e('footer')" v-if="!hasFooter">
|
|
23
|
+
<ct-button @click="handleConfirm">确定</ct-button>
|
|
24
|
+
</div>
|
|
25
|
+
<slot name="footer" v-else></slot>
|
|
26
|
+
</template>
|
|
27
|
+
</el-dialog>
|
|
28
|
+
</template>
|
|
29
|
+
|
|
30
|
+
<script setup>
|
|
31
|
+
import { ref, reactive, onMounted, computed } from "vue";
|
|
32
|
+
import { useNamespace } from "../../../hooks";
|
|
33
|
+
const ns = useNamespace("dialog");
|
|
34
|
+
|
|
35
|
+
const props = defineProps({
|
|
36
|
+
modelValue: {
|
|
37
|
+
type: Boolean,
|
|
38
|
+
required: true,
|
|
39
|
+
},
|
|
40
|
+
title: {
|
|
41
|
+
type: String,
|
|
42
|
+
},
|
|
43
|
+
width: {
|
|
44
|
+
type: [String, Number],
|
|
45
|
+
default: 480,
|
|
46
|
+
},
|
|
47
|
+
hasFooter: {
|
|
48
|
+
type: Boolean,
|
|
49
|
+
default: false,
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
const emit = defineEmits(["update:modelValue", "handleConfirm"]);
|
|
53
|
+
|
|
54
|
+
const dialogVisible = computed({
|
|
55
|
+
get() {
|
|
56
|
+
return props.modelValue;
|
|
57
|
+
},
|
|
58
|
+
set(val) {
|
|
59
|
+
emit("update:modelValue", val);
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
const handleConfirm = () => {
|
|
64
|
+
emit("handleConfirm");
|
|
65
|
+
dialogVisible.value = false;
|
|
66
|
+
};
|
|
67
|
+
</script>
|
|
68
|
+
|
|
69
|
+
<style lang='less'>
|
|
70
|
+
.el-dialog.ct-dialog {
|
|
71
|
+
@R: .el-dialog;
|
|
72
|
+
@{R}__header {
|
|
73
|
+
padding: 26px 40px !important;
|
|
74
|
+
margin-right: 0 !important;
|
|
75
|
+
position: relative;
|
|
76
|
+
}
|
|
77
|
+
@{R}__title {
|
|
78
|
+
display: flex;
|
|
79
|
+
align-items: center;
|
|
80
|
+
&::before {
|
|
81
|
+
content: "";
|
|
82
|
+
width: 8px;
|
|
83
|
+
height: 8px;
|
|
84
|
+
border-radius: var(--ct-border-radius-s);
|
|
85
|
+
margin-right: 12px;
|
|
86
|
+
background: var(--ct-color-primary);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
.ct-dialog__close-btn {
|
|
90
|
+
position: absolute;
|
|
91
|
+
top: 20px;
|
|
92
|
+
right: 20px;
|
|
93
|
+
cursor: pointer;
|
|
94
|
+
}
|
|
95
|
+
@{R}__body {
|
|
96
|
+
padding: 0 40px 32px !important;
|
|
97
|
+
font-size: 15px;
|
|
98
|
+
line-height: 28px;
|
|
99
|
+
}
|
|
100
|
+
@{R}__footer {
|
|
101
|
+
padding: 0 40px 32px !important;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
</style>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import CtEmpty from './src/empty.vue';
|
|
2
|
+
|
|
3
|
+
/* istanbul ignore next */
|
|
4
|
+
CtEmpty.install = function (Vue) {
|
|
5
|
+
// TODO 这里的组件名是这这里写死的,不是使用CtButton.name的形式,因为setup里面不可以直接什么组件的name属性,故而这里没有这个属性,后续可以考虑使用defineOptions(需要安装unplugin-vue-macros插件)
|
|
6
|
+
Vue.component('CtEmpty', CtEmpty);
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export default CtEmpty;
|