mirror of
https://github.com/mayswind/ezbookkeeping.git
synced 2026-05-18 08:44:25 +08:00
migrate tree view selection sheet to composition API and typescript
This commit is contained in:
@@ -6,32 +6,32 @@
|
|||||||
<div class="swipe-handler"></div>
|
<div class="swipe-handler"></div>
|
||||||
<div class="left"></div>
|
<div class="left"></div>
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<f7-link sheet-close :text="$t('Done')"></f7-link>
|
<f7-link sheet-close :text="tt('Done')"></f7-link>
|
||||||
</div>
|
</div>
|
||||||
</f7-toolbar>
|
</f7-toolbar>
|
||||||
<f7-page-content>
|
<f7-page-content>
|
||||||
<f7-treeview>
|
<f7-treeview>
|
||||||
<f7-treeview-item item-toggle
|
<f7-treeview-item item-toggle
|
||||||
:opened="isPrimaryItemHasSecondaryValue(item)"
|
:opened="isPrimaryItemHasSecondaryValue(item)"
|
||||||
:label="$tIf((primaryTitleField ? item[primaryTitleField] : item), primaryTitleI18n)"
|
:label="ti((primaryTitleField ? item[primaryTitleField] : item) as string, !!primaryTitleI18n)"
|
||||||
:key="primaryKeyField ? item[primaryKeyField] : item"
|
:key="primaryKeyField ? item[primaryKeyField] : item"
|
||||||
v-for="item in items"
|
v-for="item in items"
|
||||||
v-show="item && (!primaryHiddenField || !item[primaryHiddenField])">
|
v-show="item && (!primaryHiddenField || !item[primaryHiddenField])">
|
||||||
<template #media>
|
<template #media>
|
||||||
<ItemIcon :icon-type="primaryIconType" :icon-id="item[primaryIconField]"
|
<ItemIcon :icon-type="primaryIconType" :icon-id="item[primaryIconField]"
|
||||||
:color="item[primaryColorField]" v-if="primaryIconField"></ItemIcon>
|
:color="primaryColorField ? item[primaryColorField] : undefined" v-if="primaryIconField"></ItemIcon>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<f7-treeview-item selectable
|
<f7-treeview-item selectable
|
||||||
:selected="isSecondarySelected(subItem)"
|
:selected="isSecondarySelected(subItem)"
|
||||||
:label="$tIf((secondaryTitleField ? subItem[secondaryTitleField] : subItem), secondaryTitleI18n)"
|
:label="ti((secondaryTitleField ? (subItem as Record<string, unknown>)[secondaryTitleField] : subItem) as string, !!secondaryTitleI18n)"
|
||||||
:key="secondaryKeyField ? subItem[secondaryKeyField] : subItem"
|
:key="secondaryKeyField ? (subItem as Record<string, unknown>)[secondaryKeyField] : subItem"
|
||||||
v-for="subItem in item[primarySubItemsField]"
|
v-for="subItem in item[primarySubItemsField]"
|
||||||
v-show="subItem && (!secondaryHiddenField || !subItem[secondaryHiddenField])"
|
v-show="subItem && (!secondaryHiddenField || !(subItem as Record<string, unknown>)[secondaryHiddenField])"
|
||||||
@click="onSecondaryItemClicked(subItem)">
|
@click="onSecondaryItemClicked(subItem)">
|
||||||
<template #media>
|
<template #media>
|
||||||
<ItemIcon :icon-type="secondaryIconType" :icon-id="subItem[secondaryIconField]"
|
<ItemIcon :icon-type="secondaryIconType" :icon-id="(subItem as Record<string, unknown>)[secondaryIconField]"
|
||||||
:color="subItem[secondaryColorField]" v-if="secondaryIconField"></ItemIcon>
|
:color="secondaryColorField ? (subItem as Record<string, unknown>)[secondaryColorField] : undefined" v-if="secondaryIconField"></ItemIcon>
|
||||||
</template>
|
</template>
|
||||||
</f7-treeview-item>
|
</f7-treeview-item>
|
||||||
</f7-treeview-item>
|
</f7-treeview-item>
|
||||||
@@ -40,112 +40,119 @@
|
|||||||
</f7-sheet>
|
</f7-sheet>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
|
import { ref, computed } from 'vue';
|
||||||
|
|
||||||
|
import { useI18n } from '@/locales/helpers.ts';
|
||||||
|
|
||||||
import { isArray } from '@/lib/common.ts';
|
import { isArray } from '@/lib/common.ts';
|
||||||
import { scrollToSelectedItem } from '@/lib/ui/mobile.ts';
|
import { type Framework7Dom, scrollToSelectedItem } from '@/lib/ui/mobile.ts';
|
||||||
|
|
||||||
export default {
|
const props = defineProps<{
|
||||||
props: [
|
modelValue: unknown;
|
||||||
'modelValue',
|
primaryKeyField?: string;
|
||||||
'primaryKeyField',
|
primaryTitleField?: string;
|
||||||
'primaryValueField',
|
primaryTitleI18n?: boolean;
|
||||||
'primaryTitleField',
|
primaryIconField?: string;
|
||||||
'primaryTitleI18n',
|
primaryIconType?: string;
|
||||||
'primaryIconField',
|
primaryColorField?: string;
|
||||||
'primaryIconType',
|
primaryHiddenField?: string;
|
||||||
'primaryColorField',
|
primarySubItemsField: string;
|
||||||
'primaryHiddenField',
|
secondaryKeyField?: string;
|
||||||
'primarySubItemsField',
|
secondaryValueField?: string;
|
||||||
'secondaryKeyField',
|
secondaryTitleField?: string;
|
||||||
'secondaryValueField',
|
secondaryTitleI18n?: boolean;
|
||||||
'secondaryTitleField',
|
secondaryIconField?: string;
|
||||||
'secondaryTitleI18n',
|
secondaryIconType?: string;
|
||||||
'secondaryIconField',
|
secondaryColorField?: string;
|
||||||
'secondaryIconType',
|
secondaryHiddenField?: string;
|
||||||
'secondaryColorField',
|
items: Record<string, unknown>[];
|
||||||
'secondaryHiddenField',
|
show: boolean;
|
||||||
'items',
|
}>();
|
||||||
'show'
|
|
||||||
],
|
|
||||||
emits: [
|
|
||||||
'update:modelValue',
|
|
||||||
'update:show'
|
|
||||||
],
|
|
||||||
data() {
|
|
||||||
const self = this;
|
|
||||||
|
|
||||||
return {
|
const emit = defineEmits<{
|
||||||
currentValue: self.modelValue
|
(e: 'update:modelValue', value: unknown): void;
|
||||||
}
|
(e: 'update:show', value: boolean): void;
|
||||||
},
|
}>();
|
||||||
computed: {
|
|
||||||
heightClass() {
|
|
||||||
let count = 0;
|
|
||||||
|
|
||||||
if (isArray(this.items)) {
|
const { tt, ti } = useI18n();
|
||||||
count = this.items.length;
|
|
||||||
} else {
|
|
||||||
for (const field in this.items) {
|
|
||||||
if (!Object.prototype.hasOwnProperty.call(this.items, field)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
count++;
|
const currentValue = ref<unknown>(props.modelValue);
|
||||||
}
|
|
||||||
|
const heightClass = computed<string>(() => {
|
||||||
|
let count = 0;
|
||||||
|
|
||||||
|
if (isArray(props.items)) {
|
||||||
|
count = props.items.length;
|
||||||
|
} else {
|
||||||
|
for (const field in props.items) {
|
||||||
|
if (!Object.prototype.hasOwnProperty.call(props.items, field)) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count > 6) {
|
count++;
|
||||||
return 'tree-view-selection-huge-sheet';
|
|
||||||
} else if (count > 2) {
|
|
||||||
return 'tree-view-selection-large-sheet';
|
|
||||||
} else {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
onSheetOpen(event) {
|
|
||||||
this.currentValue = this.modelValue;
|
|
||||||
scrollToSelectedItem(event.$el, '.page-content', '.treeview-item .treeview-item-selected');
|
|
||||||
},
|
|
||||||
onSheetClosed() {
|
|
||||||
this.$emit('update:show', false);
|
|
||||||
},
|
|
||||||
onSecondaryItemClicked(subItem) {
|
|
||||||
if (this.secondaryValueField) {
|
|
||||||
this.currentValue = subItem[this.secondaryValueField];
|
|
||||||
} else {
|
|
||||||
this.currentValue = subItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.$emit('update:modelValue', this.currentValue);
|
|
||||||
this.$emit('update:show', false);
|
|
||||||
},
|
|
||||||
isPrimaryItemHasSecondaryValue(primaryItem) {
|
|
||||||
for (let i = 0; i < primaryItem[this.primarySubItemsField].length; i++) {
|
|
||||||
const secondaryItem = primaryItem[this.primarySubItemsField][i];
|
|
||||||
|
|
||||||
if (this.secondaryHiddenField && secondaryItem[this.secondaryHiddenField]) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.secondaryValueField && secondaryItem[this.secondaryValueField] === this.currentValue) {
|
|
||||||
return true;
|
|
||||||
} else if (!this.secondaryValueField && secondaryItem === this.currentValue) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
isSecondarySelected(subItem) {
|
|
||||||
if (this.secondaryValueField) {
|
|
||||||
return this.currentValue === subItem[this.secondaryValueField];
|
|
||||||
} else {
|
|
||||||
return this.currentValue === subItem;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (count > 6) {
|
||||||
|
return 'tree-view-selection-huge-sheet';
|
||||||
|
} else if (count > 2) {
|
||||||
|
return 'tree-view-selection-large-sheet';
|
||||||
|
} else {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function isPrimaryItemHasSecondaryValue(primaryItem: Record<string, unknown>): boolean {
|
||||||
|
const subItems = primaryItem[props.primarySubItemsField] as unknown[];
|
||||||
|
|
||||||
|
if (subItems.length < 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < subItems.length; i++) {
|
||||||
|
const secondaryItem = subItems[i];
|
||||||
|
|
||||||
|
if (props.secondaryHiddenField && (secondaryItem as Record<string, unknown>)[props.secondaryHiddenField]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.secondaryValueField && (secondaryItem as Record<string, unknown>)[props.secondaryValueField] === currentValue.value) {
|
||||||
|
return true;
|
||||||
|
} else if (!props.secondaryValueField && secondaryItem === currentValue.value) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isSecondarySelected(subItem: unknown): boolean {
|
||||||
|
if (props.secondaryValueField) {
|
||||||
|
return currentValue.value === (subItem as Record<string, unknown>)[props.secondaryValueField];
|
||||||
|
} else {
|
||||||
|
return currentValue.value === subItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onSecondaryItemClicked(subItem: unknown): void {
|
||||||
|
if (props.secondaryValueField) {
|
||||||
|
currentValue.value = (subItem as Record<string, unknown>)[props.secondaryValueField];
|
||||||
|
} else {
|
||||||
|
currentValue.value = subItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit('update:modelValue', currentValue.value);
|
||||||
|
emit('update:show', false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onSheetOpen(event: { $el: Framework7Dom }): void {
|
||||||
|
currentValue.value = props.modelValue;
|
||||||
|
scrollToSelectedItem(event.$el, '.page-content', '.treeview-item .treeview-item-selected');
|
||||||
|
}
|
||||||
|
|
||||||
|
function onSheetClosed() {
|
||||||
|
emit('update:show', false);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -112,7 +112,7 @@
|
|||||||
<span>{{ $t('None') }}</span>
|
<span>{{ $t('None') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<tree-view-selection-sheet primary-key-field="id" primary-value-field="id" primary-title-field="name"
|
<tree-view-selection-sheet primary-key-field="id" primary-title-field="name"
|
||||||
primary-icon-field="icon" primary-icon-type="category" primary-color-field="color"
|
primary-icon-field="icon" primary-icon-type="category" primary-color-field="color"
|
||||||
primary-hidden-field="hidden" primary-sub-items-field="subCategories"
|
primary-hidden-field="hidden" primary-sub-items-field="subCategories"
|
||||||
secondary-key-field="id" secondary-value-field="id" secondary-title-field="name"
|
secondary-key-field="id" secondary-value-field="id" secondary-title-field="name"
|
||||||
@@ -143,7 +143,7 @@
|
|||||||
<span>{{ $t('None') }}</span>
|
<span>{{ $t('None') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<tree-view-selection-sheet primary-key-field="id" primary-value-field="id" primary-title-field="name"
|
<tree-view-selection-sheet primary-key-field="id" primary-title-field="name"
|
||||||
primary-icon-field="icon" primary-icon-type="category" primary-color-field="color"
|
primary-icon-field="icon" primary-icon-type="category" primary-color-field="color"
|
||||||
primary-hidden-field="hidden" primary-sub-items-field="subCategories"
|
primary-hidden-field="hidden" primary-sub-items-field="subCategories"
|
||||||
secondary-key-field="id" secondary-value-field="id" secondary-title-field="name"
|
secondary-key-field="id" secondary-value-field="id" secondary-title-field="name"
|
||||||
@@ -174,7 +174,7 @@
|
|||||||
<span>{{ $t('None') }}</span>
|
<span>{{ $t('None') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<tree-view-selection-sheet primary-key-field="id" primary-value-field="id" primary-title-field="name"
|
<tree-view-selection-sheet primary-key-field="id" primary-title-field="name"
|
||||||
primary-icon-field="icon" primary-icon-type="category" primary-color-field="color"
|
primary-icon-field="icon" primary-icon-type="category" primary-color-field="color"
|
||||||
primary-hidden-field="hidden" primary-sub-items-field="subCategories"
|
primary-hidden-field="hidden" primary-sub-items-field="subCategories"
|
||||||
secondary-key-field="id" secondary-value-field="id" secondary-title-field="name"
|
secondary-key-field="id" secondary-value-field="id" secondary-title-field="name"
|
||||||
|
|||||||
Reference in New Issue
Block a user