多维表格
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

161 lines
4.5 KiB

<script setup lang="ts">
import type { ColumnType } from 'nocodb-sdk'
import {
ActiveCellInj,
ColumnInj,
EditModeInj,
IsFormInj,
IsLockedInj,
IsPublicInj,
ReadonlyInj,
computed,
inject,
provide,
ref,
toRef,
useColumn,
useDebounceFn,
useSmartsheetRowStoreOrThrow,
useVModel,
} from '#imports'
import { NavigateDir } from '~/lib'
interface Props {
column: ColumnType
modelValue: any
editEnabled: boolean
readOnly?: boolean
rowIndex?: number
active?: boolean
virtual?: boolean
}
const props = defineProps<Props>()
const emit = defineEmits(['update:modelValue', 'save', 'navigate', 'update:editEnabled'])
const column = toRef(props, 'column')
const active = toRef(props, 'active', false)
const readOnly = toRef(props, 'readOnly', undefined)
provide(ColumnInj, column)
provide(EditModeInj, useVModel(props, 'editEnabled', emit))
provide(ActiveCellInj, active)
if (readOnly?.value) {
provide(ReadonlyInj, readOnly)
}
const isForm = inject(IsFormInj, ref(false))
const isPublic = inject(IsPublicInj, ref(false))
const isLocked = inject(IsLockedInj, ref(false))
const { currentRow } = useSmartsheetRowStoreOrThrow()
const syncValue = useDebounceFn(
() => {
currentRow.value.rowMeta.changed = false
emit('save')
},
500,
{ maxWait: 2000 },
)
const {
isPrimary,
isURL,
isEmail,
isJSON,
isGeoData,
isDate,
isYear,
isDateTime,
isTime,
isBoolean,
isDuration,
isRating,
isCurrency,
isAttachment,
isTextArea,
isString,
isInt,
isFloat,
isDecimal,
isSingleSelect,
isMultiSelect,
isPercent,
isPhoneNumber,
isAutoSaved,
isManualSaved,
} = useColumn(column)
const vModel = computed({
get: () => props.modelValue,
set: (val) => {
if (val !== props.modelValue) {
currentRow.value.rowMeta.changed = true
emit('update:modelValue', val)
if (isAutoSaved.value) {
syncValue()
} else if (!isManualSaved.value) {
emit('save')
currentRow.value.rowMeta.changed = true
}
}
},
})
const syncAndNavigate = (dir: NavigateDir, e: KeyboardEvent) => {
if (isJSON.value) return
if (currentRow.value.rowMeta.changed || currentRow.value.rowMeta.new) {
emit('save')
currentRow.value.rowMeta.changed = false
}
emit('navigate', dir)
if (!isForm.value) e.stopImmediatePropagation()
}
</script>
<template>
<div
class="nc-cell w-full"
:class="[`nc-cell-${(column?.uidt || 'default').toLowerCase()}`, { 'text-blue-600': isPrimary && !virtual && !isForm }]"
@keydown.enter.exact="syncAndNavigate(NavigateDir.NEXT, $event)"
@keydown.shift.enter.exact="syncAndNavigate(NavigateDir.PREV, $event)"
>
<LazyCellTextArea v-if="isTextArea" v-model="vModel" />
<!-- TODO: review the hacky type checking here (we had to move geoData check at the beginning atm,
otherwise isString would kick in also for the current GeoData types, since it's abstractType is also a string) -->
<LazyCellGeoData v-else-if="isGeoData" v-model="vModel" />
<LazyCellCheckbox v-else-if="isBoolean" v-model="vModel" />
<LazyCellAttachment v-else-if="isAttachment" v-model="vModel" :row-index="props.rowIndex" />
<LazyCellSingleSelect v-else-if="isSingleSelect" v-model="vModel" :row-index="props.rowIndex" />
<LazyCellMultiSelect v-else-if="isMultiSelect" v-model="vModel" :row-index="props.rowIndex" />
<LazyCellDatePicker v-else-if="isDate" v-model="vModel" />
<LazyCellYearPicker v-else-if="isYear" v-model="vModel" />
<LazyCellDateTimePicker v-else-if="isDateTime" v-model="vModel" />
<LazyCellTimePicker v-else-if="isTime" v-model="vModel" />
<LazyCellRating v-else-if="isRating" v-model="vModel" />
<LazyCellDuration v-else-if="isDuration" v-model="vModel" />
<LazyCellEmail v-else-if="isEmail" v-model="vModel" />
<LazyCellUrl v-else-if="isURL" v-model="vModel" />
<LazyCellPhoneNumber v-else-if="isPhoneNumber" v-model="vModel" />
<LazyCellPercent v-else-if="isPercent" v-model="vModel" />
<LazyCellCurrency v-else-if="isCurrency" v-model="vModel" @save="emit('save')" />
<LazyCellDecimal v-else-if="isDecimal" v-model="vModel" />
<LazyCellInteger v-else-if="isInt" v-model="vModel" />
<LazyCellFloat v-else-if="isFloat" v-model="vModel" />
<LazyCellText v-else-if="isString" v-model="vModel" />
<LazyCellJson v-else-if="isJSON" v-model="vModel" />
<LazyCellText v-else v-model="vModel" />
<div v-if="(isLocked || (isPublic && readOnly && !isForm)) && !isAttachment" class="nc-locked-overlay" @click.stop.prevent />
</div>
</template>