v-nuxt-ui 0.1.35 → 0.1.36
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/dist/module.json +1 -1
- package/dist/runtime/components/button/Dropdown.vue +5 -1
- package/dist/runtime/components/date-picker/Input.d.vue.ts +9 -1
- package/dist/runtime/components/date-picker/Input.vue +55 -11
- package/dist/runtime/components/date-picker/Input.vue.d.ts +9 -1
- package/dist/runtime/components/date-picker/index.vue +3 -3
- package/dist/runtime/components/form/field/DatePicker.vue +1 -1
- package/dist/runtime/components/sys/table/CreateModal.vue +31 -33
- package/dist/runtime/components/sys/table/Table.vue +6 -4
- package/dist/runtime/components/sys/user/Table.vue +44 -27
- package/dist/runtime/components/table/permission/TablePermissionConfig.d.vue.ts +2 -2
- package/dist/runtime/components/table/permission/TablePermissionConfig.vue +3 -3
- package/dist/runtime/components/table/permission/TablePermissionConfig.vue.d.ts +2 -2
- package/dist/runtime/components/table/permission/TablePermissionTab.vue +7 -4
- package/dist/runtime/components/table/query/where/Newer.vue +2 -0
- package/dist/runtime/components/table/query/where/index.vue +46 -15
- package/dist/runtime/components/table/query/where/simple/item/ColumnPicker.vue +9 -4
- package/dist/runtime/components/table/query/where/simple/item/OprPicker.vue +3 -3
- package/dist/runtime/components/table/query/where/simple/item/opr/AsyncSelect.vue +45 -48
- package/dist/runtime/components/table/query/where/simple/item/opr/DatePicker.vue +137 -131
- package/dist/runtime/components/table/query/where/simple/item/opr/Select.d.vue.ts +4 -2
- package/dist/runtime/components/table/query/where/simple/item/opr/Select.vue +40 -40
- package/dist/runtime/components/table/query/where/simple/item/opr/Select.vue.d.ts +4 -2
- package/dist/runtime/components/table/query/where/simple/item/opr/index.vue +2 -0
- package/dist/runtime/components/table/settings/TableSettings.d.vue.ts +1 -1
- package/dist/runtime/components/table/settings/TableSettings.vue +0 -3
- package/dist/runtime/components/table/settings/TableSettings.vue.d.ts +1 -1
- package/dist/runtime/composables/api/sys/useRoleApi.js +3 -1
- package/dist/runtime/composables/api/sys/useUserApi.js +3 -1
- package/dist/runtime/composables/useDate.js +8 -8
- package/dist/runtime/constants/index.d.ts +1 -0
- package/dist/runtime/constants/index.js +1 -0
- package/dist/runtime/constants/options.js +2 -3
- package/dist/runtime/constants/table.d.ts +2 -0
- package/dist/runtime/constants/table.js +8 -0
- package/dist/runtime/types/components/table/column.d.ts +4 -3
- package/dist/runtime/types/components/table/query/where.d.ts +1 -5
- package/package.json +1 -1
- package/dist/runtime/components/table/query/where/simple/index.d.vue.ts +0 -21
- package/dist/runtime/components/table/query/where/simple/index.vue +0 -52
- package/dist/runtime/components/table/query/where/simple/index.vue.d.ts +0 -21
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
import { computed,
|
|
2
|
+
import { computed, ref, nextTick } from "vue";
|
|
3
3
|
import { useTableOpr } from "#v/composables/table/useTableOpr";
|
|
4
4
|
import { useToast } from "@nuxt/ui/composables";
|
|
5
|
-
import
|
|
5
|
+
import TableQueryWhereSimpleItem from "#v/components/table/query/where/simple/item/index.vue";
|
|
6
6
|
import TableQueryWhereNewer from "#v/components/table/query/where/Newer.vue";
|
|
7
7
|
const props = defineProps({
|
|
8
8
|
whereOptions: { type: Array, required: true },
|
|
@@ -23,7 +23,19 @@ const selectedWhereFields = computed(() => {
|
|
|
23
23
|
const unselectedWhereFields = computed(() => {
|
|
24
24
|
return props.whereOptions.map((option) => option.field).filter((field) => !selectedWhereFields.value.includes(field));
|
|
25
25
|
});
|
|
26
|
-
const
|
|
26
|
+
const itemRefMap = ref(/* @__PURE__ */ new Map());
|
|
27
|
+
function setItemRef(field, el) {
|
|
28
|
+
if (el && "focus" in el && typeof el.focus === "function") {
|
|
29
|
+
itemRefMap.value.set(field, el);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const onRemoveFilter = (field) => {
|
|
33
|
+
const updatedItems = props.whereQuery?.items?.filter((query) => query.field !== field) ?? [];
|
|
34
|
+
props.onUpdateWhereQuery({
|
|
35
|
+
...props.whereQuery,
|
|
36
|
+
items: updatedItems
|
|
37
|
+
});
|
|
38
|
+
};
|
|
27
39
|
const onNewField = (field) => {
|
|
28
40
|
const option = props.whereOptions.find((option2) => option2.field === field);
|
|
29
41
|
if (!option || !option.type) {
|
|
@@ -44,7 +56,10 @@ const onNewField = (field) => {
|
|
|
44
56
|
}]
|
|
45
57
|
});
|
|
46
58
|
nextTick(() => {
|
|
47
|
-
|
|
59
|
+
const item = itemRefMap.value.get(field);
|
|
60
|
+
if (item) {
|
|
61
|
+
item.focus();
|
|
62
|
+
}
|
|
48
63
|
});
|
|
49
64
|
};
|
|
50
65
|
const isWhereQueryEmpty = computed(() => {
|
|
@@ -52,7 +67,12 @@ const isWhereQueryEmpty = computed(() => {
|
|
|
52
67
|
(props.whereQuery?.items?.filter((query) => props.whereOptions.find((option) => option.field === query.field)).length ?? 0) === 0 && (props.whereQuery?.groups?.length ?? 0) === 0;
|
|
53
68
|
});
|
|
54
69
|
const focusField = (field) => {
|
|
55
|
-
|
|
70
|
+
const item = itemRefMap.value.get(field);
|
|
71
|
+
if (item) {
|
|
72
|
+
item.focus();
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
return false;
|
|
56
76
|
};
|
|
57
77
|
defineExpose({ focusField });
|
|
58
78
|
</script>
|
|
@@ -61,16 +81,27 @@ defineExpose({ focusField });
|
|
|
61
81
|
<div class="flex items-start gap-2 pl-4 pr-2.5 py-2.5">
|
|
62
82
|
<!-- conditions -->
|
|
63
83
|
<div class="flex flex-wrap items-center gap-2.5">
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
84
|
+
<!-- key如果是field,那么field修改后,不能聚焦后面的组件,所以这里的key用idx代替 -->
|
|
85
|
+
<template v-if="!isWhereQueryEmpty">
|
|
86
|
+
<TableQueryWhereSimpleItem
|
|
87
|
+
v-for="(item, idx) in whereQuery?.items"
|
|
88
|
+
:ref="(el) => setItemRef(item.field, el)"
|
|
89
|
+
:key="idx"
|
|
90
|
+
:where-query-item="item"
|
|
91
|
+
:options="whereOptions"
|
|
92
|
+
:fetching="fetching"
|
|
93
|
+
:trigger-fetching="() => triggerFetching(true)"
|
|
94
|
+
@remove="onRemoveFilter"
|
|
95
|
+
@update:where-query-item="(newWhereQueryItem) => {
|
|
96
|
+
const updatedItems = [...props.whereQuery?.items ?? []];
|
|
97
|
+
updatedItems[idx] = newWhereQueryItem;
|
|
98
|
+
onUpdateWhereQuery({
|
|
99
|
+
...whereQuery,
|
|
100
|
+
items: updatedItems
|
|
101
|
+
});
|
|
102
|
+
}"
|
|
103
|
+
/>
|
|
104
|
+
</template>
|
|
74
105
|
<TableQueryWhereNewer
|
|
75
106
|
:options="whereOptions"
|
|
76
107
|
:unselected-fields="unselectedWhereFields"
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { computed, nextTick } from "vue";
|
|
3
3
|
import { useTableOpr } from "#v/composables/table/useTableOpr";
|
|
4
4
|
import ButtonDropdown from "#v/components/button/Dropdown.vue";
|
|
5
|
+
import { tableWhereQueryItemIconMap } from "#v/constants";
|
|
5
6
|
const props = defineProps({
|
|
6
7
|
options: { type: Array, required: true },
|
|
7
8
|
disabled: { type: Boolean, required: false },
|
|
@@ -16,6 +17,7 @@ const items = computed(() => {
|
|
|
16
17
|
items: props.options.map((option) => ({
|
|
17
18
|
label: option.label,
|
|
18
19
|
value: option.field,
|
|
20
|
+
icon: tableWhereQueryItemIconMap.get(option.type) || "field",
|
|
19
21
|
onSelect: () => {
|
|
20
22
|
modelValue.value = option.field;
|
|
21
23
|
nextTick(() => {
|
|
@@ -43,9 +45,8 @@ const modelValue = computed({
|
|
|
43
45
|
};
|
|
44
46
|
}
|
|
45
47
|
});
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
return option?.label || "";
|
|
48
|
+
const currentOption = computed(() => {
|
|
49
|
+
return props.options.find((opt) => opt.field === modelValue.value);
|
|
49
50
|
});
|
|
50
51
|
</script>
|
|
51
52
|
|
|
@@ -58,8 +59,12 @@ const currentLabel = computed(() => {
|
|
|
58
59
|
:size="'sm'"
|
|
59
60
|
:color="'neutral'"
|
|
60
61
|
:variant="'outline'"
|
|
61
|
-
:label="
|
|
62
|
+
:label="currentOption?.label || '\u9009\u62E9\u5B57\u6BB5'"
|
|
62
63
|
:disabled="disabled"
|
|
64
|
+
:icon="tableWhereQueryItemIconMap.get(currentOption?.type ?? 'unknown') || 'field'"
|
|
65
|
+
:ui="{
|
|
66
|
+
label: 'font-bold'
|
|
67
|
+
}"
|
|
63
68
|
/>
|
|
64
69
|
</ButtonDropdown>
|
|
65
70
|
</template>
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
import { ref, computed, useTemplateRef } from "vue";
|
|
2
|
+
import { ref, computed, useTemplateRef, watch } from "vue";
|
|
3
3
|
import { useDebounceFn } from "@vueuse/core";
|
|
4
4
|
import { defu } from "defu";
|
|
5
5
|
import { useFetching } from "#v/composables/useBoolean";
|
|
6
6
|
import { isEmptyString } from "#v/utils";
|
|
7
|
-
import ButtonDropdown from "#v/components/button/Dropdown.vue";
|
|
8
7
|
const props = defineProps({
|
|
9
8
|
label: { type: String, required: true },
|
|
10
9
|
disabled: { type: Boolean, required: false },
|
|
@@ -57,7 +56,7 @@ const items = computed(() => {
|
|
|
57
56
|
value: p[props.valueField]
|
|
58
57
|
})).filter((p) => p.label && !isEmptyString(String(p.value)));
|
|
59
58
|
});
|
|
60
|
-
const
|
|
59
|
+
const inputMenuValue = computed({
|
|
61
60
|
get() {
|
|
62
61
|
return whereQueryItem.value.value;
|
|
63
62
|
},
|
|
@@ -80,26 +79,16 @@ const commandPaletteValue = computed({
|
|
|
80
79
|
};
|
|
81
80
|
}
|
|
82
81
|
});
|
|
83
|
-
const
|
|
84
|
-
const options = [
|
|
85
|
-
{
|
|
86
|
-
id: "fields",
|
|
87
|
-
items: items.value,
|
|
88
|
-
ignoreFilter: true
|
|
89
|
-
}
|
|
90
|
-
];
|
|
91
|
-
return options;
|
|
92
|
-
});
|
|
93
|
-
const onFetchItems = async (searchTerm) => {
|
|
82
|
+
const onFetchItems = async (searchTerm2) => {
|
|
94
83
|
try {
|
|
95
84
|
startFetching();
|
|
96
85
|
const query = {
|
|
97
86
|
pagination: { pageNum: 1, pageSize: 10 },
|
|
98
87
|
whereQuery: { items: [] }
|
|
99
88
|
};
|
|
100
|
-
if (!isEmptyString(
|
|
89
|
+
if (!isEmptyString(searchTerm2)) {
|
|
101
90
|
props.searchFields.forEach((field) => {
|
|
102
|
-
query.whereQuery?.items?.push({ field, opr: "like", value:
|
|
91
|
+
query.whereQuery?.items?.push({ field, opr: "like", value: searchTerm2, andOr: "or" });
|
|
103
92
|
});
|
|
104
93
|
}
|
|
105
94
|
const result = await props.listApi(defu(query, props.extraQuery));
|
|
@@ -110,45 +99,53 @@ const onFetchItems = async (searchTerm) => {
|
|
|
110
99
|
endFetching();
|
|
111
100
|
}
|
|
112
101
|
};
|
|
102
|
+
const searchTerm = ref("");
|
|
113
103
|
const onDebounceFetchItems = useDebounceFn(onFetchItems, 512);
|
|
114
|
-
|
|
104
|
+
watch(searchTerm, (newVal) => {
|
|
105
|
+
onDebounceFetchItems(newVal);
|
|
106
|
+
}, { immediate: false });
|
|
107
|
+
const inputMenuRef = useTemplateRef("inputMenu");
|
|
115
108
|
defineExpose({
|
|
116
109
|
focus: () => {
|
|
117
|
-
|
|
110
|
+
inputMenuRef.value?.inputRef.focus();
|
|
118
111
|
}
|
|
119
112
|
});
|
|
120
113
|
</script>
|
|
121
114
|
|
|
122
115
|
<template>
|
|
123
|
-
<
|
|
124
|
-
ref="
|
|
125
|
-
v-model="
|
|
126
|
-
|
|
116
|
+
<UInputMenu
|
|
117
|
+
ref="inputMenu"
|
|
118
|
+
v-model:search-term="searchTerm"
|
|
119
|
+
v-model="inputMenuValue"
|
|
120
|
+
:items="items"
|
|
121
|
+
:placeholder="placeholder"
|
|
127
122
|
multiple
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
123
|
+
color="neutral"
|
|
124
|
+
delete-icon="i-lucide-trash"
|
|
125
|
+
value-key="value"
|
|
126
|
+
clear
|
|
127
|
+
clear-icon="i-lucide-circle-x"
|
|
128
|
+
icon=""
|
|
129
|
+
:loading="fetching"
|
|
130
|
+
:disabled="disabled"
|
|
131
|
+
open-on-focus
|
|
132
|
+
trailing
|
|
133
|
+
:ui="{
|
|
134
|
+
root: 'rounded-none min-w-32',
|
|
135
|
+
// TODO: 不然有rounded,这个应该是个bug
|
|
136
|
+
content: 'min-w-fit',
|
|
137
|
+
tagsInput: 'min-w-4 w-0'
|
|
138
|
+
}"
|
|
139
|
+
:content="{
|
|
140
|
+
align: 'start'
|
|
141
|
+
}"
|
|
142
|
+
@update:open="(opened) => {
|
|
143
|
+
if (opened) {
|
|
144
|
+
onFetchItems(searchTerm);
|
|
145
|
+
}
|
|
146
|
+
}"
|
|
147
|
+
@update:model-value="() => {
|
|
148
|
+
inputMenuRef?.inputRef.focus();
|
|
149
|
+
}"
|
|
150
|
+
/>
|
|
154
151
|
</template>
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import { computed, useTemplateRef, nextTick, ref } from "vue";
|
|
3
|
-
import { now
|
|
3
|
+
import { now } from "@internationalized/date";
|
|
4
4
|
import dayjs from "dayjs";
|
|
5
5
|
import { useDate } from "#v/composables/useDate";
|
|
6
6
|
import { useApp } from "#v/composables/useApp";
|
|
7
|
-
import {
|
|
7
|
+
import { TIME_ZONE } from "#v/constants";
|
|
8
8
|
import DatePickerInput from "#v/components/date-picker/Input.vue";
|
|
9
9
|
defineProps({
|
|
10
10
|
disabled: { type: Boolean, required: false }
|
|
@@ -55,177 +55,183 @@ const calendarValue = computed({
|
|
|
55
55
|
whereQueryItem.value = { ...whereQueryItem.value, value: updatedValue };
|
|
56
56
|
}
|
|
57
57
|
});
|
|
58
|
-
const
|
|
59
|
-
|
|
58
|
+
const displayDateFormat = "YYYY-MM-DD";
|
|
59
|
+
const startDateStrValueInput = useTemplateRef("startDateStrValueInput");
|
|
60
|
+
const endDateStrValueInput = useTemplateRef("endDateStrValueInput");
|
|
61
|
+
const startDateStrValue = computed({
|
|
62
|
+
get() {
|
|
63
|
+
return useDate().dateValueToDayjs(calendarValue.value?.start)?.format(displayDateFormat) ?? void 0;
|
|
64
|
+
},
|
|
60
65
|
set(newValue) {
|
|
61
66
|
if (!newValue) {
|
|
62
|
-
|
|
67
|
+
calendarValue.value = { ...calendarValue.value, start: void 0 };
|
|
63
68
|
return;
|
|
64
69
|
}
|
|
65
|
-
const formattedDayjs = dayjs(newValue,
|
|
70
|
+
const formattedDayjs = dayjs(newValue, displayDateFormat, true);
|
|
66
71
|
if (formattedDayjs.isValid()) {
|
|
67
|
-
|
|
72
|
+
calendarValue.value = {
|
|
73
|
+
...calendarValue.value,
|
|
74
|
+
start: useDate().dayjsToDateValue(formattedDayjs)
|
|
75
|
+
};
|
|
68
76
|
}
|
|
69
77
|
}
|
|
70
78
|
});
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
79
|
+
const endDateStrValue = computed({
|
|
80
|
+
get() {
|
|
81
|
+
return useDate().dateValueToDayjs(calendarValue.value?.end)?.format(displayDateFormat) ?? void 0;
|
|
82
|
+
},
|
|
83
|
+
set(newValue) {
|
|
84
|
+
if (!newValue) {
|
|
85
|
+
calendarValue.value = { ...calendarValue.value, end: void 0 };
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
const formattedDayjs = dayjs(newValue, displayDateFormat, true);
|
|
89
|
+
if (formattedDayjs.isValid()) {
|
|
90
|
+
calendarValue.value = {
|
|
91
|
+
...calendarValue.value,
|
|
92
|
+
end: useDate().dayjsToDateValue(formattedDayjs)
|
|
93
|
+
};
|
|
94
|
+
}
|
|
82
95
|
}
|
|
83
|
-
);
|
|
96
|
+
});
|
|
84
97
|
const singleDateStrValueInput = useTemplateRef("singleDateStrValueInput");
|
|
85
|
-
const singleDateStrValue =
|
|
86
|
-
()
|
|
87
|
-
|
|
88
|
-
|
|
98
|
+
const singleDateStrValue = computed({
|
|
99
|
+
get() {
|
|
100
|
+
return useDate().dateValueToDayjs(calendarValue.value)?.format(displayDateFormat) || void 0;
|
|
101
|
+
},
|
|
102
|
+
set(newValue) {
|
|
103
|
+
if (!newValue) {
|
|
104
|
+
calendarValue.value = null;
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
const formattedDayjs = dayjs(newValue, displayDateFormat, true);
|
|
108
|
+
if (formattedDayjs.isValid()) {
|
|
109
|
+
calendarValue.value = useDate().dayjsToDateValue(formattedDayjs);
|
|
110
|
+
}
|
|
89
111
|
}
|
|
90
|
-
);
|
|
91
|
-
const
|
|
112
|
+
});
|
|
113
|
+
const popoverOpen = ref(false);
|
|
114
|
+
const onOpenCalendar = () => {
|
|
115
|
+
popoverOpen.value = true;
|
|
116
|
+
};
|
|
117
|
+
const onCloseCalendar = () => {
|
|
118
|
+
popoverOpen.value = false;
|
|
119
|
+
};
|
|
120
|
+
const focusStartInput = () => {
|
|
92
121
|
nextTick(() => {
|
|
93
|
-
|
|
94
|
-
|
|
122
|
+
if (isRangeOpr.value) {
|
|
123
|
+
startDateStrValueInput.value?.focus();
|
|
124
|
+
} else {
|
|
125
|
+
singleDateStrValueInput.value?.focus();
|
|
126
|
+
}
|
|
95
127
|
});
|
|
96
128
|
};
|
|
97
|
-
const popoverOpen = ref(false);
|
|
98
129
|
defineExpose({
|
|
99
130
|
focus: () => {
|
|
100
|
-
|
|
101
|
-
dateStrInputFocus();
|
|
131
|
+
focusStartInput();
|
|
102
132
|
}
|
|
103
133
|
});
|
|
134
|
+
const date = useDate();
|
|
104
135
|
const dateRangeShortcuts = [
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
return {
|
|
110
|
-
start: startOfWeek(today, "zh-CN", "mon"),
|
|
111
|
-
end: endOfWeek(today, "zh-CN", "mon")
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
},
|
|
115
|
-
{
|
|
116
|
-
label: "\u672C\u6708",
|
|
117
|
-
dateFn: () => {
|
|
118
|
-
const today = now(TIME_ZONE);
|
|
119
|
-
return {
|
|
120
|
-
start: startOfMonth(today),
|
|
121
|
-
end: endOfMonth(today)
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
},
|
|
125
|
-
{
|
|
126
|
-
label: "\u4E0A\u5468",
|
|
127
|
-
dateFn: () => {
|
|
128
|
-
const today = now(TIME_ZONE);
|
|
129
|
-
const lastWeek = today.subtract({ weeks: 1 });
|
|
130
|
-
return {
|
|
131
|
-
start: startOfWeek(lastWeek, "zh-CN", "mon"),
|
|
132
|
-
end: endOfWeek(lastWeek, "zh-CN", "mon")
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
},
|
|
136
|
-
{
|
|
137
|
-
label: "\u4E0A\u6708",
|
|
138
|
-
dateFn: () => {
|
|
139
|
-
const today = now(TIME_ZONE);
|
|
140
|
-
const lastMonth = today.subtract({ months: 1 });
|
|
141
|
-
return {
|
|
142
|
-
start: startOfMonth(lastMonth),
|
|
143
|
-
end: endOfMonth(lastMonth)
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
}
|
|
136
|
+
date.lastWeekDateShortcut,
|
|
137
|
+
date.lastMonthDateShortcut,
|
|
138
|
+
date.currentWeekDateShortcut,
|
|
139
|
+
date.currentMonthDateShortcut
|
|
147
140
|
];
|
|
148
|
-
const isValueEmpty = computed(() => {
|
|
149
|
-
if (isNoCalendarOpr.value) return false;
|
|
150
|
-
const value = whereQueryItem.value.value;
|
|
151
|
-
if (isRangeOpr.value) {
|
|
152
|
-
return value === null || value?.start === null && value?.end === null;
|
|
153
|
-
}
|
|
154
|
-
return value === null || value === "";
|
|
155
|
-
});
|
|
156
|
-
const displayValue = computed(() => {
|
|
157
|
-
if (isValueEmpty.value) return "";
|
|
158
|
-
if (isRangeOpr.value) {
|
|
159
|
-
const range = calendarValue.value;
|
|
160
|
-
const start = useDate().dateValueToDayjs(range?.start)?.format(dateFormat) || "";
|
|
161
|
-
const end = useDate().dateValueToDayjs(range?.end)?.format(dateFormat) || "";
|
|
162
|
-
return `${start} ~ ${end}`;
|
|
163
|
-
}
|
|
164
|
-
return useDate().dateValueToDayjs(calendarValue.value)?.format(dateFormat) || "";
|
|
165
|
-
});
|
|
166
141
|
</script>
|
|
167
142
|
|
|
168
143
|
<template>
|
|
169
144
|
<UPopover
|
|
170
145
|
v-model:open="popoverOpen"
|
|
146
|
+
:dismissible="false"
|
|
171
147
|
:content="{
|
|
172
148
|
align: 'start',
|
|
173
|
-
onCloseAutoFocus: (e) => e.preventDefault()
|
|
149
|
+
onCloseAutoFocus: (e) => e.preventDefault(),
|
|
150
|
+
onOpenAutoFocus: (e) => e.preventDefault()
|
|
174
151
|
}"
|
|
175
152
|
>
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
</UButton>
|
|
153
|
+
<!-- 输入框直接暴露 -->
|
|
154
|
+
<template v-if="isNoCalendarOpr" />
|
|
179
155
|
|
|
180
|
-
<template
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
156
|
+
<template v-else-if="isRangeOpr">
|
|
157
|
+
<!-- 必须加这个div,不然第一个输入框无法正确渲染 -->
|
|
158
|
+
<div />
|
|
159
|
+
<DatePickerInput
|
|
160
|
+
ref="startDateStrValueInput"
|
|
161
|
+
v-model:value="startDateStrValue"
|
|
162
|
+
icon=""
|
|
163
|
+
input-class="w-32"
|
|
164
|
+
placeholder="YYYY-MM-DD"
|
|
165
|
+
@focus="onOpenCalendar"
|
|
166
|
+
@blur="onCloseCalendar"
|
|
167
|
+
/>
|
|
168
|
+
<UBadge variant="outline" color="neutral">
|
|
169
|
+
~
|
|
170
|
+
</UBadge>
|
|
171
|
+
<DatePickerInput
|
|
172
|
+
ref="endDateStrValueInput"
|
|
173
|
+
v-model:value="endDateStrValue"
|
|
174
|
+
icon=""
|
|
175
|
+
input-class="w-32"
|
|
176
|
+
placeholder="YYYY-MM-DD"
|
|
177
|
+
@focus="onOpenCalendar"
|
|
178
|
+
@blur="onCloseCalendar"
|
|
179
|
+
/>
|
|
180
|
+
</template>
|
|
196
181
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
182
|
+
<template v-else>
|
|
183
|
+
<div />
|
|
184
|
+
<DatePickerInput
|
|
185
|
+
ref="singleDateStrValueInput"
|
|
186
|
+
v-model:value="singleDateStrValue"
|
|
187
|
+
icon=""
|
|
188
|
+
input-class="w-32"
|
|
189
|
+
placeholder="YYYY-MM-DD"
|
|
190
|
+
@focus="onOpenCalendar"
|
|
191
|
+
@blur="onCloseCalendar"
|
|
192
|
+
/>
|
|
193
|
+
</template>
|
|
204
194
|
|
|
195
|
+
<template #content>
|
|
196
|
+
<div
|
|
197
|
+
class="p-3 flex flex-col gap-2"
|
|
198
|
+
@mousedown.prevent
|
|
199
|
+
>
|
|
205
200
|
<UCalendar
|
|
206
201
|
v-if="!isNoCalendarOpr"
|
|
207
202
|
:model-value="calendarValue"
|
|
208
203
|
:range="isRangeOpr"
|
|
209
204
|
size="sm"
|
|
205
|
+
variant="subtle"
|
|
210
206
|
:disabled="disabled"
|
|
211
207
|
:number-of-months="app.isMobile.value || !isRangeOpr ? 1 : 2"
|
|
212
208
|
@update:model-value="(newValue) => calendarValue = newValue ?? null"
|
|
213
209
|
/>
|
|
214
210
|
|
|
215
|
-
<
|
|
216
|
-
<
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
211
|
+
<UFieldGroup class="ml-auto">
|
|
212
|
+
<UButton
|
|
213
|
+
v-for="shortcut in isRangeOpr ? dateRangeShortcuts : []"
|
|
214
|
+
:key="shortcut.label"
|
|
215
|
+
:label="shortcut.label"
|
|
216
|
+
size="xs"
|
|
217
|
+
color="neutral"
|
|
218
|
+
variant="outline"
|
|
219
|
+
:disabled="disabled"
|
|
220
|
+
:tabindex="-1"
|
|
221
|
+
@click="calendarValue = shortcut.dateFn()"
|
|
222
|
+
/>
|
|
223
|
+
<UButton
|
|
224
|
+
v-if="!isRangeOpr"
|
|
225
|
+
label="今天"
|
|
226
|
+
size="xs"
|
|
227
|
+
color="neutral"
|
|
228
|
+
variant="outline"
|
|
229
|
+
:tabindex="-1"
|
|
230
|
+
@click="() => {
|
|
231
|
+
calendarValue = now(TIME_ZONE);
|
|
232
|
+
}"
|
|
233
|
+
/>
|
|
234
|
+
</UFieldGroup>
|
|
229
235
|
</div>
|
|
230
236
|
</template>
|
|
231
237
|
</UPopover>
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { WhereQueryItem } from '#v/types';
|
|
2
|
+
import type { InputMenuItem, InputMenuProps } from '@nuxt/ui';
|
|
2
3
|
declare const __VLS_export: <T>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
|
|
3
4
|
props: import("vue").PublicProps & __VLS_PrettifyLocal<({
|
|
4
5
|
disabled?: boolean;
|
|
5
|
-
items:
|
|
6
|
+
items: InputMenuItem[];
|
|
7
|
+
placeholder?: InputMenuProps["placeholder"];
|
|
6
8
|
} & {
|
|
7
9
|
whereQueryItem: WhereQueryItem<T>;
|
|
8
10
|
}) & {
|