2 Commits

Author SHA1 Message Date
d5ed64511e auto generate /dist file 2025-02-08 09:52:46 +08:00
88343bbfdf fix multi input 2025-02-08 09:50:48 +08:00
15 changed files with 5846 additions and 1001 deletions

View File

@@ -7,7 +7,6 @@ export {}
/* prettier-ignore */
declare module 'vue' {
export interface GlobalComponents {
CellInput: typeof import('./src/components/basic/conditions/CellInput.vue')['default']
Config: typeof import('./src/components/Config.vue')['default']
ErrorDialog: typeof import('./src/components/basic/ErrorDialog.vue')['default']
PluginDropdown: typeof import('./src/components/basic/PluginDropdown.vue')['default']

View File

@@ -1,4 +1,4 @@
<script type="module" crossorigin src="/src/js/config.js"></script>
<section class="settings">
<div id="app"></div>
</section>
<section class="settings">
<div id="app"></div>
</section>

Binary file not shown.

View File

@@ -11,7 +11,7 @@
/* config 页面 */
#app {
width: 60vw;
min-width: 940px;
min-width: 1030px;
}
/* 最上面的说明 */
@@ -62,11 +62,14 @@
border-right: 1px solid #e3e7e8;
padding-top: 24px;
}
.table-area {
border-bottom: none;
}
.footer-row {
padding: 24px 0;
margin-bottom: 32px;
text-align: right;
border-top: none;
/* border-top: none; */
}
/* 底部按钮空间 */
@@ -77,11 +80,33 @@
/* 输入框宽度 */
.kuc-text-input {
--kuc-text-input-width: max(16vw, 200px);
--kuc-dropdown-toggle-width: max(16vw, 200px);
--kuc-combobox-toggle-width: max(16vw, 200px);
}
.plugin-kuc-table .kuc-text-input {
--kuc-text-input-width: max(15vw, 200px);
--kuc-dropdown-toggle-width: max(15vw, 200px);
--kuc-combobox-toggle-width: max(15vw, 200px);
}
@media screen and (max-width: 1840px) {
.plugin-kuc-table .kuc-text-input {
--kuc-text-input-width: max(13vw, 200px);
--kuc-dropdown-toggle-width: max(13vw, 200px);
--kuc-combobox-toggle-width: max(13vw, 200px);
}
}
@media screen and (max-width: 1760px) {
.plugin-kuc-table .kuc-text-input {
--kuc-text-input-width: max(12vw, 200px);
--kuc-dropdown-toggle-width: max(12vw, 200px);
--kuc-combobox-toggle-width: max(12vw, 200px);
}
}
/* 统一 kintone +/- 按钮样式 */
.kuc-action-button {
width: 24px;
@@ -107,24 +132,129 @@
}
/* 覆盖表格样式 */
.plugin-kuc-table td {
.plugin-kuc-table > table > tbody > tr > td {
border-left-color: rgba(0, 0, 0, 0);
border-right-color: rgba(0, 0, 0, 0);
vertical-align: middle;
}
.plugin-kuc-table tr td:nth-last-child(2) {
.plugin-kuc-table > table > tbody > tr > td:nth-last-child(2) {
border-right-color: #e3e7e8;
}
.plugin-kuc-table tr td:first-child {
.plugin-kuc-table > table > tbody > tr > td:first-child {
border-left-color: #e3e7e8;
}
.plugin-kuc-table .kuc-table-1-18-0__table__body__row__action {
.plugin-kuc-table > table > tbody > tr > td[class$="table__body__row__action"] {
height: 55px;
align-items: center;
}
.table-option > table > tbody > tr > td[class$="table__body__row__action"] {
height: 40px;
align-items: center;
}
.plugin-kuc-table:not(.condition-table) > table > tbody > tr > td:nth-child(2) {
--kuc-table-header-1-width: 30px;
text-align: center;
}
.condition-table > table > tbody > tr > td[style]:not(:first-child),
.condition-table > table > thead > tr > th[style]:not(:first-child) {
padding-left: 0;
}
/* 絞り込み条件选择相关样式 */
.row-connector-area {
margin: 0 1em;
}
.condition-combobox-short {
--kuc-combobox-toggle-width: 168px;
}
/* .condition-combobox-short {
--kuc-combobox-toggle-width: 140px
}
.condition-combobox-short[data-val='!='] {
--kuc-combobox-toggle-width: 168px
}
.condition-combobox-short[data-val='like'] {
--kuc-combobox-toggle-width: 200px
}
.condition-combobox-short[data-val='in'] {
--kuc-combobox-toggle-width: 185px
}
.condition-combobox-short[data-val='not like'] {
--kuc-combobox-toggle-width: 225px
}
.condition-combobox-short[data-val='not in'] {
--kuc-combobox-toggle-width: 200px
} */
.kuc-text-input-placeholder-width {
--kuc-text-input-width: 258px;
}
.datetime-condition-combobox {
--kuc-combobox-toggle-width: 130px;
}
.datetime-condition-combobox.mid {
--kuc-combobox-toggle-width: 112px;
}
.datetime-condition-combobox.short {
--kuc-combobox-toggle-width: 92px;
}
.datetime-condition-combobox + * {
margin-left: 8px;
}
.datetime-condition-combobox li[value^='\-'] {
user-select: none;
margin: 8px 0;
cursor: default;
padding: 0;
height: 1px;
background-color: #eee;
list-style: none;
pointer-events: none;
}
.week-all-combobox {
--kuc-combobox-toggle-width: 140px;
}
.week-combobox {
--kuc-combobox-toggle-width: 72px;
}
.month-all-combobox {
--kuc-combobox-toggle-width: 100px;
}
.month-combobox {
--kuc-combobox-toggle-width: 86px;
}
.from-today-input {
--kuc-text-input-width: 75px;
--kuc-combobox-toggle-width: 75px;
}
.from-today-input.input {
--kuc-text-input-width: 50px;
--kuc-combobox-toggle-width: 50px;
}
/* .from-today-input error */
.condition-table.plugin-kuc-table > table > tbody > tr > td {
vertical-align: top;
}
.from-today-input.input div[class^="kuc-base-error"] {
position: absolute;
left: 0;
right: 0;
}
.from-today-input.input.error {
margin-bottom: 20px;
}
.table-option td {
padding: 1px;
margin: 0;
border: none;
}
.dialog-action-bar{
text-align: right;
}

View File

@@ -1,4 +1,4 @@
<script type="module" crossorigin src="/src/js/config.js"></script>
<section class="settings">
<div id="app"></div>
</section>
<section class="settings">
<div id="app"></div>
</section>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -24,8 +24,7 @@
</plugin-row>
<plugin-row class="flex-row">
<plugin-label label="絞込条件" />
<plugin-table-condition-row :modelValue="table.whereConditions" :table="table"
@update:modelValue="(newData:any) => table.whereConditions = newData"/>
<plugin-table-condition-row :modelValue="table.whereConditions" />
</plugin-row>
</div>
<div class="table-action-area">

View File

@@ -1,8 +1,5 @@
<template>
<kuc-table className='plugin-kuc-table condition-table'
:columns="columns"
:data="modelValue"
/>
<kuc-table className="plugin-kuc-table condition-table" :columns="columns" :data="modelValue" />
</template>
<script setup lang="ts">
@@ -15,30 +12,25 @@ import TableConditionValue from './conditions/TableConditionValue.vue';
const props = defineProps<{
modelValue: WhereCondition[];
table:JoinTable;
}>();
const emit = defineEmits<{
(event: 'update:modelValue', value: WhereCondition[]): void;
}>();
const savedData = inject<SavedData>('savedData') as SavedData;
const cachedData = inject<CachedData>('cachedData') as CachedData;
const selectedAppData = inject<CachedSelectedAppData>('selectedAppData') as CachedSelectedAppData;
// const table = computed(() => selectedAppData.table.table);
const canSave = inject<(canSave: boolean) => void>('canSave') as (canSave: boolean) => void;
watch(
()=>props.modelValue,
(newValue,oldValue)=>{
console.log(newValue);
console.log(oldValue);
},{
deep:true,
immediate:true
}
)
() => props.modelValue,
(newValue, oldValue) => {
console.log(newValue);
console.log(oldValue);
},
{
deep: true,
immediate: true,
},
);
const columns = reactive([
{
@@ -63,10 +55,10 @@ const columns = reactive([
dataList: props.modelValue,
id: rowData.id,
'onUpdate:modelValue': (data) => {
const obj = (data.obj as WhereCondition);
const obj = data.obj as WhereCondition;
if (obj) {
obj.field = data.value;
obj.condition = '',
obj.condition = '';
obj.data = '';
}
},
@@ -85,8 +77,8 @@ const columns = reactive([
selectedAppData,
id: rowData.id,
whereConditions: props.modelValue,
'onUpdate:modelValue': ({obj, value}) => {
obj && (obj.condition = value);
'onUpdate:modelValue': ({ obj, value }) => {
obj && (obj.condition = value);
},
});
render(vnode, container);
@@ -104,14 +96,8 @@ const columns = reactive([
canSave,
id: rowData.id,
whereConditions: props.modelValue,
'onUpdate:modelValue': ({obj, value}) => {
if(obj){
obj.data = value;
const newData = props.modelValue.map((item) =>
item.id === obj.id ? { ...item, data: value } : item
);
emit('update:modelValue', newData);
}
'onUpdate:modelValue': ({ obj, value }) => {
obj && (obj.data = value);
},
});
render(vnode, container);
@@ -119,5 +105,4 @@ const columns = reactive([
},
},
]);
</script>

View File

@@ -1,22 +0,0 @@
<template>
<kuc-text className="kuc-text-input" :value="modelValue" @change="updateValue" />
</template>
<script setup lang="ts">
import type { KucEvent } from '@/types/my-kintone';
import type { TextInputEventDetail } from 'kintone-ui-component';
import { defineProps, defineEmits, type Ref } from 'vue';
const props = defineProps<{
modelValue: string;
}>();
const emit = defineEmits<{
(e: 'update:modelValue', value: string): void;
}>();
const updateValue = ({ detail }: KucEvent<TextInputEventDetail>) => {
emit('update:modelValue', detail.value || '');
};
</script>

View File

@@ -27,29 +27,32 @@
:disabled="selectedAppData.loading == undefined ? false : selectedAppData.loading"
/>
<kuc-multi-choice
v-else-if="valueType === 'kuc-multichoice'"
:value="multiValue"
v-else-if="isMultiChoice"
:value="multiChoice"
:items="multiChoiceItems"
:requiredIcon="true"
@change="updateMultiValue"
@change="updateMultiChoice"
:disabled="selectedAppData.loading == undefined ? false : selectedAppData.loading"
/>
<table-condition-value-multi-input
v-else-if="valueType === 'multi-input'"
v-else-if="isMultiInput"
:value="multiInput"
@change="updateTableValue"
@change="updateMultiInput"
:disabled="selectedAppData.loading == undefined ? false : selectedAppData.loading"
/>
</template>
<script setup lang="ts">
import { getComponent } from '@/js/conditions';
import { getComponent, multiValueComponent } from '@/js/conditions';
import { getFieldObj, isStringArray, search } from '@/js/helper';
import { isType } from '@/js/kintone-rest-api-client';
import { isSelectType } from '@/js/mapping';
import type { CachedSelectedAppData, StringValue, WhereCondition } from '@/types/model';
import type { KucEvent } from '@/types/my-kintone';
import type { ComboboxChangeEventDetail, TextInputEventDetail, MultiChoiceChangeEventDetail } from 'kintone-ui-component';
import type {
ComboboxChangeEventDetail,
TextInputEventDetail,
MultiChoiceChangeEventDetail,
} from 'kintone-ui-component';
import { defineProps, defineEmits, computed, type Ref, inject, provide, ref, watch, watchEffect } from 'vue';
const props = defineProps<{
@@ -78,25 +81,6 @@ const placeholder = computed(() => {
return '';
});
const multiChoiceItems = computed(() => {
const field = getFieldObj(whereCondition.value?.field || '', props.selectedAppData.appFields, '');
const items = [{
label: '--',
value: '',
}];
if (field && isSelectType(field)) {
const opts = field.options;
const multiOpts = Object.values(opts).map((opt) => {
return {
label: opt.label,
value: opt.label,
};
});
items.push(...multiOpts);
}
return items;
});
const valueType = computed(() => {
const field = getFieldObj(whereCondition.value?.field || '', props.selectedAppData.appFields, '');
return getComponent(whereCondition.value?.condition || '', field);
@@ -115,36 +99,44 @@ const updateValue = (event: KucEvent<ComboboxChangeEventDetail | TextInputEventD
emit('update:modelValue', { obj: whereCondition.value, value: event.detail.value || '' });
};
const multiValue = ref(isStringArray(props.modelValue.value) ? props.modelValue.value : []);
// multi choice
const isMultiChoice = computed(() => valueType.value === multiValueComponent.multiChoice);
watch(
() => props.modelValue,
() => {
const field = getFieldObj(whereCondition.value?.field || '', props.selectedAppData.appFields, '');
const vType = valueType.value;
const moduleValue = props.modelValue.value;
if (field && isSelectType(field) && vType === 'kuc-multichoice') {
multiValue.value = isStringArray(moduleValue) ? moduleValue : [];
}
},
);
const multiInput = ref(isStringArray(props.modelValue.value) ? (props.modelValue.value as string[]) : ['', '']);
watchEffect(() => {
const vType = valueType.value;
const moduleValue = props.modelValue.value;
if (vType === 'multi-input') {
multiInput.value = isStringArray(moduleValue) ? (moduleValue as string[]) : ['', ''];
const multiChoice = computed(() => {
if (!isMultiChoice.value) {
return props.modelValue.value;
}
return isStringArray(props.modelValue.value) ? props.modelValue.value : [];
});
const updateMultiValue = (event: KucEvent<MultiChoiceChangeEventDetail>) => {
const multiChoiceItems = computed(() => {
if (!isMultiChoice.value) {
return [];
}
const field = getFieldObj(whereCondition.value?.field || '', props.selectedAppData.appFields, '');
const items = [{ label: '--', value: '' }];
if (field && isSelectType(field)) {
const multiOpts = Object.values(field.options).map((opt) => ({ label: opt.label, value: opt.label }));
items.push(...multiOpts);
}
return items;
});
const updateMultiChoice = (event: KucEvent<MultiChoiceChangeEventDetail>) => {
emit('update:modelValue', { obj: whereCondition.value, value: event.detail.value || [] });
};
const updateTableValue = (event: KucEvent<string[]>) => {
let value = event.detail || ['', ''];
multiInput.value = value;
emit('update:modelValue', { obj: whereCondition.value, value: value });
// multi input
const isMultiInput = computed(() => valueType.value === multiValueComponent.multiInput);
const multiInput = computed(() => {
if (!isMultiInput.value) {
return props.modelValue.value as string[];
}
return isStringArray(props.modelValue.value) ? props.modelValue.value as string[] : ['', ''];
});
const updateMultiInput = (event: KucEvent<string[]>) => {
emit('update:modelValue', { obj: whereCondition.value, value: event.detail || ['', ''] });
};
</script>

View File

@@ -1,82 +1,45 @@
<template>
<kuc-table
className="table-option"
:columns="columns"
:data="data"
@change.stop="updateValue"
:headerVisible="false"
/>
</template>
<template>
<!-- <kuc-table className='table-option'
:columns="columns"
:data="data"
@change="updateValue"
:headerVisible="false"
ref="table"/> -->
<div ref="tableContainer"></div>
</template>
<script setup lang="ts">
import type { KucEvent } from '@/types/my-kintone';
import { Table, Text, type TableChangeEventDetail } from 'kintone-ui-component';
import { defineProps, defineEmits, computed, ref, watch, inject, type Ref, onMounted, onUnmounted } from 'vue';
interface MuiltItem{
value:string
}
<script setup lang="ts">
import type { KucEvent } from '@/types/my-kintone';
import { Table, Text, type TableChangeEventDetail } from 'kintone-ui-component';
import { defineProps, defineEmits, ref, watch, h, render, reactive } from 'vue';
interface MultiItem {
value: string;
}
const props = defineProps<{
value: string[];
}>();
const props = defineProps<{
value: string[];
}>();
const tableContainer = ref<HTMLDivElement>();
const table = ref<Table | null>(null);
const data = ref<MuiltItem[]>((props.value || ['', '']).map(x => ({ value: x })));
watch(
() => props.value,
(newValue)=>{
data.value =(newValue || ['', '']).map((x) => ({ value: x }));
if (table.value) {
table.value.data = data.value; // 更新 Table 数据
}
const data = ref<MultiItem[]>((props.value || ['', '']).map((x) => ({ value: x })));
const columns = reactive([
{
title: '',
field: 'value',
render: (cellData: string) => {
return new Text({ value: cellData });
},
{
deep:true,immediate:true
});
const emit = defineEmits<{
(e: 'change', data: KucEvent<string[]>): void;
(e: 'update:modelValue', value: string[]): void;
}>();
},
]);
const emit = defineEmits<{
(e: 'change', data: KucEvent<string[]>): void;
}>();
const updateValue=(event:KucEvent<TableChangeEventDetail<MuiltItem>>)=>{
data.value = event.detail.data||[{value:''},{value:''}];
if (table.value) {
table.value.data = data.value;
}
const muiltData = event.detail.data ? event.detail.data.map(x=>x.value) :[];
emit('change', { detail: [...muiltData] });
// emit('update:modelValue', [...muiltData] );
// emit('change', muiltData);
}
const updateValue = (event: KucEvent<TableChangeEventDetail<MultiItem>>) => {
data.value = event.detail.data || [{ value: '' }, { value: '' }];
const multiData = event.detail.data ? event.detail.data.map((x) => x.value) : [];
emit('change', { detail: [...multiData] });
};
onMounted(()=>{
table.value = new Table({
className:'table-option',
headerVisible:false,
actionButton:true,
columns:[
{
field:"value",
render:(cellData:any)=>{
const text = new Text({value:cellData});
return text;
}
},
],
data:data.value
});
table.value.addEventListener('change', updateValue);
tableContainer.value?.appendChild(table.value);
});
onUnmounted(() => {
if (table.value) {
table.value.removeEventListener('change', updateValue);
}
});
</script>
</script>

View File

@@ -62,11 +62,14 @@
border-right: 1px solid #e3e7e8;
padding-top: 24px;
}
.table-area {
border-bottom: none;
}
.footer-row {
padding: 24px 0;
margin-bottom: 32px;
text-align: right;
border-top: none;
/* border-top: none; */
}
/* 底部按钮空间 */
@@ -141,10 +144,14 @@
.plugin-kuc-table > table > tbody > tr > td:first-child {
border-left-color: #e3e7e8;
}
.plugin-kuc-table > table > tbody > tr > .kuc-table-1-18-0__table__body__row__action {
.plugin-kuc-table > table > tbody > tr > td[class$="table__body__row__action"] {
height: 55px;
align-items: center;
}
.table-option > table > tbody > tr > td[class$="table__body__row__action"] {
height: 40px;
align-items: center;
}
.plugin-kuc-table:not(.condition-table) > table > tbody > tr > td:nth-child(2) {
--kuc-table-header-1-width: 30px;
text-align: center;

View File

@@ -14,24 +14,32 @@ type ConditionItem = {
};
export const conditionList: ConditionItem[] = [
{ value: '=', label: '=(等しい)', type: (field) => dateTimeComponent[field.type] || 'input' },
{ value: '!=', label: '≠ (等しくない)', type: (field) => dateTimeComponent[field.type] || 'input' },
{ value: '=', label: '=(等しい)', type: (field) => dateTimeComponentMap[field.type] || 'input' },
{ value: '!=', label: '≠ (等しくない)', type: (field) => dateTimeComponentMap[field.type] || 'input' },
{
value: '<=',
label: (field) => (isDateTimeType(field) ? '≦ (以前)' : '≦ (以下)'),
type: (field) => dateTimeComponent[field.type] || 'input',
type: (field) => dateTimeComponentMap[field.type] || 'input',
},
{ value: '<', label: '< (より前)', type: (field) => dateTimeComponent[field.type] || 'input' },
{ value: '<', label: '< (より前)', type: (field) => dateTimeComponentMap[field.type] || 'input' },
{
value: '>=',
label: (field) => (isDateTimeType(field) ? '≧ (以降)' : '≧ (以上)'),
type: (field) => dateTimeComponent[field.type] || 'input',
type: (field) => dateTimeComponentMap[field.type] || 'input',
},
{ value: '>', label: '> (より後)', type: (field) => dateTimeComponent[field.type] || 'input' },
{ value: '>', label: '> (より後)', type: (field) => dateTimeComponentMap[field.type] || 'input' },
{ value: 'like', label: '次のキーワードを含む', type: 'input' },
{ value: 'not like', label: '次のキーワードを含まない', type: 'input' },
{ value: 'in', label: '次のいずれかを含む', type: (field) => MultiChoiceComponent[field.type] || 'input' },
{ value: 'not in', label: '次のいずれも含まない', type: (field) => MultiChoiceComponent[field.type] || 'input' },
{
value: 'in',
label: (field) => (isMultiInputType(field) ? '次のいずれかと等しい' : '次のいずれかを含む'),
type: (field) => multiValueComponentMap[field.type] || 'input',
},
{
value: 'not in',
label: (field) => (isMultiInputType(field) ? '次のいずれとも等しくない' : '次のいずれも含まない'),
type: (field) => multiValueComponentMap[field.type] || 'input',
},
];
// search from conditionList
@@ -89,21 +97,35 @@ export const getAvailableCondition = (fieldCode: string, fieldsInfo: FieldsInfo,
});
};
const component = {
input: 'kuc-text',
select: 'kuc-combobox',
const dateTimeComponent = {
time: 'kuc-time',
date: 'date',
datetime: 'datetime',
} as const;
export const multiValueComponent = {
multiChoice: 'kuc-multichoice',
multiInput: 'multi-input',
} as const;
const component = {
input: 'kuc-text',
select: 'kuc-combobox',
...dateTimeComponent,
...multiValueComponent,
} as const;
export type ComponentType = keyof typeof component;
const isDateTimeType = (field: OneOf) => {
return field.type in dateTimeComponentMap;
};
export const isDateTimeType = (field: OneOf) => {
return field.type in dateTimeComponent;
const isMultiInputType = (field: OneOf) => {
return multiValueComponentMap[field.type] === 'multiInput';
};
const dateTimeComponent: Partial<Record<FieldType, ComponentType>> = {
const dateTimeComponentMap: Partial<Record<FieldType, keyof typeof dateTimeComponent>> = {
TIME: 'time',
DATE: 'date',
DATETIME: 'datetime',
@@ -111,7 +133,7 @@ const dateTimeComponent: Partial<Record<FieldType, ComponentType>> = {
UPDATED_TIME: 'datetime',
};
const MultiChoiceComponent: Partial<Record<FieldType, ComponentType>> = {
const multiValueComponentMap: Partial<Record<FieldType, keyof typeof multiValueComponent>> = {
CHECK_BOX: 'multiChoice',
DROP_DOWN: 'multiChoice',
RADIO_BUTTON: 'multiChoice',
@@ -120,7 +142,6 @@ const MultiChoiceComponent: Partial<Record<FieldType, ComponentType>> = {
LINK: 'multiInput',
};
export type ComponentType = keyof typeof component;
export const getComponent = (value: ConditionValue, fieldObj: OneOf) => {
if (!value || !fieldObj) return;
const condition = conditionMap[value].type;