186 lines
4.6 KiB
Vue
186 lines
4.6 KiB
Vue
<script setup>
|
|
import { markRaw, computed, defineModel } from 'vue';
|
|
import { QIcon, QCheckbox } from 'quasar';
|
|
import { dashIfEmpty } from 'src/filters';
|
|
|
|
/* basic input */
|
|
import VnSelect from 'components/common/VnSelect.vue';
|
|
import VnSelectCache from 'components/common/VnSelectCache.vue';
|
|
import VnInput from 'components/common/VnInput.vue';
|
|
import VnInputDate from 'components/common/VnInputDate.vue';
|
|
import VnInputTime from 'components/common/VnInputTime.vue';
|
|
import VnComponent from 'components/common/VnComponent.vue';
|
|
|
|
const model = defineModel(undefined, { required: true });
|
|
const $props = defineProps({
|
|
column: {
|
|
type: Object,
|
|
required: true,
|
|
},
|
|
row: {
|
|
type: Object,
|
|
default: () => {},
|
|
},
|
|
default: {
|
|
type: [Object, String],
|
|
default: null,
|
|
},
|
|
componentProp: {
|
|
type: String,
|
|
default: null,
|
|
},
|
|
isEditable: {
|
|
type: Boolean,
|
|
default: true,
|
|
},
|
|
components: {
|
|
type: Object,
|
|
default: null,
|
|
},
|
|
showLabel: {
|
|
type: Boolean,
|
|
default: null,
|
|
},
|
|
});
|
|
|
|
const defaultSelect = {
|
|
attrs: {
|
|
row: $props.row,
|
|
disable: !$props.isEditable,
|
|
class: 'fit',
|
|
},
|
|
forceAttrs: {
|
|
label: $props.showLabel && $props.column.label,
|
|
},
|
|
};
|
|
|
|
const defaultComponents = {
|
|
input: {
|
|
component: markRaw(VnInput),
|
|
attrs: {
|
|
disable: !$props.isEditable,
|
|
class: 'fit',
|
|
},
|
|
forceAttrs: {
|
|
label: $props.showLabel && $props.column.label,
|
|
},
|
|
},
|
|
number: {
|
|
component: markRaw(VnInput),
|
|
attrs: {
|
|
disable: !$props.isEditable,
|
|
class: 'fit',
|
|
},
|
|
forceAttrs: {
|
|
label: $props.showLabel && $props.column.label,
|
|
},
|
|
},
|
|
date: {
|
|
component: markRaw(VnInputDate),
|
|
attrs: {
|
|
readonly: true,
|
|
disable: !$props.isEditable,
|
|
style: 'min-width: 125px',
|
|
class: 'fit',
|
|
},
|
|
forceAttrs: {
|
|
label: $props.showLabel && $props.column.label,
|
|
},
|
|
},
|
|
time: {
|
|
component: markRaw(VnInputTime),
|
|
attrs: {
|
|
disable: !$props.isEditable,
|
|
},
|
|
forceAttrs: {
|
|
label: $props.showLabel && $props.column.label,
|
|
},
|
|
},
|
|
checkbox: {
|
|
component: markRaw(QCheckbox),
|
|
attrs: (prop) => {
|
|
const defaultAttrs = {
|
|
disable: !$props.isEditable,
|
|
'model-value': Boolean(prop),
|
|
class: 'no-padding fit',
|
|
};
|
|
|
|
if (typeof prop == 'number') {
|
|
defaultAttrs['true-value'] = 1;
|
|
defaultAttrs['false-value'] = 0;
|
|
}
|
|
return defaultAttrs;
|
|
},
|
|
forceAttrs: {
|
|
label: $props.showLabel && $props.column.label,
|
|
},
|
|
},
|
|
select: {
|
|
component: markRaw(VnSelectCache),
|
|
...defaultSelect,
|
|
},
|
|
rawSelect: {
|
|
component: markRaw(VnSelect),
|
|
...defaultSelect,
|
|
},
|
|
icon: {
|
|
component: markRaw(QIcon),
|
|
},
|
|
};
|
|
|
|
const value = computed(() => {
|
|
return $props.column.format
|
|
? $props.column.format($props.row, dashIfEmpty)
|
|
: dashIfEmpty($props.row[$props.column.name]);
|
|
});
|
|
|
|
const col = computed(() => {
|
|
let newColumn = { ...$props.column };
|
|
const specific = newColumn[$props.componentProp];
|
|
if (specific) {
|
|
newColumn = {
|
|
...newColumn,
|
|
...specific,
|
|
...specific.attrs,
|
|
...specific.forceAttrs,
|
|
};
|
|
}
|
|
if (
|
|
(newColumn.name.startsWith('is') || newColumn.name.startsWith('has')) &&
|
|
!newColumn.component
|
|
)
|
|
newColumn.component = 'checkbox';
|
|
if ($props.default && !newColumn.component) newColumn.component = $props.default;
|
|
|
|
return newColumn;
|
|
});
|
|
|
|
const components = computed(() => $props.components ?? defaultComponents);
|
|
</script>
|
|
<template>
|
|
<div class="row no-wrap">
|
|
<VnComponent
|
|
v-if="col.before"
|
|
:prop="col.before"
|
|
:components="components"
|
|
:value="model"
|
|
v-model="model"
|
|
/>
|
|
<VnComponent
|
|
v-if="col.component"
|
|
:prop="col"
|
|
:components="components"
|
|
:value="model"
|
|
v-model="model"
|
|
/>
|
|
<span :title="value" v-else>{{ value }}</span>
|
|
<VnComponent
|
|
v-if="col.after"
|
|
:prop="col.after"
|
|
:components="components"
|
|
:value="model"
|
|
v-model="model"
|
|
/>
|
|
</div>
|
|
</template>
|