87 changed files with 6739 additions and 4064 deletions
@ -0,0 +1,232 @@ |
|||
{ |
|||
"enable": true, |
|||
"url": "/api/rwa/params/isc/fetchParams?pageable=false&sortBy=sortNo", |
|||
"method": "get", |
|||
"response": { |
|||
"code" : 200, |
|||
"messageI18nKey" : "success", |
|||
"message" : "success", |
|||
"data" : [ { |
|||
"jpaVersion" : null, |
|||
"dataComeFrom" : "INPUT", |
|||
"creator" : "admin", |
|||
"createDate" : "2023-09-05 02:02:14", |
|||
"lastModifier" : "admin", |
|||
"lastModifyDate" : "2023-09-05 02:02:14", |
|||
"corporationCode" : null, |
|||
"id" : "2268c3e2-c03f-4d8a-8bcd-e37d24cf955e", |
|||
"name" : "银行参数", |
|||
"parent" : null, |
|||
"children" : [ ], |
|||
"icon" : "folder", |
|||
"isFolder" : true, |
|||
"sortNo" : null, |
|||
"isDefault" : false, |
|||
"pageType" : null, |
|||
"templateId" : null, |
|||
"routeName" : null, |
|||
"routeQuery" : null |
|||
}, { |
|||
"jpaVersion" : null, |
|||
"dataComeFrom" : "INPUT", |
|||
"creator" : "admin", |
|||
"createDate" : "2023-08-30 08:00:00", |
|||
"lastModifier" : "admin", |
|||
"lastModifyDate" : "2023-08-30 08:00:00", |
|||
"corporationCode" : null, |
|||
"id" : "BIII", |
|||
"name" : "BIII参数", |
|||
"parent" : null, |
|||
"children" : [ { |
|||
"jpaVersion" : null, |
|||
"dataComeFrom" : "INPUT", |
|||
"creator" : "admin", |
|||
"createDate" : "2024-02-26 17:34:22", |
|||
"lastModifier" : "admin", |
|||
"lastModifyDate" : "2024-02-26 17:34:22", |
|||
"corporationCode" : "_PRIMARY_", |
|||
"id" : "478b6c43-ca5b-45c4-a0cb-14715f45c98c", |
|||
"name" : "信用风险-表内风险权重参数表", |
|||
"parent" : "BIII", |
|||
"ticked" : true, |
|||
"children" : [ ], |
|||
"icon" : "calendar_month", |
|||
"isFolder" : false, |
|||
"sortNo" : 100, |
|||
"isDefault" : true, |
|||
"pageType" : "TEMPLATE", |
|||
"templateId" : "47442edb-7b0d-4dc4-ab71-755ddbae71bf", |
|||
"routeName" : null, |
|||
"routeQuery" : null |
|||
}, { |
|||
"jpaVersion" : null, |
|||
"dataComeFrom" : "INPUT", |
|||
"creator" : null, |
|||
"createDate" : null, |
|||
"lastModifier" : "admin", |
|||
"lastModifyDate" : "2024-02-27 15:41:34", |
|||
"corporationCode" : "_PRIMARY_", |
|||
"id" : "BWFXQZ", |
|||
"name" : "信用风险-表外主体权重参数表", |
|||
"parent" : "BIII", |
|||
"children" : [ ], |
|||
"icon" : "calendar_today", |
|||
"isFolder" : false, |
|||
"sortNo" : 200, |
|||
"isDefault" : false, |
|||
"pageType" : "TEMPLATE", |
|||
"templateId" : "1b42b129-b683-4ac0-a8dc-3d39db1eb836", |
|||
"routeName" : null, |
|||
"routeQuery" : null |
|||
} ], |
|||
"icon" : "folder", |
|||
"isFolder" : true, |
|||
"sortNo" : 100, |
|||
"isDefault" : false, |
|||
"pageType" : null, |
|||
"templateId" : null, |
|||
"routeName" : null, |
|||
"routeQuery" : null |
|||
}, { |
|||
"jpaVersion" : null, |
|||
"dataComeFrom" : "INPUT", |
|||
"creator" : "admin", |
|||
"createDate" : "2024-02-28 13:56:36", |
|||
"lastModifier" : "admin", |
|||
"lastModifyDate" : "2024-02-28 13:56:36", |
|||
"corporationCode" : "_PRIMARY_", |
|||
"id" : "bc56db9d-c4ad-4d66-9d55-7ae1a9ad3af3", |
|||
"name" : "交易对手信用风险", |
|||
"parent" : null, |
|||
"children" : [ { |
|||
"jpaVersion" : null, |
|||
"dataComeFrom" : "INPUT", |
|||
"creator" : "admin", |
|||
"createDate" : "2024-02-28 14:03:45", |
|||
"lastModifier" : "admin", |
|||
"lastModifyDate" : "2024-02-28 14:03:45", |
|||
"corporationCode" : "_PRIMARY_", |
|||
"id" : "fac9819a-84a7-46bd-9e89-47e07ebeb31b", |
|||
"name" : "交易对手信用风险设置", |
|||
"parent" : "bc56db9d-c4ad-4d66-9d55-7ae1a9ad3af3", |
|||
"children" : [ ], |
|||
"icon" : "settings_suggest", |
|||
"isFolder" : false, |
|||
"sortNo" : 100, |
|||
"isDefault" : false, |
|||
"pageType" : "TEMPLATE", |
|||
"templateId" : "61da07af-351f-4c70-9e58-0ab99ca1d730", |
|||
"routeName" : null, |
|||
"routeQuery" : null |
|||
}, { |
|||
"jpaVersion" : null, |
|||
"dataComeFrom" : "INPUT", |
|||
"creator" : "admin", |
|||
"createDate" : "2024-02-28 14:55:57", |
|||
"lastModifier" : "admin", |
|||
"lastModifyDate" : "2024-02-28 14:55:57", |
|||
"corporationCode" : "_PRIMARY_", |
|||
"id" : "2389c168-12c5-4955-b31f-5090f9dcea4b", |
|||
"name" : "SACCR监管参数配置", |
|||
"parent" : "bc56db9d-c4ad-4d66-9d55-7ae1a9ad3af3", |
|||
"children" : [ ], |
|||
"icon" : "settings_applications", |
|||
"isFolder" : false, |
|||
"sortNo" : 200, |
|||
"isDefault" : false, |
|||
"pageType" : "TEMPLATE", |
|||
"templateId" : "df6de052-7f56-42bd-895b-ca09088e0906", |
|||
"routeName" : null, |
|||
"routeQuery" : null |
|||
}, { |
|||
"jpaVersion" : null, |
|||
"dataComeFrom" : "INPUT", |
|||
"creator" : null, |
|||
"createDate" : null, |
|||
"lastModifier" : "admin", |
|||
"lastModifyDate" : "2024-02-28 16:13:48", |
|||
"corporationCode" : "_PRIMARY_", |
|||
"id" : "ec48aefe-1181-4764-9a97-b149f20b520e", |
|||
"name" : "CVA行业类别映射", |
|||
"parent" : "bc56db9d-c4ad-4d66-9d55-7ae1a9ad3af3", |
|||
"children" : [ ], |
|||
"icon" : "linear_scale", |
|||
"isFolder" : false, |
|||
"sortNo" : 300, |
|||
"isDefault" : false, |
|||
"pageType" : "TEMPLATE", |
|||
"templateId" : "125dc90f-15cb-4b82-961b-1b7361f0df5e", |
|||
"routeName" : null, |
|||
"routeQuery" : null |
|||
}, { |
|||
"jpaVersion" : null, |
|||
"dataComeFrom" : "INPUT", |
|||
"creator" : null, |
|||
"createDate" : null, |
|||
"lastModifier" : "admin", |
|||
"lastModifyDate" : "2024-02-28 16:31:40", |
|||
"corporationCode" : "_PRIMARY_", |
|||
"id" : "a315ede8-3438-4d00-a60a-c9ef2babc0b1", |
|||
"name" : "货币优先顺序", |
|||
"parent" : "bc56db9d-c4ad-4d66-9d55-7ae1a9ad3af3", |
|||
"children" : [ ], |
|||
"icon" : "currency_yen", |
|||
"isFolder" : false, |
|||
"sortNo" : 400, |
|||
"isDefault" : false, |
|||
"pageType" : "TEMPLATE", |
|||
"templateId" : "3fcee541-43f6-480e-827b-6cf021f748eb", |
|||
"routeName" : null, |
|||
"routeQuery" : null |
|||
}, { |
|||
"jpaVersion" : null, |
|||
"dataComeFrom" : "INPUT", |
|||
"creator" : "admin", |
|||
"createDate" : "2024-02-28 16:45:56", |
|||
"lastModifier" : "admin", |
|||
"lastModifyDate" : "2024-02-28 16:45:56", |
|||
"corporationCode" : "_PRIMARY_", |
|||
"id" : "8865a5dd-0a88-4362-9ba9-192009072ad0", |
|||
"name" : "CVA评级等级映射", |
|||
"parent" : "bc56db9d-c4ad-4d66-9d55-7ae1a9ad3af3", |
|||
"children" : [ ], |
|||
"icon" : "format_list_numbered", |
|||
"isFolder" : false, |
|||
"sortNo" : 500, |
|||
"isDefault" : false, |
|||
"pageType" : "TEMPLATE", |
|||
"templateId" : "637eea6b-1fcf-4977-a56b-9653b0703c31", |
|||
"routeName" : null, |
|||
"routeQuery" : null |
|||
}, { |
|||
"jpaVersion" : null, |
|||
"dataComeFrom" : "INPUT", |
|||
"creator" : "admin", |
|||
"createDate" : "2024-02-28 17:08:39", |
|||
"lastModifier" : "admin", |
|||
"lastModifyDate" : "2024-02-28 17:08:39", |
|||
"corporationCode" : "_PRIMARY_", |
|||
"id" : "62021407-ac21-4fde-a37d-e53865b94aa5", |
|||
"name" : "CVA权重映射", |
|||
"parent" : "bc56db9d-c4ad-4d66-9d55-7ae1a9ad3af3", |
|||
"children" : [ ], |
|||
"icon" : "percent", |
|||
"isFolder" : false, |
|||
"sortNo" : 600, |
|||
"isDefault" : false, |
|||
"pageType" : "TEMPLATE", |
|||
"templateId" : "dacd1de2-8492-4123-b1fb-f8abb4f6346b", |
|||
"routeName" : null, |
|||
"routeQuery" : null |
|||
} ], |
|||
"icon" : "folder", |
|||
"isFolder" : true, |
|||
"sortNo" : 300, |
|||
"isDefault" : false, |
|||
"pageType" : null, |
|||
"templateId" : null, |
|||
"routeName" : null, |
|||
"routeQuery" : null |
|||
} ] |
|||
} |
|||
} |
@ -0,0 +1,104 @@ |
|||
<template> |
|||
<div v-show="FieldMethods.getShow(props, modelValue)" :class="props.outlined ? 'w-checkbox' : ''"> |
|||
<template v-if="props.outlined"> |
|||
<q-field |
|||
ref="checkboxRef" |
|||
v-model="modelValue" |
|||
:hide-bottom-space="true" |
|||
:hide-hint="true" |
|||
v-bind="attrs" |
|||
:outlined="props.outlined" |
|||
:borderless="!props.outlined" |
|||
:stack-label="true" |
|||
:dense="true" |
|||
:rules="FieldMethods.getRules(props, modelValue, checkboxRef, undefined)" |
|||
:readonly="FieldMethods.getReadOnly(props, modelValue)" |
|||
:disable="FieldMethods.getDisable(props, modelValue)" |
|||
@update:model-value="fieldMethodsClass.updateValue" |
|||
> |
|||
<template #label><w-label :required="FieldMethods.getRequired(props, modelValue)" :label="attrs.label"></w-label></template> |
|||
<template #append> |
|||
<q-checkbox |
|||
v-model="modelValue" |
|||
:readonly="FieldMethods.getReadOnly(props, modelValue)" |
|||
:disable="FieldMethods.getDisable(props, modelValue)" |
|||
@update:model-value="fieldMethodsClass.updateValue" |
|||
></q-checkbox> |
|||
</template> |
|||
</q-field> |
|||
</template> |
|||
<template v-else> |
|||
<q-checkbox |
|||
ref="checkboxRef" |
|||
v-model="modelValue" |
|||
v-bind="attrs" |
|||
:readonly="FieldMethods.getReadOnly(props, modelValue)" |
|||
:disable="FieldMethods.getDisable(props, modelValue)" |
|||
@update:model-value="fieldMethodsClass.updateValue" |
|||
></q-checkbox> |
|||
</template> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup lang="ts"> |
|||
import { ref, useAttrs } from 'vue'; |
|||
import { FormFieldProps } from '@/platform/components/form/FormField.ts'; |
|||
import { FormFieldMethods } from '../form/FormField'; |
|||
|
|||
const checkboxRef = ref(); |
|||
const attrs = useAttrs(); |
|||
const modelValue = defineModel({ type: Boolean, default: false }); |
|||
|
|||
interface FieldProps extends FormFieldProps { |
|||
outlined?: boolean; |
|||
borderless?: boolean; |
|||
} |
|||
const props = withDefaults(defineProps<FieldProps>(), { |
|||
outlined: true, |
|||
showIf: true, |
|||
}); |
|||
class FieldMethods extends FormFieldMethods { |
|||
updateValue = (value_) => { |
|||
if (props['onUpdateValue']) { |
|||
props['onUpdateValue']({ |
|||
value: value_, |
|||
form: props['form'], |
|||
}); |
|||
} |
|||
}; |
|||
validate = () => { |
|||
if (props.outlined && checkboxRef.value) { |
|||
return checkboxRef.value.validate(); |
|||
} |
|||
return true; |
|||
}; |
|||
setValue = (value_) => { |
|||
modelValue.value = value_; |
|||
}; |
|||
getValue = () => { |
|||
return modelValue.value; |
|||
}; |
|||
clearValue = () => { |
|||
modelValue.value = false; |
|||
}; |
|||
} |
|||
const fieldMethodsClass = new FieldMethods(); |
|||
|
|||
defineExpose({ |
|||
validate: fieldMethodsClass.validate, |
|||
setValue: fieldMethodsClass.setValue, |
|||
getValue: fieldMethodsClass.getValue, |
|||
clearValue: fieldMethodsClass.clearValue, |
|||
}); |
|||
</script> |
|||
|
|||
<style lang="css"> |
|||
.w-checkbox .q-field--dense .q-field__label { |
|||
font-size: 18px; |
|||
top: 18px; |
|||
} |
|||
.w-checkbox .q-field__marginal { |
|||
font-size: 16px; |
|||
color: #0f0f0f; |
|||
} |
|||
</style> |
@ -0,0 +1,114 @@ |
|||
<template> |
|||
<div v-show="FieldMethods.getShow(props, modelValue)" :class="props.simple ? 'w-checkbox-group' : ''"> |
|||
<q-field |
|||
ref="checkboxGroupRef" |
|||
v-model="modelValue" |
|||
:hide-bottom-space="true" |
|||
:hide-hint="true" |
|||
v-bind="attrs" |
|||
:outlined="props.outlined" |
|||
:borderless="!props.outlined" |
|||
:stack-label="true" |
|||
:dense="true" |
|||
:rules="FieldMethods.getRules(props, modelValue, checkboxGroupRef, undefined)" |
|||
:readonly="FieldMethods.getReadOnly(props, modelValue)" |
|||
:disable="FieldMethods.getDisable(props, modelValue)" |
|||
@update:model-value="fieldMethodsClass.updateValue" |
|||
> |
|||
<template #label><w-label :required="FieldMethods.getRequired(props, modelValue)" :label="attrs.label"></w-label></template> |
|||
<template v-if="!props.simple" #control> |
|||
<div class="pt-[5px]"> |
|||
<q-option-group |
|||
v-model="modelValue" |
|||
type="checkbox" |
|||
:dense="props.dense" |
|||
:options="props.options" |
|||
:inline="props.inline" |
|||
:readonly="FieldMethods.getReadOnly(props, modelValue)" |
|||
:disable="FieldMethods.getDisable(props, modelValue)" |
|||
/> |
|||
</div> |
|||
</template> |
|||
<template v-else #append> |
|||
<q-option-group |
|||
v-model="modelValue" |
|||
type="checkbox" |
|||
:dense="props.dense" |
|||
:options="props.options" |
|||
:inline="props.inline" |
|||
:readonly="FieldMethods.getReadOnly(props, modelValue)" |
|||
:disable="FieldMethods.getDisable(props, modelValue)" |
|||
/> |
|||
</template> |
|||
</q-field> |
|||
</div> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import { ref, useAttrs } from 'vue'; |
|||
import { FormFieldProps } from '@/platform/components/form/FormField.ts'; |
|||
import { FormFieldMethods } from '../form/FormField'; |
|||
|
|||
const checkboxGroupRef = ref(); |
|||
const attrs = useAttrs(); |
|||
const modelValue = defineModel<Array<string> | Array<number>>(); |
|||
|
|||
interface FieldProps extends FormFieldProps { |
|||
dense?: boolean; |
|||
inline?: boolean; |
|||
outlined?: boolean; |
|||
borderless?: boolean; |
|||
simple?: boolean; // 是否简单选项的checkbox选项组,默认为是,将label与选项放在同一行,选项过多时使用该模式会导致很难看 |
|||
options: Array<() => void>; |
|||
} |
|||
const props = withDefaults(defineProps<FieldProps>(), { |
|||
showIf: true, |
|||
dense: true, |
|||
inline: true, |
|||
outlined: true, |
|||
simple: true, |
|||
options: () => { |
|||
return []; |
|||
}, |
|||
}); |
|||
class FieldMethods extends FormFieldMethods { |
|||
updateValue = (value_) => { |
|||
if (props['onUpdateValue']) { |
|||
props['onUpdateValue']({ |
|||
value: value_, |
|||
form: props['form'], |
|||
}); |
|||
} |
|||
}; |
|||
validate = () => { |
|||
return checkboxGroupRef.value.validate(); |
|||
}; |
|||
setValue = (value_) => { |
|||
modelValue.value = value_; |
|||
}; |
|||
getValue = () => { |
|||
return modelValue.value; |
|||
}; |
|||
clearValue = () => { |
|||
modelValue.value = undefined; |
|||
}; |
|||
} |
|||
const fieldMethodsClass = new FieldMethods(); |
|||
|
|||
defineExpose({ |
|||
validate: fieldMethodsClass.validate, |
|||
setValue: fieldMethodsClass.setValue, |
|||
getValue: fieldMethodsClass.getValue, |
|||
clearValue: fieldMethodsClass.clearValue, |
|||
}); |
|||
</script> |
|||
|
|||
<style lang="css"> |
|||
.w-checkbox-group .q-field--dense .q-field__label { |
|||
font-size: 18px; |
|||
top: 18px; |
|||
} |
|||
.w-checkbox-group .q-field__marginal { |
|||
font-size: 16px; |
|||
color: #0f0f0f; |
|||
} |
|||
</style> |
@ -0,0 +1,321 @@ |
|||
<template> |
|||
<div v-show="FieldMethods.getShow(props, modelValue)"> |
|||
<q-field |
|||
ref="fieldRef" |
|||
v-model="modelValue" |
|||
:hide-bottom-space="true" |
|||
:hide-hint="true" |
|||
:outlined="true" |
|||
:dense="true" |
|||
v-bind="attrs" |
|||
style="position: relative" |
|||
:rules="FieldMethods.getRules(props, modelValue, fieldRef, undefined)" |
|||
:readonly="FieldMethods.getReadOnly(props, modelValue)" |
|||
:disable="FieldMethods.getDisable(props, modelValue)" |
|||
@update:model-value="fieldMethodsClass.updateValue" |
|||
@focus.stop.prevent="focus" |
|||
@blur.stop.prevent="blur" |
|||
> |
|||
<template #label><w-label :required="FieldMethods.getRequired(props, modelValue)" :label="attrs.label"></w-label></template> |
|||
<template #control> |
|||
<div v-if="editable && toolbar" class="w-full pt-2 border-b border-b-gray-200"> |
|||
<Toolbar :source-code-editor="editorView" :user-defined-functions="userDefinedFunctions"></Toolbar> |
|||
</div> |
|||
<div |
|||
ref="codemirrorRef" |
|||
:style="`width:100%; padding-top: ${lineNumber ? 4 : 2}px; overflow: auto;`" |
|||
@focus.stop.prevent="() => {}" |
|||
@click.stop.prevent="() => {}" |
|||
></div> |
|||
</template> |
|||
<template v-if="!Tools.isEmpty(modelValue) && attrs.button" #append> |
|||
<q-btn |
|||
round |
|||
dense |
|||
flat |
|||
v-bind="attrs.button" |
|||
:style="{ |
|||
content: '', |
|||
position: 'absolute', |
|||
bottom: '5px', |
|||
right: '5px', |
|||
}" |
|||
@click.stop.prevent="buttonClick(attrs.button)" |
|||
/> |
|||
</template> |
|||
</q-field> |
|||
</div> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import { ref, useAttrs, onMounted, onUnmounted, watch } from 'vue'; |
|||
import { Tools } from '@/platform'; |
|||
import { EditorView } from '@codemirror/view'; |
|||
import { EditorState, StateEffect, Compartment } from '@codemirror/state'; |
|||
import * as view from '@codemirror/view'; |
|||
import * as language from '@codemirror/language'; |
|||
import * as commands from '@codemirror/commands'; |
|||
import * as search from '@codemirror/search'; |
|||
import * as autocomplete from '@codemirror/autocomplete'; |
|||
|
|||
import { LanguageSupport } from '@codemirror/language'; |
|||
import { html, htmlLanguage } from '@codemirror/lang-html'; |
|||
import { java, javaLanguage } from '@codemirror/lang-java'; |
|||
import { javascript, javascriptLanguage } from '@codemirror/lang-javascript'; |
|||
import { json, jsonLanguage } from '@codemirror/lang-json'; |
|||
import { sql } from '@codemirror/lang-sql'; |
|||
import { xml, xmlLanguage } from '@codemirror/lang-xml'; |
|||
|
|||
import PlaceholderPlugin from './w-code-mirror/PlaceholderPlugin'; |
|||
import Toolbar from '@/platform/components/math/toolbar/Toolbar.vue'; |
|||
|
|||
import { FormFieldProps } from '@/platform/components/form/FormField.ts'; |
|||
import { FormFieldMethods } from '../form/FormField'; |
|||
|
|||
const fieldRef = ref(); |
|||
const codemirrorRef = ref(); |
|||
const attrs = useAttrs(); |
|||
const modelValue = defineModel<string>(); |
|||
|
|||
interface FieldProps extends FormFieldProps { |
|||
// 语言 |
|||
lang?: string; |
|||
// 宽度 |
|||
width?: number | string; |
|||
// 高度 |
|||
height?: number | string; |
|||
// 行高 |
|||
lineHeight?: number | string; |
|||
// 行数 |
|||
rows?: number; |
|||
// 是否包含工具条 |
|||
toolbar?: boolean; |
|||
// 是否可编辑 |
|||
editable?: boolean; |
|||
// 是否允许自动换行 |
|||
lineWrap?: boolean; |
|||
// tab size |
|||
tabSize?: number; |
|||
// 是否显示行号 |
|||
lineNumber?: boolean; |
|||
// 是否允许回车换行 |
|||
lineBreak?: boolean; |
|||
// 是否开启变量替换 |
|||
placeholder?: boolean; |
|||
autoCompletion?: () => void; |
|||
userDefinedFunctions?: Array<() => void>; |
|||
activateOnCompletion?: () => void; |
|||
} |
|||
const props = withDefaults(defineProps<FieldProps>(), { |
|||
showIf: true, |
|||
lang: 'json', |
|||
width: '100%', |
|||
height: undefined, |
|||
lineHeight: 20, |
|||
rows: 4, |
|||
toolbar: true, |
|||
editable: true, |
|||
lineWrap: false, |
|||
tabSize: 4, |
|||
lineNumber: false, |
|||
lineBreak: true, |
|||
placeholder: false, |
|||
autoCompletion: undefined, |
|||
userDefinedFunctions: () => { |
|||
return []; |
|||
}, |
|||
activateOnCompletion: undefined, |
|||
}); |
|||
class FieldMethods extends FormFieldMethods { |
|||
updateValue = (value_) => { |
|||
if (props['onUpdateValue']) { |
|||
props['onUpdateValue']({ |
|||
value: value_, |
|||
form: props['form'], |
|||
}); |
|||
} |
|||
}; |
|||
validate = () => { |
|||
return fieldRef.value.validate(); |
|||
}; |
|||
setValue = (value_) => { |
|||
editorView.dispatch({ changes: { from: 0, to: editorView.state.doc.length, insert: value_ } }); |
|||
}; |
|||
getValue = () => { |
|||
return editorView.state.doc.toString(); |
|||
}; |
|||
clearValue = () => { |
|||
modelValue.value = undefined; |
|||
}; |
|||
} |
|||
const fieldMethodsClass = new FieldMethods(); |
|||
|
|||
const basicSetup = [ |
|||
EditorState.allowMultipleSelections.of(true), |
|||
|
|||
//view.lineNumbers(), |
|||
//view.highlightActiveLine(), |
|||
view.highlightActiveLineGutter(), |
|||
view.highlightSpecialChars(), |
|||
view.drawSelection(), |
|||
view.dropCursor(), |
|||
view.rectangularSelection(), |
|||
view.crosshairCursor(), |
|||
|
|||
commands.history(), |
|||
|
|||
//language.foldGutter(), |
|||
language.indentOnInput(), |
|||
language.syntaxHighlighting(language.defaultHighlightStyle, { fallback: true }), |
|||
language.bracketMatching(), |
|||
|
|||
//search.highlightSelectionMatches(), |
|||
|
|||
view.keymap.of([ |
|||
...commands.defaultKeymap, |
|||
...commands.historyKeymap, |
|||
...language.foldKeymap, |
|||
...autocomplete.completionKeymap, |
|||
...autocomplete.closeBracketsKeymap, |
|||
...search.searchKeymap, |
|||
commands.indentWithTab, |
|||
]), |
|||
]; |
|||
|
|||
const getLanguage = (lang: string): LanguageSupport => { |
|||
lang = lang || 'json'; |
|||
switch (lang.toLowerCase()) { |
|||
case 'html': |
|||
return html(); |
|||
case 'java': |
|||
return java(); |
|||
case 'javascript': |
|||
return javascript(); |
|||
case 'json': |
|||
return json(); |
|||
case 'sql': |
|||
return sql(); |
|||
case 'xml': |
|||
return xml(); |
|||
default: |
|||
return json(); |
|||
} |
|||
}; |
|||
|
|||
let editorView; |
|||
let isFocus = false; |
|||
|
|||
if (props.lineNumber) { |
|||
// 行号 |
|||
basicSetup.push(view.lineNumbers()); |
|||
} |
|||
if (props.autoCompletion) { |
|||
// 自动完成 |
|||
basicSetup.push(autocomplete.closeBrackets()); |
|||
basicSetup.push( |
|||
autocomplete.autocompletion({ override: [props.autoCompletion], activateOnCompletion: props.activateOnCompletion, maxRenderedOptions: 1000 }), |
|||
); |
|||
} |
|||
if (props.placeholder) { |
|||
// 变量标识替换 |
|||
basicSetup.push(PlaceholderPlugin); |
|||
} |
|||
|
|||
if (props.lineWrap) { |
|||
basicSetup.push(EditorView.lineWrapping); |
|||
} |
|||
|
|||
// 是否可编辑 |
|||
basicSetup.push(EditorView.editable.of(props.editable)); |
|||
|
|||
onMounted(() => { |
|||
if (codemirrorRef.value) { |
|||
let language = new Compartment(); |
|||
let tabSize = new Compartment(); |
|||
editorView = new EditorView({ |
|||
extensions: [ |
|||
basicSetup, |
|||
language.of(getLanguage(props.lang)), |
|||
tabSize.of(EditorState.tabSize.of(props.tabSize)), |
|||
EditorState.readOnly.of(FieldMethods.getReadOnly(props, modelValue.value)), |
|||
EditorView.theme({ |
|||
'&': { |
|||
outline: 'none !important', |
|||
width: Tools.px(props.width), |
|||
height: props.height ? Tools.px(props.height) : props.rows * 20 + (props.lineNumber ? 8 : 6) + 'px', |
|||
}, |
|||
'.cm-content': { |
|||
'line-height': props.lineHeight + 'px', |
|||
}, |
|||
}), |
|||
|
|||
// 以下代码可以添加内容变化后的操作, 为避免重复操作, 更新操作放到 blur 方法中了 |
|||
EditorView.updateListener.of(function (e) { |
|||
// emits('update:modelValue', e.state.doc.toString()); |
|||
let content = e.state.doc.toString(); |
|||
if (!props.lineBreak) { |
|||
content = content?.replace(/[\r\n]/g, ''); |
|||
} |
|||
//updateModelValue(content); |
|||
}), |
|||
], |
|||
parent: codemirrorRef.value, |
|||
doc: modelValue.value, |
|||
}); |
|||
watch( |
|||
() => modelValue.value, |
|||
() => { |
|||
// 当未获得焦点时,更新变更, 当获得焦点时不能更新 |
|||
if (!isFocus) { |
|||
let content = modelValue.value; |
|||
if (!props.lineBreak && !Tools.isEmpty(content)) { |
|||
content = content.replace(/[\r\n]/g, ''); |
|||
} |
|||
editorView.dispatch({ changes: { from: 0, to: editorView.state.doc.length, insert: content } }); |
|||
} |
|||
}, |
|||
); |
|||
} |
|||
}); |
|||
|
|||
onUnmounted(() => { |
|||
editorView.destroy(); |
|||
}); |
|||
|
|||
const focus = () => { |
|||
isFocus = true; |
|||
}; |
|||
|
|||
const blur = () => { |
|||
isFocus = false; |
|||
let content = editorView.state.doc.toString(); |
|||
if (Tools.isUndefinedOrNull(content)) { |
|||
modelValue.value = ''; |
|||
} |
|||
const reg = /\$\{(.+?)\}\.\$\{(.+?)\}/g; |
|||
while (reg.test(content)) { |
|||
content = content.replace(reg, '${$1.$2}'); |
|||
} |
|||
modelValue.value = content; |
|||
}; |
|||
|
|||
const configure = (values) => { |
|||
editorView.dispatch({ effects: StateEffect.reconfigure.of(values) }); |
|||
}; |
|||
|
|||
const buttonClick = (button) => { |
|||
if (button.click) { |
|||
button.click({ |
|||
value: modelValue.value, |
|||
form: props['form'], |
|||
}); |
|||
} |
|||
}; |
|||
|
|||
defineExpose({ |
|||
validate: fieldMethodsClass.validate, |
|||
setValue: fieldMethodsClass.setValue, |
|||
getValue: fieldMethodsClass.getValue, |
|||
clearValue: fieldMethodsClass.clearValue, |
|||
configure, |
|||
}); |
|||
</script> |
@ -0,0 +1,76 @@ |
|||
import { EditorView, ViewPlugin, ViewUpdate, MatchDecorator, Decoration, DecorationSet, WidgetType } from '@codemirror/view'; |
|||
|
|||
class PlaceholderWidget extends WidgetType { |
|||
constructor(name) { |
|||
super(); |
|||
this.name = name; |
|||
} |
|||
|
|||
eq(other) { |
|||
return this.name == other.name; |
|||
} |
|||
|
|||
toDOM() { |
|||
const container = document.createElement('span'); |
|||
container.className = 'px-0.5'; |
|||
|
|||
const elt = document.createElement('span'); |
|||
elt.setAttribute('placeholder', true); |
|||
elt.className = 'p-0.5 border border-gray-800 rounded-md'; |
|||
elt.textContent = this.name; |
|||
|
|||
container.appendChild(elt); |
|||
return container; |
|||
} |
|||
|
|||
ignoreEvent() { |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
const placeholderMatcher = new MatchDecorator({ |
|||
regexp: /\$\{(.+?)\}/g, |
|||
decoration: (match) => |
|||
Decoration.replace({ |
|||
widget: new PlaceholderWidget(match[1]), |
|||
}), |
|||
}); |
|||
|
|||
const placeholderPlugin = ViewPlugin.fromClass( |
|||
class { |
|||
placeholders: DecorationSet; |
|||
constructor(view: EditorView) { |
|||
this.placeholders = placeholderMatcher.createDeco(view); |
|||
} |
|||
update(update: ViewUpdate) { |
|||
this.placeholders = placeholderMatcher.updateDeco(update, this.placeholders); |
|||
} |
|||
}, |
|||
{ |
|||
decorations: (instance) => instance.placeholders, |
|||
provide: (plugin) => |
|||
EditorView.atomicRanges.of((view) => { |
|||
return view.plugin(plugin)?.placeholders || Decoration.none; |
|||
}), |
|||
eventHandlers: { |
|||
mouseover: (e, view) => { |
|||
const target = e.target as HTMLElement; |
|||
if (target.tagName.toLowerCase() === 'span' && target.getAttribute('placeholder')) { |
|||
target.className = 'p-0.5 border border-orange-400 rounded-md'; |
|||
} |
|||
}, |
|||
mouseout: (e, view) => { |
|||
const target = e.target as HTMLElement; |
|||
if (target.tagName.toLowerCase() === 'span' && target.getAttribute('placeholder')) { |
|||
target.className = 'p-0.5 border border-gray-800 rounded-md'; |
|||
} |
|||
}, |
|||
contextmenu: (e, view) => { |
|||
e.preventDefault(); |
|||
console.log(view); |
|||
}, |
|||
}, |
|||
}, |
|||
); |
|||
|
|||
export default placeholderPlugin; |
@ -0,0 +1,128 @@ |
|||
<template> |
|||
<div v-show="FieldMethods.getShow(props, modelValue)"> |
|||
<q-input |
|||
ref="colorRef" |
|||
v-model="modelValue" |
|||
:hide-bottom-space="true" |
|||
:hide-hint="true" |
|||
:outlined="true" |
|||
:dense="true" |
|||
v-bind="attrs" |
|||
:rules="FieldMethods.getRules(props, modelValue, colorRef, undefined)" |
|||
:readonly="FieldMethods.getReadOnly(props, modelValue)" |
|||
:disable="FieldMethods.getDisable(props, modelValue)" |
|||
@update:model-value="fieldMethodsClass.updateValue" |
|||
> |
|||
<template #label><w-label :required="FieldMethods.getRequired(props, modelValue)" :label="attrs.label"></w-label></template> |
|||
<template v-if="!props['form'] || (props['form'] && props['form'].getStatus() !== 'view')" #append> |
|||
<!-- 选择颜色按钮 --> |
|||
<q-btn |
|||
icon="square" |
|||
size="10px" |
|||
padding="2px" |
|||
flat |
|||
square |
|||
unelevated |
|||
:title="$t('select')" |
|||
:style="{ border: '1px solid #e5e7eb', color: modelValue, 'background-color': computedStoreBackgroundColorValue }" |
|||
> |
|||
<q-popup-proxy v-model:model-value="isShow" anchor="bottom right" self="top right" :offset="[0, 10]"> |
|||
<q-color |
|||
v-model="modelValue" |
|||
:default-value="modelValue" |
|||
format-model="hex" |
|||
default-view="palette" |
|||
style="max-width: 250px" |
|||
@update:model-value="fieldMethodsClass.updateValue" |
|||
/> |
|||
</q-popup-proxy> |
|||
</q-btn> |
|||
<!-- 恢复默认值按钮 --> |
|||
<q-btn |
|||
v-if="restore" |
|||
icon="bi-arrow-counterclockwise" |
|||
size="10px" |
|||
padding="2px" |
|||
flat |
|||
square |
|||
unelevated |
|||
:title="$t('restore')" |
|||
:style="{ 'margin-left': '5px', border: '1px solid #e5e7eb', color: restoreValue, 'background-color': computedStoreBackgroundColorValue }" |
|||
@click="restoreDefaultValue" |
|||
></q-btn> |
|||
</template> |
|||
</q-input> |
|||
</div> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import { ref, toRaw, computed, useAttrs, onBeforeMount } from 'vue'; |
|||
import { Tools } from '@/platform'; |
|||
import { FormFieldProps } from '@/platform/components/form/FormField.ts'; |
|||
import { FormFieldMethods } from '../form/FormField'; |
|||
|
|||
const colorRef = ref(); |
|||
const attrs = useAttrs(); |
|||
const modelValue = defineModel<string>(); |
|||
|
|||
const isShow = ref(false); |
|||
const defaultValue = '#000000'; |
|||
const restoreValue = toRaw(modelValue.value || defaultValue); |
|||
|
|||
interface FieldProps extends FormFieldProps { |
|||
restore?: boolean; |
|||
} |
|||
const props = withDefaults(defineProps<FieldProps>(), { |
|||
showIf: true, |
|||
restore: false, |
|||
}); |
|||
class FieldMethods extends FormFieldMethods { |
|||
updateValue = (value_) => { |
|||
isShow.value = false; |
|||
if (props['onUpdateValue']) { |
|||
props['onUpdateValue']({ |
|||
value: value_, |
|||
form: props['form'], |
|||
}); |
|||
} |
|||
}; |
|||
validate = () => { |
|||
return colorRef.value.validate(); |
|||
}; |
|||
setValue = (value_) => { |
|||
modelValue.value = value_; |
|||
}; |
|||
getValue = () => { |
|||
return modelValue.value; |
|||
}; |
|||
clearValue = () => { |
|||
modelValue.value = restoreValue; |
|||
}; |
|||
} |
|||
const fieldMethodsClass = new FieldMethods(); |
|||
|
|||
const computedStoreBackgroundColorValue = computed(() => { |
|||
const color: string = restoreValue; |
|||
if (color.toLowerCase() === 'white' || color.toLowerCase() === '#ffffff' || color.toLowerCase() === '#fff') { |
|||
return '#eee'; |
|||
} |
|||
return undefined; |
|||
}); |
|||
|
|||
const restoreDefaultValue = () => { |
|||
modelValue.value = restoreValue; |
|||
fieldMethodsClass.updateValue(restoreValue); |
|||
}; |
|||
|
|||
onBeforeMount(() => { |
|||
if (Tools.isEmpty(modelValue.value)) { |
|||
modelValue.value = defaultValue; |
|||
} |
|||
}); |
|||
|
|||
defineExpose({ |
|||
validate: fieldMethodsClass.validate, |
|||
setValue: fieldMethodsClass.setValue, |
|||
getValue: fieldMethodsClass.getValue, |
|||
clearValue: fieldMethodsClass.clearValue, |
|||
}); |
|||
</script> |
@ -0,0 +1,148 @@ |
|||
<template> |
|||
<div v-show="FieldMethods.getShow(props, modelValue)"> |
|||
<q-input |
|||
ref="colorRef" |
|||
v-model="modelValue" |
|||
:hide-bottom-space="true" |
|||
:hide-hint="true" |
|||
:outlined="true" |
|||
:dense="true" |
|||
v-bind="attrs" |
|||
:rules="FieldMethods.getRules(props, modelValue, colorRef, undefined)" |
|||
:readonly="FieldMethods.getReadOnly(props, modelValue)" |
|||
:disable="FieldMethods.getDisable(props, modelValue)" |
|||
@update:model-value="fieldMethodsClass.updateValue" |
|||
> |
|||
<template #label><w-label :required="FieldMethods.getRequired(props, modelValue)" :label="attrs.label"></w-label></template> |
|||
<template v-if="!props['form'] || (props['form'] && props['form'].getStatus() !== 'view')" #append> |
|||
<!-- 选择颜色按钮 --> |
|||
<q-btn |
|||
icon="bi-palette" |
|||
size="10px" |
|||
padding="2px" |
|||
flat |
|||
square |
|||
unelevated |
|||
:title="$t('select')" |
|||
:class="`text-${modelValue}`" |
|||
:style="{ border: '1px solid #e5e7eb', 'background-color': computedBackgroundColorValue }" |
|||
> |
|||
<q-popup-proxy v-model:model-value="isShow" anchor="bottom right" self="top right" :offset="[0, 10]"> |
|||
<div v-for="(colors, index) in quasarColors" :key="index" class="row"> |
|||
<div |
|||
v-for="color in colors" |
|||
:key="`${color}`" |
|||
:class="`bg-${color}`" |
|||
style="min-width: 20px; max-width: 20px; min-height: 20px; max-height: 20px" |
|||
@click="colorClick(`${color}`)" |
|||
> |
|||
<q-tooltip> {{ color }}</q-tooltip> |
|||
</div> |
|||
</div> |
|||
</q-popup-proxy> |
|||
</q-btn> |
|||
<!-- 恢复默认值按钮 --> |
|||
<q-btn |
|||
v-if="restore" |
|||
icon="bi-arrow-counterclockwise" |
|||
size="10px" |
|||
padding="2px" |
|||
flat |
|||
square |
|||
unelevated |
|||
:title="$t('restore')" |
|||
:class="`text-${restoreValue}`" |
|||
:style="{ 'margin-left': '5px', border: '1px solid #e5e7eb', 'background-color': computedStoreBackgroundColorValue }" |
|||
@click="restoreDefaultValue" |
|||
></q-btn> |
|||
</template> |
|||
</q-input> |
|||
</div> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import { ref, toRaw, computed, useAttrs, onBeforeMount } from 'vue'; |
|||
import { Tools } from '@/platform'; |
|||
import { FormFieldProps } from '@/platform/components/form/FormField.ts'; |
|||
import { FormFieldMethods } from '../form/FormField'; |
|||
import { quasarColors } from './quasarColors'; |
|||
|
|||
const colorRef = ref(); |
|||
const attrs = useAttrs(); |
|||
const modelValue = defineModel<string>(); |
|||
|
|||
const isShow = ref(false); |
|||
const defaultValue = 'black'; |
|||
const restoreValue = toRaw(modelValue.value || defaultValue); |
|||
|
|||
interface FieldProps extends FormFieldProps { |
|||
restore?: boolean; |
|||
} |
|||
const props = withDefaults(defineProps<FieldProps>(), { |
|||
showIf: true, |
|||
restore: false, |
|||
}); |
|||
class FieldMethods extends FormFieldMethods { |
|||
updateValue = (value_) => { |
|||
modelValue.value = value_; |
|||
isShow.value = false; |
|||
if (props['onUpdateValue']) { |
|||
props['onUpdateValue']({ |
|||
value: value_, |
|||
form: props['form'], |
|||
}); |
|||
} |
|||
}; |
|||
validate = () => { |
|||
return colorRef.value.validate(); |
|||
}; |
|||
setValue = (value_) => { |
|||
modelValue.value = value_; |
|||
}; |
|||
getValue = () => { |
|||
return modelValue.value; |
|||
}; |
|||
clearValue = () => { |
|||
modelValue.value = restoreValue; |
|||
}; |
|||
} |
|||
const fieldMethodsClass = new FieldMethods(); |
|||
|
|||
const computedBackgroundColorValue = computed(() => { |
|||
if (!Tools.isEmpty(modelValue.value)) { |
|||
const color: string = toRaw(modelValue.value); |
|||
if (color.toLowerCase() === 'white' || color.toLowerCase() === '#ffffff' || color.toLowerCase() === '#fff') { |
|||
return '#eee'; |
|||
} |
|||
} |
|||
return undefined; |
|||
}); |
|||
|
|||
const computedStoreBackgroundColorValue = computed(() => { |
|||
const color: string = restoreValue; |
|||
if (color.toLowerCase() === 'white' || color.toLowerCase() === '#ffffff' || color.toLowerCase() === '#fff') { |
|||
return '#eee'; |
|||
} |
|||
return undefined; |
|||
}); |
|||
|
|||
const colorClick = (value) => { |
|||
fieldMethodsClass.updateValue(value); |
|||
}; |
|||
|
|||
const restoreDefaultValue = () => { |
|||
fieldMethodsClass.updateValue(restoreValue); |
|||
}; |
|||
|
|||
onBeforeMount(() => { |
|||
if (Tools.isEmpty(modelValue.value)) { |
|||
modelValue.value = defaultValue; |
|||
} |
|||
}); |
|||
|
|||
defineExpose({ |
|||
validate: fieldMethodsClass.validate, |
|||
setValue: fieldMethodsClass.setValue, |
|||
getValue: fieldMethodsClass.getValue, |
|||
clearValue: fieldMethodsClass.clearValue, |
|||
}); |
|||
</script> |
@ -0,0 +1,214 @@ |
|||
export const quasarColors = [ |
|||
['red', 'red-1', 'red-2', 'red-3', 'red-4', 'red-5', 'red-6', 'red-7', 'red-8', 'red-9', 'red-10', 'red-11', 'red-12', 'red-13', 'red-14'], |
|||
['pink', 'pink-1', 'pink-2', 'pink-3', 'pink-4', 'pink-5', 'pink-6', 'pink-7', 'pink-8', 'pink-9', 'pink-10', 'pink-11', 'pink-12', 'pink-13', 'pink-14'], |
|||
[ |
|||
'purple', |
|||
'purple-1', |
|||
'purple-2', |
|||
'purple-3', |
|||
'purple-4', |
|||
'purple-5', |
|||
'purple-6', |
|||
'purple-7', |
|||
'purple-8', |
|||
'purple-9', |
|||
'purple-10', |
|||
'purple-11', |
|||
'purple-12', |
|||
'purple-13', |
|||
'purple-14', |
|||
], |
|||
[ |
|||
'deep-purple', |
|||
'deep-purple-1', |
|||
'deep-purple-2', |
|||
'deep-purple-3', |
|||
'deep-purple-4', |
|||
'deep-purple-5', |
|||
'deep-purple-6', |
|||
'deep-purple-7', |
|||
'deep-purple-8', |
|||
'deep-purple-9', |
|||
'deep-purple-10', |
|||
'deep-purple-11', |
|||
'deep-purple-12', |
|||
'deep-purple-13', |
|||
'deep-purple-14', |
|||
], |
|||
[ |
|||
'indigo', |
|||
'indigo-1', |
|||
'indigo-2', |
|||
'indigo-3', |
|||
'indigo-4', |
|||
'indigo-5', |
|||
'indigo-6', |
|||
'indigo-7', |
|||
'indigo-8', |
|||
'indigo-9', |
|||
'indigo-10', |
|||
'indigo-11', |
|||
'indigo-12', |
|||
'indigo-13', |
|||
'indigo-14', |
|||
], |
|||
['blue', 'blue-1', 'blue-2', 'blue-3', 'blue-4', 'blue-5', 'blue-6', 'blue-7', 'blue-8', 'blue-9', 'blue-10', 'blue-11', 'blue-12', 'blue-13', 'blue-14'], |
|||
[ |
|||
'light-blue', |
|||
'light-blue-1', |
|||
'light-blue-2', |
|||
'light-blue-3', |
|||
'light-blue-4', |
|||
'light-blue-5', |
|||
'light-blue-6', |
|||
'light-blue-7', |
|||
'light-blue-8', |
|||
'light-blue-9', |
|||
'light-blue-10', |
|||
'light-blue-11', |
|||
'light-blue-12', |
|||
'light-blue-13', |
|||
'light-blue-14', |
|||
], |
|||
['cyan', 'cyan-1', 'cyan-2', 'cyan-3', 'cyan-4', 'cyan-5', 'cyan-6', 'cyan-7', 'cyan-8', 'cyan-9', 'cyan-10', 'cyan-11', 'cyan-12', 'cyan-13', 'cyan-14'], |
|||
['teal', 'teal-1', 'teal-2', 'teal-3', 'teal-4', 'teal-5', 'teal-6', 'teal-7', 'teal-8', 'teal-9', 'teal-10', 'teal-11', 'teal-12', 'teal-13', 'teal-14'], |
|||
[ |
|||
'green', |
|||
'green-1', |
|||
'green-2', |
|||
'green-3', |
|||
'green-4', |
|||
'green-5', |
|||
'green-6', |
|||
'green-7', |
|||
'green-8', |
|||
'green-9', |
|||
'green-10', |
|||
'green-11', |
|||
'green-12', |
|||
'green-13', |
|||
'green-14', |
|||
], |
|||
[ |
|||
'light-green', |
|||
'light-green-1', |
|||
'light-green-2', |
|||
'light-green-3', |
|||
'light-green-4', |
|||
'light-green-5', |
|||
'light-green-6', |
|||
'light-green-7', |
|||
'light-green-8', |
|||
'light-green-9', |
|||
'light-green-10', |
|||
'light-green-11', |
|||
'light-green-12', |
|||
'light-green-13', |
|||
'light-green-14', |
|||
], |
|||
['lime', 'lime-1', 'lime-2', 'lime-3', 'lime-4', 'lime-5', 'lime-6', 'lime-7', 'lime-8', 'lime-9', 'lime-10', 'lime-11', 'lime-12', 'lime-13', 'lime-14'], |
|||
[ |
|||
'yellow', |
|||
'yellow-1', |
|||
'yellow-2', |
|||
'yellow-3', |
|||
'yellow-4', |
|||
'yellow-5', |
|||
'yellow-6', |
|||
'yellow-7', |
|||
'yellow-8', |
|||
'yellow-9', |
|||
'yellow-10', |
|||
'yellow-11', |
|||
'yellow-12', |
|||
'yellow-13', |
|||
'yellow-14', |
|||
], |
|||
[ |
|||
'amber', |
|||
'amber-1', |
|||
'amber-2', |
|||
'amber-3', |
|||
'amber-4', |
|||
'amber-5', |
|||
'amber-6', |
|||
'amber-7', |
|||
'amber-8', |
|||
'amber-9', |
|||
'amber-10', |
|||
'amber-11', |
|||
'amber-12', |
|||
'amber-13', |
|||
'amber-14', |
|||
], |
|||
[ |
|||
'orange', |
|||
'orange-1', |
|||
'orange-2', |
|||
'orange-3', |
|||
'orange-4', |
|||
'orange-5', |
|||
'orange-6', |
|||
'orange-7', |
|||
'orange-8', |
|||
'orange-9', |
|||
'orange-10', |
|||
'orange-11', |
|||
'orange-12', |
|||
'orange-13', |
|||
'orange-14', |
|||
], |
|||
[ |
|||
'deep-orange', |
|||
'deep-orange-1', |
|||
'deep-orange-2', |
|||
'deep-orange-3', |
|||
'deep-orange-4', |
|||
'deep-orange-5', |
|||
'deep-orange-6', |
|||
'deep-orange-7', |
|||
'deep-orange-8', |
|||
'deep-orange-9', |
|||
'deep-orange-10', |
|||
'deep-orange-11', |
|||
'deep-orange-12', |
|||
'deep-orange-13', |
|||
'deep-orange-14', |
|||
], |
|||
[ |
|||
'brown', |
|||
'brown-1', |
|||
'brown-2', |
|||
'brown-3', |
|||
'brown-4', |
|||
'brown-5', |
|||
'brown-6', |
|||
'brown-7', |
|||
'brown-8', |
|||
'brown-9', |
|||
'brown-10', |
|||
'brown-11', |
|||
'brown-12', |
|||
'brown-13', |
|||
'brown-14', |
|||
], |
|||
['grey', 'grey-1', 'grey-2', 'grey-3', 'grey-4', 'grey-5', 'grey-6', 'grey-7', 'grey-8', 'grey-9', 'grey-10', 'grey-11', 'grey-12', 'grey-13', 'grey-14'], |
|||
[ |
|||
'blue-grey', |
|||
'blue-grey-1', |
|||
'blue-grey-2', |
|||
'blue-grey-3', |
|||
'blue-grey-4', |
|||
'blue-grey-5', |
|||
'blue-grey-6', |
|||
'blue-grey-7', |
|||
'blue-grey-8', |
|||
'blue-grey-9', |
|||
'blue-grey-10', |
|||
'blue-grey-11', |
|||
'blue-grey-12', |
|||
'blue-grey-13', |
|||
'blue-grey-14', |
|||
], |
|||
['white', 'black'], |
|||
]; |
@ -0,0 +1,138 @@ |
|||
<template> |
|||
<div v-show="FieldMethods.getShow(props, modelValue)"> |
|||
<q-input |
|||
ref="cronRef" |
|||
v-model="modelValue" |
|||
:hide-bottom-space="true" |
|||
:hide-hint="true" |
|||
:outlined="true" |
|||
:dense="true" |
|||
v-bind="attrs" |
|||
:rules="FieldMethods.getRules(props, modelValue, cronRef, undefined)" |
|||
:readonly="FieldMethods.getReadOnly(props, modelValue)" |
|||
:disable="FieldMethods.getDisable(props, modelValue)" |
|||
:v-bind="attrs" |
|||
@update:model-value="fieldMethodsClass.updateValue" |
|||
> |
|||
<template #label><w-label :required="FieldMethods.getRequired(props, modelValue)" :label="attrs.label"></w-label></template> |
|||
<template v-if="!props['form'] || (props['form'] && props['form'].getStatus() !== 'view')" #append> |
|||
<!-- 选择颜色按钮 --> |
|||
<q-btn icon="bi-pencil-square" padding="2px" flat square unelevated :title="$t('select')"> |
|||
<q-popup-proxy v-model:model-value="isShow" anchor="bottom right" self="top right" :offset="[0, 10]" style="width: 800px"> |
|||
<q-tabs v-model="selectedTab" no-caps> |
|||
<q-tab name="second" :label="$t('second')" /> |
|||
<q-tab name="minute" :label="$t('minute')" /> |
|||
<q-tab name="hour" :label="$t('hour')" /> |
|||
<q-tab name="day" :label="$t('day')" /> |
|||
<q-tab name="month" :label="$t('month')" /> |
|||
<q-tab name="week" :label="$t('week')" /> |
|||
<q-tab name="year" :label="$t('year')" /> |
|||
</q-tabs> |
|||
|
|||
<q-tab-panels v-model="selectedTab" animated swipeable vertical transition-prev="jump-up" transition-next="jump-up" :keep-alive="true"> |
|||
<q-tab-panel name="second"> |
|||
<SecondSegment v-model="secondValueRef" @update:model-value="valueChanged"></SecondSegment> |
|||
</q-tab-panel> |
|||
<q-tab-panel name="minute"> |
|||
<MinuteSegment v-model="minuteValueRef" @update:model-value="valueChanged"></MinuteSegment> |
|||
</q-tab-panel> |
|||
<q-tab-panel name="hour"> |
|||
<HourSegment v-model="hourValueRef" @update:model-value="valueChanged"></HourSegment> |
|||
</q-tab-panel> |
|||
<q-tab-panel name="day"> |
|||
<DaySegment v-model="dayValueRef" @update:model-value="valueChanged"></DaySegment> |
|||
</q-tab-panel> |
|||
<q-tab-panel name="month"> |
|||
<MonthSegment v-model="monthValueRef" @update:model-value="valueChanged"></MonthSegment> |
|||
</q-tab-panel> |
|||
<q-tab-panel name="week"> |
|||
<WeekSegment v-model="weekValueRef" @update:model-value="valueChanged"></WeekSegment> |
|||
</q-tab-panel> |
|||
<q-tab-panel name="year"> |
|||
<YearSegment v-model="yearValueRef" @update:model-value="valueChanged"></YearSegment> |
|||
</q-tab-panel> |
|||
</q-tab-panels> |
|||
</q-popup-proxy> |
|||
</q-btn> |
|||
</template> |
|||
</q-input> |
|||
</div> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import { ref, useAttrs } from 'vue'; |
|||
import { Tools } from '@/platform'; |
|||
import SecondSegment from './w-cron-segment/SecondSegment.vue'; |
|||
import MinuteSegment from './w-cron-segment/MinuteSegment.vue'; |
|||
import HourSegment from './w-cron-segment/HourSegment.vue'; |
|||
import DaySegment from './w-cron-segment/DaySegment.vue'; |
|||
import MonthSegment from './w-cron-segment/MonthSegment.vue'; |
|||
import WeekSegment from './w-cron-segment/WeekSegment.vue'; |
|||
import YearSegment from './w-cron-segment/YearSegment.vue'; |
|||
import { FormFieldProps } from '@/platform/components/form/FormField.ts'; |
|||
import { FormFieldMethods } from '../form/FormField'; |
|||
|
|||
const cronRef = ref(); |
|||
const attrs = useAttrs(); |
|||
const modelValue = defineModel<string>(); |
|||
|
|||
const isShow = ref(false); |
|||
const selectedTab = ref('second'); |
|||
const splits = (modelValue.value || '').split(' '); |
|||
const secondValueRef = ref(splits[0]); |
|||
const minuteValueRef = ref(splits[1]); |
|||
const hourValueRef = ref(splits[2]); |
|||
const dayValueRef = ref(splits[3]); |
|||
const monthValueRef = ref(splits[4]); |
|||
const weekValueRef = ref(splits[5]); |
|||
const yearValueRef = ref(splits[6]); |
|||
|
|||
interface FieldProps extends FormFieldProps {} |
|||
const props = withDefaults(defineProps<FieldProps>(), { |
|||
showIf: true, |
|||
}); |
|||
class FieldMethods extends FormFieldMethods { |
|||
updateValue = (value_) => { |
|||
if (props['onUpdateValue']) { |
|||
props['onUpdateValue']({ |
|||
value: value_, |
|||
form: props['form'], |
|||
}); |
|||
} |
|||
}; |
|||
validate = () => { |
|||
return cronRef.value.validate(); |
|||
}; |
|||
setValue = (value_) => { |
|||
modelValue.value = value_; |
|||
}; |
|||
getValue = () => { |
|||
return modelValue.value; |
|||
}; |
|||
clearValue = () => { |
|||
modelValue.value = undefined; |
|||
}; |
|||
} |
|||
const fieldMethodsClass = new FieldMethods(); |
|||
|
|||
const valueChanged = () => { |
|||
const values = <any>[]; |
|||
values.push(secondValueRef.value ? secondValueRef.value : '*'); |
|||
values.push(minuteValueRef.value ? minuteValueRef.value : '*'); |
|||
values.push(hourValueRef.value ? hourValueRef.value : '*'); |
|||
values.push(dayValueRef.value ? dayValueRef.value : '*'); |
|||
values.push(monthValueRef.value ? monthValueRef.value : '*'); |
|||
values.push(weekValueRef.value ? weekValueRef.value : '*'); |
|||
values.push(yearValueRef.value ? yearValueRef.value : '*'); |
|||
|
|||
const result = Tools.join(values, ' '); |
|||
modelValue.value = result; |
|||
fieldMethodsClass.updateValue(result); |
|||
}; |
|||
|
|||
defineExpose({ |
|||
validate: fieldMethodsClass.validate, |
|||
setValue: fieldMethodsClass.setValue, |
|||
getValue: fieldMethodsClass.getValue, |
|||
clearValue: fieldMethodsClass.clearValue, |
|||
}); |
|||
</script> |
@ -0,0 +1,251 @@ |
|||
<template> |
|||
<q-list dense style="width: 100%"> |
|||
<q-item> |
|||
<q-item-section avatar> |
|||
<q-radio v-model="modeRef" val="per" @update:model-value="valueChanged" /> |
|||
</q-item-section> |
|||
<q-item-section> |
|||
<q-item-label>{{ $t('cron.day.per') }}</q-item-label> |
|||
</q-item-section> |
|||
</q-item> |
|||
<q-item> |
|||
<q-item-section avatar> |
|||
<q-radio v-model="modeRef" val="notSpecify" @update:model-value="valueChanged" /> |
|||
</q-item-section> |
|||
<q-item-section> |
|||
<q-item-label>{{ $t('cron.day.notSpecify') }}</q-item-label> |
|||
</q-item-section> |
|||
</q-item> |
|||
<q-item> |
|||
<q-item-section avatar> |
|||
<q-radio v-model="modeRef" val="period" @update:model-value="valueChanged" /> |
|||
</q-item-section> |
|||
<q-item-section> |
|||
<q-item-label> |
|||
<div class="row no-wrap items-center"> |
|||
<span class="pr-2">{{ $t('cron.day.period.1') }}</span> |
|||
<q-input |
|||
v-model="periodFromRef" |
|||
type="number" |
|||
:disable="!periodFromEnableRef" |
|||
outlined |
|||
dense |
|||
style="width: 100px" |
|||
@update:model-value="valueChanged" |
|||
></q-input> |
|||
<span class="px-2">{{ $t('cron.day.period.2') }}</span> |
|||
<q-input |
|||
v-model="periodToRef" |
|||
type="number" |
|||
:disable="!periodToEnableRef" |
|||
outlined |
|||
dense |
|||
style="width: 100px" |
|||
@update:model-value="valueChanged" |
|||
></q-input> |
|||
<span class="px-2">{{ $t('cron.day.period.3') }}</span> |
|||
</div> |
|||
</q-item-label> |
|||
</q-item-section> |
|||
</q-item> |
|||
<q-item> |
|||
<q-item-section avatar> |
|||
<q-radio v-model="modeRef" val="per2" @update:model-value="valueChanged" /> |
|||
</q-item-section> |
|||
<q-item-section> |
|||
<q-item-label> |
|||
<div class="row no-wrap items-center"> |
|||
<span class="pr-2">{{ $t('cron.day.per2.1') }}</span> |
|||
<q-input |
|||
v-model="per2FromRef" |
|||
type="number" |
|||
:disable="!per2FromEnableRef" |
|||
outlined |
|||
dense |
|||
style="width: 100px" |
|||
@update:model-value="valueChanged" |
|||
></q-input> |
|||
<span class="px-2">{{ $t('cron.day.per2.2') }}</span> |
|||
<q-input |
|||
v-model="per2PerRef" |
|||
type="number" |
|||
:disable="!per2PerEnableRef" |
|||
outlined |
|||
dense |
|||
style="width: 100px" |
|||
@update:model-value="valueChanged" |
|||
></q-input> |
|||
<span class="px-2">{{ $t('cron.day.per2.3') }}</span> |
|||
</div> |
|||
</q-item-label> |
|||
</q-item-section> |
|||
</q-item> |
|||
|
|||
<q-item> |
|||
<q-item-section avatar> |
|||
<q-radio v-model="modeRef" val="workDay" @update:model-value="valueChanged" /> |
|||
</q-item-section> |
|||
<q-item-section> |
|||
<q-item-label> |
|||
<div class="row no-wrap items-center"> |
|||
<span class="pr-2">{{ $t('cron.day.workDay.1') }}</span> |
|||
<q-input |
|||
v-model="workDayRef" |
|||
type="number" |
|||
:disable="!workDayEnableRef" |
|||
outlined |
|||
dense |
|||
style="width: 100px" |
|||
@update:model-value="valueChanged" |
|||
></q-input> |
|||
<span class="px-2">{{ $t('cron.day.workDay.2') }}</span> |
|||
</div> |
|||
</q-item-label> |
|||
</q-item-section> |
|||
</q-item> |
|||
|
|||
<q-item> |
|||
<q-item-section avatar> |
|||
<q-radio v-model="modeRef" val="lastDay" @update:model-value="valueChanged" /> |
|||
</q-item-section> |
|||
<q-item-section> |
|||
<q-item-label>{{ $t('cron.day.lastDay') }}</q-item-label> |
|||
</q-item-section> |
|||
</q-item> |
|||
|
|||
<q-item> |
|||
<q-item-section avatar> |
|||
<q-radio v-model="modeRef" val="specify" @update:model-value="valueChanged" /> |
|||
</q-item-section> |
|||
<q-item-section> |
|||
<q-item-label>{{ $t('cron.day.specify') }}</q-item-label> |
|||
</q-item-section> |
|||
</q-item> |
|||
<q-item> |
|||
<q-item-section> |
|||
<q-item-label> |
|||
<div class="row"> |
|||
<template v-for="index in 31" :key="index"> |
|||
<template v-if="index % 10 === 1"> |
|||
<div class="col-1"></div> |
|||
</template> |
|||
<div class="col-1"> |
|||
<q-checkbox |
|||
v-model="optionsRef[index - 1]" |
|||
dense |
|||
:label="'' + index" |
|||
:disable="!optionsEnableRef" |
|||
@update:model-value="valueChanged" |
|||
></q-checkbox> |
|||
</div> |
|||
<template v-if="index % 10 === 0"> |
|||
<div class="col-1"></div> |
|||
</template> |
|||
</template> |
|||
</div> |
|||
</q-item-label> |
|||
</q-item-section> |
|||
</q-item> |
|||
</q-list> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import { ref } from 'vue'; |
|||
import { Tools } from '@/platform'; |
|||
|
|||
const props = defineProps({ |
|||
modelValue: { type: String, default: '' }, |
|||
}); |
|||
const emit = defineEmits(['update:modelValue']); |
|||
|
|||
const valueRef = ref(props.modelValue); |
|||
const modeRef = ref(''); |
|||
|
|||
const periodFromEnableRef = ref(false); |
|||
const periodFromRef = ref(''); |
|||
|
|||
const periodToEnableRef = ref(false); |
|||
const periodToRef = ref(''); |
|||
|
|||
const per2FromEnableRef = ref(false); |
|||
const per2FromRef = ref(''); |
|||
|
|||
const per2PerEnableRef = ref(false); |
|||
const per2PerRef = ref(''); |
|||
|
|||
const workDayEnableRef = ref(false); |
|||
const workDayRef = ref(''); |
|||
|
|||
const optionsEnableRef = ref(false); |
|||
const optionsRef = ref([]); |
|||
for (let i = 0; i < 31; i++) { |
|||
optionsRef.value.push(false); |
|||
} |
|||
|
|||
const valueChanged = () => { |
|||
if (modeRef.value === 'per') { |
|||
periodFromEnableRef.value = false; |
|||
periodToEnableRef.value = false; |
|||
per2FromEnableRef.value = false; |
|||
per2PerEnableRef.value = false; |
|||
workDayEnableRef.value = false; |
|||
optionsEnableRef.value = false; |
|||
} else if (modeRef.value === 'period') { |
|||
periodFromEnableRef.value = true; |
|||
periodToEnableRef.value = true; |
|||
per2FromEnableRef.value = false; |
|||
per2PerEnableRef.value = false; |
|||
workDayEnableRef.value = false; |
|||
optionsEnableRef.value = false; |
|||
} else if (modeRef.value === 'per2') { |
|||
periodFromEnableRef.value = false; |
|||
periodToEnableRef.value = false; |
|||
per2FromEnableRef.value = true; |
|||
per2PerEnableRef.value = true; |
|||
workDayEnableRef.value = false; |
|||
optionsEnableRef.value = false; |
|||
} else if (modeRef.value === 'workDay') { |
|||
periodFromEnableRef.value = false; |
|||
periodToEnableRef.value = false; |
|||
per2FromEnableRef.value = false; |
|||
per2PerEnableRef.value = false; |
|||
workDayEnableRef.value = true; |
|||
optionsEnableRef.value = false; |
|||
} else if (modeRef.value === 'lastDay') { |
|||
periodFromEnableRef.value = false; |
|||
periodToEnableRef.value = false; |
|||
per2FromEnableRef.value = false; |
|||
per2PerEnableRef.value = false; |
|||
workDayEnableRef.value = false; |
|||
optionsEnableRef.value = false; |
|||
} else if (modeRef.value === 'specify') { |
|||
periodFromEnableRef.value = false; |
|||
periodToEnableRef.value = false; |
|||
per2FromEnableRef.value = false; |
|||
per2PerEnableRef.value = false; |
|||
workDayEnableRef.value = false; |
|||
optionsEnableRef.value = true; |
|||
} |
|||
|
|||
if (modeRef.value === 'per') { |
|||
valueRef.value = '*'; |
|||
} else if (modeRef.value === 'period') { |
|||
valueRef.value = periodFromRef.value + '-' + periodToRef.value; |
|||
} else if (modeRef.value === 'per2') { |
|||
valueRef.value = per2FromRef.value + '/' + per2PerRef.value; |
|||
} else if (modeRef.value === 'workDay') { |
|||
valueRef.value = workDayRef.value + 'W'; |
|||
} else if (modeRef.value === 'lastDay') { |
|||
valueRef.value = 'L'; |
|||
} else if (modeRef.value === 'specify') { |
|||
let seconds = []; |
|||
for (let i = 0; i < 31; i++) { |
|||
if (optionsRef.value[i]) { |
|||
seconds.push(i + 1); |
|||
} |
|||
} |
|||
valueRef.value = Tools.join(seconds, ','); |
|||
} |
|||
|
|||
emit('update:modelValue', valueRef.value); |
|||
}; |
|||
</script> |
@ -0,0 +1,185 @@ |
|||
<template> |
|||
<q-list dense style="width: 100%"> |
|||
<q-item> |
|||
<q-item-section avatar> |
|||
<q-radio v-model="modeRef" val="per" @update:model-value="valueChanged" /> |
|||
</q-item-section> |
|||
<q-item-section> |
|||
<q-item-label>{{ $t('cron.hour.per') }}</q-item-label> |
|||
</q-item-section> |
|||
</q-item> |
|||
<q-item> |
|||
<q-item-section avatar> |
|||
<q-radio v-model="modeRef" val="period" @update:model-value="valueChanged" /> |
|||
</q-item-section> |
|||
<q-item-section> |
|||
<q-item-label> |
|||
<div class="row no-wrap items-center"> |
|||
<span class="pr-2">{{ $t('cron.hour.period.1') }}</span> |
|||
<q-input |
|||
v-model="periodFromRef" |
|||
type="number" |
|||
:disable="!periodFromEnableRef" |
|||
outlined |
|||
dense |
|||
style="width: 100px" |
|||
@update:model-value="valueChanged" |
|||
></q-input> |
|||
<span class="px-2">{{ $t('cron.hour.period.2') }}</span> |
|||
<q-input |
|||
v-model="periodToRef" |
|||
type="number" |
|||
:disable="!periodToEnableRef" |
|||
outlined |
|||
dense |
|||
style="width: 100px" |
|||
@update:model-value="valueChanged" |
|||
></q-input> |
|||
<span class="px-2">{{ $t('cron.hour.period.3') }}</span> |
|||
</div> |
|||
</q-item-label> |
|||
</q-item-section> |
|||
</q-item> |
|||
<q-item> |
|||
<q-item-section avatar> |
|||
<q-radio v-model="modeRef" val="per2" @update:model-value="valueChanged" /> |
|||
</q-item-section> |
|||
<q-item-section> |
|||
<q-item-label> |
|||
<div class="row no-wrap items-center"> |
|||
<span class="pr-2">{{ $t('cron.hour.per2.1') }}</span> |
|||
<q-input |
|||
v-model="per2FromRef" |
|||
type="number" |
|||
:disable="!per2FromEnableRef" |
|||
outlined |
|||
dense |
|||
style="width: 100px" |
|||
@update:model-value="valueChanged" |
|||
></q-input> |
|||
<span class="px-2">{{ $t('cron.hour.per2.2') }}</span> |
|||
<q-input |
|||
v-model="per2PerRef" |
|||
type="number" |
|||
:disable="!per2PerEnableRef" |
|||
outlined |
|||
dense |
|||
style="width: 100px" |
|||
@update:model-value="valueChanged" |
|||
></q-input> |
|||
<span class="px-2">{{ $t('cron.hour.per2.3') }}</span> |
|||
</div> |
|||
</q-item-label> |
|||
</q-item-section> |
|||
</q-item> |
|||
<q-item> |
|||
<q-item-section avatar> |
|||
<q-radio v-model="modeRef" val="specify" @update:model-value="valueChanged" /> |
|||
</q-item-section> |
|||
<q-item-section> |
|||
<q-item-label>{{ $t('cron.hour.specify') }}</q-item-label> |
|||
</q-item-section> |
|||
</q-item> |
|||
<q-item> |
|||
<q-item-section avatar> |
|||
<q-item-label> |
|||
<div class="row"> |
|||
<template v-for="index in 24" :key="index"> |
|||
<template v-if="index % 8 === 1"> |
|||
<div class="col-1"></div> |
|||
</template> |
|||
<div class="col-1"> |
|||
<q-checkbox |
|||
v-model="optionsRef[index - 1]" |
|||
dense |
|||
:label="'' + (index - 1)" |
|||
:disable="!optionsEnableRef" |
|||
@update:model-value="valueChanged" |
|||
></q-checkbox> |
|||
</div> |
|||
<template v-if="index % 8 === 0"> |
|||
<div class="col-3"></div> |
|||
</template> |
|||
</template> |
|||
</div> |
|||
</q-item-label> |
|||
</q-item-section> |
|||
</q-item> |
|||
</q-list> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import { ref } from 'vue'; |
|||
import { Tools } from '@/platform'; |
|||
|
|||
const props = defineProps({ |
|||
modelValue: { type: String, default: '' }, |
|||
}); |
|||
const emit = defineEmits(['update:modelValue']); |
|||
|
|||
const valueRef = ref(props.modelValue); |
|||
const modeRef = ref(''); |
|||
|
|||
const periodFromEnableRef = ref(false); |
|||
const periodFromRef = ref(''); |
|||
|
|||
const periodToEnableRef = ref(false); |
|||
const periodToRef = ref(''); |
|||
|
|||
const per2FromEnableRef = ref(false); |
|||
const per2FromRef = ref(''); |
|||
|
|||
const per2PerEnableRef = ref(false); |
|||
const per2PerRef = ref(''); |
|||
|
|||
const optionsEnableRef = ref(false); |
|||
const optionsRef = ref([]); |
|||
for (let i = 0; i < 24; i++) { |
|||
optionsRef.value.push(false); |
|||
} |
|||
|
|||
const valueChanged = () => { |
|||
if (modeRef.value === 'per') { |
|||
periodFromEnableRef.value = false; |
|||
periodToEnableRef.value = false; |
|||
per2FromEnableRef.value = false; |
|||
per2PerEnableRef.value = false; |
|||
optionsEnableRef.value = false; |
|||
} else if (modeRef.value === 'period') { |
|||
periodFromEnableRef.value = true; |
|||
periodToEnableRef.value = true; |
|||
per2FromEnableRef.value = false; |
|||
per2PerEnableRef.value = false; |
|||
optionsEnableRef.value = false; |
|||
} else if (modeRef.value === 'per2') { |
|||
periodFromEnableRef.value = false; |
|||
periodToEnableRef.value = false; |
|||
per2FromEnableRef.value = true; |
|||
per2PerEnableRef.value = true; |
|||
optionsEnableRef.value = false; |
|||
} else if (modeRef.value === 'specify') { |
|||
periodFromEnableRef.value = false; |
|||
periodToEnableRef.value = false; |
|||
per2FromEnableRef.value = false; |
|||
per2PerEnableRef.value = false; |
|||
optionsEnableRef.value = true; |
|||
} |
|||
|
|||
if (modeRef.value === 'per') { |
|||
valueRef.value = '*'; |
|||
} else if (modeRef.value === 'period') { |
|||
valueRef.value = periodFromRef.value + '-' + periodToRef.value; |
|||
} else if (modeRef.value === 'per2') { |
|||
valueRef.value = per2FromRef.value + '/' + per2PerRef.value; |
|||
} else if (modeRef.value === 'specify') { |
|||
let seconds = []; |
|||
for (let i = 0; i < 24; i++) { |
|||
if (optionsRef.value[i]) { |
|||
seconds.push(i); |
|||
} |
|||
} |
|||
valueRef.value = Tools.join(seconds, ','); |
|||
} |
|||
|
|||
emit('update:modelValue', valueRef.value); |
|||
}; |
|||
</script> |
@ -0,0 +1,185 @@ |
|||
<template> |
|||
<q-list dense style="width: 100%"> |
|||
<q-item> |
|||
<q-item-section avatar> |
|||
<q-radio v-model="modeRef" val="per" @update:model-value="valueChanged" /> |
|||
</q-item-section> |
|||
<q-item-section> |
|||
<q-item-label>{{ $t('cron.minute.per') }}</q-item-label> |
|||
</q-item-section> |
|||
</q-item> |
|||
<q-item> |
|||
<q-item-section avatar> |
|||
<q-radio v-model="modeRef" val="period" @update:model-value="valueChanged" /> |
|||
</q-item-section> |
|||
<q-item-section> |
|||
<q-item-label> |
|||
<div class="row no-wrap items-center"> |
|||
<span class="pr-2">{{ $t('cron.minute.period.1') }}</span> |
|||
<q-input |
|||
v-model="periodFromRef" |
|||
type="number" |
|||
:disable="!periodFromEnableRef" |
|||
outlined |
|||
dense |
|||
style="width: 100px" |
|||
@update:model-value="valueChanged" |
|||
></q-input> |
|||
<span class="px-2">{{ $t('cron.minute.period.2') }}</span> |
|||
<q-input |
|||
v-model="periodToRef" |
|||
type="number" |
|||
:disable="!periodToEnableRef" |
|||
outlined |
|||
dense |
|||
style="width: 100px" |
|||
@update:model-value="valueChanged" |
|||
></q-input> |
|||
<span class="px-2">{{ $t('cron.minute.period.3') }}</span> |
|||
</div> |
|||
</q-item-label> |
|||
</q-item-section> |
|||
</q-item> |
|||
<q-item> |
|||
<q-item-section avatar> |
|||
<q-radio v-model="modeRef" val="per2" @update:model-value="valueChanged" /> |
|||
</q-item-section> |
|||
<q-item-section> |
|||
<q-item-label> |
|||
<div class="row no-wrap items-center"> |
|||
<span class="pr-2">{{ $t('cron.minute.per2.1') }}</span> |
|||
<q-input |
|||
v-model="per2FromRef" |
|||
type="number" |
|||
:disable="!per2FromEnableRef" |
|||
outlined |
|||
dense |
|||
style="width: 100px" |
|||
@update:model-value="valueChanged" |
|||
></q-input> |
|||
<span class="px-2">{{ $t('cron.minute.per2.2') }}</span> |
|||
<q-input |
|||
v-model="per2PerRef" |
|||
type="number" |
|||
:disable="!per2PerEnableRef" |
|||
outlined |
|||
dense |
|||
style="width: 100px" |
|||
@update:model-value="valueChanged" |
|||
></q-input> |
|||
<span class="px-2">{{ $t('cron.minute.per2.3') }}</span> |
|||
</div> |
|||
</q-item-label> |
|||
</q-item-section> |
|||
</q-item> |
|||
<q-item> |
|||
<q-item-section avatar> |
|||
<q-radio v-model="modeRef" val="specify" @update:model-value="valueChanged" /> |
|||
</q-item-section> |
|||
<q-item-section> |
|||
<q-item-label>{{ $t('cron.minute.specify') }}</q-item-label> |
|||
</q-item-section> |
|||
</q-item> |
|||
<q-item> |
|||
<q-item-section avatar> |
|||
<q-item-label> |
|||
<div class="row"> |
|||
<template v-for="index in 60" :key="index"> |
|||
<template v-if="index % 10 === 1"> |
|||
<div class="col-1"></div> |
|||
</template> |
|||
<div class="col-1"> |
|||
<q-checkbox |
|||
v-model="optionsRef[index - 1]" |
|||
dense |
|||
:label="'' + (index - 1)" |
|||
:disable="!optionsEnableRef" |
|||
@update:model-value="valueChanged" |
|||
></q-checkbox> |
|||
</div> |
|||
<template v-if="index % 10 === 0"> |
|||
<div class="col-1"></div> |
|||
</template> |
|||
</template> |
|||
</div> |
|||
</q-item-label> |
|||
</q-item-section> |
|||
</q-item> |
|||
</q-list> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import { ref } from 'vue'; |
|||
import { Tools } from '@/platform'; |
|||
|
|||
const props = defineProps({ |
|||
modelValue: { type: String, default: '' }, |
|||
}); |
|||
const emit = defineEmits(['update:modelValue']); |
|||
|
|||
const valueRef = ref(props.modelValue); |
|||
const modeRef = ref(''); |
|||
|
|||
const periodFromEnableRef = ref(false); |
|||
const periodFromRef = ref(''); |
|||
|
|||
const periodToEnableRef = ref(false); |
|||
const periodToRef = ref(''); |
|||
|
|||
const per2FromEnableRef = ref(false); |
|||
const per2FromRef = ref(''); |
|||
|
|||
const per2PerEnableRef = ref(false); |
|||
const per2PerRef = ref(''); |
|||
|
|||
const optionsEnableRef = ref(false); |
|||
const optionsRef = ref([]); |
|||
for (let i = 0; i < 60; i++) { |
|||
optionsRef.value.push(false); |
|||
} |
|||
|
|||
const valueChanged = () => { |
|||
if (modeRef.value === 'per') { |
|||
periodFromEnableRef.value = false; |
|||
periodToEnableRef.value = false; |
|||
per2FromEnableRef.value = false; |
|||
per2PerEnableRef.value = false; |
|||
optionsEnableRef.value = false; |
|||
} else if (modeRef.value === 'period') { |
|||
periodFromEnableRef.value = true; |
|||
periodToEnableRef.value = true; |
|||
per2FromEnableRef.value = false; |
|||
per2PerEnableRef.value = false; |
|||
optionsEnableRef.value = false; |
|||
} else if (modeRef.value === 'per2') { |
|||
periodFromEnableRef.value = false; |
|||
periodToEnableRef.value = false; |
|||
per2FromEnableRef.value = true; |
|||
per2PerEnableRef.value = true; |
|||
optionsEnableRef.value = false; |
|||
} else if (modeRef.value === 'specify') { |
|||
periodFromEnableRef.value = false; |
|||
periodToEnableRef.value = false; |
|||
per2FromEnableRef.value = false; |
|||
per2PerEnableRef.value = false; |
|||
optionsEnableRef.value = true; |
|||
} |
|||
|
|||
if (modeRef.value === 'per') { |
|||
valueRef.value = '*'; |
|||
} else if (modeRef.value === 'period') { |
|||
valueRef.value = periodFromRef.value + '-' + periodToRef.value; |
|||
} else if (modeRef.value === 'per2') { |
|||
valueRef.value = per2FromRef.value + '/' + per2PerRef.value; |
|||
} else if (modeRef.value === 'specify') { |
|||
let seconds = []; |
|||
for (let i = 0; i < 60; i++) { |
|||
if (optionsRef.value[i]) { |
|||
seconds.push(i); |
|||
} |
|||
} |
|||
valueRef.value = Tools.join(seconds, ','); |
|||
} |
|||
|
|||
emit('update:modelValue', valueRef.value); |
|||
}; |
|||
</script> |
@ -0,0 +1,197 @@ |
|||
<template> |
|||
<q-list dense style="width: 100%"> |
|||
<q-item> |
|||
<q-item-section avatar> |
|||
<q-radio v-model="modeRef" val="per" @update:model-value="valueChanged" /> |
|||
</q-item-section> |
|||
<q-item-section> |
|||
<q-item-label>{{ $t('cron.month.per') }}</q-item-label> |
|||
</q-item-section> |
|||
</q-item> |
|||
<q-item> |
|||
<q-item-section avatar> |
|||
<q-radio v-model="modeRef" val="notSpecify" @update:model-value="valueChanged" /> |
|||
</q-item-section> |
|||
<q-item-section> |
|||
<q-item-label>{{ $t('cron.month.notSpecify') }}</q-item-label> |
|||
</q-item-section> |
|||
</q-item> |
|||
<q-item> |
|||
<q-item-section avatar> |
|||
<q-radio v-model="modeRef" val="period" @update:model-value="valueChanged" /> |
|||
</q-item-section> |
|||
<q-item-section> |
|||
<q-item-label> |
|||
<div class="row no-wrap items-center"> |
|||
<span class="pr-2">{{ $t('cron.month.period.1') }}</span> |
|||
<q-input |
|||
v-model="periodFromRef" |
|||
type="number" |
|||
:disable="!periodFromEnableRef" |
|||
outlined |
|||
dense |
|||
style="width: 100px" |
|||
@update:model-value="valueChanged" |
|||
></q-input> |
|||
<span class="px-2">{{ $t('cron.month.period.2') }}</span> |
|||
<q-input |
|||
v-model="periodToRef" |
|||
type="number" |
|||
:disable="!periodToEnableRef" |
|||
outlined |
|||
dense |
|||
style="width: 100px" |
|||
@update:model-value="valueChanged" |
|||
></q-input> |
|||
<span class="px-2">{{ $t('cron.month.period.3') }}</span> |
|||
</div> |
|||
</q-item-label> |
|||
</q-item-section> |
|||
</q-item> |
|||
<q-item> |
|||
<q-item-section avatar> |
|||
<q-radio v-model="modeRef" val="per2" @update:model-value="valueChanged" /> |
|||
</q-item-section> |
|||
<q-item-section> |
|||
<q-item-label> |
|||
<div class="row no-wrap items-center"> |
|||
<span class="pr-2">{{ $t('cron.month.per2.1') }}</span> |
|||
<q-input |
|||
v-model="per2FromRef" |
|||
type="number" |
|||
:disable="!per2FromEnableRef" |
|||
outlined |
|||
dense |
|||
style="width: 100px" |
|||
@update:model-value="valueChanged" |
|||
></q-input> |
|||
<span class="px-2">{{ $t('cron.month.per2.2') }}</span> |
|||
<q-input |
|||
v-model="per2PerRef" |
|||
type="number" |
|||
:disable="!per2PerEnableRef" |
|||
outlined |
|||
dense |
|||
style="width: 100px" |
|||
@update:model-value="valueChanged" |
|||
></q-input> |
|||
<span class="px-2">{{ $t('cron.month.per2.3') }}</span> |
|||
</div> |
|||
</q-item-label> |
|||
</q-item-section> |
|||
</q-item> |
|||
|
|||
<q-item> |
|||
<q-item-section avatar> |
|||
<q-radio v-model="modeRef" val="specify" @update:model-value="valueChanged" /> |
|||
</q-item-section> |
|||
<q-item-section> |
|||
<q-item-label>{{ $t('cron.month.specify') }}</q-item-label> |
|||
</q-item-section> |
|||
</q-item> |
|||
<q-item> |
|||
<q-item-section> |
|||
<q-item-label> |
|||
<div class="row"> |
|||
<template v-for="index in 12" :key="index"> |
|||
<template v-if="index % 6 === 1"> |
|||
<div class="col-1"></div> |
|||
</template> |
|||
<div class="col-1"> |
|||
<q-checkbox |
|||
v-model="optionsRef[index - 1]" |
|||
dense |
|||
:label="'' + index" |
|||
:disable="!optionsEnableRef" |
|||
@update:model-value="valueChanged" |
|||
></q-checkbox> |
|||
</div> |
|||
<template v-if="index % 6 === 0"> |
|||
<div class="col-5"></div> |
|||
</template> |
|||
</template> |
|||
</div> |
|||
</q-item-label> |
|||
</q-item-section> |
|||
</q-item> |
|||
</q-list> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import { ref } from 'vue'; |
|||
import { Tools } from '@/platform'; |
|||
|
|||
const props = defineProps({ |
|||
modelValue: { type: String, default: '' }, |
|||
}); |
|||
const emit = defineEmits(['update:modelValue']); |
|||
|
|||
const valueRef = ref(props.modelValue); |
|||
const modeRef = ref(''); |
|||
|
|||
const periodFromEnableRef = ref(false); |
|||
const periodFromRef = ref(''); |
|||
|
|||
const periodToEnableRef = ref(false); |
|||
const periodToRef = ref(''); |
|||
|
|||
const per2FromEnableRef = ref(false); |
|||
const per2FromRef = ref(''); |
|||
|
|||
const per2PerEnableRef = ref(false); |
|||
const per2PerRef = ref(''); |
|||
|
|||
const workDayEnableRef = ref(false); |
|||
const workDayRef = ref(''); |
|||
|
|||
const optionsEnableRef = ref(false); |
|||
const optionsRef = ref([]); |
|||
for (let i = 0; i < 12; i++) { |
|||
optionsRef.value.push(false); |
|||
} |
|||
|
|||
const valueChanged = () => { |
|||
if (modeRef.value === 'per') { |
|||
periodFromEnableRef.value = false; |
|||
periodToEnableRef.value = false; |
|||
per2FromEnableRef.value = false; |
|||
per2PerEnableRef.value = false; |
|||
optionsEnableRef.value = false; |
|||
} else if (modeRef.value === 'period') { |
|||
periodFromEnableRef.value = true; |
|||
periodToEnableRef.value = true; |
|||
per2FromEnableRef.value = false; |
|||
per2PerEnableRef.value = false; |
|||
optionsEnableRef.value = false; |
|||
} else if (modeRef.value === 'per2') { |
|||
periodFromEnableRef.value = false; |
|||
periodToEnableRef.value = false; |
|||
per2FromEnableRef.value = true; |
|||
per2PerEnableRef.value = true; |
|||
optionsEnableRef.value = false; |
|||
} else if (modeRef.value === 'specify') { |
|||
periodFromEnableRef.value = false; |
|||
periodToEnableRef.value = false; |
|||
per2FromEnableRef.value = false; |
|||
per2PerEnableRef.value = false; |
|||
optionsEnableRef.value = true; |
|||
} |
|||
|
|||
if (modeRef.value === 'per') { |
|||
valueRef.value = '*'; |
|||
} else if (modeRef.value === 'period') { |
|||
valueRef.value = periodFromRef.value + '-' + periodToRef.value; |
|||
} else if (modeRef.value === 'per2') { |
|||
valueRef.value = per2FromRef.value + '/' + per2PerRef.value; |
|||
} else if (modeRef.value === 'specify') { |
|||
let seconds = []; |
|||
for (let i = 0; i < 12; i++) { |
|||
if (optionsRef.value[i]) { |
|||
seconds.push(i + 1); |
|||
} |
|||
} |
|||
valueRef.value = Tools.join(seconds, ','); |
|||
} |
|||
|
|||
emit('update:modelValue', valueRef.value); |
|||
}; |
|||
</script> |
@ -0,0 +1,185 @@ |
|||
<template> |
|||
<q-list dense style="width: 100%"> |
|||
<q-item> |
|||
<q-item-section avatar> |
|||
<q-radio v-model="modeRef" val="per" @update:model-value="valueChanged" /> |
|||
</q-item-section> |
|||
<q-item-section> |
|||
<q-item-label>{{ $t('cron.second.per') }}</q-item-label> |
|||
</q-item-section> |
|||
</q-item> |
|||
<q-item> |
|||
<q-item-section avatar> |
|||
<q-radio v-model="modeRef" val="period" @update:model-value="valueChanged" /> |
|||
</q-item-section> |
|||
<q-item-section> |
|||
<q-item-label> |
|||
<div class="row no-wrap items-center"> |
|||
<span class="pr-2">{{ $t('cron.second.period.1') }}</span> |
|||
<q-input |
|||
v-model="periodFromRef" |
|||
type="number" |
|||
:disable="!periodFromEnableRef" |
|||
outlined |
|||
dense |
|||
style="width: 100px" |
|||
@update:model-value="valueChanged" |
|||
></q-input> |
|||
<span class="px-2">{{ $t('cron.second.period.2') }}</span> |
|||
<q-input |
|||
v-model="periodToRef" |
|||
type="number" |
|||
:disable="!periodToEnableRef" |
|||
outlined |
|||
dense |
|||
style="width: 100px" |
|||
@update:model-value="valueChanged" |
|||
></q-input> |
|||
<span class="px-2">{{ $t('cron.second.period.3') }}</span> |
|||
</div> |
|||
</q-item-label> |
|||
</q-item-section> |
|||
</q-item> |
|||
<q-item> |
|||
<q-item-section avatar> |
|||
<q-radio v-model="modeRef" val="per2" @update:model-value="valueChanged" /> |
|||
</q-item-section> |
|||
<q-item-section> |
|||
<q-item-label> |
|||
<div class="row no-wrap items-center"> |
|||
<span class="pr-2">{{ $t('cron.second.per2.1') }}</span> |
|||
<q-input |
|||
v-model="per2FromRef" |
|||
type="number" |
|||
:disable="!per2FromEnableRef" |
|||
outlined |
|||
dense |
|||
style="width: 100px" |
|||
@update:model-value="valueChanged" |
|||
></q-input> |
|||
<span class="px-2">{{ $t('cron.second.per2.2') }}</span> |
|||
<q-input |
|||
v-model="per2PerRef" |
|||
type="number" |
|||
:disable="!per2PerEnableRef" |
|||
outlined |
|||
dense |
|||
style="width: 100px" |
|||
@update:model-value="valueChanged" |
|||
></q-input> |
|||
<span class="px-2">{{ $t('cron.second.per2.3') }}</span> |
|||
</div> |
|||
</q-item-label> |
|||
</q-item-section> |
|||
</q-item> |
|||
<q-item> |
|||
<q-item-section avatar> |
|||
<q-radio v-model="modeRef" val="specify" @update:model-value="valueChanged" /> |
|||
</q-item-section> |
|||
<q-item-section> |
|||
<q-item-label>{{ $t('cron.second.specify') }}</q-item-label> |
|||
</q-item-section> |
|||
</q-item> |
|||
<q-item> |
|||
<q-item-section avatar> |
|||
<q-item-label> |
|||
<div class="row"> |
|||
<template v-for="index in 60" :key="index"> |
|||
<template v-if="index % 10 === 1"> |
|||
<div class="col-1"></div> |
|||
</template> |
|||
<div class="col-1"> |
|||
<q-checkbox |
|||
v-model="optionsRef[index - 1]" |
|||
dense |
|||
:label="'' + (index - 1)" |
|||
:disable="!optionsEnableRef" |
|||
@update:model-value="valueChanged" |
|||
></q-checkbox> |
|||
</div> |
|||
<template v-if="index % 10 === 0"> |
|||
<div class="col-1"></div> |
|||
</template> |
|||
</template> |
|||
</div> |
|||
</q-item-label> |
|||
</q-item-section> |
|||
</q-item> |
|||
</q-list> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import { ref } from 'vue'; |
|||
import { Tools } from '@/platform'; |
|||
|
|||
const props = defineProps({ |
|||
modelValue: { type: String, default: '' }, |
|||
}); |
|||
const emit = defineEmits(['update:modelValue']); |
|||
|
|||
const valueRef = ref(props.modelValue); |
|||
const modeRef = ref(''); |
|||
|
|||
const periodFromEnableRef = ref(false); |
|||
const periodFromRef = ref(''); |
|||
|
|||
const periodToEnableRef = ref(false); |
|||
const periodToRef = ref(''); |
|||
|
|||
const per2FromEnableRef = ref(false); |
|||
const per2FromRef = ref(''); |
|||
|
|||
const per2PerEnableRef = ref(false); |
|||
const per2PerRef = ref(''); |
|||
|
|||
const optionsEnableRef = ref(false); |
|||
const optionsRef = ref([]); |
|||
for (let i = 0; i < 60; i++) { |
|||
optionsRef.value.push(false); |
|||
} |
|||
|
|||
const valueChanged = () => { |
|||
if (modeRef.value === 'per') { |
|||
periodFromEnableRef.value = false; |
|||
periodToEnableRef.value = false; |
|||
per2FromEnableRef.value = false; |
|||
per2PerEnableRef.value = false; |
|||
optionsEnableRef.value = false; |
|||
} else if (modeRef.value === 'period') { |
|||
periodFromEnableRef.value = true; |
|||
periodToEnableRef.value = true; |
|||
per2FromEnableRef.value = false; |
|||
per2PerEnableRef.value = false; |
|||
optionsEnableRef.value = false; |
|||
} else if (modeRef.value === 'per2') { |
|||
periodFromEnableRef.value = false; |
|||
periodToEnableRef.value = false; |
|||
per2FromEnableRef.value = true; |
|||
per2PerEnableRef.value = true; |
|||
optionsEnableRef.value = false; |
|||
} else if (modeRef.value === 'specify') { |
|||
periodFromEnableRef.value = false; |
|||
periodToEnableRef.value = false; |
|||
per2FromEnableRef.value = false; |
|||
per2PerEnableRef.value = false; |
|||
optionsEnableRef.value = true; |
|||
} |
|||
|
|||
if (modeRef.value === 'per') { |
|||
valueRef.value = '*'; |
|||
} else if (modeRef.value === 'period') { |
|||
valueRef.value = periodFromRef.value + '-' + periodToRef.value; |
|||
} else if (modeRef.value === 'per2') { |
|||
valueRef.value = per2FromRef.value + '/' + per2PerRef.value; |
|||
} else if (modeRef.value === 'specify') { |
|||
let seconds = []; |
|||
for (let i = 0; i < 60; i++) { |
|||
if (optionsRef.value[i]) { |
|||
seconds.push(i); |
|||
} |
|||
} |
|||
valueRef.value = Tools.join(seconds, ','); |
|||
} |
|||
|
|||
emit('update:modelValue', valueRef.value); |
|||
}; |
|||
</script> |
@ -0,0 +1,233 @@ |
|||
<template> |
|||
<q-list dense style="width: 100%"> |
|||
<q-item> |
|||
<q-item-section avatar> |
|||
<q-radio v-model="modeRef" val="per" @update:model-value="valueChanged" /> |
|||
</q-item-section> |
|||
<q-item-section> |
|||
<q-item-label>{{ $t('cron.week.per') }}</q-item-label> |
|||
</q-item-section> |
|||
</q-item> |
|||
<q-item> |
|||
<q-item-section avatar> |
|||
<q-radio v-model="modeRef" val="notSpecify" @update:model-value="valueChanged" /> |
|||
</q-item-section> |
|||
<q-item-section> |
|||
<q-item-label>{{ $t('cron.week.notSpecify') }}</q-item-label> |
|||
</q-item-section> |
|||
</q-item> |
|||
<q-item> |
|||
<q-item-section avatar> |
|||
<q-radio v-model="modeRef" val="period" @update:model-value="valueChanged" /> |
|||
</q-item-section> |
|||
<q-item-section> |
|||
<q-item-label> |
|||
<div class="row no-wrap items-center"> |
|||
<span class="pr-2">{{ $t('cron.week.period.1') }}</span> |
|||
<q-input |
|||
v-model="periodFromRef" |
|||
type="number" |
|||
:disable="!periodFromEnableRef" |
|||
outlined |
|||
dense |
|||
style="width: 100px" |
|||
@update:model-value="valueChanged" |
|||
></q-input> |
|||
<span class="px-2">{{ $t('cron.week.period.2') }}</span> |
|||
<q-input |
|||
v-model="periodToRef" |
|||
type="number" |
|||
:disable="!periodToEnableRef" |
|||
outlined |
|||
dense |
|||
style="width: 100px" |
|||
@update:model-value="valueChanged" |
|||
></q-input> |
|||
<span class="px-2">{{ $t('cron.week.period.3') }}</span> |
|||
</div> |
|||
</q-item-label> |
|||
</q-item-section> |
|||
</q-item> |
|||
<q-item> |
|||
<q-item-section avatar> |
|||
<q-radio v-model="modeRef" val="weekOfYear" @update:model-value="valueChanged" /> |
|||
</q-item-section> |
|||
<q-item-section> |
|||
<q-item-label> |
|||
<div class="row no-wrap items-center"> |
|||
<span class="pr-2">{{ $t('cron.week.weekOfYear.1') }}</span> |
|||
<q-input |
|||
v-model="weekOfYearRef" |
|||
type="number" |
|||
:disable="!weekOfYearEnableRef" |
|||
outlined |
|||
dense |
|||
style="width: 100px" |
|||
@update:model-value="valueChanged" |
|||
></q-input> |
|||
<span class="px-2">{{ $t('cron.week.weekOfYear.2') }}</span> |
|||
<q-input |
|||
v-model="dayOfWeekRef" |
|||
type="number" |
|||
:disable="!dayOfWeekEnableRef" |
|||
outlined |
|||
dense |
|||
style="width: 100px" |
|||
@update:model-value="valueChanged" |
|||
></q-input> |
|||
<span class="px-2">{{ $t('cron.week.weekOfYear.3') }}</span> |
|||
</div> |
|||
</q-item-label> |
|||
</q-item-section> |
|||
</q-item> |
|||
|
|||
<q-item> |
|||
<q-item-section avatar> |
|||
<q-radio v-model="modeRef" val="lastWeek" @update:model-value="valueChanged" /> |
|||
</q-item-section> |
|||
<q-item-section> |
|||
<q-item-label> |
|||
<div class="row no-wrap items-center"> |
|||
<span class="pr-2">{{ $t('cron.week.lastDay.1') }}</span> |
|||
<q-input |
|||
v-model="lastWeekRef" |
|||
type="number" |
|||
:disable="!lastWeekEnableRef" |
|||
outlined |
|||
dense |
|||
style="width: 100px" |
|||
@update:model-value="valueChanged" |
|||
></q-input> |
|||
<span class="px-2">{{ $t('cron.week.lastDay.2') }}</span> |
|||
</div> |
|||
</q-item-label> |
|||
</q-item-section> |
|||
</q-item> |
|||
|
|||
<q-item> |
|||
<q-item-section avatar> |
|||
<q-radio v-model="modeRef" val="specify" @update:model-value="valueChanged" /> |
|||
</q-item-section> |
|||
<q-item-section> |
|||
<q-item-label>{{ $t('cron.week.specify') }}</q-item-label> |
|||
</q-item-section> |
|||
</q-item> |
|||
<q-item> |
|||
<q-item-section> |
|||
<q-item-label> |
|||
<div class="row"> |
|||
<template v-for="index in 7" :key="index"> |
|||
<template v-if="index % 7 === 1"> |
|||
<div class="col-1"></div> |
|||
</template> |
|||
<div class="col-1"> |
|||
<q-checkbox |
|||
v-model="optionsRef[index - 1]" |
|||
dense |
|||
:label="'' + index" |
|||
:disable="!optionsEnableRef" |
|||
@update:model-value="valueChanged" |
|||
></q-checkbox> |
|||
</div> |
|||
<template v-if="index % 7 === 0"> |
|||
<div class="col-5"></div> |
|||
</template> |
|||
</template> |
|||
</div> |
|||
</q-item-label> |
|||
</q-item-section> |
|||
</q-item> |
|||
</q-list> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import { ref } from 'vue'; |
|||
import { Tools } from '@/platform'; |
|||
|
|||
const props = defineProps({ |
|||
modelValue: { type: String, default: '' }, |
|||
}); |
|||
const emit = defineEmits(['update:modelValue']); |
|||
|
|||
const valueRef = ref(props.modelValue); |
|||
const modeRef = ref(''); |
|||
|
|||
const periodFromEnableRef = ref(false); |
|||
const periodFromRef = ref(''); |
|||
|
|||
const periodToEnableRef = ref(false); |
|||
const periodToRef = ref(''); |
|||
|
|||
const weekOfYearEnableRef = ref(false); |
|||
const weekOfYearRef = ref(''); |
|||
|
|||
const dayOfWeekEnableRef = ref(false); |
|||
const dayOfWeekRef = ref(''); |
|||
|
|||
const lastWeekEnableRef = ref(false); |
|||
const lastWeekRef = ref(''); |
|||
|
|||
const optionsEnableRef = ref(false); |
|||
const optionsRef = ref([]); |
|||
for (let i = 0; i < 7; i++) { |
|||
optionsRef.value.push(false); |
|||
} |
|||
|
|||
const valueChanged = () => { |
|||
if (modeRef.value === 'per') { |
|||
periodFromEnableRef.value = false; |
|||
periodToEnableRef.value = false; |
|||
weekOfYearEnableRef.value = false; |
|||
dayOfWeekEnableRef.value = false; |
|||
lastWeekEnableRef.value = false; |
|||
optionsEnableRef.value = false; |
|||
} else if (modeRef.value === 'period') { |
|||
periodFromEnableRef.value = true; |
|||
periodToEnableRef.value = true; |
|||
weekOfYearEnableRef.value = false; |
|||
dayOfWeekEnableRef.value = false; |
|||
lastWeekEnableRef.value = false; |
|||
optionsEnableRef.value = false; |
|||
} else if (modeRef.value === 'weekOfYear') { |
|||
periodFromEnableRef.value = false; |
|||
periodToEnableRef.value = false; |
|||
weekOfYearEnableRef.value = true; |
|||
dayOfWeekEnableRef.value = true; |
|||
lastWeekEnableRef.value = false; |
|||
optionsEnableRef.value = false; |
|||
} else if (modeRef.value === 'lastWeek') { |
|||
periodFromEnableRef.value = false; |
|||
periodToEnableRef.value = false; |
|||
weekOfYearEnableRef.value = false; |
|||
dayOfWeekEnableRef.value = false; |
|||
lastWeekEnableRef.value = true; |
|||
optionsEnableRef.value = false; |
|||
} else if (modeRef.value === 'specify') { |
|||
periodFromEnableRef.value = false; |
|||
periodToEnableRef.value = false; |
|||
weekOfYearEnableRef.value = false; |
|||
dayOfWeekEnableRef.value = false; |
|||
lastWeekEnableRef.value = false; |
|||
optionsEnableRef.value = true; |
|||
} |
|||
|
|||
if (modeRef.value === 'per') { |
|||
valueRef.value = '*'; |
|||
} else if (modeRef.value === 'period') { |
|||
valueRef.value = periodFromRef.value + '-' + periodToRef.value; |
|||
} else if (modeRef.value === 'weekOfYear') { |
|||
valueRef.value = weekOfYearRef.value + '/' + dayOfWeekRef.value; |
|||
} else if (modeRef.value === 'lastWeek') { |
|||
valueRef.value = lastWeekRef.value + 'L'; |
|||
} else if (modeRef.value === 'specify') { |
|||
let seconds = []; |
|||
for (let i = 0; i < 7; i++) { |
|||
if (optionsRef.value[i]) { |
|||
seconds.push(i + 1); |
|||
} |
|||
} |
|||
valueRef.value = Tools.join(seconds, ','); |
|||
} |
|||
|
|||
emit('update:modelValue', valueRef.value); |
|||
}; |
|||
</script> |
@ -0,0 +1,93 @@ |
|||
<template> |
|||
<q-list dense style="width: 100%"> |
|||
<q-item> |
|||
<q-item-section avatar> |
|||
<q-radio v-model="modeRef" val="per" @update:model-value="valueChanged" /> |
|||
</q-item-section> |
|||
<q-item-section> |
|||
<q-item-label>{{ $t('cron.year.per') }}</q-item-label> |
|||
</q-item-section> |
|||
</q-item> |
|||
<q-item> |
|||
<q-item-section avatar> |
|||
<q-radio v-model="modeRef" val="notSpecify" @update:model-value="valueChanged" /> |
|||
</q-item-section> |
|||
<q-item-section> |
|||
<q-item-label>{{ $t('cron.year.notSpecify') }}</q-item-label> |
|||
</q-item-section> |
|||
</q-item> |
|||
<q-item> |
|||
<q-item-section avatar> |
|||
<q-radio v-model="modeRef" val="period" @update:model-value="valueChanged" /> |
|||
</q-item-section> |
|||
<q-item-section> |
|||
<q-item-label> |
|||
<div class="row no-wrap items-center"> |
|||
<span class="pr-2">{{ $t('cron.year.period.1') }}</span> |
|||
<q-input |
|||
v-model="periodFromRef" |
|||
type="number" |
|||
:disable="!periodFromEnableRef" |
|||
outlined |
|||
dense |
|||
style="width: 100px" |
|||
@update:model-value="valueChanged" |
|||
></q-input> |
|||
<span class="px-2">{{ $t('cron.year.period.2') }}</span> |
|||
<q-input |
|||
v-model="periodToRef" |
|||
type="number" |
|||
:disable="!periodToEnableRef" |
|||
outlined |
|||
dense |
|||
style="width: 100px" |
|||
@update:model-value="valueChanged" |
|||
></q-input> |
|||
<span class="px-2">{{ $t('cron.year.period.3') }}</span> |
|||
</div> |
|||
</q-item-label> |
|||
</q-item-section> |
|||
</q-item> |
|||
</q-list> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import { ref } from 'vue'; |
|||
import { Tools } from '@/platform'; |
|||
|
|||
const props = defineProps({ |
|||
modelValue: { type: String, default: '' }, |
|||
}); |
|||
const emit = defineEmits(['update:modelValue']); |
|||
|
|||
const valueRef = ref(props.modelValue); |
|||
const modeRef = ref(''); |
|||
|
|||
const periodFromEnableRef = ref(false); |
|||
const periodFromRef = ref(''); |
|||
|
|||
const periodToEnableRef = ref(false); |
|||
const periodToRef = ref(''); |
|||
|
|||
const valueChanged = () => { |
|||
if (modeRef.value === 'per') { |
|||
periodFromEnableRef.value = false; |
|||
periodToEnableRef.value = false; |
|||
} else if (modeRef.value === 'notSpecify') { |
|||
periodFromEnableRef.value = false; |
|||
periodToEnableRef.value = false; |
|||
} else if (modeRef.value === 'period') { |
|||
periodFromEnableRef.value = true; |
|||
periodToEnableRef.value = true; |
|||
} |
|||
|
|||
if (modeRef.value === 'per') { |
|||
valueRef.value = '*'; |
|||
} else if (modeRef.value === 'notSpecify') { |
|||
valueRef.value = ''; |
|||
} else if (modeRef.value === 'period') { |
|||
valueRef.value = periodFromRef.value + '-' + periodToRef.value; |
|||
} |
|||
|
|||
emit('update:modelValue', valueRef.value); |
|||
}; |
|||
</script> |
@ -0,0 +1,78 @@ |
|||
<template> |
|||
<div v-show="FieldMethods.getShow(props, modelValue)"> |
|||
<q-input |
|||
ref="dateRef" |
|||
v-model="modelValue" |
|||
:hide-bottom-space="true" |
|||
:hide-hint="true" |
|||
:outlined="true" |
|||
:dense="true" |
|||
v-bind="attrs" |
|||
:rules="FieldMethods.getRules(props, modelValue, dateRef, undefined)" |
|||
:readonly="FieldMethods.getReadOnly(props, modelValue)" |
|||
:disable="FieldMethods.getDisable(props, modelValue)" |
|||
@update:model-value="fieldMethodsClass.updateValue" |
|||
@focus=" |
|||
() => { |
|||
dateRef?.blur(); |
|||
} |
|||
" |
|||
> |
|||
<template #label> |
|||
<w-label :required="FieldMethods.getRequired(props, modelValue)" :label="attrs.label"></w-label> |
|||
</template> |
|||
<template v-if="!FieldMethods.getReadOnly(props, modelValue)" #append> |
|||
<q-icon name="event" class="cursor-pointer"> |
|||
<q-popup-proxy cover transition-show="scale" transition-hide="scale"> |
|||
<q-date v-model="modelValue" today-btn mask="YYYY-MM-DD" @update:model-value="fieldMethodsClass.updateValue"> </q-date> |
|||
</q-popup-proxy> |
|||
</q-icon> |
|||
</template> |
|||
</q-input> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup lang="ts"> |
|||
import { ref, useAttrs } from 'vue'; |
|||
import { FormFieldProps } from '@/platform/components/form/FormField.ts'; |
|||
import { FormFieldMethods } from '../form/FormField'; |
|||
|
|||
const dateRef = ref(); |
|||
const attrs = useAttrs(); |
|||
const modelValue = defineModel<string>(); |
|||
|
|||
interface FieldProps extends FormFieldProps {} |
|||
const props = withDefaults(defineProps<FieldProps>(), { |
|||
showIf: true, |
|||
}); |
|||
class FieldMethods extends FormFieldMethods { |
|||
updateValue = (value_) => { |
|||
if (props['onUpdateValue']) { |
|||
props['onUpdateValue']({ |
|||
value: value_, |
|||
form: props['form'], |
|||
}); |
|||
} |
|||
}; |
|||
validate = () => { |
|||
return dateRef.value.validate(); |
|||
}; |
|||
setValue = (value_) => { |
|||
modelValue.value = value_; |
|||
}; |
|||
getValue = () => { |
|||
return modelValue.value; |
|||
}; |
|||
clearValue = () => { |
|||
modelValue.value = undefined; |
|||
}; |
|||
} |
|||
const fieldMethodsClass = new FieldMethods(); |
|||
|
|||
defineExpose({ |
|||
validate: fieldMethodsClass.validate, |
|||
setValue: fieldMethodsClass.setValue, |
|||
getValue: fieldMethodsClass.getValue, |
|||
clearValue: fieldMethodsClass.clearValue, |
|||
}); |
|||
</script> |
@ -0,0 +1,88 @@ |
|||
<template> |
|||
<div v-show="FieldMethods.getShow(props, modelValue)"> |
|||
<q-input |
|||
ref="dateRangeRef" |
|||
v-model="displayValueComputed" |
|||
:hide-bottom-space="true" |
|||
:hide-hint="true" |
|||
:outlined="true" |
|||
:dense="true" |
|||
v-bind="attrs" |
|||
:clearable="false" |
|||
:rules="FieldMethods.getRules(props, modelValue, dateRangeRef, undefined)" |
|||
:readonly="FieldMethods.getReadOnly(props, modelValue)" |
|||
:disable="FieldMethods.getDisable(props, modelValue)" |
|||
@update:model-value="fieldMethodsClass.updateValue" |
|||
@focus=" |
|||
() => { |
|||
dateRangeRef?.blur(); |
|||
} |
|||
" |
|||
> |
|||
<template #label> |
|||
<w-label :required="FieldMethods.getRequired(props, modelValue)" :label="attrs.label"></w-label> |
|||
</template> |
|||
<template v-if="!FieldMethods.getReadOnly(props, modelValue)" #append> |
|||
<q-btn v-if="!Tools.isEmpty(displayValueComputed)" flat square unelevated dense icon="cancel" @click="fieldMethodsClass.clearValue"></q-btn> |
|||
<q-icon name="event" class="cursor-pointer"> |
|||
<q-popup-proxy cover transition-show="scale" transition-hide="scale"> |
|||
<q-date v-model="modelValue" today-btn mask="YYYY-MM-DD" :range="true" @update:model-value="fieldMethodsClass.updateValue"> </q-date> |
|||
</q-popup-proxy> |
|||
</q-icon> |
|||
</template> |
|||
</q-input> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup lang="ts"> |
|||
import { ref, useAttrs, computed } from 'vue'; |
|||
import { Tools } from '@/platform'; |
|||
import { FormFieldProps } from '@/platform/components/form/FormField.ts'; |
|||
import { FormFieldMethods } from '../form/FormField'; |
|||
|
|||
const dateRangeRef = ref(); |
|||
const attrs = useAttrs(); |
|||
const modelValue = defineModel<object>(); |
|||
|
|||
interface FieldProps extends FormFieldProps {} |
|||
const props = withDefaults(defineProps<FieldProps>(), { |
|||
showIf: true, |
|||
}); |
|||
class FieldMethods extends FormFieldMethods { |
|||
updateValue = (value_) => { |
|||
if (props['onUpdateValue']) { |
|||
props['onUpdateValue']({ |
|||
value: value_, |
|||
form: props['form'], |
|||
}); |
|||
} |
|||
}; |
|||
validate = () => { |
|||
return dateRangeRef.value.validate(); |
|||
}; |
|||
setValue = (value_) => { |
|||
modelValue.value = value_; |
|||
}; |
|||
getValue = () => { |
|||
return modelValue.value; |
|||
}; |
|||
clearValue = () => { |
|||
modelValue.value = undefined; |
|||
}; |
|||
} |
|||
const fieldMethodsClass = new FieldMethods(); |
|||
|
|||
const displayValueComputed = computed(() => { |
|||
if (modelValue.value) { |
|||
return modelValue.value['from'] + ' 至 ' + modelValue.value['to']; |
|||
} |
|||
return ''; |
|||
}); |
|||
|
|||
defineExpose({ |
|||
validate: fieldMethodsClass.validate, |
|||
setValue: fieldMethodsClass.setValue, |
|||
getValue: fieldMethodsClass.getValue, |
|||
clearValue: fieldMethodsClass.clearValue, |
|||
}); |
|||
</script> |
@ -0,0 +1,70 @@ |
|||
<template> |
|||
<div v-show="FieldMethods.getShow(props, modelValue)"> |
|||
<q-file |
|||
ref="fileRef" |
|||
v-model="modelValue" |
|||
:hide-bottom-space="true" |
|||
:hide-hint="true" |
|||
:outlined="true" |
|||
:dense="true" |
|||
:clearable="true" |
|||
v-bind="attrs" |
|||
:rules="FieldMethods.getRules(props, modelValue, fileRef, undefined)" |
|||
:readonly="FieldMethods.getReadOnly(props, modelValue)" |
|||
:disable="FieldMethods.getDisable(props, modelValue)" |
|||
@update:model-value="fieldMethodsClass.updateValue" |
|||
> |
|||
<template #label> |
|||
<w-label :required="FieldMethods.getRequired(props, modelValue)" :label="attrs.label"></w-label> |
|||
</template> |
|||
<template v-if="!FieldMethods.getReadOnly(props, modelValue)" #append> |
|||
<q-icon name="attachment" /> |
|||
</template> |
|||
</q-file> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup lang="ts"> |
|||
import { ref, useAttrs } from 'vue'; |
|||
import { FormFieldProps } from '@/platform/components/form/FormField.ts'; |
|||
import { FormFieldMethods } from '../form/FormField'; |
|||
|
|||
const fileRef = ref(); |
|||
const attrs = useAttrs(); |
|||
const modelValue = defineModel<File | Array<File>>(); |
|||
|
|||
interface FieldProps extends FormFieldProps {} |
|||
const props = withDefaults(defineProps<FieldProps>(), { |
|||
showIf: true, |
|||
}); |
|||
class FieldMethods extends FormFieldMethods { |
|||
updateValue = (value_) => { |
|||
if (props['onUpdateValue']) { |
|||
props['onUpdateValue']({ |
|||
value: value_, |
|||
form: props['form'], |
|||
}); |
|||
} |
|||
}; |
|||
validate = () => { |
|||
return fileRef.value.validate(); |
|||
}; |
|||
setValue = (value_) => { |
|||
modelValue.value = value_; |
|||
}; |
|||
getValue = () => { |
|||
return modelValue.value; |
|||
}; |
|||
clearValue = () => { |
|||
modelValue.value = undefined; |
|||
}; |
|||
} |
|||
const fieldMethodsClass = new FieldMethods(); |
|||
|
|||
defineExpose({ |
|||
validate: fieldMethodsClass.validate, |
|||
setValue: fieldMethodsClass.setValue, |
|||
getValue: fieldMethodsClass.getValue, |
|||
clearValue: fieldMethodsClass.clearValue, |
|||
}); |
|||
</script> |
@ -0,0 +1,92 @@ |
|||
import { Tools } from '@/platform'; |
|||
import { FormValidators } from '@/platform/components'; |
|||
|
|||
export interface FormFieldProps { |
|||
name?: string; |
|||
form?: object; // form对象实例
|
|||
showIf?: boolean | (() => void); // 是否显示
|
|||
requiredIf?: boolean | (() => void); // 是否必填
|
|||
readOnlyIf?: boolean | (() => void); // 是否只读
|
|||
disableIf?: boolean | (() => void); // 是否禁用
|
|||
rules?: Array<() => void>; // 验证规则集合
|
|||
onUpdateValue?: () => void; // 值改变事件函数
|
|||
} |
|||
|
|||
export abstract class FormFieldMethods { |
|||
// 值改变事件
|
|||
abstract updateValue(value_): void; |
|||
// 验证方法
|
|||
abstract validate(): Promise<boolean> | boolean; |
|||
// 设置值
|
|||
abstract setValue(value_): void; |
|||
// 获取值
|
|||
abstract getValue(): any; |
|||
// 清空值
|
|||
abstract clearValue(): void; |
|||
|
|||
// 获取验证规则集结果
|
|||
static getRules = (props_, value_, componentRef_, defaultValue_) => { |
|||
let result = props_.rules || <any>[]; |
|||
if (!Tools.isEmpty(defaultValue_)) { |
|||
result.push(...defaultValue_); |
|||
} |
|||
const showResult = FormFieldMethods.getShow(props_, value_); |
|||
const requiredResult = FormFieldMethods.getRequired(props_, value_); |
|||
if (showResult && requiredResult) { |
|||
result.push(FormValidators.required()); |
|||
} else if (!showResult) { |
|||
result = []; |
|||
} |
|||
if (componentRef_?.value) { |
|||
componentRef_.value.resetValidation(); |
|||
} |
|||
return result; |
|||
}; |
|||
// 获取是否必填结果
|
|||
static getRequired = (props_, value_) => { |
|||
if (!Tools.isEmpty(props_.requiredIf)) { |
|||
if (typeof props_.requiredIf === 'boolean') { |
|||
return props_.requiredIf; |
|||
} else if (typeof props_.requiredIf === 'function') { |
|||
return props_.requiredIf({ value: value_, form: props_.form }) || false; |
|||
} |
|||
} |
|||
return false; |
|||
}; |
|||
// 获取是否显示结果
|
|||
static getShow = (props_, value_) => { |
|||
if (!Tools.isEmpty(props_.showIf)) { |
|||
if (typeof props_.showIf === 'boolean') { |
|||
return props_.showIf; |
|||
} else if (typeof props_.showIf === 'function') { |
|||
return props_.showIf({ value: value_, form: props_.form }) || false; |
|||
} |
|||
} |
|||
return true; |
|||
}; |
|||
// 获取是否只读结果
|
|||
static getReadOnly = (props_, value_) => { |
|||
if (props_.form && props_.form.getStatus() === 'view') { |
|||
return true; |
|||
} |
|||
if (!Tools.isEmpty(props_.readOnlyIf)) { |
|||
if (typeof props_.readOnlyIf === 'boolean') { |
|||
return props_.readOnlyIf; |
|||
} else if (typeof props_.readOnlyIf === 'function') { |
|||
return props_.readOnlyIf({ value: value_, form: props_.form }) || false; |
|||
} |
|||
} |
|||
return false; |
|||
}; |
|||
// 获取是否禁用结果
|
|||
static getDisable = (props_, value_) => { |
|||
if (!Tools.isEmpty(props_.disableIf)) { |
|||
if (typeof props_.disableIf === 'boolean') { |
|||
return props_.disableIf; |
|||
} else if (typeof props_.disableIf === 'function') { |
|||
return props_.disableIf({ value: value_, form: props_.form }) || false; |
|||
} |
|||
} |
|||
return false; |
|||
}; |
|||
} |
@ -0,0 +1,320 @@ |
|||
<template> |
|||
<div> |
|||
<q-form ref="formRef" :autofocus="false" :greedy="true" v-bind="attrs"> |
|||
<div v-if="fieldsComputed.length > 0" class="grid" :class="formLayoutComputed"> |
|||
<template v-for="(field, index) in fieldsComputed as any" :key="String(index)"> |
|||
<template v-if="field.name"> |
|||
<component |
|||
:is="field.type" |
|||
:ref="(el) => setComponentRef(el, field.name)" |
|||
v-model="formData[field.name]" |
|||
v-bind="field" |
|||
:form="instance" |
|||
:class=" |
|||
(field.colsFirst ? 'col-start-1 ' : ' ') + |
|||
(field.colSpan === 'full' |
|||
? ' col-span-' + screenColsNumComputed |
|||
: field.colSpan && screenColsNumComputed >= field.colSpan |
|||
? ' col-span-' + field.colSpan |
|||
: ' col-span-1') |
|||
" |
|||
@update:model-value="updateModelValue(field.name, formData[field.name])" |
|||
></component> |
|||
</template> |
|||
<template v-else> |
|||
<component |
|||
:is="field.type" |
|||
:ref="(el) => setComponentRef(el, field.name)" |
|||
:form-ref="formRef" |
|||
v-bind="field" |
|||
:form="instance" |
|||
:class=" |
|||
(field.colsFirst ? 'col-start-1 ' : ' ') + |
|||
(field.colSpan === 'full' |
|||
? ' col-span-' + screenColsNumComputed |
|||
: field.colSpan && screenColsNumComputed >= field.colSpan |
|||
? ' col-span-' + field.colSpan |
|||
: ' col-span-1') |
|||
" |
|||
></component> |
|||
</template> |
|||
</template> |
|||
</div> |
|||
<slot></slot> |
|||
</q-form> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup lang="ts"> |
|||
import { ref, reactive, watch, computed, toRaw, useAttrs, getCurrentInstance } from 'vue'; |
|||
import { useQuasar } from 'quasar'; |
|||
import { VueTools, Tools } from '@/platform'; |
|||
import { PageStatusEnum } from '@/platform/components/utils'; |
|||
|
|||
const $q = useQuasar(); |
|||
const attrs = useAttrs(); |
|||
const componentRef = ref({}); |
|||
|
|||
const props = defineProps({ |
|||
modelValue: { |
|||
type: Object, |
|||
default: () => { |
|||
return undefined; |
|||
}, |
|||
}, |
|||
colsNum: { type: [Number, Object], default: 0 }, |
|||
colsXGap: { type: Number, default: 8 }, |
|||
colsYGap: { type: Number, default: 4 }, |
|||
fields: { |
|||
type: Array, |
|||
default: () => { |
|||
return []; |
|||
}, |
|||
}, |
|||
}); |
|||
|
|||
const localFlag = ref(false); |
|||
const formRef = ref(); |
|||
const formStatus = ref(PageStatusEnum.新增); |
|||
const formModel: any = {}; |
|||
const formFields = {}; |
|||
let fields_ = ref([...props.fields]); |
|||
// 不同屏幕尺寸下 colsNum 为 0 时一行显示的字段个数 |
|||
const screenCols = { xs: 1, sm: 2, md: 3, lg: 4, xl: 6 }; |
|||
|
|||
const defaultValueHandler = (field) => { |
|||
if (!Tools.isUndefinedOrNull(field.defaultValue)) { |
|||
return field.defaultValue; |
|||
} else if (field.type === 'w-checkbox') { |
|||
return false; |
|||
} else if (field.type === 'w-option-group') { |
|||
if (!field.optionType || field.optionType === 'radio') { |
|||
return undefined; |
|||
} else { |
|||
return []; |
|||
} |
|||
} else if (field.type === 'w-select' && field.multiple) { |
|||
return []; |
|||
} |
|||
return undefined; |
|||
}; |
|||
|
|||
watch( |
|||
() => props.fields, |
|||
(newVal, oldVal) => { |
|||
if (newVal.length !== oldVal.length) { |
|||
fields_ = ref([...props.fields]); |
|||
for (const field of fields_.value as any) { |
|||
if (field.name) { |
|||
formModel[field.name] = defaultValueHandler(field); |
|||
formFields[field.name] = field; |
|||
} |
|||
} |
|||
} |
|||
}, |
|||
); |
|||
|
|||
watch( |
|||
() => props.fields.map((item) => item['label']), |
|||
(newVal, oldVal) => { |
|||
fields_ = ref([...props.fields]); |
|||
for (const field of fields_.value as any) { |
|||
if (field.name) { |
|||
formFields[field.name] = field; |
|||
} |
|||
} |
|||
localFlag.value = !localFlag.value; |
|||
}, |
|||
); |
|||
const fieldsComputed = computed(() => { |
|||
localFlag.value; |
|||
return fields_.value; |
|||
}); |
|||
|
|||
for (const field of fields_.value as any) { |
|||
if (field.name) { |
|||
formModel[field.name] = defaultValueHandler(field); |
|||
formFields[field.name] = field; |
|||
} |
|||
} |
|||
|
|||
let formData = reactive(!Tools.isEmpty(props.modelValue) ? props.modelValue : formModel); |
|||
watch( |
|||
() => props.modelValue, |
|||
(newVal, oldVal) => { |
|||
formData = reactive(!Tools.isEmpty(props.modelValue) ? props.modelValue : formModel); |
|||
}, |
|||
); |
|||
|
|||
const screenColsNumComputed = computed(() => { |
|||
if (typeof props.colsNum === 'number' && props.colsNum > 0) { |
|||
return props.colsNum; |
|||
} else if (typeof props.colsNum === 'object') { |
|||
const screen = { ...screenCols, ...props.colsNum }; |
|||
return screen[$q.screen.name]; |
|||
} |
|||
return screenCols[$q.screen.name]; |
|||
}); |
|||
const formLayoutComputed = computed(() => { |
|||
let className = ''; |
|||
if (typeof props.colsNum === 'number' && props.colsNum > 0) { |
|||
className = 'grid-cols-' + props.colsNum; |
|||
} else { |
|||
className = 'grid-cols-' + screenColsNumComputed.value; |
|||
} |
|||
className += ' gap-x-[' + props.colsXGap + 'px]'; |
|||
className += ' gap-y-[' + props.colsYGap + 'px]'; |
|||
return className; |
|||
}); |
|||
|
|||
const updateModelValue = (name, value) => { |
|||
if (formFields[name].error) { |
|||
formFields[name].error = false; |
|||
formFields[name].errorMessage = undefined; |
|||
} |
|||
}; |
|||
|
|||
const setComponentRef = (el, fieldName) => { |
|||
if (el) { |
|||
componentRef.value[fieldName] = el; |
|||
} |
|||
}; |
|||
|
|||
/** |
|||
* 对外暴露方法-获取form所有数据 |
|||
*/ |
|||
const getData = () => { |
|||
const data = { ...toRaw(formData) }; |
|||
return data; |
|||
}; |
|||
/** |
|||
* 对外暴露方法-设置form所有字段值 |
|||
* @param data 数据对象(JSON格式) |
|||
*/ |
|||
const setData = (data) => { |
|||
for (const field of fields_.value as any) { |
|||
if (data[field.name] !== undefined) { |
|||
formData[field.name] = data[field.name]; |
|||
} |
|||
} |
|||
}; |
|||
/** |
|||
* 对外暴露方法-重置表单 |
|||
*/ |
|||
const reset = () => { |
|||
Object.keys(formData).forEach((key) => { |
|||
formData[key] = defaultValueHandler(formFields[key]); |
|||
}); |
|||
}; |
|||
const formValidate = async () => { |
|||
let validate = false; |
|||
await formRef.value.validate().then((success) => { |
|||
if (success) { |
|||
validate = true; |
|||
} |
|||
}); |
|||
return validate; |
|||
}; |
|||
/** |
|||
* 对外暴露方法-表单验证 |
|||
*/ |
|||
const validate = async () => { |
|||
const v = await formValidate(); |
|||
return v; |
|||
}; |
|||
/** |
|||
* 对外暴露方法-设置字段值 |
|||
* @param fieldName 字段name |
|||
* @param value 字段值 |
|||
*/ |
|||
const setFieldValue = (fieldName, value) => { |
|||
formData[fieldName] = value; |
|||
}; |
|||
/** |
|||
* 对外暴露方法-获取字段值 |
|||
* @param fieldName 字段name |
|||
*/ |
|||
const getFieldValue = (fieldName) => { |
|||
return formData[fieldName]; |
|||
}; |
|||
/** |
|||
* 对外暴露方法-设置form状态 |
|||
* @param status 状态 |
|||
*/ |
|||
const setStatus = (status) => { |
|||
formStatus.value = status; |
|||
}; |
|||
/** |
|||
* 对外暴露方法-获取form状态 |
|||
*/ |
|||
const getStatus = () => { |
|||
return toRaw(formStatus.value); |
|||
}; |
|||
/** |
|||
* 对外暴露方法-获取当前一行应该显示的元素个数 |
|||
*/ |
|||
const getColsNum = () => { |
|||
return screenColsNumComputed.value; |
|||
}; |
|||
|
|||
/** |
|||
* 错误消息类型 |
|||
* |
|||
* @param fieldName 字段名 |
|||
* @param errorMessage 错误消息 |
|||
*/ |
|||
type errorType = { |
|||
fieldName: string; |
|||
errorMessage: string; |
|||
}; |
|||
|
|||
/** |
|||
* 对外暴露方法-设置后台校验错误信息 |
|||
* @param errors 错误消息集合 |
|||
*/ |
|||
const setValidationErrors = (errors: errorType[]) => { |
|||
if (errors && errors.length > 0) { |
|||
const grouped = {}; |
|||
errors.map(({ fieldName, ...rest }) => { |
|||
grouped[fieldName] = grouped[fieldName] || []; |
|||
grouped[fieldName].push(rest); |
|||
}); |
|||
for (let name in grouped) { |
|||
if (formFields[name]) { |
|||
formFields[name].error = true; |
|||
formFields[name].errorMessage = grouped[name] |
|||
.map((obj) => { |
|||
return obj.errorMessage; |
|||
}) |
|||
.join('、'); |
|||
} |
|||
} |
|||
} |
|||
}; |
|||
|
|||
const getFields = () => { |
|||
return formFields; |
|||
}; |
|||
|
|||
const getFieldComponent = (name) => { |
|||
return componentRef.value[name]; |
|||
}; |
|||
|
|||
defineExpose({ |
|||
getFields, |
|||
getData, |
|||
setData, |
|||
reset, |
|||
validate, |
|||
getFieldValue, |
|||
setFieldValue, |
|||
setStatus, |
|||
getStatus, |
|||
getColsNum, |
|||
setValidationErrors, |
|||
getFieldComponent, |
|||
}); |
|||
|
|||
const instance = getCurrentInstance(); |
|||
VueTools.expose2Instance(instance); |
|||
</script> |
@ -1,70 +0,0 @@ |
|||
<template> |
|||
<div v-show="showIfComputed"> |
|||
<q-checkbox v-model="checkboxValue" v-bind="attrs" :disable="disableIfComputed" @update:model-value="updateModelValue" @change="changeValue"></q-checkbox> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup lang="ts"> |
|||
import { computed, useAttrs, ref, watch } from 'vue'; |
|||
|
|||
const attrs = useAttrs(); |
|||
const props = defineProps({ |
|||
onChange: { |
|||
type: Function, |
|||
default: () => {}, |
|||
}, |
|||
modelValue: { type: Boolean, default: false }, |
|||
showIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return true; |
|||
}, |
|||
}, |
|||
disableIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return false; |
|||
}, |
|||
}, |
|||
form: { |
|||
type: Object, |
|||
default: undefined, |
|||
}, |
|||
}); |
|||
const emit = defineEmits(['update:modelValue', 'change']); |
|||
const checkboxValue = ref(props.modelValue); |
|||
watch( |
|||
() => props.modelValue, |
|||
(newVal, oldVal) => { |
|||
checkboxValue.value = newVal; |
|||
}, |
|||
); |
|||
|
|||
const showIfComputed = computed(() => { |
|||
return props.showIf({ |
|||
value: checkboxValue.value, |
|||
form: props.form, |
|||
}); |
|||
}); |
|||
const disableIfComputed = computed(() => { |
|||
if (props.form && props.form.getStatus() === 'view') { |
|||
return true; |
|||
} |
|||
return props.disableIf({ |
|||
value: checkboxValue.value, |
|||
form: props.form, |
|||
}); |
|||
}); |
|||
|
|||
const updateModelValue = (value) => { |
|||
emit('update:modelValue', value, props.form); |
|||
changeValue(value); |
|||
}; |
|||
|
|||
const changeValue = (value) => { |
|||
emit('change', { |
|||
value: value, |
|||
form: props.form, |
|||
}); |
|||
}; |
|||
</script> |
@ -1,205 +0,0 @@ |
|||
<template> |
|||
<div v-show="showIfComputed"> |
|||
<q-input |
|||
ref="colorRef" |
|||
v-model="colorValueRef" |
|||
:hide-bottom-space="true" |
|||
:hide-hint="true" |
|||
:outlined="true" |
|||
:dense="true" |
|||
v-bind="attrs" |
|||
:rules="rulesComputed" |
|||
:readonly="readonlyIfComputed" |
|||
:disable="disableIfComputed" |
|||
@update:model-value="colorChanged" |
|||
@change="changeValue" |
|||
> |
|||
<template #label> <span v-if="requiredIfComputed" style="color: red">*</span> {{ attrs.label }} </template> |
|||
<template v-if="!props.form || (props.form && props.form.getStatus() !== 'view')" #append> |
|||
<!-- 选择颜色按钮 --> |
|||
<q-btn |
|||
icon="square" |
|||
size="10px" |
|||
padding="2px" |
|||
flat |
|||
square |
|||
unelevated |
|||
:title="$t('select')" |
|||
:style="{ border: '1px solid #e5e7eb', color: computedColorValue, 'background-color': computedStoreBackgroundColorValue }" |
|||
> |
|||
<q-popup-proxy v-model:model-value="isShow" anchor="bottom right" self="top right" :offset="[0, 10]"> |
|||
<q-color |
|||
v-model="colorValueRef" |
|||
default-value="colorValueRef" |
|||
format-model="hex" |
|||
default-view="palette" |
|||
style="max-width: 250px" |
|||
@update:model-value="colorChanged" |
|||
@change="changeValue" |
|||
/> |
|||
</q-popup-proxy> |
|||
</q-btn> |
|||
<!-- 恢复默认值按钮 --> |
|||
<q-btn |
|||
v-if="restore" |
|||
icon="bi-arrow-counterclockwise" |
|||
size="10px" |
|||
padding="2px" |
|||
flat |
|||
square |
|||
unelevated |
|||
:title="$t('restore')" |
|||
:style="{ 'margin-left': '5px', border: '1px solid #e5e7eb', color: restoreValue, 'background-color': computedStoreBackgroundColorValue }" |
|||
@click="restoreDefaultValue" |
|||
></q-btn> |
|||
</template> |
|||
</q-input> |
|||
</div> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import { ref, toRaw, computed, useAttrs, watch } from 'vue'; |
|||
import { Tools } from '@/platform'; |
|||
import { FormValidators } from '@/platform/components'; |
|||
|
|||
const attrs = useAttrs(); |
|||
const rules = attrs.rules; |
|||
const colorRef = ref(); |
|||
const props = defineProps({ |
|||
onChange: { |
|||
type: Function, |
|||
default: () => {}, |
|||
}, |
|||
modelValue: { type: String, default: '' }, |
|||
restore: { type: Boolean, default: false }, |
|||
showIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return true; |
|||
}, |
|||
}, |
|||
required: { |
|||
type: Boolean, |
|||
default: false, |
|||
}, |
|||
requiredIf: { |
|||
type: Function, |
|||
default: undefined, |
|||
}, |
|||
readOnlyIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return false; |
|||
}, |
|||
}, |
|||
disableIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return false; |
|||
}, |
|||
}, |
|||
form: { |
|||
type: Object, |
|||
default: undefined, |
|||
}, |
|||
}); |
|||
const emit = defineEmits(['update:modelValue', 'change']); |
|||
|
|||
const isShow = ref(false); |
|||
const defaultValue = '#000000'; |
|||
const colorValueRef = ref(props.modelValue || defaultValue); |
|||
if (Tools.isEmpty(props.modelValue)) { |
|||
emit('update:modelValue', colorValueRef.value); |
|||
} |
|||
const restoreValue = toRaw(props.modelValue || defaultValue); |
|||
|
|||
watch( |
|||
() => props.modelValue, |
|||
(newVal, oldVal) => { |
|||
colorValueRef.value = newVal; |
|||
}, |
|||
); |
|||
|
|||
const computedColorValue = computed(() => { |
|||
return colorValueRef.value; |
|||
}); |
|||
|
|||
const rulesComputed = computed(() => { |
|||
let result = rules || <any>[]; |
|||
if (showIfComputed.value && requiredIfComputed.value) { |
|||
result.push(FormValidators.required()); |
|||
} else if (!showIfComputed.value) { |
|||
result = []; |
|||
} |
|||
if (colorRef?.value) { |
|||
colorRef.value.resetValidation(); |
|||
} |
|||
return result; |
|||
}); |
|||
|
|||
const showIfComputed = computed(() => { |
|||
return props.showIf({ |
|||
value: colorValueRef.value, |
|||
form: props.form, |
|||
}); |
|||
}); |
|||
const requiredIfComputed = computed(() => { |
|||
if (props.requiredIf) { |
|||
return ( |
|||
props.requiredIf({ |
|||
value: colorValueRef.value, |
|||
form: props.form, |
|||
}) || false |
|||
); |
|||
} else if (props.required) { |
|||
return true; |
|||
} |
|||
return false; |
|||
}); |
|||
const readonlyIfComputed = computed(() => { |
|||
if (props.form && props.form.getStatus() === 'view') { |
|||
return true; |
|||
} |
|||
return props.readOnlyIf({ |
|||
value: colorValueRef.value, |
|||
form: props.form, |
|||
}); |
|||
}); |
|||
const disableIfComputed = computed(() => { |
|||
return props.disableIf({ |
|||
value: colorValueRef.value, |
|||
form: props.form, |
|||
}); |
|||
}); |
|||
|
|||
const computedStoreBackgroundColorValue = computed(() => { |
|||
const color: string = restoreValue; |
|||
if (color.toLowerCase() === 'white' || color.toLowerCase() === '#ffffff' || color.toLowerCase() === '#fff') { |
|||
return '#eee'; |
|||
} |
|||
return undefined; |
|||
}); |
|||
|
|||
const colorChanged = (value) => { |
|||
emit('update:modelValue', value, props.form); |
|||
isShow.value = false; |
|||
}; |
|||
const changeValue = (value) => { |
|||
emit('change', { |
|||
value: value, |
|||
form: props.form, |
|||
}); |
|||
}; |
|||
|
|||
const restoreDefaultValue = () => { |
|||
colorValueRef.value = restoreValue; |
|||
emit('update:modelValue', restoreValue, props.form); |
|||
}; |
|||
|
|||
const validate = () => { |
|||
return colorRef.value.validate(); |
|||
}; |
|||
|
|||
defineExpose({ |
|||
validate, |
|||
}); |
|||
</script> |
@ -1,440 +0,0 @@ |
|||
<template> |
|||
<div v-show="showIfComputed"> |
|||
<q-input |
|||
ref="colorRef" |
|||
v-model="colorValueRef" |
|||
:hide-bottom-space="true" |
|||
:hide-hint="true" |
|||
:outlined="true" |
|||
:dense="true" |
|||
v-bind="attrs" |
|||
:rules="rulesComputed" |
|||
:readonly="readonlyIfComputed" |
|||
:disable="disableIfComputed" |
|||
@update:model-value="colorSelected" |
|||
@change="changeValue" |
|||
> |
|||
<template #label> <span v-if="requiredIfComputed" style="color: red">*</span> {{ attrs.label }} </template> |
|||
<template v-if="!props.form || (props.form && props.form.getStatus() !== 'view')" #append> |
|||
<!-- 选择颜色按钮 --> |
|||
<q-btn |
|||
icon="bi-palette" |
|||
size="10px" |
|||
padding="2px" |
|||
flat |
|||
square |
|||
unelevated |
|||
:title="$t('select')" |
|||
:class="`text-${computedColorValue}`" |
|||
:style="{ border: '1px solid #e5e7eb', 'background-color': computedBackgroundColorValue }" |
|||
> |
|||
<q-popup-proxy v-model:model-value="isShow" anchor="bottom right" self="top right" :offset="[0, 10]"> |
|||
<div v-for="(colors, index) in quasarColors" :key="index" class="row"> |
|||
<div |
|||
v-for="color in colors" |
|||
:key="`${color}`" |
|||
:class="`bg-${color}`" |
|||
style="min-width: 20px; max-width: 20px; min-height: 20px; max-height: 20px" |
|||
@click="colorClick(`${color}`)" |
|||
> |
|||
<q-tooltip> {{ color }}</q-tooltip> |
|||
</div> |
|||
</div> |
|||
</q-popup-proxy> |
|||
</q-btn> |
|||
<!-- 恢复默认值按钮 --> |
|||
<q-btn |
|||
v-if="restore" |
|||
icon="bi-arrow-counterclockwise" |
|||
size="10px" |
|||
padding="2px" |
|||
flat |
|||
square |
|||
unelevated |
|||
:title="$t('restore')" |
|||
:class="`text-${restoreValue}`" |
|||
:style="{ 'margin-left': '5px', border: '1px solid #e5e7eb', 'background-color': computedStoreBackgroundColorValue }" |
|||
@click="restoreDefaultValue" |
|||
></q-btn> |
|||
</template> |
|||
</q-input> |
|||
</div> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import { ref, toRaw, computed, useAttrs, watch } from 'vue'; |
|||
import { Tools } from '@/platform'; |
|||
import { FormValidators } from '@/platform/components'; |
|||
|
|||
const attrs = useAttrs(); |
|||
const rules = attrs.rules; |
|||
const colorRef = ref(); |
|||
const props = defineProps({ |
|||
onChange: { |
|||
type: Function, |
|||
default: () => {}, |
|||
}, |
|||
modelValue: { type: String, default: '' }, |
|||
restore: { type: Boolean, default: false }, |
|||
showIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return true; |
|||
}, |
|||
}, |
|||
required: { |
|||
type: Boolean, |
|||
default: false, |
|||
}, |
|||
requiredIf: { |
|||
type: Function, |
|||
default: undefined, |
|||
}, |
|||
readOnlyIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return false; |
|||
}, |
|||
}, |
|||
disableIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return false; |
|||
}, |
|||
}, |
|||
form: { |
|||
type: Object, |
|||
default: undefined, |
|||
}, |
|||
}); |
|||
const emit = defineEmits(['update:modelValue', 'change']); |
|||
|
|||
const quasarColors = [ |
|||
['red', 'red-1', 'red-2', 'red-3', 'red-4', 'red-5', 'red-6', 'red-7', 'red-8', 'red-9', 'red-10', 'red-11', 'red-12', 'red-13', 'red-14'], |
|||
['pink', 'pink-1', 'pink-2', 'pink-3', 'pink-4', 'pink-5', 'pink-6', 'pink-7', 'pink-8', 'pink-9', 'pink-10', 'pink-11', 'pink-12', 'pink-13', 'pink-14'], |
|||
[ |
|||
'purple', |
|||
'purple-1', |
|||
'purple-2', |
|||
'purple-3', |
|||
'purple-4', |
|||
'purple-5', |
|||
'purple-6', |
|||
'purple-7', |
|||
'purple-8', |
|||
'purple-9', |
|||
'purple-10', |
|||
'purple-11', |
|||
'purple-12', |
|||
'purple-13', |
|||
'purple-14', |
|||
], |
|||
[ |
|||
'deep-purple', |
|||
'deep-purple-1', |
|||
'deep-purple-2', |
|||
'deep-purple-3', |
|||
'deep-purple-4', |
|||
'deep-purple-5', |
|||
'deep-purple-6', |
|||
'deep-purple-7', |
|||
'deep-purple-8', |
|||
'deep-purple-9', |
|||
'deep-purple-10', |
|||
'deep-purple-11', |
|||
'deep-purple-12', |
|||
'deep-purple-13', |
|||
'deep-purple-14', |
|||
], |
|||
[ |
|||
'indigo', |
|||
'indigo-1', |
|||
'indigo-2', |
|||
'indigo-3', |
|||
'indigo-4', |
|||
'indigo-5', |
|||
'indigo-6', |
|||
'indigo-7', |
|||
'indigo-8', |
|||
'indigo-9', |
|||
'indigo-10', |
|||
'indigo-11', |
|||
'indigo-12', |
|||
'indigo-13', |
|||
'indigo-14', |
|||
], |
|||
['blue', 'blue-1', 'blue-2', 'blue-3', 'blue-4', 'blue-5', 'blue-6', 'blue-7', 'blue-8', 'blue-9', 'blue-10', 'blue-11', 'blue-12', 'blue-13', 'blue-14'], |
|||
[ |
|||
'light-blue', |
|||
'light-blue-1', |
|||
'light-blue-2', |
|||
'light-blue-3', |
|||
'light-blue-4', |
|||
'light-blue-5', |
|||
'light-blue-6', |
|||
'light-blue-7', |
|||
'light-blue-8', |
|||
'light-blue-9', |
|||
'light-blue-10', |
|||
'light-blue-11', |
|||
'light-blue-12', |
|||
'light-blue-13', |
|||
'light-blue-14', |
|||
], |
|||
['cyan', 'cyan-1', 'cyan-2', 'cyan-3', 'cyan-4', 'cyan-5', 'cyan-6', 'cyan-7', 'cyan-8', 'cyan-9', 'cyan-10', 'cyan-11', 'cyan-12', 'cyan-13', 'cyan-14'], |
|||
['teal', 'teal-1', 'teal-2', 'teal-3', 'teal-4', 'teal-5', 'teal-6', 'teal-7', 'teal-8', 'teal-9', 'teal-10', 'teal-11', 'teal-12', 'teal-13', 'teal-14'], |
|||
[ |
|||
'green', |
|||
'green-1', |
|||
'green-2', |
|||
'green-3', |
|||
'green-4', |
|||
'green-5', |
|||
'green-6', |
|||
'green-7', |
|||
'green-8', |
|||
'green-9', |
|||
'green-10', |
|||
'green-11', |
|||
'green-12', |
|||
'green-13', |
|||
'green-14', |
|||
], |
|||
[ |
|||
'light-green', |
|||
'light-green-1', |
|||
'light-green-2', |
|||
'light-green-3', |
|||
'light-green-4', |
|||
'light-green-5', |
|||
'light-green-6', |
|||
'light-green-7', |
|||
'light-green-8', |
|||
'light-green-9', |
|||
'light-green-10', |
|||
'light-green-11', |
|||
'light-green-12', |
|||
'light-green-13', |
|||
'light-green-14', |
|||
], |
|||
['lime', 'lime-1', 'lime-2', 'lime-3', 'lime-4', 'lime-5', 'lime-6', 'lime-7', 'lime-8', 'lime-9', 'lime-10', 'lime-11', 'lime-12', 'lime-13', 'lime-14'], |
|||
[ |
|||
'yellow', |
|||
'yellow-1', |
|||
'yellow-2', |
|||
'yellow-3', |
|||
'yellow-4', |
|||
'yellow-5', |
|||
'yellow-6', |
|||
'yellow-7', |
|||
'yellow-8', |
|||
'yellow-9', |
|||
'yellow-10', |
|||
'yellow-11', |
|||
'yellow-12', |
|||
'yellow-13', |
|||
'yellow-14', |
|||
], |
|||
[ |
|||
'amber', |
|||
'amber-1', |
|||
'amber-2', |
|||
'amber-3', |
|||
'amber-4', |
|||
'amber-5', |
|||
'amber-6', |
|||
'amber-7', |
|||
'amber-8', |
|||
'amber-9', |
|||
'amber-10', |
|||
'amber-11', |
|||
'amber-12', |
|||
'amber-13', |
|||
'amber-14', |
|||
], |
|||
[ |
|||
'orange', |
|||
'orange-1', |
|||
'orange-2', |
|||
'orange-3', |
|||
'orange-4', |
|||
'orange-5', |
|||
'orange-6', |
|||
'orange-7', |
|||
'orange-8', |
|||
'orange-9', |
|||
'orange-10', |
|||
'orange-11', |
|||
'orange-12', |
|||
'orange-13', |
|||
'orange-14', |
|||
], |
|||
[ |
|||
'deep-orange', |
|||
'deep-orange-1', |
|||
'deep-orange-2', |
|||
'deep-orange-3', |
|||
'deep-orange-4', |
|||
'deep-orange-5', |
|||
'deep-orange-6', |
|||
'deep-orange-7', |
|||
'deep-orange-8', |
|||
'deep-orange-9', |
|||
'deep-orange-10', |
|||
'deep-orange-11', |
|||
'deep-orange-12', |
|||
'deep-orange-13', |
|||
'deep-orange-14', |
|||
], |
|||
[ |
|||
'brown', |
|||
'brown-1', |
|||
'brown-2', |
|||
'brown-3', |
|||
'brown-4', |
|||
'brown-5', |
|||
'brown-6', |
|||
'brown-7', |
|||
'brown-8', |
|||
'brown-9', |
|||
'brown-10', |
|||
'brown-11', |
|||
'brown-12', |
|||
'brown-13', |
|||
'brown-14', |
|||
], |
|||
['grey', 'grey-1', 'grey-2', 'grey-3', 'grey-4', 'grey-5', 'grey-6', 'grey-7', 'grey-8', 'grey-9', 'grey-10', 'grey-11', 'grey-12', 'grey-13', 'grey-14'], |
|||
[ |
|||
'blue-grey', |
|||
'blue-grey-1', |
|||
'blue-grey-2', |
|||
'blue-grey-3', |
|||
'blue-grey-4', |
|||
'blue-grey-5', |
|||
'blue-grey-6', |
|||
'blue-grey-7', |
|||
'blue-grey-8', |
|||
'blue-grey-9', |
|||
'blue-grey-10', |
|||
'blue-grey-11', |
|||
'blue-grey-12', |
|||
'blue-grey-13', |
|||
'blue-grey-14', |
|||
], |
|||
['white', 'black'], |
|||
]; |
|||
|
|||
const isShow = ref(false); |
|||
const defaultValue = 'black'; |
|||
const colorValueRef = ref(props.modelValue || defaultValue); |
|||
if (Tools.isEmpty(props.modelValue)) { |
|||
emit('update:modelValue', { |
|||
value: colorValueRef.value, |
|||
form: props.form, |
|||
}); |
|||
} |
|||
const restoreValue = toRaw(props.modelValue || defaultValue); |
|||
|
|||
watch( |
|||
() => props.modelValue, |
|||
(newVal, oldVal) => { |
|||
colorValueRef.value = newVal; |
|||
}, |
|||
); |
|||
|
|||
const computedColorValue = computed(() => { |
|||
return colorValueRef.value; |
|||
}); |
|||
|
|||
const computedBackgroundColorValue = computed(() => { |
|||
const color: string = toRaw(colorValueRef.value); |
|||
if (color.toLowerCase() === 'white' || color.toLowerCase() === '#ffffff' || color.toLowerCase() === '#fff') { |
|||
return '#eee'; |
|||
} |
|||
return undefined; |
|||
}); |
|||
|
|||
const computedStoreBackgroundColorValue = computed(() => { |
|||
const color: string = restoreValue; |
|||
if (color.toLowerCase() === 'white' || color.toLowerCase() === '#ffffff' || color.toLowerCase() === '#fff') { |
|||
return '#eee'; |
|||
} |
|||
return undefined; |
|||
}); |
|||
|
|||
const rulesComputed = computed(() => { |
|||
let result = rules || <any>[]; |
|||
if (showIfComputed.value && requiredIfComputed.value) { |
|||
result.push(FormValidators.required()); |
|||
} else if (!showIfComputed.value) { |
|||
result = []; |
|||
} |
|||
if (colorRef?.value) { |
|||
colorRef.value.resetValidation(); |
|||
} |
|||
return result; |
|||
}); |
|||
|
|||
const showIfComputed = computed(() => { |
|||
return props.showIf({ |
|||
value: colorValueRef.value, |
|||
form: props.form, |
|||
}); |
|||
}); |
|||
const requiredIfComputed = computed(() => { |
|||
if (props.requiredIf) { |
|||
return ( |
|||
props.requiredIf({ |
|||
value: colorValueRef.value, |
|||
form: props.form, |
|||
}) || false |
|||
); |
|||
} else if (props.required) { |
|||
return true; |
|||
} |
|||
return false; |
|||
}); |
|||
const readonlyIfComputed = computed(() => { |
|||
if (props.form && props.form.getStatus() === 'view') { |
|||
return true; |
|||
} |
|||
return props.readOnlyIf({ |
|||
value: colorValueRef.value, |
|||
form: props.form, |
|||
}); |
|||
}); |
|||
const disableIfComputed = computed(() => { |
|||
return props.disableIf({ |
|||
value: colorValueRef.value, |
|||
form: props.form, |
|||
}); |
|||
}); |
|||
|
|||
const colorSelected = (value) => { |
|||
colorValueRef.value = value; |
|||
emit('update:modelValue', value, props.form); |
|||
isShow.value = false; |
|||
}; |
|||
const changeValue = (value) => { |
|||
emit('change', { |
|||
value: value, |
|||
form: props.form, |
|||
}); |
|||
}; |
|||
const colorClick = (value) => { |
|||
colorSelected(value); |
|||
changeValue(value); |
|||
}; |
|||
|
|||
const restoreDefaultValue = () => { |
|||
colorValueRef.value = restoreValue; |
|||
emit('update:modelValue', restoreValue, props.form); |
|||
}; |
|||
|
|||
const validate = () => { |
|||
return colorRef.value.validate(); |
|||
}; |
|||
|
|||
defineExpose({ |
|||
validate, |
|||
}); |
|||
</script> |
@ -1,161 +0,0 @@ |
|||
<template> |
|||
<div v-show="showIfComputed"> |
|||
<q-input |
|||
ref="dateRef" |
|||
v-model="dateValue" |
|||
:hide-bottom-space="true" |
|||
:hide-hint="true" |
|||
:outlined="true" |
|||
:dense="true" |
|||
v-bind="attrs" |
|||
:rules="rulesComputed" |
|||
:readonly="readonlyIfComputed" |
|||
:disable="disableIfComputed" |
|||
@update:model-value="updateModelValue" |
|||
@change="changeValue" |
|||
> |
|||
<template #label> <span v-if="requiredIfComputed" style="color: red">*</span> {{ attrs.label }}</template> |
|||
<template v-if="!props.form || (props.form && props.form.getStatus() !== 'view')" #append> |
|||
<q-icon :name="IconEnum.日期" class="cursor-pointer"> |
|||
<q-popup-proxy cover transition-show="scale" transition-hide="scale"> |
|||
<q-date v-model="dateValue" today-btn mask="YYYY-MM-DD" @update:model-value="dateSelected"> |
|||
<div class="row items-center justify-end"> |
|||
<q-btn v-close-popup label="关闭" color="primary" flat /> |
|||
</div> |
|||
</q-date> |
|||
</q-popup-proxy> |
|||
</q-icon> |
|||
</template> |
|||
</q-input> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup lang="ts"> |
|||
import { ref, computed, useAttrs, watch } from 'vue'; |
|||
import { FormValidators } from '@/platform/components'; |
|||
import { IconEnum } from '@/platform/enums'; |
|||
|
|||
const dateRef = ref(); |
|||
const attrs = useAttrs(); |
|||
const rules = attrs.rules; |
|||
const props = defineProps({ |
|||
onChange: { |
|||
type: Function, |
|||
default: () => {}, |
|||
}, |
|||
type: { |
|||
type: String, |
|||
default: 'w-date', |
|||
}, |
|||
modelValue: { type: String, default: '' }, |
|||
showIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return true; |
|||
}, |
|||
}, |
|||
required: { |
|||
type: Boolean, |
|||
default: false, |
|||
}, |
|||
requiredIf: { |
|||
type: Function, |
|||
default: undefined, |
|||
}, |
|||
readOnlyIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return false; |
|||
}, |
|||
}, |
|||
disableIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return false; |
|||
}, |
|||
}, |
|||
form: { |
|||
type: Object, |
|||
default: undefined, |
|||
}, |
|||
}); |
|||
const emit = defineEmits(['update:modelValue', 'change']); |
|||
const dateValue = ref(props.modelValue); |
|||
watch( |
|||
() => props.modelValue, |
|||
(newVal, oldVal) => { |
|||
dateValue.value = newVal; |
|||
}, |
|||
); |
|||
|
|||
const rulesComputed = computed(() => { |
|||
let result = rules || <any>[]; |
|||
if (showIfComputed.value && requiredIfComputed.value) { |
|||
result.push(FormValidators.required()); |
|||
} else if (!showIfComputed.value) { |
|||
result = []; |
|||
} |
|||
if (dateRef?.value) { |
|||
dateRef.value.resetValidation(); |
|||
} |
|||
return result; |
|||
}); |
|||
|
|||
const showIfComputed = computed(() => { |
|||
return props.showIf({ |
|||
value: dateValue.value, |
|||
form: props.form, |
|||
}); |
|||
}); |
|||
const requiredIfComputed = computed(() => { |
|||
if (props.requiredIf) { |
|||
return ( |
|||
props.requiredIf({ |
|||
value: dateValue.value, |
|||
form: props.form, |
|||
}) || false |
|||
); |
|||
} else if (props.required) { |
|||
return true; |
|||
} |
|||
return false; |
|||
}); |
|||
const readonlyIfComputed = computed(() => { |
|||
if (props.form && props.form.getStatus() === 'view') { |
|||
return true; |
|||
} |
|||
return props.readOnlyIf({ |
|||
value: dateValue.value, |
|||
form: props.form, |
|||
}); |
|||
}); |
|||
const disableIfComputed = computed(() => { |
|||
return props.disableIf({ |
|||
value: dateValue.value, |
|||
form: props.form, |
|||
}); |
|||
}); |
|||
|
|||
const updateModelValue = (value) => { |
|||
emit('update:modelValue', value, props.form); |
|||
}; |
|||
const dateSelected = (value) => { |
|||
updateModelValue(value); |
|||
changeValue(value); |
|||
}; |
|||
|
|||
const changeValue = (value) => { |
|||
emit('change', { |
|||
value: value, |
|||
form: props.form, |
|||
}); |
|||
}; |
|||
|
|||
const validate = () => { |
|||
return dateRef.value.validate(); |
|||
}; |
|||
|
|||
defineExpose({ |
|||
validate, |
|||
}); |
|||
</script> |
@ -1,145 +0,0 @@ |
|||
<template> |
|||
<div v-show="showIfComputed"> |
|||
<q-file |
|||
ref="fileRef" |
|||
v-model="fileValue" |
|||
:hide-bottom-space="true" |
|||
:hide-hint="true" |
|||
:outlined="true" |
|||
:dense="true" |
|||
:clearable="true" |
|||
v-bind="attrs" |
|||
:rules="rulesComputed" |
|||
:readonly="readonlyIfComputed" |
|||
:disable="disableIfComputed" |
|||
@update:model-value="updateModelValue" |
|||
@change="changeValue" |
|||
> |
|||
<template #label> <span v-if="requiredIfComputed" style="color: red">*</span> {{ attrs.label }}</template> |
|||
<template v-if="!props.form || (props.form && props.form.getStatus() !== 'view')" #append> |
|||
<q-icon name="attachment" /> |
|||
</template> |
|||
</q-file> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup lang="ts"> |
|||
import { ref, computed, useAttrs, watch } from 'vue'; |
|||
import { FormValidators } from '@/platform/components'; |
|||
|
|||
const fileRef = ref(); |
|||
const attrs = useAttrs(); |
|||
const rules = attrs.rules; |
|||
const props = defineProps({ |
|||
onChange: { |
|||
type: Function, |
|||
default: () => {}, |
|||
}, |
|||
modelValue: { type: [File, Array], default: undefined }, |
|||
showIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return true; |
|||
}, |
|||
}, |
|||
required: { |
|||
type: Boolean, |
|||
default: false, |
|||
}, |
|||
requiredIf: { |
|||
type: Function, |
|||
default: undefined, |
|||
}, |
|||
readOnlyIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return false; |
|||
}, |
|||
}, |
|||
disableIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return false; |
|||
}, |
|||
}, |
|||
form: { |
|||
type: Object, |
|||
default: undefined, |
|||
}, |
|||
}); |
|||
const emit = defineEmits(['update:modelValue', 'change']); |
|||
const fileValue = ref(props.modelValue); |
|||
watch( |
|||
() => props.modelValue, |
|||
(newVal, oldVal) => { |
|||
fileValue.value = newVal; |
|||
}, |
|||
); |
|||
|
|||
const rulesComputed = computed(() => { |
|||
let result = rules || <any>[]; |
|||
if (showIfComputed.value && requiredIfComputed.value) { |
|||
result.push(FormValidators.required()); |
|||
} else if (!showIfComputed.value) { |
|||
result = []; |
|||
} |
|||
if (fileRef?.value) { |
|||
fileRef.value.resetValidation(); |
|||
} |
|||
return result; |
|||
}); |
|||
|
|||
const showIfComputed = computed(() => { |
|||
return props.showIf({ |
|||
value: fileValue.value, |
|||
form: props.form, |
|||
}); |
|||
}); |
|||
const requiredIfComputed = computed(() => { |
|||
if (props.requiredIf) { |
|||
return ( |
|||
props.requiredIf({ |
|||
value: fileValue.value, |
|||
form: props.form, |
|||
}) || false |
|||
); |
|||
} else if (props.required) { |
|||
return true; |
|||
} |
|||
return false; |
|||
}); |
|||
const readonlyIfComputed = computed(() => { |
|||
if (props.form && props.form.getStatus() === 'view') { |
|||
return true; |
|||
} |
|||
return props.readOnlyIf({ |
|||
value: fileValue.value, |
|||
form: props.form, |
|||
}); |
|||
}); |
|||
const disableIfComputed = computed(() => { |
|||
return props.disableIf({ |
|||
value: fileValue.value, |
|||
form: props.form, |
|||
}); |
|||
}); |
|||
|
|||
const updateModelValue = (value) => { |
|||
emit('update:modelValue', value, props.form); |
|||
}; |
|||
|
|||
const changeValue = (value) => { |
|||
emit('change', { |
|||
value: value, |
|||
form: props.form, |
|||
}); |
|||
}; |
|||
|
|||
const validate = () => { |
|||
return fileRef.value.validate(); |
|||
}; |
|||
|
|||
defineExpose({ |
|||
validate, |
|||
}); |
|||
</script> |
@ -1,81 +0,0 @@ |
|||
<template> |
|||
<div v-show="showIfComputed"> |
|||
<w-grid ref="gridRef" v-bind="attrs"></w-grid> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup lang="ts"> |
|||
import { computed, useAttrs, ref, watch } from 'vue'; |
|||
|
|||
const attrs = useAttrs(); |
|||
const rules = attrs.rules; |
|||
const props = defineProps({ |
|||
onChange: { |
|||
type: Function, |
|||
default: () => {}, |
|||
}, |
|||
modelValue: { type: String, default: undefined }, |
|||
showIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return true; |
|||
}, |
|||
}, |
|||
disableIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return false; |
|||
}, |
|||
}, |
|||
form: { |
|||
type: Object, |
|||
default: undefined, |
|||
}, |
|||
}); |
|||
const emit = defineEmits(['update:modelValue', 'change']); |
|||
|
|||
const gridRef =ref(); |
|||
const gridValue = ref(props.modelValue); |
|||
watch( |
|||
() => props.modelValue, |
|||
(newVal, oldVal) => { |
|||
gridValue.value = newVal; |
|||
}, |
|||
); |
|||
|
|||
const rulesComputed = computed(() => { |
|||
let result = rules || <any>[]; |
|||
if (!showIfComputed.value) { |
|||
result = []; |
|||
} |
|||
return result; |
|||
}); |
|||
|
|||
const showIfComputed = computed(() => { |
|||
return props.showIf({ |
|||
value: gridValue.value, |
|||
form: props.form, |
|||
}); |
|||
}); |
|||
const disableIfComputed = computed(() => { |
|||
if (props.form && props.form.getStatus() === 'view') { |
|||
return true; |
|||
} |
|||
return props.disableIf({ |
|||
value: gridValue.value, |
|||
form: props.form, |
|||
}); |
|||
}); |
|||
|
|||
const updateModelValue = (value) => { |
|||
emit('update:modelValue', value, props.form); |
|||
changeValue(value); |
|||
}; |
|||
|
|||
const changeValue = (value) => { |
|||
emit('change', { |
|||
value: value, |
|||
form: props.form, |
|||
}); |
|||
}; |
|||
</script> |
@ -1,144 +0,0 @@ |
|||
<template> |
|||
<div v-show="showIfComputed"> |
|||
<q-input |
|||
ref="numberRef" |
|||
v-model="numberValue" |
|||
:hide-bottom-space="true" |
|||
:hide-hint="true" |
|||
:outlined="true" |
|||
:dense="true" |
|||
v-bind="attrs" |
|||
type="number" |
|||
title="" |
|||
:rules="rulesComputed" |
|||
:readonly="readonlyIfComputed" |
|||
:disable="disableIfComputed" |
|||
@update:model-value="updateModelValue" |
|||
@change="changeValue" |
|||
> |
|||
<template #label> <span v-if="requiredIfComputed" style="color: red">*</span> {{ attrs.label }}</template> |
|||
</q-input> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup lang="ts"> |
|||
import { ref, computed, useAttrs, watch } from 'vue'; |
|||
import { FormValidators } from '@/platform/components'; |
|||
|
|||
const numberRef = ref(); |
|||
const attrs = useAttrs(); |
|||
const rules = attrs.rules; |
|||
const props = defineProps({ |
|||
onChange: { |
|||
type: Function, |
|||
default: () => {}, |
|||
}, |
|||
modelValue: { type: Number, default: undefined }, |
|||
precision: { type: Number, default: 0 }, |
|||
showIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return true; |
|||
}, |
|||
}, |
|||
required: { |
|||
type: Boolean, |
|||
default: false, |
|||
}, |
|||
requiredIf: { |
|||
type: Function, |
|||
default: undefined, |
|||
}, |
|||
readOnlyIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return false; |
|||
}, |
|||
}, |
|||
disableIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return false; |
|||
}, |
|||
}, |
|||
form: { |
|||
type: Object, |
|||
default: undefined, |
|||
}, |
|||
}); |
|||
const emit = defineEmits(['update:modelValue', 'change']); |
|||
const numberValue = ref(props.modelValue); |
|||
watch( |
|||
() => props.modelValue, |
|||
(newVal, oldVal) => { |
|||
numberValue.value = newVal; |
|||
}, |
|||
); |
|||
|
|||
const rulesComputed = computed(() => { |
|||
let result = rules || <any>[]; |
|||
result.push(FormValidators.maxPrecision(props.precision)); |
|||
if (showIfComputed.value && requiredIfComputed.value) { |
|||
result.push(FormValidators.required()); |
|||
} else if (!showIfComputed.value) { |
|||
result = []; |
|||
} |
|||
if (numberRef?.value) { |
|||
numberRef.value.resetValidation(); |
|||
} |
|||
return result; |
|||
}); |
|||
|
|||
const showIfComputed = computed(() => { |
|||
return props.showIf({ |
|||
value: numberValue.value, |
|||
form: props.form, |
|||
}); |
|||
}); |
|||
const requiredIfComputed = computed(() => { |
|||
if (props.requiredIf) { |
|||
return ( |
|||
props.requiredIf({ |
|||
value: numberValue.value, |
|||
form: props.form, |
|||
}) || false |
|||
); |
|||
} else if (props.required) { |
|||
return true; |
|||
} |
|||
return false; |
|||
}); |
|||
const readonlyIfComputed = computed(() => { |
|||
if (props.form && props.form.getStatus() === 'view') { |
|||
return true; |
|||
} |
|||
return props.readOnlyIf({ |
|||
value: numberValue.value, |
|||
form: props.form, |
|||
}); |
|||
}); |
|||
const disableIfComputed = computed(() => { |
|||
return props.disableIf({ |
|||
value: numberValue.value, |
|||
form: props.form, |
|||
}); |
|||
}); |
|||
|
|||
const updateModelValue = (value) => { |
|||
emit('update:modelValue', Number(value), props.form); |
|||
}; |
|||
const changeValue = (value) => { |
|||
emit('change', { |
|||
value: value, |
|||
form: props.form, |
|||
}); |
|||
}; |
|||
|
|||
const validate = () => { |
|||
return numberRef.value.validate(); |
|||
}; |
|||
|
|||
defineExpose({ |
|||
validate, |
|||
}); |
|||
</script> |
@ -1,93 +0,0 @@ |
|||
<template> |
|||
<div v-show="showIfComputed" class="border-solid border"> |
|||
<div style="color: rgba(0, 0, 0, 0.6)" class="px-1"> |
|||
{{ label }} |
|||
</div> |
|||
<q-separator /> |
|||
<q-option-group |
|||
v-model="optionGroupValue" |
|||
v-bind="attrs" |
|||
:type="optionType" |
|||
:disable="disableIfComputed" |
|||
@update:model-value="updateModelValue" |
|||
@change="changeValue" |
|||
/> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup lang="ts"> |
|||
import { computed, useAttrs, ref, watch } from 'vue'; |
|||
|
|||
const attrs = useAttrs(); |
|||
const props = defineProps({ |
|||
onChange: { |
|||
type: Function, |
|||
default: () => {}, |
|||
}, |
|||
modelValue: { type: [Number, Boolean, String, Array], default: undefined }, |
|||
type: { |
|||
type: String, |
|||
default: '', |
|||
}, |
|||
label: { |
|||
type: String, |
|||
default: '', |
|||
}, |
|||
optionType: { |
|||
type: String, |
|||
default: 'radio', |
|||
}, |
|||
showIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return true; |
|||
}, |
|||
}, |
|||
disableIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return false; |
|||
}, |
|||
}, |
|||
form: { |
|||
type: Object, |
|||
default: undefined, |
|||
}, |
|||
}); |
|||
const emit = defineEmits(['update:modelValue', 'change']); |
|||
const optionGroupValue = ref(props.modelValue); |
|||
watch( |
|||
() => props.modelValue, |
|||
(newVal, oldVal) => { |
|||
optionGroupValue.value = newVal; |
|||
}, |
|||
); |
|||
|
|||
const showIfComputed = computed(() => { |
|||
return props.showIf({ |
|||
value: optionGroupValue.value, |
|||
form: props.form, |
|||
}); |
|||
}); |
|||
const disableIfComputed = computed(() => { |
|||
if (props.form && props.form.getStatus() === 'view') { |
|||
return true; |
|||
} |
|||
return props.disableIf({ |
|||
value: optionGroupValue.value, |
|||
form: props.form, |
|||
}); |
|||
}); |
|||
|
|||
const updateModelValue = (value) => { |
|||
emit('update:modelValue', value, props.form); |
|||
changeValue(value); |
|||
}; |
|||
|
|||
const changeValue = (value) => { |
|||
emit('change', { |
|||
value: value, |
|||
form: props.form, |
|||
}); |
|||
}; |
|||
</script> |
@ -1,143 +0,0 @@ |
|||
<template> |
|||
<div v-show="showIfComputed"> |
|||
<q-input |
|||
ref="pwdRef" |
|||
v-model="passwordValue" |
|||
:hide-bottom-space="true" |
|||
:hide-hint="true" |
|||
:outlined="true" |
|||
:dense="true" |
|||
v-bind="attrs" |
|||
type="password" |
|||
autocomplete="off" |
|||
:rules="rulesComputed" |
|||
:readonly="readonlyIfComputed" |
|||
:disable="disableIfComputed" |
|||
@update:model-value="updateModelValue" |
|||
@change="changeValue" |
|||
> |
|||
<template #label> <span v-if="requiredIfComputed" style="color: red">*</span> {{ attrs.label }}</template> |
|||
</q-input> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup lang="ts"> |
|||
import { ref, computed, useAttrs, watch } from 'vue'; |
|||
import { FormValidators } from '@/platform/components'; |
|||
|
|||
const pwdRef = ref(); |
|||
const attrs = useAttrs(); |
|||
const rules = attrs.rules; |
|||
const props = defineProps({ |
|||
onChange: { |
|||
type: Function, |
|||
default: () => {}, |
|||
}, |
|||
modelValue: { type: String, default: '' }, |
|||
showIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return true; |
|||
}, |
|||
}, |
|||
required: { |
|||
type: Boolean, |
|||
default: false, |
|||
}, |
|||
requiredIf: { |
|||
type: Function, |
|||
default: undefined, |
|||
}, |
|||
readOnlyIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return false; |
|||
}, |
|||
}, |
|||
disableIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return false; |
|||
}, |
|||
}, |
|||
form: { |
|||
type: Object, |
|||
default: undefined, |
|||
}, |
|||
}); |
|||
const emit = defineEmits(['update:modelValue', 'change']); |
|||
const passwordValue = ref(props.modelValue); |
|||
watch( |
|||
() => props.modelValue, |
|||
(newVal, oldVal) => { |
|||
passwordValue.value = newVal; |
|||
}, |
|||
); |
|||
|
|||
const rulesComputed = computed(() => { |
|||
let result = rules || <any>[]; |
|||
if (showIfComputed.value && requiredIfComputed.value) { |
|||
result.push(FormValidators.required()); |
|||
} else if (!showIfComputed.value) { |
|||
result = []; |
|||
} |
|||
if (pwdRef?.value) { |
|||
pwdRef.value.resetValidation(); |
|||
} |
|||
return result; |
|||
}); |
|||
|
|||
const showIfComputed = computed(() => { |
|||
return props.showIf({ |
|||
value: passwordValue.value, |
|||
form: props.form, |
|||
}); |
|||
}); |
|||
const requiredIfComputed = computed(() => { |
|||
if (props.requiredIf) { |
|||
return ( |
|||
props.requiredIf({ |
|||
value: passwordValue.value, |
|||
form: props.form, |
|||
}) || false |
|||
); |
|||
} else if (props.required) { |
|||
return true; |
|||
} |
|||
return false; |
|||
}); |
|||
const readonlyIfComputed = computed(() => { |
|||
if (props.form && props.form.getStatus() === 'view') { |
|||
return true; |
|||
} |
|||
return props.readOnlyIf({ |
|||
value: passwordValue.value, |
|||
form: props.form, |
|||
}); |
|||
}); |
|||
const disableIfComputed = computed(() => { |
|||
return props.disableIf({ |
|||
value: passwordValue.value, |
|||
form: props.form, |
|||
}); |
|||
}); |
|||
|
|||
const updateModelValue = (value) => { |
|||
emit('update:modelValue', value, props.form); |
|||
}; |
|||
|
|||
const changeValue = (value) => { |
|||
emit('change', { |
|||
value: value, |
|||
form: props.form, |
|||
}); |
|||
}; |
|||
|
|||
const validate = () => { |
|||
return pwdRef.value.validate(); |
|||
}; |
|||
|
|||
defineExpose({ |
|||
validate, |
|||
}); |
|||
</script> |
@ -1,206 +0,0 @@ |
|||
<template> |
|||
<div v-show="showIfComputed"> |
|||
<q-input |
|||
ref="positionRef" |
|||
v-model="positionValueRef" |
|||
:hide-bottom-space="true" |
|||
:hide-hint="true" |
|||
:outlined="true" |
|||
:dense="true" |
|||
v-bind="attrs" |
|||
:rules="rulesComputed" |
|||
:readonly="readonlyIfComputed" |
|||
:disable="disableIfComputed" |
|||
@update:model-value="positionChanged" |
|||
@change="changeValue" |
|||
> |
|||
<template #label> <span v-if="requiredIfComputed" style="color: red">*</span> {{ attrs.label }} </template> |
|||
<template v-if="!props.form || (props.form && props.form.getStatus() !== 'view')" #append> |
|||
<!-- 选择位置按钮 --> |
|||
<q-btn |
|||
icon="bi-pin-angle" |
|||
size="10px" |
|||
padding="2px" |
|||
flat |
|||
square |
|||
unelevated |
|||
:title="$t('select')" |
|||
:style="{ border: '1px solid #e5e7eb', 'background-color': computedStoreBackgroundColorValue }" |
|||
> |
|||
<q-popup-proxy v-model:model-value="isShow" anchor="bottom right" self="top right" :offset="[0, 10]"> |
|||
<div class="row q-col-gutter-sm q-pa-sm" style="width: 150px"> |
|||
<div v-for="position in positionList" :key="position" class="col-4"> |
|||
<q-btn |
|||
unelevated |
|||
:title="$t(position)" |
|||
:color="positionValueRef == position ? 'primary' : ''" |
|||
:style="{ |
|||
width: '100%', |
|||
border: positionValueRef == position ? '' : '1px solid #dddddd', |
|||
}" |
|||
@click="positionChanged(position)" |
|||
></q-btn> |
|||
</div> |
|||
</div> |
|||
</q-popup-proxy> |
|||
</q-btn> |
|||
<!-- 恢复默认值按钮 --> |
|||
<q-btn |
|||
v-if="restore" |
|||
icon="bi-arrow-counterclockwise" |
|||
size="10px" |
|||
padding="2px" |
|||
flat |
|||
square |
|||
unelevated |
|||
:title="$t('restore')" |
|||
:style="{ 'margin-left': '5px', border: '1px solid #e5e7eb', color: restoreValue, 'background-color': computedStoreBackgroundColorValue }" |
|||
@click="restoreDefaultValue" |
|||
></q-btn> |
|||
</template> |
|||
</q-input> |
|||
</div> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import { ref, toRaw, computed, useAttrs, watch } from 'vue'; |
|||
import { Tools } from '@/platform'; |
|||
import { FormValidators } from '@/platform/components'; |
|||
|
|||
const attrs = useAttrs(); |
|||
const rules = attrs.rules; |
|||
const positionRef = ref(); |
|||
const props = defineProps({ |
|||
onChange: { |
|||
type: Function, |
|||
default: () => {}, |
|||
}, |
|||
modelValue: { type: String, default: '' }, |
|||
restore: { type: Boolean, default: false }, |
|||
showIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return true; |
|||
}, |
|||
}, |
|||
required: { |
|||
type: Boolean, |
|||
default: false, |
|||
}, |
|||
requiredIf: { |
|||
type: Function, |
|||
default: undefined, |
|||
}, |
|||
readOnlyIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return false; |
|||
}, |
|||
}, |
|||
disableIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return false; |
|||
}, |
|||
}, |
|||
form: { |
|||
type: Object, |
|||
default: undefined, |
|||
}, |
|||
}); |
|||
const emit = defineEmits(['update:modelValue', 'change']); |
|||
|
|||
const positionList = ['top-left', 'top', 'top-right', 'left', 'center', 'right', 'bottom-left', 'bottom', 'bottom-right']; |
|||
|
|||
const isShow = ref(false); |
|||
const positionValueRef = ref(props.modelValue || ''); |
|||
const restoreValue = toRaw(props.modelValue || ''); |
|||
|
|||
watch( |
|||
() => props.modelValue, |
|||
(newVal, oldVal) => { |
|||
positionValueRef.value = newVal; |
|||
}, |
|||
); |
|||
|
|||
const computedStoreBackgroundColorValue = computed(() => { |
|||
const color: string = restoreValue; |
|||
if (color.toLowerCase() === 'white' || color.toLowerCase() === '#ffffff' || color.toLowerCase() === '#fff') { |
|||
return '#eee'; |
|||
} |
|||
return undefined; |
|||
}); |
|||
|
|||
const rulesComputed = computed(() => { |
|||
let result = rules || <any>[]; |
|||
if (showIfComputed.value && requiredIfComputed.value) { |
|||
result.push(FormValidators.required()); |
|||
} else if (!showIfComputed.value) { |
|||
result = []; |
|||
} |
|||
if (positionRef?.value) { |
|||
positionRef.value.resetValidation(); |
|||
} |
|||
return result; |
|||
}); |
|||
|
|||
const showIfComputed = computed(() => { |
|||
return props.showIf({ |
|||
value: positionValueRef.value, |
|||
form: props.form, |
|||
}); |
|||
}); |
|||
const requiredIfComputed = computed(() => { |
|||
if (props.requiredIf) { |
|||
return ( |
|||
props.requiredIf({ |
|||
value: positionValueRef.value, |
|||
form: props.form, |
|||
}) || false |
|||
); |
|||
} else if (props.required) { |
|||
return true; |
|||
} |
|||
return false; |
|||
}); |
|||
const readonlyIfComputed = computed(() => { |
|||
if (props.form && props.form.getStatus() === 'view') { |
|||
return true; |
|||
} |
|||
return props.readOnlyIf({ |
|||
value: positionValueRef.value, |
|||
form: props.form, |
|||
}); |
|||
}); |
|||
const disableIfComputed = computed(() => { |
|||
return props.disableIf({ |
|||
value: positionValueRef.value, |
|||
form: props.form, |
|||
}); |
|||
}); |
|||
|
|||
const positionChanged = (value) => { |
|||
positionValueRef.value = value; |
|||
emit('update:modelValue', value, props.form); |
|||
isShow.value = false; |
|||
changeValue(value); |
|||
}; |
|||
|
|||
const restoreDefaultValue = () => { |
|||
positionValueRef.value = restoreValue; |
|||
emit('update:modelValue', restoreValue, props.form); |
|||
}; |
|||
const changeValue = (value) => { |
|||
emit('change', { |
|||
value: value, |
|||
form: props.form, |
|||
}); |
|||
}; |
|||
|
|||
const validate = () => { |
|||
return positionRef.value.validate(); |
|||
}; |
|||
|
|||
defineExpose({ |
|||
validate, |
|||
}); |
|||
</script> |
@ -1,7 +0,0 @@ |
|||
<template> |
|||
<div> |
|||
|
|||
</div> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
</script> |
@ -1,144 +0,0 @@ |
|||
<template> |
|||
<div v-show="showIfComputed"> |
|||
<q-select |
|||
ref="selectRef" |
|||
v-model="selectValue" |
|||
emit-value |
|||
map-options |
|||
:hide-bottom-space="true" |
|||
:hide-hint="true" |
|||
:outlined="true" |
|||
:dense="true" |
|||
v-bind="attrs" |
|||
:rules="rulesComputed" |
|||
:readonly="readonlyIfComputed" |
|||
:disable="disableIfComputed" |
|||
@update:model-value="updateModelValue" |
|||
@change="changeValue" |
|||
> |
|||
<template #label> <span v-if="requiredIfComputed" style="color: red">*</span> {{ attrs.label }}</template> |
|||
</q-select> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup lang="ts"> |
|||
import { ref, computed, useAttrs, watch } from 'vue'; |
|||
import { FormValidators } from '@/platform/components'; |
|||
|
|||
const selectRef = ref(); |
|||
const attrs = useAttrs(); |
|||
const rules = attrs.rules; |
|||
const props = defineProps({ |
|||
onChange: { |
|||
type: Function, |
|||
default: () => {}, |
|||
}, |
|||
modelValue: { type: [String, Number, Boolean, Array], default: '' }, |
|||
showIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return true; |
|||
}, |
|||
}, |
|||
required: { |
|||
type: Boolean, |
|||
default: false, |
|||
}, |
|||
requiredIf: { |
|||
type: Function, |
|||
default: undefined, |
|||
}, |
|||
readOnlyIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return false; |
|||
}, |
|||
}, |
|||
disableIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return false; |
|||
}, |
|||
}, |
|||
form: { |
|||
type: Object, |
|||
default: undefined, |
|||
}, |
|||
}); |
|||
const emit = defineEmits(['update:modelValue', 'change']); |
|||
const selectValue = ref(props.modelValue); |
|||
watch( |
|||
() => props.modelValue, |
|||
(newVal, oldVal) => { |
|||
selectValue.value = newVal; |
|||
}, |
|||
); |
|||
|
|||
const rulesComputed = computed(() => { |
|||
let result = rules || <any>[]; |
|||
if (showIfComputed.value && requiredIfComputed.value) { |
|||
result.push(FormValidators.required()); |
|||
} else if (!showIfComputed.value) { |
|||
result = []; |
|||
} |
|||
if (selectRef?.value) { |
|||
selectRef.value.resetValidation(); |
|||
} |
|||
return result; |
|||
}); |
|||
|
|||
const showIfComputed = computed(() => { |
|||
return props.showIf({ |
|||
value: selectValue.value, |
|||
form: props.form, |
|||
}); |
|||
}); |
|||
const requiredIfComputed = computed(() => { |
|||
if (props.requiredIf) { |
|||
return ( |
|||
props.requiredIf({ |
|||
value: selectValue.value, |
|||
form: props.form, |
|||
}) || false |
|||
); |
|||
} else if (props.required) { |
|||
return true; |
|||
} |
|||
return false; |
|||
}); |
|||
const readonlyIfComputed = computed(() => { |
|||
if (props.form && props.form.getStatus() === 'view') { |
|||
return true; |
|||
} |
|||
return props.readOnlyIf({ |
|||
value: selectValue.value, |
|||
form: props.form, |
|||
}); |
|||
}); |
|||
const disableIfComputed = computed(() => { |
|||
return props.disableIf({ |
|||
value: selectValue.value, |
|||
form: props.form, |
|||
}); |
|||
}); |
|||
|
|||
const updateModelValue = (value) => { |
|||
emit('update:modelValue', value, props.form); |
|||
changeValue(value); |
|||
}; |
|||
|
|||
const changeValue = (value) => { |
|||
emit('change', { |
|||
value: value, |
|||
form: props.form, |
|||
}); |
|||
}; |
|||
|
|||
const validate = () => { |
|||
return selectRef.value.validate(); |
|||
}; |
|||
|
|||
defineExpose({ |
|||
validate, |
|||
}); |
|||
</script> |
@ -1,99 +0,0 @@ |
|||
<template> |
|||
<div> |
|||
<q-input |
|||
v-show="!hideIfComputed" |
|||
ref="textRef" |
|||
:hide-bottom-space="true" |
|||
:hide-hint="true" |
|||
:outlined="true" |
|||
:dense="true" |
|||
v-bind="attrs" |
|||
type="text" |
|||
:rules="rulesComputed" |
|||
:readonly="readonlyIfComputed" |
|||
:disable="disableIfComputed" |
|||
> |
|||
<template #label> <span v-if="requiredIfComputed" style="color: red">*</span> {{ attrs.label }}</template> |
|||
</q-input> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup lang="ts"> |
|||
import { ref, computed, useAttrs } from 'vue'; |
|||
import { FormValidators } from '@/platform/components'; |
|||
|
|||
const textRef = ref(); |
|||
const attrs = useAttrs(); |
|||
const inRules = attrs.rules; |
|||
const props = defineProps({ |
|||
hideIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return false; |
|||
}, |
|||
}, |
|||
required: { |
|||
type: Boolean, |
|||
default: false, |
|||
}, |
|||
requiredIf: { |
|||
type: Function, |
|||
default: undefined, |
|||
}, |
|||
readOnlyIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return false; |
|||
}, |
|||
}, |
|||
disableIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return false; |
|||
}, |
|||
}, |
|||
form: { |
|||
type: Object, |
|||
default: undefined, |
|||
}, |
|||
}); |
|||
|
|||
const rulesComputed = computed(() => { |
|||
let rules = inRules || <any>[]; |
|||
if (!hideIfComputed.value && requiredIfComputed.value) { |
|||
rules.push(FormValidators.required()); |
|||
} else if (hideIfComputed.value) { |
|||
rules = []; |
|||
} |
|||
if (textRef?.value) { |
|||
textRef.value.resetValidation(); |
|||
} |
|||
return rules; |
|||
}); |
|||
|
|||
const hideIfComputed = computed(() => { |
|||
return props.hideIf(props.form); |
|||
}); |
|||
const requiredIfComputed = computed(() => { |
|||
if (props.requiredIf) { |
|||
return props.requiredIf(props.form) || false; |
|||
} else if (props.required) { |
|||
return true; |
|||
} |
|||
return false; |
|||
}); |
|||
const readonlyIfComputed = computed(() => { |
|||
return props.readOnlyIf(props.form); |
|||
}); |
|||
const disableIfComputed = computed(() => { |
|||
return props.disableIf(props.form); |
|||
}); |
|||
|
|||
const validate = () => { |
|||
return textRef.value.validate(); |
|||
}; |
|||
|
|||
defineExpose({ |
|||
validate, |
|||
}); |
|||
</script> |
@ -1,142 +0,0 @@ |
|||
<template> |
|||
<div v-show="showIfComputed"> |
|||
<q-input |
|||
ref="textRef" |
|||
v-model="textValue" |
|||
:hide-bottom-space="true" |
|||
:hide-hint="true" |
|||
:outlined="true" |
|||
:dense="true" |
|||
v-bind="attrs" |
|||
type="text" |
|||
:rules="rulesComputed" |
|||
:readonly="readonlyIfComputed" |
|||
:disable="disableIfComputed" |
|||
@update:model-value="updateModelValue" |
|||
@change="changeValue" |
|||
> |
|||
<template #label> <span v-if="requiredIfComputed" style="color: red">*</span> {{ attrs.label }}</template> |
|||
</q-input> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup lang="ts"> |
|||
import { ref, computed, useAttrs, watch } from 'vue'; |
|||
import { FormValidators } from '@/platform/components'; |
|||
|
|||
const textRef = ref(); |
|||
const attrs = useAttrs(); |
|||
const rules = attrs.rules; |
|||
const props = defineProps({ |
|||
onChange: { |
|||
type: Function, |
|||
default: () => {}, |
|||
}, |
|||
modelValue: { type: String, default: '' }, |
|||
showIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return true; |
|||
}, |
|||
}, |
|||
required: { |
|||
type: Boolean, |
|||
default: false, |
|||
}, |
|||
requiredIf: { |
|||
type: Function, |
|||
default: undefined, |
|||
}, |
|||
readOnlyIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return false; |
|||
}, |
|||
}, |
|||
disableIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return false; |
|||
}, |
|||
}, |
|||
form: { |
|||
type: Object, |
|||
default: undefined, |
|||
}, |
|||
}); |
|||
const emit = defineEmits(['update:modelValue', 'change']); |
|||
const textValue = ref(props.modelValue); |
|||
watch( |
|||
() => props.modelValue, |
|||
(newVal, oldVal) => { |
|||
textValue.value = newVal; |
|||
}, |
|||
); |
|||
|
|||
const rulesComputed = computed(() => { |
|||
let result = rules || <any>[]; |
|||
if (showIfComputed.value && requiredIfComputed.value) { |
|||
result.push(FormValidators.required()); |
|||
} else if (!showIfComputed.value) { |
|||
result = []; |
|||
} |
|||
if (textRef?.value) { |
|||
textRef.value.resetValidation(); |
|||
} |
|||
return result; |
|||
}); |
|||
|
|||
const showIfComputed = computed(() => { |
|||
return props.showIf({ |
|||
value: textValue.value, |
|||
form: props.form, |
|||
}); |
|||
}); |
|||
const requiredIfComputed = computed(() => { |
|||
if (props.requiredIf) { |
|||
return ( |
|||
props.requiredIf({ |
|||
value: textValue.value, |
|||
form: props.form, |
|||
}) || false |
|||
); |
|||
} else if (props.required) { |
|||
return true; |
|||
} |
|||
return false; |
|||
}); |
|||
const readonlyIfComputed = computed(() => { |
|||
if (props.form && props.form.getStatus() === 'view') { |
|||
return true; |
|||
} |
|||
return props.readOnlyIf({ |
|||
value: textValue.value, |
|||
form: props.form, |
|||
}); |
|||
}); |
|||
const disableIfComputed = computed(() => { |
|||
return props.disableIf({ |
|||
value: textValue.value, |
|||
form: props.form, |
|||
}); |
|||
}); |
|||
|
|||
const updateModelValue = (value) => { |
|||
emit('update:modelValue', value, props.form); |
|||
}; |
|||
|
|||
const changeValue = (value) => { |
|||
emit('change', { |
|||
value: value, |
|||
form: props.form, |
|||
}); |
|||
}; |
|||
|
|||
const validate = () => { |
|||
return textRef.value.validate(); |
|||
}; |
|||
|
|||
defineExpose({ |
|||
validate, |
|||
}); |
|||
</script> |
@ -1,155 +0,0 @@ |
|||
<template> |
|||
<div v-show="showIfComputed"> |
|||
<q-input |
|||
ref="textBtnRef" |
|||
v-model="textBtnValue" |
|||
:hide-bottom-space="true" |
|||
:hide-hint="true" |
|||
:outlined="true" |
|||
:dense="true" |
|||
v-bind="attrs" |
|||
type="text" |
|||
:rules="rulesComputed" |
|||
:readonly="readonlyIfComputed" |
|||
:disable="disableIfComputed" |
|||
@focus="() => {}" |
|||
@update:model-value="updateModelValue" |
|||
@change="changeValue" |
|||
> |
|||
<template #label> <span v-if="requiredIfComputed" style="color: red">*</span> {{ attrs.label }}</template> |
|||
<template v-if="attrs.button && attrs.buttonPosition === 'prepend' && (!props.form || (props.form && props.form.getStatus() !== 'view'))" #prepend> |
|||
<q-btn round dense flat v-bind="attrs.button" @click="attrs.button.click" /> |
|||
</template> |
|||
<template v-else-if="attrs.button && attrs.buttonPosition === 'before' && (!props.form || (props.form && props.form.getStatus() !== 'view'))" #before> |
|||
<q-btn round dense flat v-bind="attrs.button" @click="attrs.button.click" /> |
|||
</template> |
|||
<template v-else-if="attrs.button && attrs.buttonPosition === 'after' && (!props.form || (props.form && props.form.getStatus() !== 'view'))" #after> |
|||
<q-btn round dense flat v-bind="attrs.button" @click="attrs.button.click" /> |
|||
</template> |
|||
<template v-else-if="attrs.button && props.form && (!props.form || (props.form && props.form.getStatus() !== 'view'))" #append> |
|||
<q-btn round dense flat v-bind="attrs.button" @click="attrs.button.click" /> |
|||
</template> |
|||
</q-input> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup lang="ts"> |
|||
import { ref, computed, useAttrs, watch } from 'vue'; |
|||
import { FormValidators } from '@/platform/components'; |
|||
|
|||
const textBtnRef = ref(); |
|||
const attrs = useAttrs(); |
|||
const rules = attrs.rules; |
|||
const props = defineProps({ |
|||
onChange: { |
|||
type: Function, |
|||
default: () => {}, |
|||
}, |
|||
modelValue: { type: String, default: '' }, |
|||
showIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return true; |
|||
}, |
|||
}, |
|||
required: { |
|||
type: Boolean, |
|||
default: false, |
|||
}, |
|||
requiredIf: { |
|||
type: Function, |
|||
default: undefined, |
|||
}, |
|||
readOnlyIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return true; |
|||
}, |
|||
}, |
|||
disableIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return false; |
|||
}, |
|||
}, |
|||
form: { |
|||
type: Object, |
|||
default: undefined, |
|||
}, |
|||
}); |
|||
const emit = defineEmits(['update:modelValue', 'change']); |
|||
const textBtnValue = ref(props.modelValue); |
|||
watch( |
|||
() => props.modelValue, |
|||
(newVal, oldVal) => { |
|||
textBtnValue.value = newVal; |
|||
}, |
|||
); |
|||
|
|||
const rulesComputed = computed(() => { |
|||
let result = rules || <any>[]; |
|||
if (showIfComputed.value && requiredIfComputed.value) { |
|||
result.push(FormValidators.required()); |
|||
} else if (!showIfComputed.value) { |
|||
result = []; |
|||
} |
|||
if (textBtnRef?.value) { |
|||
textBtnRef.value.resetValidation(); |
|||
} |
|||
return result; |
|||
}); |
|||
|
|||
const showIfComputed = computed(() => { |
|||
return props.showIf({ |
|||
value: textBtnValue.value, |
|||
form: props.form, |
|||
}); |
|||
}); |
|||
const requiredIfComputed = computed(() => { |
|||
if (props.requiredIf) { |
|||
return ( |
|||
props.requiredIf({ |
|||
value: textBtnValue.value, |
|||
form: props.form, |
|||
}) || false |
|||
); |
|||
} else if (props.required) { |
|||
return true; |
|||
} |
|||
return false; |
|||
}); |
|||
const readonlyIfComputed = computed(() => { |
|||
if (props.form && props.form.getStatus() === 'view') { |
|||
return true; |
|||
} |
|||
return props.readOnlyIf({ |
|||
value: textBtnValue.value, |
|||
form: props.form, |
|||
}); |
|||
}); |
|||
const disableIfComputed = computed(() => { |
|||
return props.disableIf({ |
|||
value: textBtnValue.value, |
|||
form: props.form, |
|||
}); |
|||
}); |
|||
|
|||
const updateModelValue = (value) => { |
|||
emit('update:modelValue', value, props.form); |
|||
}; |
|||
|
|||
const changeValue = (value) => { |
|||
emit('change', { |
|||
value: value, |
|||
form: props.form, |
|||
}); |
|||
}; |
|||
|
|||
const validate = () => { |
|||
return textBtnRef.value.validate(); |
|||
}; |
|||
|
|||
defineExpose({ |
|||
validate, |
|||
}); |
|||
</script> |
@ -1,142 +0,0 @@ |
|||
<template> |
|||
<div v-show="showIfComputed"> |
|||
<q-input |
|||
ref="textareaRef" |
|||
v-model="textareaValue" |
|||
:hide-bottom-space="true" |
|||
:hide-hint="true" |
|||
:outlined="true" |
|||
:dense="true" |
|||
v-bind="attrs" |
|||
type="textarea" |
|||
:rules="rulesComputed" |
|||
:readonly="readonlyIfComputed" |
|||
:disable="disableIfComputed" |
|||
@update:model-value="updateModelValue" |
|||
@change="changeValue" |
|||
> |
|||
<template #label> <span v-if="requiredIfComputed" style="color: red">*</span> {{ attrs.label }}</template> |
|||
</q-input> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup lang="ts"> |
|||
import { ref, computed, useAttrs, watch } from 'vue'; |
|||
import { FormValidators } from '@/platform/components'; |
|||
|
|||
const textareaRef = ref(); |
|||
const attrs = useAttrs(); |
|||
const rules = attrs.rules; |
|||
const props = defineProps({ |
|||
onChange: { |
|||
type: Function, |
|||
default: () => {}, |
|||
}, |
|||
modelValue: { type: String, default: '' }, |
|||
showIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return true; |
|||
}, |
|||
}, |
|||
required: { |
|||
type: Boolean, |
|||
default: false, |
|||
}, |
|||
requiredIf: { |
|||
type: Function, |
|||
default: undefined, |
|||
}, |
|||
readOnlyIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return false; |
|||
}, |
|||
}, |
|||
disableIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return false; |
|||
}, |
|||
}, |
|||
form: { |
|||
type: Object, |
|||
default: undefined, |
|||
}, |
|||
}); |
|||
const emit = defineEmits(['update:modelValue', 'change']); |
|||
const textareaValue = ref(props.modelValue); |
|||
watch( |
|||
() => props.modelValue, |
|||
(newVal, oldVal) => { |
|||
textareaValue.value = newVal; |
|||
}, |
|||
); |
|||
|
|||
const rulesComputed = computed(() => { |
|||
let result = rules || <any>[]; |
|||
if (showIfComputed.value && requiredIfComputed.value) { |
|||
result.push(FormValidators.required()); |
|||
} else if (!showIfComputed.value) { |
|||
result = []; |
|||
} |
|||
if (textareaRef?.value) { |
|||
textareaRef.value.resetValidation(); |
|||
} |
|||
return result; |
|||
}); |
|||
|
|||
const showIfComputed = computed(() => { |
|||
return props.showIf({ |
|||
value: textareaValue.value, |
|||
form: props.form, |
|||
}); |
|||
}); |
|||
const requiredIfComputed = computed(() => { |
|||
if (props.requiredIf) { |
|||
return ( |
|||
props.requiredIf({ |
|||
value: textareaValue.value, |
|||
form: props.form, |
|||
}) || false |
|||
); |
|||
} else if (props.required) { |
|||
return true; |
|||
} |
|||
return false; |
|||
}); |
|||
const readonlyIfComputed = computed(() => { |
|||
if (props.form && props.form.getStatus() === 'view') { |
|||
return true; |
|||
} |
|||
return props.readOnlyIf({ |
|||
value: textareaValue.value, |
|||
form: props.form, |
|||
}); |
|||
}); |
|||
const disableIfComputed = computed(() => { |
|||
return props.disableIf({ |
|||
value: textareaValue.value, |
|||
form: props.form, |
|||
}); |
|||
}); |
|||
|
|||
const updateModelValue = (value) => { |
|||
emit('update:modelValue', value, props.form); |
|||
}; |
|||
|
|||
const changeValue = (value) => { |
|||
emit('change', { |
|||
value: value, |
|||
form: props.form, |
|||
}); |
|||
}; |
|||
|
|||
const validate = () => { |
|||
return textareaRef.value.validate(); |
|||
}; |
|||
|
|||
defineExpose({ |
|||
validate, |
|||
}); |
|||
</script> |
@ -1,154 +0,0 @@ |
|||
<template> |
|||
<div v-show="showIfComputed"> |
|||
<q-select |
|||
ref="selectRef" |
|||
v-model="selectValue" |
|||
emit-value |
|||
map-options |
|||
:hide-bottom-space="true" |
|||
:hide-hint="true" |
|||
:outlined="true" |
|||
:dense="true" |
|||
v-bind="attrs" |
|||
:rules="rulesComputed" |
|||
:readonly="readonlyIfComputed" |
|||
:disable="disableIfComputed" |
|||
@update:model-value="updateModelValue" |
|||
@change="changeValue" |
|||
> |
|||
<template #label> <span v-if="requiredIfComputed" style="color: red">*</span> {{ attrs.label }}</template> |
|||
<template #option="scope"> |
|||
<q-item v-bind="scope.itemProps"> |
|||
<q-item-section avatar style="width: 30px"> |
|||
<q-icon name="folder" color="amber" /> |
|||
</q-item-section> |
|||
<q-item-section> |
|||
<q-item-label>{{ scope.opt.label }}</q-item-label> |
|||
</q-item-section> |
|||
</q-item> |
|||
</template> |
|||
</q-select> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup lang="ts"> |
|||
import { ref, computed, useAttrs, watch } from 'vue'; |
|||
import { FormValidators } from '@/platform/components'; |
|||
|
|||
const selectRef = ref(); |
|||
const attrs = useAttrs(); |
|||
const rules = attrs.rules; |
|||
const props = defineProps({ |
|||
onChange: { |
|||
type: Function, |
|||
default: () => {}, |
|||
}, |
|||
modelValue: { type: [String, Number, Boolean, Array], default: '' }, |
|||
showIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return true; |
|||
}, |
|||
}, |
|||
required: { |
|||
type: Boolean, |
|||
default: false, |
|||
}, |
|||
requiredIf: { |
|||
type: Function, |
|||
default: undefined, |
|||
}, |
|||
readOnlyIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return false; |
|||
}, |
|||
}, |
|||
disableIf: { |
|||
type: Function, |
|||
default: () => { |
|||
return false; |
|||
}, |
|||
}, |
|||
form: { |
|||
type: Object, |
|||
default: undefined, |
|||
}, |
|||
}); |
|||
const emit = defineEmits(['update:modelValue', 'change']); |
|||
const selectValue = ref(props.modelValue); |
|||
watch( |
|||
() => props.modelValue, |
|||
(newVal, oldVal) => { |
|||
selectValue.value = newVal; |
|||
}, |
|||
); |
|||
|
|||
const rulesComputed = computed(() => { |
|||
let result = rules || <any>[]; |
|||
if (showIfComputed.value && requiredIfComputed.value) { |
|||
result.push(FormValidators.required()); |
|||
} else if (!showIfComputed.value) { |
|||
result = []; |
|||
} |
|||
if (selectRef?.value) { |
|||
selectRef.value.resetValidation(); |
|||
} |
|||
return result; |
|||
}); |
|||
|
|||
const showIfComputed = computed(() => { |
|||
return props.showIf({ |
|||
value: selectValue.value, |
|||
form: props.form, |
|||
}); |
|||
}); |
|||
const requiredIfComputed = computed(() => { |
|||
if (props.requiredIf) { |
|||
return ( |
|||
props.requiredIf({ |
|||
value: selectValue.value, |
|||
form: props.form, |
|||
}) || false |
|||
); |
|||
} else if (props.required) { |
|||
return true; |
|||
} |
|||
return false; |
|||
}); |
|||
const readonlyIfComputed = computed(() => { |
|||
if (props.form && props.form.getStatus() === 'view') { |
|||
return true; |
|||
} |
|||
return props.readOnlyIf({ |
|||
value: selectValue.value, |
|||
form: props.form, |
|||
}); |
|||
}); |
|||
const disableIfComputed = computed(() => { |
|||
return props.disableIf({ |
|||
value: selectValue.value, |
|||
form: props.form, |
|||
}); |
|||
}); |
|||
|
|||
const updateModelValue = (value) => { |
|||
emit('update:modelValue', value, props.form); |
|||
changeValue(value); |
|||
}; |
|||
|
|||
const changeValue = (value) => { |
|||
emit('change', { |
|||
value: value, |
|||
form: props.form, |
|||
}); |
|||
}; |
|||
|
|||
const validate = () => { |
|||
return selectRef.value.validate(); |
|||
}; |
|||
|
|||
defineExpose({ |
|||
validate, |
|||
}); |
|||
</script> |
File diff suppressed because it is too large
@ -0,0 +1,7 @@ |
|||
<template><span v-if="props.required" style="color: red">*</span> {{ props.label }}</template> |
|||
<script setup lang="ts"> |
|||
const props = defineProps({ |
|||
required: { type: Boolean, default: false }, |
|||
label: { type: String, default: '' }, |
|||
}); |
|||
</script> |
@ -0,0 +1,75 @@ |
|||
<template> |
|||
<div v-show="FieldMethods.getShow(props, modelValue)"> |
|||
<q-input |
|||
ref="numberRef" |
|||
v-model="modelValue" |
|||
:hide-bottom-space="true" |
|||
:hide-hint="true" |
|||
:outlined="true" |
|||
:dense="true" |
|||
v-bind="attrs" |
|||
type="number" |
|||
title="" |
|||
:rules="FieldMethods.getRules(props, modelValue, numberRef, [FormValidators.maxPrecision(props.precision)])" |
|||
:readonly="FieldMethods.getReadOnly(props, modelValue)" |
|||
:disable="FieldMethods.getDisable(props, modelValue)" |
|||
@update:model-value="fieldMethodsClass.updateValue" |
|||
> |
|||
<template #label><w-label :required="FieldMethods.getRequired(props, modelValue)" :label="attrs.label"></w-label></template> |
|||
</q-input> |
|||
</div> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import { ref, useAttrs } from 'vue'; |
|||
import { FormValidators } from '@/platform/components'; |
|||
import { FormFieldProps } from '@/platform/components/form/FormField.ts'; |
|||
import { FormFieldMethods } from '../form/FormField'; |
|||
|
|||
const numberRef = ref(); |
|||
const attrs = useAttrs(); |
|||
const modelValue = defineModel<number>(); |
|||
|
|||
interface FieldProps extends FormFieldProps { |
|||
// 继承FieldProps接口,可以将公共的props属性继承下来,defineProps尖括号的泛型只能是接口,不能为类 |
|||
precision?: number; |
|||
} |
|||
const props = withDefaults(defineProps<FieldProps>(), { precision: 0, showIf: true }); // 使用withDefaults设置属性默认值 |
|||
class FieldMethods extends FormFieldMethods { |
|||
// 继承FieldMethods抽象类,该类中包含必须实现的抽象方法并提供了一些获取计算后的是否必填,是否显示等静态方法 |
|||
updateValue = (value_) => { |
|||
const floatValue = parseFloat(value_); |
|||
if (!isNaN(floatValue)) { |
|||
modelValue.value = floatValue; |
|||
if (props['onUpdateValue']) { |
|||
props['onUpdateValue']({ |
|||
value: floatValue, |
|||
form: props['form'], |
|||
}); |
|||
} |
|||
} else { |
|||
modelValue.value = undefined; |
|||
} |
|||
}; |
|||
validate = () => { |
|||
return numberRef.value.validate(); |
|||
}; |
|||
setValue = (value_) => { |
|||
modelValue.value = value_; |
|||
}; |
|||
getValue = () => { |
|||
return modelValue.value; |
|||
}; |
|||
clearValue = () => { |
|||
modelValue.value = undefined; |
|||
}; |
|||
} |
|||
const fieldMethodsClass = new FieldMethods(); |
|||
|
|||
// 暴露该组件的以下方法 |
|||
defineExpose({ |
|||
validate: fieldMethodsClass.validate, |
|||
setValue: fieldMethodsClass.setValue, |
|||
getValue: fieldMethodsClass.getValue, |
|||
clearValue: fieldMethodsClass.clearValue, |
|||
}); |
|||
</script> |
@ -0,0 +1,66 @@ |
|||
<template> |
|||
<div v-show="FieldMethods.getShow(props, modelValue)"> |
|||
<q-input |
|||
ref="pwdRef" |
|||
v-model="modelValue" |
|||
:hide-bottom-space="true" |
|||
:hide-hint="true" |
|||
:outlined="true" |
|||
:dense="true" |
|||
v-bind="attrs" |
|||
type="password" |
|||
autocomplete="off" |
|||
:rules="FieldMethods.getRules(props, modelValue, pwdRef, undefined)" |
|||
::readonly="FieldMethods.getReadOnly(props, modelValue)" |
|||
:disable="FieldMethods.getDisable(props, modelValue)" |
|||
@update:model-value="fieldMethodsClass.updateValue" |
|||
> |
|||
<template #label><w-label :required="FieldMethods.getRequired(props, modelValue)" :label="attrs.label"></w-label></template> |
|||
</q-input> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup lang="ts"> |
|||
import { ref, useAttrs } from 'vue'; |
|||
import { FormFieldProps } from '@/platform/components/form/FormField.ts'; |
|||
import { FormFieldMethods } from '../form/FormField'; |
|||
|
|||
const pwdRef = ref(); |
|||
const attrs = useAttrs(); |
|||
const modelValue = defineModel<string>(); |
|||
|
|||
interface FieldProps extends FormFieldProps {} |
|||
const props = withDefaults(defineProps<FieldProps>(), { |
|||
showIf: true, |
|||
}); |
|||
class FieldMethods extends FormFieldMethods { |
|||
updateValue = (value_) => { |
|||
if (props['onUpdateValue']) { |
|||
props['onUpdateValue']({ |
|||
value: value_, |
|||
form: props['form'], |
|||
}); |
|||
} |
|||
}; |
|||
validate = () => { |
|||
return pwdRef.value.validate(); |
|||
}; |
|||
setValue = (value_) => { |
|||
modelValue.value = value_; |
|||
}; |
|||
getValue = () => { |
|||
return modelValue.value; |
|||
}; |
|||
clearValue = () => { |
|||
modelValue.value = undefined; |
|||
}; |
|||
} |
|||
const fieldMethodsClass = new FieldMethods(); |
|||
|
|||
defineExpose({ |
|||
validate: fieldMethodsClass.validate, |
|||
setValue: fieldMethodsClass.setValue, |
|||
getValue: fieldMethodsClass.getValue, |
|||
clearValue: fieldMethodsClass.clearValue, |
|||
}); |
|||
</script> |
@ -0,0 +1,141 @@ |
|||
<template> |
|||
<div v-show="FieldMethods.getShow(props, modelValue)"> |
|||
<q-input |
|||
ref="positionRef" |
|||
v-model="modelValue" |
|||
:hide-bottom-space="true" |
|||
:hide-hint="true" |
|||
:outlined="true" |
|||
:dense="true" |
|||
v-bind="attrs" |
|||
:rules="FieldMethods.getRules(props, modelValue, positionRef, undefined)" |
|||
:readonly="FieldMethods.getReadOnly(props, modelValue)" |
|||
:disable="FieldMethods.getDisable(props, modelValue)" |
|||
@update:model-value="fieldMethodsClass.updateValue" |
|||
> |
|||
<template #label><w-label :required="FieldMethods.getRequired(props, modelValue)" :label="attrs.label"></w-label></template> |
|||
<template v-if="!props['form'] || (props['form'] && props['form'].getStatus() !== 'view')" #append> |
|||
<!-- 选择位置按钮 --> |
|||
<q-btn |
|||
icon="bi-pin-angle" |
|||
size="10px" |
|||
padding="2px" |
|||
flat |
|||
square |
|||
unelevated |
|||
:title="$t('select')" |
|||
:style="{ border: '1px solid #e5e7eb', 'background-color': computedStoreBackgroundColorValue }" |
|||
> |
|||
<q-popup-proxy v-model:model-value="isShow" anchor="bottom right" self="top right" :offset="[0, 10]"> |
|||
<div class="row q-col-gutter-sm q-pa-sm" style="width: 150px"> |
|||
<div v-for="position in positionList" :key="position" class="col-4"> |
|||
<q-btn |
|||
unelevated |
|||
:title="$t(position)" |
|||
:color="modelValue == position ? 'primary' : ''" |
|||
:style="{ |
|||
width: '100%', |
|||
border: modelValue == position ? '' : '1px solid #dddddd', |
|||
}" |
|||
@click="fieldMethodsClass.updateValue(position)" |
|||
></q-btn> |
|||
</div> |
|||
</div> |
|||
</q-popup-proxy> |
|||
</q-btn> |
|||
<!-- 恢复默认值按钮 --> |
|||
<q-btn |
|||
v-if="restore" |
|||
icon="bi-arrow-counterclockwise" |
|||
size="10px" |
|||
padding="2px" |
|||
flat |
|||
square |
|||
unelevated |
|||
:title="$t('restore')" |
|||
:style="{ 'margin-left': '5px', border: '1px solid #e5e7eb', color: restoreValue, 'background-color': computedStoreBackgroundColorValue }" |
|||
@click="restoreDefaultValue" |
|||
></q-btn> |
|||
</template> |
|||
</q-input> |
|||
</div> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import { ref, toRaw, computed, useAttrs, onBeforeMount } from 'vue'; |
|||
import { Tools } from '@/platform'; |
|||
import { FormFieldProps } from '@/platform/components/form/FormField.ts'; |
|||
import { FormFieldMethods } from '../form/FormField'; |
|||
|
|||
const positionRef = ref(); |
|||
const attrs = useAttrs(); |
|||
const modelValue = defineModel<string>(); |
|||
|
|||
const positionList = ['top-left', 'top', 'top-right', 'left', 'center', 'right', 'bottom-left', 'bottom', 'bottom-right']; |
|||
const isShow = ref(false); |
|||
const defaultValue = 'center'; |
|||
const restoreValue = toRaw(modelValue.value || defaultValue); |
|||
|
|||
interface FieldProps extends FormFieldProps { |
|||
restore?: boolean; |
|||
} |
|||
const props = withDefaults(defineProps<FieldProps>(), { |
|||
showIf: true, |
|||
restore: false, |
|||
}); |
|||
class FieldMethods extends FormFieldMethods { |
|||
updateValue = (value_) => { |
|||
isShow.value = false; |
|||
modelValue.value = value_; |
|||
if (props['onUpdateValue']) { |
|||
props['onUpdateValue']({ |
|||
value: value_, |
|||
form: props['form'], |
|||
}); |
|||
} |
|||
}; |
|||
validate = () => { |
|||
return positionRef.value.validate(); |
|||
}; |
|||
setValue = (value_) => { |
|||
modelValue.value = value_; |
|||
}; |
|||
getValue = () => { |
|||
return modelValue.value; |
|||
}; |
|||
clearValue = () => { |
|||
modelValue.value = restoreValue; |
|||
}; |
|||
} |
|||
const fieldMethodsClass = new FieldMethods(); |
|||
|
|||
const computedStoreBackgroundColorValue = computed(() => { |
|||
const color: string = restoreValue; |
|||
if (color.toLowerCase() === 'white' || color.toLowerCase() === '#ffffff' || color.toLowerCase() === '#fff') { |
|||
return '#eee'; |
|||
} |
|||
return undefined; |
|||
}); |
|||
|
|||
const restoreDefaultValue = () => { |
|||
modelValue.value = restoreValue; |
|||
if (props['onUpdateValue']) { |
|||
props['onUpdateValue']({ |
|||
value: restoreValue, |
|||
form: props['form'], |
|||
}); |
|||
} |
|||
}; |
|||
|
|||
onBeforeMount(() => { |
|||
if (Tools.isEmpty(modelValue.value)) { |
|||
modelValue.value = defaultValue; |
|||
} |
|||
}); |
|||
|
|||
defineExpose({ |
|||
validate: fieldMethodsClass.validate, |
|||
setValue: fieldMethodsClass.setValue, |
|||
getValue: fieldMethodsClass.getValue, |
|||
clearValue: fieldMethodsClass.clearValue, |
|||
}); |
|||
</script> |
@ -0,0 +1,119 @@ |
|||
<template> |
|||
<div v-show="FieldMethods.getShow(props, modelValue)" :class="props.simple ? 'w-radio' : ''"> |
|||
<q-field |
|||
ref="radioRef" |
|||
v-model="modelValue" |
|||
:hide-bottom-space="true" |
|||
:hide-hint="true" |
|||
v-bind="attrs" |
|||
:outlined="props.outlined" |
|||
:borderless="!props.outlined" |
|||
:stack-label="true" |
|||
:dense="true" |
|||
:clearable="false" |
|||
:rules="FieldMethods.getRules(props, modelValue, radioRef, undefined)" |
|||
:readonly="FieldMethods.getReadOnly(props, modelValue)" |
|||
:disable="FieldMethods.getDisable(props, modelValue)" |
|||
@update:model-value="fieldMethodsClass.updateValue" |
|||
> |
|||
<template #label><w-label :required="FieldMethods.getRequired(props, modelValue)" :label="attrs.label"></w-label></template> |
|||
<template v-if="!props.simple && !Tools.isEmpty(modelValue) && props.clearable" #append> |
|||
<q-btn flat square unelevated dense icon="cancel" @click="fieldMethodsClass.clearValue"></q-btn> |
|||
</template> |
|||
<template v-else-if="!props.simple" #control> |
|||
<div class="pt-[5px]"> |
|||
<q-option-group |
|||
v-model="modelValue" |
|||
:dense="props.dense" |
|||
:options="props.options" |
|||
:inline="props.inline" |
|||
:readonly="FieldMethods.getReadOnly(props, modelValue)" |
|||
:disable="FieldMethods.getDisable(props, modelValue)" |
|||
/> |
|||
</div> |
|||
</template> |
|||
<template v-else #append> |
|||
<q-option-group |
|||
v-model="modelValue" |
|||
:dense="props.dense" |
|||
:options="props.options" |
|||
:inline="props.inline" |
|||
:readonly="FieldMethods.getReadOnly(props, modelValue)" |
|||
:disable="FieldMethods.getDisable(props, modelValue)" |
|||
/> |
|||
<q-btn v-if="!Tools.isEmpty(modelValue) && props.clearable" flat square unelevated dense icon="cancel" @click="fieldMethodsClass.clearValue"></q-btn> |
|||
</template> |
|||
</q-field> |
|||
</div> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import { ref, useAttrs } from 'vue'; |
|||
import { Tools } from '@/platform'; |
|||
import { FormFieldProps } from '@/platform/components/form/FormField.ts'; |
|||
import { FormFieldMethods } from '../form/FormField'; |
|||
|
|||
const radioRef = ref(); |
|||
const attrs = useAttrs(); |
|||
const modelValue = defineModel<string | boolean | number>(); |
|||
|
|||
interface FieldProps extends FormFieldProps { |
|||
clearable?: boolean; |
|||
dense?: boolean; |
|||
inline?: boolean; |
|||
outlined?: boolean; |
|||
borderless?: boolean; |
|||
simple?: boolean; // 是否简单选项的单选按钮,默认为是,将label与选项放在同一行,选项过多时使用该模式会导致很难看 |
|||
options: Array<() => void>; |
|||
} |
|||
const props = withDefaults(defineProps<FieldProps>(), { |
|||
showIf: true, |
|||
clearable: true, |
|||
dense: true, |
|||
inline: true, |
|||
outlined: true, |
|||
simple: true, |
|||
options: () => { |
|||
return []; |
|||
}, |
|||
}); |
|||
class FieldMethods extends FormFieldMethods { |
|||
updateValue = (value_) => { |
|||
if (props['onUpdateValue']) { |
|||
props['onUpdateValue']({ |
|||
value: value_, |
|||
form: props['form'], |
|||
}); |
|||
} |
|||
}; |
|||
validate = () => { |
|||
return radioRef.value.validate(); |
|||
}; |
|||
setValue = (value_) => { |
|||
modelValue.value = value_; |
|||
}; |
|||
getValue = () => { |
|||
return modelValue.value; |
|||
}; |
|||
clearValue = () => { |
|||
modelValue.value = undefined; |
|||
}; |
|||
} |
|||
const fieldMethodsClass = new FieldMethods(); |
|||
|
|||
defineExpose({ |
|||
validate: fieldMethodsClass.validate, |
|||
setValue: fieldMethodsClass.setValue, |
|||
getValue: fieldMethodsClass.getValue, |
|||
clearValue: fieldMethodsClass.clearValue, |
|||
}); |
|||
</script> |
|||
|
|||
<style lang="css"> |
|||
.w-radio .q-field--dense .q-field__label { |
|||
font-size: 18px; |
|||
top: 18px; |
|||
} |
|||
.w-radio .q-field__marginal { |
|||
font-size: 16px; |
|||
} |
|||
</style> |
@ -0,0 +1,272 @@ |
|||
<template> |
|||
<div v-show="FieldMethods.getShow(props, modelValue)"> |
|||
<q-input |
|||
ref="textSelectRef" |
|||
v-model="displayValueComputed" |
|||
:hide-bottom-space="true" |
|||
:hide-hint="true" |
|||
:outlined="true" |
|||
:dense="true" |
|||
:autogrow="true" |
|||
v-bind="attrs" |
|||
:bottom-slots="counter" |
|||
type="text" |
|||
:rules="FieldMethods.getRules(props, { value: modelValue, displayValue: displayValueComputed }, textSelectRef, undefined)" |
|||
:readonly="FieldMethods.getReadOnly(props, { value: modelValue, displayValue: displayValueComputed })" |
|||
:disable="FieldMethods.getDisable(props, { value: modelValue, displayValue: displayValueComputed })" |
|||
:clearable="false" |
|||
@update:model-value="fieldMethodsClass.updateValue" |
|||
@focus=" |
|||
() => { |
|||
textSelectRef?.blur(); |
|||
} |
|||
" |
|||
> |
|||
<!-- label --> |
|||
<template #label><w-label :required="FieldMethods.getRequired(props, modelValue)" :label="attrs.label"></w-label></template> |
|||
|
|||
<template v-if="!props['form'] || (props['form'] && props['form'].getStatus() !== 'view')" #append> |
|||
<q-btn v-if="!Tools.isEmpty(displayValueComputed)" flat square unelevated dense icon="cancel" @click="fieldMethodsClass.clearValue"></q-btn> |
|||
<q-btn flat square unelevated dense icon="manage_search"> |
|||
<q-popup-proxy v-model:model-value="isShow" anchor="bottom right" self="top right" :offset="[0, 10]"> |
|||
<div style="width: 700px; height: 300px"> |
|||
<w-grid |
|||
ref="gridRef" |
|||
v-bind="props.grid" |
|||
db-click-operation="none" |
|||
:checkbox-selection="props.multiple || false" |
|||
:dense="true" |
|||
:config-button="false" |
|||
:ticked-record="{ |
|||
columnName: valueUseColumnName, |
|||
data: typeof modelValue === 'string' ? [modelValue] : modelValue, |
|||
}" |
|||
@row-click="rowClick" |
|||
@update-ticked="updateTicked" |
|||
@update-tickeds="updateTickeds" |
|||
> |
|||
</w-grid> |
|||
</div> |
|||
</q-popup-proxy> |
|||
</q-btn> |
|||
</template> |
|||
<template v-if="counter" #counter> |
|||
<div>{{ modelValue?.length }}</div> |
|||
</template> |
|||
</q-input> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup lang="ts"> |
|||
import { ref, computed, useAttrs, onBeforeMount, toRaw } from 'vue'; |
|||
import { Tools, axios } from '@/platform'; |
|||
import { FormFieldProps } from '@/platform/components/form/FormField.ts'; |
|||
import { FormFieldMethods } from '../form/FormField'; |
|||
|
|||
const textSelectRef = ref(); |
|||
const attrs = useAttrs(); |
|||
const modelValue = defineModel<string | Array<string>>(); |
|||
const modelObjectValue = ref(<any>[]); // 模型值包含实际值与显示值的对象集合。 |
|||
const gridRef = ref(); |
|||
|
|||
const isShow = ref(false); |
|||
|
|||
interface FieldProps extends FormFieldProps { |
|||
multiple?: boolean; |
|||
counter?: boolean; |
|||
displayValue: string | ((args: object) => ''); |
|||
grid: object; // 表格配置项 |
|||
} |
|||
const props = withDefaults(defineProps<FieldProps>(), { |
|||
showIf: true, |
|||
multiple: false, // 是否允许多选,多选模式下模型绑定值必须为数组 |
|||
counter: false, // 显示右下角计数器 |
|||
/** |
|||
* 显示值配置,必须传入,可使用配置: |
|||
* 列名:填写列名 |
|||
* 自定义函数:自己定义显示的内容,组件会将用户数据传到函数中,函数必须返回一个字符串,示例: |
|||
* displayValue: (args) => { |
|||
* return args['data']['name'] + '_' + args['data']['code']; |
|||
* } |
|||
*/ |
|||
displayValue: '', |
|||
}); |
|||
class FieldMethods extends FormFieldMethods { |
|||
// 组件值改变事件调用的方法 |
|||
updateValue = (value_) => { |
|||
if (props['onUpdateValue']) { |
|||
props['onUpdateValue']({ |
|||
value: value_, |
|||
displayValue: displayValueComputed.value, |
|||
form: props['form'], |
|||
}); |
|||
} |
|||
}; |
|||
// 组件验证方法 |
|||
validate = () => { |
|||
return textSelectRef.value.validate(); |
|||
}; |
|||
|
|||
// 组件设置值 |
|||
setValue = (value) => { |
|||
if (props.multiple && Array.isArray(value) && Array.isArray(modelValue.value)) { |
|||
fieldMethodsClass.clearValue(); |
|||
modelValue.value.push(...value); |
|||
setObjectValueByValue(value); |
|||
} else if (!props.multiple && !Array.isArray(value)) { |
|||
modelValue.value = value; |
|||
setObjectValueByValue(value); |
|||
} else { |
|||
console.info('error========模型值不匹配'); |
|||
} |
|||
}; |
|||
// 获取组件值 |
|||
getValue = () => { |
|||
return modelValue.value; |
|||
}; |
|||
// 获取组件包含实际与显示值的对象 |
|||
getObjectValue = () => { |
|||
return modelObjectValue.value; |
|||
}; |
|||
// 组件清空值 |
|||
clearValue = () => { |
|||
if (props.multiple && Array.isArray(modelValue.value)) { |
|||
modelValue.value.splice(0, modelValue.value.length); |
|||
} else { |
|||
modelValue.value = undefined; |
|||
} |
|||
fieldMethodsClass.clearObjectValue(); |
|||
}; |
|||
// 清空显示值 |
|||
clearObjectValue = () => { |
|||
modelObjectValue.value.splice(0, modelObjectValue.value.length); |
|||
}; |
|||
} |
|||
const fieldMethodsClass = new FieldMethods(); |
|||
const valueUseColumnName = props.grid['primaryKey'] || 'id'; |
|||
|
|||
const displayValueComputed = computed(() => { |
|||
let result = ''; |
|||
if (modelObjectValue.value.length > 0) { |
|||
modelObjectValue.value.forEach((item) => { |
|||
result = result + ',' + item['displayValue']; |
|||
}); |
|||
result = result.substring(1, result.length); |
|||
} |
|||
return result; |
|||
}); |
|||
|
|||
// 获取最终显示在页面上的显示值 |
|||
const getActualDisplayValue = (row) => { |
|||
if (!Tools.isEmpty(props.displayValue) && typeof props.displayValue === 'function') { |
|||
return props.displayValue({ |
|||
data: toRaw(row), |
|||
grid: gridRef.value, |
|||
}); |
|||
} else if (!Tools.isEmpty(props.displayValue) && typeof props.displayValue === 'string') { |
|||
return row[props.displayValue]; |
|||
} |
|||
return ''; |
|||
}; |
|||
|
|||
// 修改列头checkbox的状态事件 |
|||
const updateTickeds = (args) => { |
|||
fieldMethodsClass.clearValue(); |
|||
if (args.value && Array.isArray(modelValue.value)) { |
|||
const rows = gridRef.value.getRows(); |
|||
rows.forEach((item) => { |
|||
modelValue.value.push(item[valueUseColumnName]); |
|||
modelObjectValue.value.push({ value: item[valueUseColumnName], displayValue: getActualDisplayValue(item) }); |
|||
}); |
|||
} |
|||
}; |
|||
// 修改行数据checkbox的状态事件 |
|||
const updateTicked = (args) => { |
|||
if (Array.isArray(modelValue.value)) { |
|||
if (props.grid['tree']) { |
|||
fieldMethodsClass.clearValue(); |
|||
|
|||
const rows = gridRef.value.getTickedRows(); |
|||
if (rows?.length > 0) { |
|||
rows.forEach((item) => { |
|||
modelValue.value.push(item[valueUseColumnName]); |
|||
modelObjectValue.value.push({ value: item[valueUseColumnName], displayValue: getActualDisplayValue(item) }); |
|||
}); |
|||
} |
|||
} else { |
|||
const index = modelValue.value.findIndex((item) => { |
|||
return item === args.row[valueUseColumnName]; |
|||
}); |
|||
if (args.row['ticked']) { |
|||
if (index < 0) { |
|||
modelValue.value.push(args.row[valueUseColumnName]); |
|||
modelObjectValue.value.push({ value: args.row[valueUseColumnName], displayValue: getActualDisplayValue(args.row) }); |
|||
} |
|||
} else { |
|||
modelValue.value.splice(index, 1); |
|||
modelObjectValue.value.splice(index, 1); |
|||
} |
|||
} |
|||
} |
|||
}; |
|||
const rowClick = (args) => { |
|||
const modelValue_ = args.row[valueUseColumnName]; |
|||
if (props.multiple && Array.isArray(modelValue.value)) { |
|||
fieldMethodsClass.clearValue(); |
|||
modelValue.value.push(modelValue_); |
|||
modelObjectValue.value.push({ value: modelValue_, displayValue: getActualDisplayValue(args.row) }); |
|||
} else if (!props.multiple) { |
|||
fieldMethodsClass.clearValue(); |
|||
modelValue.value = modelValue_; |
|||
modelObjectValue.value.push({ value: modelValue_, displayValue: getActualDisplayValue(args.row) }); |
|||
} else { |
|||
console.info('error========模型值不匹配'); |
|||
} |
|||
isShow.value = false; |
|||
}; |
|||
|
|||
// 根据实际值设置显示值 |
|||
const setObjectValueByValue = async (value) => { |
|||
if ((Array.isArray(value) && value.length > 0) || (typeof value === 'string' && !Tools.isEmpty(value))) { |
|||
const urlSearchParams = new URLSearchParams(); |
|||
urlSearchParams.append( |
|||
'criteria', |
|||
JSON.stringify({ |
|||
fieldName: valueUseColumnName, |
|||
operator: 'inSet', |
|||
value: Array.isArray(value) ? value : [value], |
|||
}), |
|||
); |
|||
const resp = await axios.get(props.grid['fetchDataUrl'] || props.grid['dataUrl'], { params: urlSearchParams }).catch((error) => { |
|||
console.info('error-------------', error); |
|||
}); |
|||
if (resp && resp.data) { |
|||
const responseData = resp.data; |
|||
if (Array.isArray(responseData) && responseData.length > 0) { |
|||
fieldMethodsClass.clearObjectValue(); |
|||
responseData.forEach((item) => { |
|||
modelObjectValue.value.push({ value: item[valueUseColumnName], displayValue: getActualDisplayValue(item) }); |
|||
}); |
|||
} else if (typeof responseData === 'object' && responseData.content?.length > 0) { |
|||
fieldMethodsClass.clearObjectValue(); |
|||
responseData.content.forEach((item) => { |
|||
modelObjectValue.value.push({ value: item[valueUseColumnName], displayValue: getActualDisplayValue(item) }); |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
}; |
|||
|
|||
onBeforeMount(() => { |
|||
// 组件挂载完成后如果存在值,需要根据值查询后台数据,并设置显示值 |
|||
setObjectValueByValue(modelValue.value); |
|||
}); |
|||
|
|||
defineExpose({ |
|||
validate: fieldMethodsClass.validate, |
|||
setValue: fieldMethodsClass.setValue, |
|||
getValue: fieldMethodsClass.getValue, |
|||
getObjectValue: fieldMethodsClass.getObjectValue, |
|||
clearValue: fieldMethodsClass.clearValue, |
|||
}); |
|||
</script> |
@ -0,0 +1,153 @@ |
|||
<template> |
|||
<div v-show="FieldMethods.getShow(props, modelValue)"> |
|||
<q-input |
|||
ref="textSelectRef" |
|||
v-model="modelDisplayValue" |
|||
:hide-bottom-space="true" |
|||
:hide-hint="true" |
|||
:outlined="true" |
|||
:dense="true" |
|||
:autogrow="true" |
|||
v-bind="attrs" |
|||
:bottom-slots="counter" |
|||
type="text" |
|||
:rules="FieldMethods.getRules(props, { value: modelValue, displayValue: modelDisplayValue }, textSelectRef, undefined)" |
|||
:readonly="FieldMethods.getReadOnly(props, { value: modelValue, displayValue: modelDisplayValue })" |
|||
:disable="FieldMethods.getDisable(props, { value: modelValue, displayValue: modelDisplayValue })" |
|||
:clearable="false" |
|||
@update:model-value="fieldMethodsClass.updateValue" |
|||
> |
|||
<template #label><w-label :required="FieldMethods.getRequired(props, modelValue)" :label="attrs.label"></w-label></template> |
|||
<template v-if="!props['form'] || (props['form'] && props['form'].getStatus() !== 'view')" #append> |
|||
<q-btn v-if="!Tools.isEmpty(modelValue)" flat square unelevated dense icon="cancel" @click="fieldMethodsClass.clearValue"></q-btn> |
|||
<q-btn flat square unelevated dense :icon="isShow ? 'arrow_drop_up' : 'arrow_drop_down'" @click="() => (isShow = !isShow)"> |
|||
<q-menu anchor="bottom start" self="top left" :offset="[50, 0]"> |
|||
<q-list style="min-width: 100px"> |
|||
<template v-for="(option, index) in options" :key="index"> |
|||
<q-item v-close-popup clickable> |
|||
<q-item-section @click="sectionClick(option)">{{ typeof option === 'object' ? option['label'] : option }}</q-item-section> |
|||
</q-item> |
|||
</template> |
|||
</q-list> |
|||
</q-menu> |
|||
</q-btn> |
|||
</template> |
|||
<template v-if="counter" #counter> |
|||
<div>{{ modelValue?.length }}</div> |
|||
</template> |
|||
</q-input> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup lang="ts"> |
|||
import { Tools } from '@/platform'; |
|||
import { FormFieldProps } from '@/platform/components/form/FormField.ts'; |
|||
import { onBeforeMount, ref, useAttrs, watch } from 'vue'; |
|||
import { FormFieldMethods } from '../form/FormField'; |
|||
|
|||
const textSelectRef = ref(); |
|||
const attrs = useAttrs(); |
|||
const modelValue = defineModel<string>(); |
|||
const modelDisplayValue = ref(''); // 模型显示值 |
|||
|
|||
const isShow = ref(false); |
|||
|
|||
interface FieldProps extends FormFieldProps { |
|||
counter?: boolean; |
|||
options: Array<string> | Array<object>; |
|||
} |
|||
const props = withDefaults(defineProps<FieldProps>(), { |
|||
showIf: true, |
|||
counter: false, // 显示右下角计数器 |
|||
}); |
|||
class FieldMethods extends FormFieldMethods { |
|||
updateValue = (value_) => { |
|||
if (props['onUpdateValue']) { |
|||
props['onUpdateValue']({ |
|||
value: value_, |
|||
displayValue: modelDisplayValue.value, |
|||
form: props['form'], |
|||
}); |
|||
} |
|||
}; |
|||
validate = () => { |
|||
return textSelectRef.value.validate(); |
|||
}; |
|||
|
|||
setValue = (value) => { |
|||
modelValue.value = value; |
|||
setDiaplayValueByValue(value); |
|||
}; |
|||
getValue = () => { |
|||
return modelValue.value; |
|||
}; |
|||
getDisplayValue = () => { |
|||
return modelDisplayValue.value; |
|||
}; |
|||
// 组件清空值 |
|||
clearValue = () => { |
|||
modelValue.value = undefined; |
|||
modelDisplayValue.value = ''; |
|||
}; |
|||
} |
|||
const fieldMethodsClass = new FieldMethods(); |
|||
|
|||
const findOption = (value, field = 'label') => { |
|||
return props.options.find((option) => { |
|||
if (typeof option === 'object') { |
|||
return option[field] === value; |
|||
} else { |
|||
return option === value; |
|||
} |
|||
}); |
|||
}; |
|||
watch( |
|||
() => modelDisplayValue.value, |
|||
(newVal, oldVal) => { |
|||
const option = findOption(newVal); |
|||
if (newVal && Tools.isEmpty(option)) { |
|||
modelValue.value = newVal; |
|||
} else if (newVal && !Tools.isEmpty(option)) { |
|||
modelValue.value = typeof option === 'object' ? option['value'] : option; |
|||
} else if (!newVal) { |
|||
modelValue.value = undefined; |
|||
} |
|||
}, |
|||
); |
|||
const sectionClick = (option) => { |
|||
if (typeof option === 'object') { |
|||
modelValue.value = option['value']; |
|||
modelDisplayValue.value = option['label']; |
|||
} else { |
|||
modelValue.value = option; |
|||
modelDisplayValue.value = option; |
|||
} |
|||
}; |
|||
// 根据实际值设置显示值 |
|||
const setDiaplayValueByValue = async (value) => { |
|||
if (!Tools.isEmpty(value)) { |
|||
const option = findOption(value, 'value'); |
|||
if (!Tools.isEmpty(option)) { |
|||
if (typeof option === 'object') { |
|||
modelDisplayValue.value = option['label']; |
|||
} else { |
|||
modelDisplayValue.value = value; |
|||
} |
|||
} else { |
|||
modelDisplayValue.value = value; |
|||
} |
|||
} |
|||
}; |
|||
|
|||
onBeforeMount(() => { |
|||
setDiaplayValueByValue(modelValue.value); |
|||
}); |
|||
|
|||
defineExpose({ |
|||
validate: fieldMethodsClass.validate, |
|||
setValue: fieldMethodsClass.setValue, |
|||
getValue: fieldMethodsClass.getValue, |
|||
getDisplayValue: fieldMethodsClass.getDisplayValue, |
|||
clearValue: fieldMethodsClass.clearValue, |
|||
}); |
|||
</script> |
@ -0,0 +1,259 @@ |
|||
<template> |
|||
<div v-show="FieldMethods.getShow(props, modelValue)"> |
|||
<q-input |
|||
ref="textSelectRef" |
|||
v-model="displayValueComputed" |
|||
:hide-bottom-space="true" |
|||
:hide-hint="true" |
|||
:outlined="true" |
|||
:dense="true" |
|||
:autogrow="true" |
|||
v-bind="attrs" |
|||
:bottom-slots="counter" |
|||
type="text" |
|||
:rules="FieldMethods.getRules(props, { value: modelValue, displayValue: displayValueComputed }, textSelectRef, undefined)" |
|||
:readonly="FieldMethods.getReadOnly(props, { value: modelValue, displayValue: displayValueComputed })" |
|||
:disable="FieldMethods.getDisable(props, { value: modelValue, displayValue: displayValueComputed })" |
|||
:clearable="false" |
|||
@update:model-value="fieldMethodsClass.updateValue" |
|||
@focus=" |
|||
() => { |
|||
textSelectRef?.blur(); |
|||
} |
|||
" |
|||
> |
|||
<template #label><w-label :required="FieldMethods.getRequired(props, modelValue)" :label="attrs.label"></w-label></template> |
|||
<template v-if="!props['form'] || (props['form'] && props['form'].getStatus() !== 'view')" #append> |
|||
<q-btn v-if="!Tools.isEmpty(displayValueComputed)" flat square unelevated dense icon="cancel" @click="fieldMethodsClass.clearValue"></q-btn> |
|||
<q-btn flat square unelevated dense icon="saved_search"> |
|||
<q-popup-proxy v-model:model-value="isShow" anchor="bottom right" self="top right" :offset="[0, 10]"> |
|||
<div style="width: 700px; height: 300px"> |
|||
<w-grid |
|||
ref="orgGridRef" |
|||
title="机构列表" |
|||
:checkbox-selection="props.multiple || false" |
|||
:dense="true" |
|||
:tree="true" |
|||
:fetch-data-url="orgGridFetchDataUrl" |
|||
:config-button="false" |
|||
:toolbar-actions="['expand']" |
|||
:columns="[ |
|||
{ name: 'name', label: $t('name'), sortable: false }, |
|||
{ name: 'code', label: $t('code'), width: 100, sortable: false }, |
|||
{ name: 'enable', label: $t('status'), format: Formater.enableTag(), width: 80, sortable: false }, |
|||
{ name: 'isDepartment', label: '是否部门', format: Formater.yesNo(), width: 80, sortable: false }, |
|||
]" |
|||
:ticked-record="{ |
|||
columnName: valueUseColumnName, |
|||
data: typeof modelValue === 'string' ? [modelValue] : modelValue, |
|||
}" |
|||
db-click-operation="none" |
|||
@row-click="rowClick" |
|||
@update-ticked="updateTicked" |
|||
> |
|||
</w-grid> |
|||
</div> |
|||
</q-popup-proxy> |
|||
</q-btn> |
|||
</template> |
|||
<template v-if="counter" #counter> |
|||
<div>{{ modelValue?.length }}</div> |
|||
</template> |
|||
</q-input> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup lang="ts"> |
|||
import { ref, computed, useAttrs, onBeforeMount, toRaw } from 'vue'; |
|||
import { Tools, axios, Environment, Formater } from '@/platform'; |
|||
import { FormFieldProps } from '@/platform/components/form/FormField.ts'; |
|||
import { FormFieldMethods } from '../form/FormField'; |
|||
|
|||
const textSelectRef = ref(); |
|||
const attrs = useAttrs(); |
|||
const modelValue = defineModel<string | Array<string>>(); |
|||
const modelObjectValue = ref(<any>[]); // 模型值包含实际值与显示值的对象集合。 |
|||
const orgGridRef = ref(); |
|||
|
|||
const orgGridFetchDataUrl = Environment.apiContextPath('/api/system/org'); |
|||
const isShow = ref(false); |
|||
|
|||
interface FieldProps extends FormFieldProps { |
|||
multiple?: boolean; |
|||
counter?: boolean; |
|||
valueUseId?: boolean; |
|||
displayValue?: string | ((args: object) => ''); |
|||
} |
|||
const props = withDefaults(defineProps<FieldProps>(), { |
|||
showIf: true, |
|||
multiple: false, // 是否允许多选,多选模式下模型绑定值必须为数组 |
|||
counter: false, // 显示右下角计数器 |
|||
/** |
|||
* 值使用机构id绑定,false则使用code |
|||
*/ |
|||
valueUseId: true, |
|||
/** |
|||
* 显示值配置,可使用选项: |
|||
* code:机构编码 |
|||
* name:机构名称,组件默认使用该选项 |
|||
* nameAppendCode:机构名追加编码,示例:上海分行(000025), |
|||
* codeAppendName:编码追加机构名,示例:000025(上海分行) |
|||
* 自定义函数:自己定义显示的内容,组件会将用户数据传到函数中,函数必须返回一个字符串,示例: |
|||
* displayValue: (args) => { |
|||
* return args['data']['name'] + '_' + args['data']['code']; |
|||
* } |
|||
*/ |
|||
displayValue: 'name', |
|||
}); |
|||
class FieldMethods extends FormFieldMethods { |
|||
updateValue = (value_) => { |
|||
if (props['onUpdateValue']) { |
|||
props['onUpdateValue']({ |
|||
value: value_, |
|||
displayValue: displayValueComputed.value, |
|||
form: props['form'], |
|||
}); |
|||
} |
|||
}; |
|||
validate = () => { |
|||
return textSelectRef.value.validate(); |
|||
}; |
|||
|
|||
setValue = (value) => { |
|||
if (props.multiple && Array.isArray(value) && Array.isArray(modelValue.value)) { |
|||
fieldMethodsClass.clearValue(); |
|||
modelValue.value.push(...value); |
|||
setObjectValueByValue(value); |
|||
} else if (!props.multiple && !Array.isArray(value)) { |
|||
modelValue.value = value; |
|||
setObjectValueByValue(value); |
|||
} else { |
|||
console.info('error========模型值不匹配'); |
|||
} |
|||
}; |
|||
getValue = () => { |
|||
return modelValue.value; |
|||
}; |
|||
getObjectValue = () => { |
|||
return modelObjectValue.value; |
|||
}; |
|||
// 组件清空值 |
|||
clearValue = () => { |
|||
if (props.multiple && Array.isArray(modelValue.value)) { |
|||
modelValue.value.splice(0, modelValue.value.length); |
|||
} else { |
|||
modelValue.value = undefined; |
|||
} |
|||
fieldMethodsClass.clearObjectValue(); |
|||
}; |
|||
// 清空显示值 |
|||
clearObjectValue = () => { |
|||
modelObjectValue.value.splice(0, modelObjectValue.value.length); |
|||
}; |
|||
} |
|||
const fieldMethodsClass = new FieldMethods(); |
|||
const valueUseColumnName = props.valueUseId ? 'id' : 'code'; |
|||
|
|||
const displayValueComputed = computed(() => { |
|||
let result = ''; |
|||
if (modelObjectValue.value.length > 0) { |
|||
modelObjectValue.value.forEach((item) => { |
|||
result = result + ',' + item['displayValue']; |
|||
}); |
|||
result = result.substring(1, result.length); |
|||
} |
|||
return result; |
|||
}); |
|||
|
|||
const getActualDisplayValue = (row) => { |
|||
if (!Tools.isEmpty(props.displayValue) && typeof props.displayValue === 'function') { |
|||
return props.displayValue({ |
|||
data: toRaw(row), |
|||
grid: orgGridRef.value, |
|||
}); |
|||
} else if (!Tools.isEmpty(props.displayValue) && typeof props.displayValue === 'string') { |
|||
if (props.displayValue === 'code') { |
|||
return row['code']; |
|||
} else if (props.displayValue === 'name') { |
|||
return row['name']; |
|||
} else if (props.displayValue === 'codeAppendName') { |
|||
return row['code'] + '(' + row['name'] + ')'; |
|||
} else if (props.displayValue === 'nameAppendCode') { |
|||
return row['name'] + '(' + row['code'] + ')'; |
|||
} |
|||
} |
|||
return ''; |
|||
}; |
|||
|
|||
const updateTicked = (args) => { |
|||
if (Array.isArray(modelValue.value)) { |
|||
fieldMethodsClass.clearValue(); |
|||
const rows = orgGridRef.value.getTickedRows(); |
|||
if (rows?.length > 0) { |
|||
rows.forEach((item) => { |
|||
modelValue.value.push(item[valueUseColumnName]); |
|||
modelObjectValue.value.push({ value: item[valueUseColumnName], displayValue: getActualDisplayValue(item) }); |
|||
}); |
|||
} |
|||
} |
|||
}; |
|||
const rowClick = (args) => { |
|||
const modelValue_ = args.row[valueUseColumnName]; |
|||
if (props.multiple && Array.isArray(modelValue.value)) { |
|||
fieldMethodsClass.clearValue(); |
|||
modelValue.value.push(modelValue_); |
|||
modelObjectValue.value.push({ value: modelValue_, displayValue: getActualDisplayValue(args.row) }); |
|||
} else if (!props.multiple) { |
|||
fieldMethodsClass.clearValue(); |
|||
modelValue.value = modelValue_; |
|||
modelObjectValue.value.push({ value: modelValue_, displayValue: getActualDisplayValue(args.row) }); |
|||
} else { |
|||
console.info('error========模型值不匹配'); |
|||
} |
|||
isShow.value = false; |
|||
}; |
|||
|
|||
// 根据实际值设置显示值 |
|||
const setObjectValueByValue = async (value) => { |
|||
if ((Array.isArray(value) && value.length > 0) || (typeof value === 'string' && !Tools.isEmpty(value))) { |
|||
const urlSearchParams = new URLSearchParams(); |
|||
urlSearchParams.append( |
|||
'criteria', |
|||
JSON.stringify({ |
|||
fieldName: valueUseColumnName, |
|||
operator: 'inSet', |
|||
value: Array.isArray(value) ? value : [value], |
|||
}), |
|||
); |
|||
const resp = await axios.get(orgGridFetchDataUrl, { params: urlSearchParams }).catch((error) => { |
|||
console.info('error-------------', error); |
|||
}); |
|||
if (resp && resp.data) { |
|||
const responseData = resp.data; |
|||
if (Array.isArray(responseData) && responseData.length > 0) { |
|||
fieldMethodsClass.clearObjectValue(); |
|||
responseData.forEach((item) => { |
|||
modelObjectValue.value.push({ value: item[valueUseColumnName], displayValue: getActualDisplayValue(item) }); |
|||
}); |
|||
} else if (typeof responseData === 'object' && responseData.content?.length > 0) { |
|||
fieldMethodsClass.clearObjectValue(); |
|||
responseData.content.forEach((item) => { |
|||
modelObjectValue.value.push({ value: item[valueUseColumnName], displayValue: getActualDisplayValue(item) }); |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
}; |
|||
|
|||
onBeforeMount(() => { |
|||
setObjectValueByValue(modelValue.value); |
|||
}); |
|||
|
|||
defineExpose({ |
|||
validate: fieldMethodsClass.validate, |
|||
setValue: fieldMethodsClass.setValue, |
|||
getValue: fieldMethodsClass.getValue, |
|||
getObjectValue: fieldMethodsClass.getObjectValue, |
|||
clearValue: fieldMethodsClass.clearValue, |
|||
}); |
|||
</script> |
@ -0,0 +1,66 @@ |
|||
<template> |
|||
<div v-show="FieldMethods.getShow(props, modelValue)"> |
|||
<q-select |
|||
ref="selectRef" |
|||
v-model="modelValue" |
|||
emit-value |
|||
map-options |
|||
:hide-bottom-space="true" |
|||
:hide-hint="true" |
|||
:outlined="true" |
|||
:dense="true" |
|||
v-bind="attrs" |
|||
:rules="FieldMethods.getRules(props, modelValue, selectRef, undefined)" |
|||
:readonly="FieldMethods.getReadOnly(props, modelValue)" |
|||
:disable="FieldMethods.getDisable(props, modelValue)" |
|||
@update:model-value="fieldMethodsClass.updateValue" |
|||
> |
|||
<template #label><w-label :required="FieldMethods.getRequired(props, modelValue)" :label="attrs.label"></w-label></template> |
|||
</q-select> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup lang="ts"> |
|||
import { ref, useAttrs } from 'vue'; |
|||
import { FormFieldProps } from '@/platform/components/form/FormField.ts'; |
|||
import { FormFieldMethods } from '../form/FormField'; |
|||
|
|||
const selectRef = ref(); |
|||
const attrs = useAttrs(); |
|||
const modelValue = defineModel<string | number | boolean | Array<string> | Array<number> | Array<boolean>>(); |
|||
|
|||
interface FieldProps extends FormFieldProps {} |
|||
const props = withDefaults(defineProps<FieldProps>(), { |
|||
showIf: true, |
|||
}); |
|||
class FieldMethods extends FormFieldMethods { |
|||
updateValue = (value_) => { |
|||
if (props['onUpdateValue']) { |
|||
props['onUpdateValue']({ |
|||
value: value_, |
|||
form: props['form'], |
|||
}); |
|||
} |
|||
}; |
|||
validate = () => { |
|||
return selectRef.value.validate(); |
|||
}; |
|||
setValue = (value_) => { |
|||
modelValue.value = value_; |
|||
}; |
|||
getValue = () => { |
|||
return modelValue.value; |
|||
}; |
|||
clearValue = () => { |
|||
modelValue.value = undefined; |
|||
}; |
|||
} |
|||
const fieldMethodsClass = new FieldMethods(); |
|||
|
|||
defineExpose({ |
|||
validate: fieldMethodsClass.validate, |
|||
setValue: fieldMethodsClass.setValue, |
|||
getValue: fieldMethodsClass.getValue, |
|||
clearValue: fieldMethodsClass.clearValue, |
|||
}); |
|||
</script> |
@ -0,0 +1,304 @@ |
|||
<template> |
|||
<div v-show="FieldMethods.getShow(props, modelValue)"> |
|||
<q-input |
|||
ref="textSelectRef" |
|||
v-model="displayValueComputed" |
|||
:hide-bottom-space="true" |
|||
:hide-hint="true" |
|||
:outlined="true" |
|||
:dense="true" |
|||
:autogrow="true" |
|||
v-bind="attrs" |
|||
:bottom-slots="counter" |
|||
type="text" |
|||
:rules="FieldMethods.getRules(props, { value: modelValue, displayValue: displayValueComputed }, textSelectRef, undefined)" |
|||
:readonly="FieldMethods.getReadOnly(props, { value: modelValue, displayValue: displayValueComputed })" |
|||
:disable="FieldMethods.getDisable(props, { value: modelValue, displayValue: displayValueComputed })" |
|||
:clearable="false" |
|||
@update:model-value="fieldMethodsClass.updateValue" |
|||
@focus=" |
|||
() => { |
|||
textSelectRef?.blur(); |
|||
} |
|||
" |
|||
> |
|||
<template #label><w-label :required="FieldMethods.getRequired(props, modelValue)" :label="attrs.label"></w-label></template> |
|||
<template v-if="!props['form'] || (props['form'] && props['form'].getStatus() !== 'view')" #append> |
|||
<q-btn v-if="!Tools.isEmpty(displayValueComputed)" flat square unelevated dense icon="cancel" @click="fieldMethodsClass.clearValue"></q-btn> |
|||
<q-btn flat square unelevated dense icon="person_search"> |
|||
<q-popup-proxy v-model:model-value="isShow" anchor="bottom right" self="top right" :offset="[0, 10]"> |
|||
<q-splitter v-model="leftWidthRef" style="width: 800px; height: 300px; position: relative"> |
|||
<template #before> |
|||
<w-grid |
|||
ref="orgGridRef" |
|||
:dense="true" |
|||
:tree="true" |
|||
:fetch-data-url="Environment.apiContextPath('/api/system/org')" |
|||
:config-button="false" |
|||
:checkbox-selection="false" |
|||
db-click-operation="expand" |
|||
:columns="[{ name: 'name', label: $t('org') }]" |
|||
@row-click="orgRowClick" |
|||
> |
|||
</w-grid> |
|||
</template> |
|||
<template #after> |
|||
<w-grid |
|||
ref="userGridRef" |
|||
:checkbox-selection="props.multiple || false" |
|||
:dense="true" |
|||
:fetch-data-url="userGridFetchDataUrl" |
|||
:config-button="false" |
|||
title="用户列表" |
|||
:sort-by="['loginName']" |
|||
:query-form-cols-num="2" |
|||
:query-form-fields="[ |
|||
{ name: 'loginName', label: $t('loginName'), type: 'w-text' }, |
|||
{ name: 'userName', label: $t('userName'), type: 'w-text' }, |
|||
]" |
|||
:toolbar-actions="['query', 'separator', 'reset']" |
|||
:ticked-record="{ |
|||
columnName: valueUseColumnName, |
|||
data: typeof modelValue === 'string' ? [modelValue] : modelValue, |
|||
}" |
|||
:columns="[ |
|||
{ name: 'loginName', label: $t('loginName') }, |
|||
{ name: 'userName', label: $t('userName') }, |
|||
{ name: 'description', label: $t('description') }, |
|||
{ name: 'enable', label: $t('status'), format: Formater.enableTag() }, |
|||
]" |
|||
@row-click="userRowClick" |
|||
@update-ticked="updateTicked" |
|||
@update-tickeds="updateTickeds" |
|||
> |
|||
</w-grid> |
|||
</template> |
|||
</q-splitter> |
|||
</q-popup-proxy> |
|||
</q-btn> |
|||
</template> |
|||
<template v-if="counter" #counter> |
|||
<div>{{ modelValue?.length }}</div> |
|||
</template> |
|||
</q-input> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup lang="ts"> |
|||
import { ref, computed, useAttrs, onBeforeMount, toRaw } from 'vue'; |
|||
import { Tools, axios, Environment, Formater } from '@/platform'; |
|||
import { FormFieldProps } from '@/platform/components/form/FormField.ts'; |
|||
import { FormFieldMethods } from '../form/FormField'; |
|||
|
|||
const textSelectRef = ref(); |
|||
const attrs = useAttrs(); |
|||
const modelValue = defineModel<string | Array<string>>(); |
|||
const modelObjectValue = ref(<any>[]); // 模型值包含实际值与显示值的对象集合。 |
|||
const orgGridRef = ref(); |
|||
const userGridRef = ref(); |
|||
|
|||
const userGridFetchDataUrl = Environment.apiContextPath('/api/system/user'); |
|||
const userGridFetchDataByOrgUrl = Environment.apiContextPath('/api/system/user/queryUsersByOrgAndQueryParameter'); |
|||
const leftWidthRef = ref(30); |
|||
const isShow = ref(false); |
|||
|
|||
interface FieldProps extends FormFieldProps { |
|||
multiple?: boolean; |
|||
counter?: boolean; |
|||
valueUseId?: boolean; |
|||
displayValue?: string | ((args: object) => ''); |
|||
} |
|||
const props = withDefaults(defineProps<FieldProps>(), { |
|||
showIf: true, |
|||
multiple: false, // 是否允许多选,多选模式下模型绑定值必须为数组 |
|||
counter: false, // 显示右下角计数器 |
|||
/** |
|||
* 值使用用户id,默认绑定的实际值为用户登录账号,true则使用id绑定 |
|||
*/ |
|||
valueUseId: false, |
|||
/** |
|||
* 显示值配置,可使用选项: |
|||
* account:用户登陆账号 |
|||
* name:用户名 |
|||
* nameAppendAccount:用户名追加登陆账号,示例:张三(zhangsan),组件默认使用该选项 |
|||
* accountAppendName:账号追加用户名,示例:zhangsan(张三) |
|||
* 自定义函数:自己定义显示的内容,组件会将用户数据传到函数中,函数必须返回一个字符串,示例: |
|||
* displayValue: (args) => { |
|||
* return args['data']['loginName'] + '_' + args['data']['userName']; |
|||
* } |
|||
*/ |
|||
displayValue: 'nameAppendAccount', |
|||
}); |
|||
class FieldMethods extends FormFieldMethods { |
|||
updateValue = (value_) => { |
|||
if (props['onUpdateValue']) { |
|||
props['onUpdateValue']({ |
|||
value: value_, |
|||
displayValue: displayValueComputed.value, |
|||
form: props['form'], |
|||
}); |
|||
} |
|||
}; |
|||
validate = () => { |
|||
return textSelectRef.value.validate(); |
|||
}; |
|||
|
|||
setValue = (value) => { |
|||
if (props.multiple && Array.isArray(value) && Array.isArray(modelValue.value)) { |
|||
fieldMethodsClass.clearValue(); |
|||
modelValue.value.push(...value); |
|||
setObjectValueByValue(value); |
|||
} else if (!props.multiple && !Array.isArray(value)) { |
|||
modelValue.value = value; |
|||
setObjectValueByValue(value); |
|||
} else { |
|||
console.info('error========模型值不匹配'); |
|||
} |
|||
}; |
|||
getValue = () => { |
|||
return modelValue.value; |
|||
}; |
|||
getObjectValue = () => { |
|||
return modelObjectValue.value; |
|||
}; |
|||
// 组件清空值 |
|||
clearValue = () => { |
|||
if (props.multiple && Array.isArray(modelValue.value)) { |
|||
modelValue.value.splice(0, modelValue.value.length); |
|||
} else { |
|||
modelValue.value = undefined; |
|||
} |
|||
fieldMethodsClass.clearObjectValue(); |
|||
}; |
|||
// 清空显示值 |
|||
clearObjectValue = () => { |
|||
modelObjectValue.value.splice(0, modelObjectValue.value.length); |
|||
}; |
|||
} |
|||
const fieldMethodsClass = new FieldMethods(); |
|||
const valueUseColumnName = props.valueUseId ? 'id' : 'loginName'; |
|||
|
|||
const displayValueComputed = computed(() => { |
|||
let result = ''; |
|||
if (modelObjectValue.value.length > 0) { |
|||
modelObjectValue.value.forEach((item) => { |
|||
result = result + ',' + item['displayValue']; |
|||
}); |
|||
result = result.substring(1, result.length); |
|||
} |
|||
return result; |
|||
}); |
|||
|
|||
const getActualDisplayValue = (row) => { |
|||
if (!Tools.isEmpty(props.displayValue) && typeof props.displayValue === 'function') { |
|||
return props.displayValue({ |
|||
data: toRaw(row), |
|||
orgGrid: orgGridRef.value, |
|||
userGrid: userGridRef.value, |
|||
}); |
|||
} else if (!Tools.isEmpty(props.displayValue) && typeof props.displayValue === 'string') { |
|||
if (props.displayValue === 'account') { |
|||
return row['loginName']; |
|||
} else if (props.displayValue === 'name') { |
|||
return row['userName']; |
|||
} else if (props.displayValue === 'accountAppendName') { |
|||
return row['loginName'] + '(' + row['userName'] + ')'; |
|||
} else if (props.displayValue === 'nameAppendAccount') { |
|||
return row['userName'] + '(' + row['loginName'] + ')'; |
|||
} |
|||
} |
|||
return ''; |
|||
}; |
|||
|
|||
const updateTickeds = (args) => { |
|||
if (args.value && Array.isArray(modelValue.value)) { |
|||
fieldMethodsClass.clearValue(); |
|||
const rows = userGridRef.value.getRows(); |
|||
rows.forEach((item) => { |
|||
modelValue.value.push(item[valueUseColumnName]); |
|||
modelObjectValue.value.push({ value: item[valueUseColumnName], displayValue: getActualDisplayValue(item) }); |
|||
}); |
|||
} else { |
|||
fieldMethodsClass.clearValue(); |
|||
} |
|||
}; |
|||
const updateTicked = (args) => { |
|||
if (Array.isArray(modelValue.value)) { |
|||
const index = modelValue.value.findIndex((item) => { |
|||
return item === args.row[valueUseColumnName]; |
|||
}); |
|||
if (args.row['ticked']) { |
|||
if (index < 0) { |
|||
modelValue.value.push(args.row[valueUseColumnName]); |
|||
modelObjectValue.value.push({ value: args.row[valueUseColumnName], displayValue: getActualDisplayValue(args.row) }); |
|||
} |
|||
} else { |
|||
modelValue.value.splice(index, 1); |
|||
modelObjectValue.value.splice(index, 1); |
|||
} |
|||
} |
|||
}; |
|||
const userRowClick = (args) => { |
|||
const modelValue_ = args.row[valueUseColumnName]; |
|||
if (props.multiple && Array.isArray(modelValue.value)) { |
|||
fieldMethodsClass.clearValue(); |
|||
modelValue.value.push(modelValue_); |
|||
modelObjectValue.value.push({ value: modelValue_, displayValue: getActualDisplayValue(args.row) }); |
|||
} else if (!props.multiple) { |
|||
fieldMethodsClass.clearValue(); |
|||
modelValue.value = modelValue_; |
|||
modelObjectValue.value.push({ value: modelValue_, displayValue: getActualDisplayValue(args.row) }); |
|||
} else { |
|||
console.info('error========模型值不匹配'); |
|||
} |
|||
isShow.value = false; |
|||
}; |
|||
const orgRowClick = (args) => { |
|||
userGridRef.value.setFetchDataUrl(userGridFetchDataByOrgUrl + '?orgId=' + args.row['id']); |
|||
userGridRef.value.refresh(); |
|||
}; |
|||
|
|||
// 根据实际值设置显示值 |
|||
const setObjectValueByValue = async (value) => { |
|||
if ((Array.isArray(value) && value.length > 0) || (typeof value === 'string' && !Tools.isEmpty(value))) { |
|||
const urlSearchParams = new URLSearchParams(); |
|||
urlSearchParams.append( |
|||
'criteria', |
|||
JSON.stringify({ |
|||
fieldName: valueUseColumnName, |
|||
operator: 'inSet', |
|||
value: Array.isArray(value) ? value : [value], |
|||
}), |
|||
); |
|||
const resp = await axios.get(userGridFetchDataUrl, { params: urlSearchParams }).catch((error) => { |
|||
console.info('error-------------', error); |
|||
}); |
|||
if (resp && resp.data) { |
|||
const responseData = resp.data; |
|||
if (Array.isArray(responseData) && responseData.length > 0) { |
|||
fieldMethodsClass.clearObjectValue(); |
|||
responseData.forEach((item) => { |
|||
modelObjectValue.value.push({ value: item[valueUseColumnName], displayValue: getActualDisplayValue(item) }); |
|||
}); |
|||
} else if (typeof responseData === 'object' && responseData.content?.length > 0) { |
|||
fieldMethodsClass.clearObjectValue(); |
|||
responseData.content.forEach((item) => { |
|||
modelObjectValue.value.push({ value: item[valueUseColumnName], displayValue: getActualDisplayValue(item) }); |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
}; |
|||
|
|||
onBeforeMount(() => { |
|||
setObjectValueByValue(modelValue.value); |
|||
}); |
|||
|
|||
defineExpose({ |
|||
validate: fieldMethodsClass.validate, |
|||
setValue: fieldMethodsClass.setValue, |
|||
getValue: fieldMethodsClass.getValue, |
|||
getObjectValue: fieldMethodsClass.getObjectValue, |
|||
clearValue: fieldMethodsClass.clearValue, |
|||
}); |
|||
</script> |
@ -0,0 +1,85 @@ |
|||
<template> |
|||
<div v-show="FieldMethods.getShow(props, modelValue)"> |
|||
<q-editor |
|||
ref="textEditorRef" |
|||
v-model="modelValue" |
|||
:dense="true" |
|||
:toolbar="[ |
|||
['label'], |
|||
['removeFormat', 'viewsource'], |
|||
[ |
|||
{ |
|||
label: $q.lang.editor.align, |
|||
icon: $q.iconSet.editor.align, |
|||
fixedLabel: true, |
|||
options: ['left', 'center', 'right', 'justify'], |
|||
}, |
|||
], |
|||
['bold', 'italic', 'strike', 'underline', 'subscript', 'superscript', 'hr'], |
|||
[ |
|||
{ |
|||
label: $q.lang.editor.fontSize, |
|||
icon: $q.iconSet.editor.fontSize, |
|||
fixedLabel: true, |
|||
fixedIcon: true, |
|||
list: 'no-icons', |
|||
options: ['size-1', 'size-2', 'size-3', 'size-4', 'size-5', 'size-6', 'size-7'], |
|||
}, |
|||
], |
|||
['print', 'fullscreen'], |
|||
]" |
|||
v-bind="attrs" |
|||
:readonly="FieldMethods.getReadOnly(props, modelValue)" |
|||
:disable="FieldMethods.getDisable(props, modelValue)" |
|||
@update:model-value="fieldMethodsClass.updateValue" |
|||
> |
|||
<template #label> |
|||
<span>{{ attrs.label }}</span> |
|||
</template> |
|||
</q-editor> |
|||
</div> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import { ref, useAttrs } from 'vue'; |
|||
import { FormFieldProps } from '@/platform/components/form/FormField.ts'; |
|||
import { FormFieldMethods } from '../form/FormField'; |
|||
|
|||
const textRef = ref(); |
|||
const attrs = useAttrs(); |
|||
const modelValue = defineModel({ type: String, default: '' }); |
|||
|
|||
interface FieldProps extends FormFieldProps {} |
|||
const props = withDefaults(defineProps<FieldProps>(), { |
|||
showIf: true, |
|||
}); |
|||
class FieldMethods extends FormFieldMethods { |
|||
updateValue = (value_) => { |
|||
if (props['onUpdateValue']) { |
|||
props['onUpdateValue']({ |
|||
value: value_, |
|||
form: props['form'], |
|||
}); |
|||
} |
|||
}; |
|||
validate = () => { |
|||
return textRef.value.validate(); |
|||
}; |
|||
setValue = (value_) => { |
|||
modelValue.value = value_; |
|||
}; |
|||
getValue = () => { |
|||
return modelValue.value; |
|||
}; |
|||
clearValue = () => { |
|||
modelValue.value = ''; |
|||
}; |
|||
} |
|||
const fieldMethodsClass = new FieldMethods(); |
|||
|
|||
defineExpose({ |
|||
validate: fieldMethodsClass.validate, |
|||
setValue: fieldMethodsClass.setValue, |
|||
getValue: fieldMethodsClass.getValue, |
|||
clearValue: fieldMethodsClass.clearValue, |
|||
}); |
|||
</script> |
@ -0,0 +1,80 @@ |
|||
<template> |
|||
<div v-show="FieldMethods.getShow(props, modelValue)"> |
|||
<q-input |
|||
ref="textRef" |
|||
v-model="modelValue" |
|||
:hide-bottom-space="true" |
|||
:hide-hint="true" |
|||
:outlined="true" |
|||
:dense="true" |
|||
v-bind="attrs" |
|||
type="text" |
|||
:rules="FieldMethods.getRules(props, modelValue, textRef, undefined)" |
|||
:readonly="FieldMethods.getReadOnly(props, modelValue)" |
|||
:disable="FieldMethods.getDisable(props, modelValue)" |
|||
@update:model-value="fieldMethodsClass.updateValue" |
|||
> |
|||
<template #label><w-label :required="FieldMethods.getRequired(props, modelValue)" :label="attrs.label"></w-label></template> |
|||
</q-input> |
|||
</div> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import { ref, useAttrs, computed } from 'vue'; |
|||
import { FormFieldProps } from '@/platform/components/form/FormField.ts'; |
|||
import { FormFieldMethods } from '../form/FormField'; |
|||
|
|||
const textRef = ref(); |
|||
const attrs = useAttrs(); |
|||
const modelValue = defineModel<string>(); |
|||
|
|||
interface FieldProps extends FormFieldProps {} |
|||
const props = withDefaults(defineProps<FieldProps>(), { |
|||
showIf: true, |
|||
}); |
|||
class FieldMethods extends FormFieldMethods { |
|||
updateValue = (value_) => { |
|||
if (props['onUpdateValue']) { |
|||
props['onUpdateValue']({ |
|||
value: value_, |
|||
form: props['form'], |
|||
}); |
|||
} |
|||
}; |
|||
validate = () => { |
|||
return textRef.value.validate(); |
|||
}; |
|||
setValue = (value_) => { |
|||
modelValue.value = value_; |
|||
}; |
|||
getValue = () => { |
|||
return modelValue.value; |
|||
}; |
|||
clearValue = () => { |
|||
modelValue.value = undefined; |
|||
}; |
|||
} |
|||
const fieldMethodsClass = new FieldMethods(); |
|||
|
|||
// const showComputed = computed(() => { |
|||
// return FieldMethods.getShow(props, modelValue.value); |
|||
// }); |
|||
// const rulesComputed = computed(() => { |
|||
// return FieldMethods.getRules(props, modelValue.value, textRef, undefined); |
|||
// }); |
|||
// const readOnlyComputed = computed(() => { |
|||
// return FieldMethods.getReadOnly(props, modelValue.value); |
|||
// }); |
|||
// const disableComputed = computed(() => { |
|||
// return FieldMethods.getDisable(props, modelValue.value); |
|||
// }); |
|||
// const requiredComputed = computed(() => { |
|||
// return FieldMethods.getRequired(props, modelValue.value); |
|||
// }); |
|||
|
|||
defineExpose({ |
|||
validate: fieldMethodsClass.validate, |
|||
setValue: fieldMethodsClass.setValue, |
|||
getValue: fieldMethodsClass.getValue, |
|||
clearValue: fieldMethodsClass.clearValue, |
|||
}); |
|||
</script> |
@ -0,0 +1,65 @@ |
|||
<template> |
|||
<div v-show="FieldMethods.getShow(props, modelValue)"> |
|||
<q-input |
|||
ref="textareaRef" |
|||
v-model="modelValue" |
|||
:hide-bottom-space="true" |
|||
:hide-hint="true" |
|||
:outlined="true" |
|||
:dense="true" |
|||
v-bind="attrs" |
|||
type="textarea" |
|||
:rules="FieldMethods.getRules(props, modelValue, textareaRef, undefined)" |
|||
:readonly="FieldMethods.getReadOnly(props, modelValue)" |
|||
:disable="FieldMethods.getDisable(props, modelValue)" |
|||
@update:model-value="fieldMethodsClass.updateValue" |
|||
> |
|||
<template #label><w-label :required="FieldMethods.getRequired(props, modelValue)" :label="attrs.label"></w-label></template> |
|||
</q-input> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup lang="ts"> |
|||
import { ref, useAttrs } from 'vue'; |
|||
import { FormFieldProps } from '@/platform/components/form/FormField.ts'; |
|||
import { FormFieldMethods } from '../form/FormField'; |
|||
|
|||
const textareaRef = ref(); |
|||
const attrs = useAttrs(); |
|||
const modelValue = defineModel<string>(); |
|||
|
|||
interface FieldProps extends FormFieldProps {} |
|||
const props = withDefaults(defineProps<FieldProps>(), { |
|||
showIf: true, |
|||
}); |
|||
class FieldMethods extends FormFieldMethods { |
|||
updateValue = (value_) => { |
|||
if (props['onUpdateValue']) { |
|||
props['onUpdateValue']({ |
|||
value: value_, |
|||
form: props['form'], |
|||
}); |
|||
} |
|||
}; |
|||
validate = () => { |
|||
return textareaRef.value.validate(); |
|||
}; |
|||
setValue = (value_) => { |
|||
modelValue.value = value_; |
|||
}; |
|||
getValue = () => { |
|||
return modelValue.value; |
|||
}; |
|||
clearValue = () => { |
|||
modelValue.value = undefined; |
|||
}; |
|||
} |
|||
const fieldMethodsClass = new FieldMethods(); |
|||
|
|||
defineExpose({ |
|||
validate: fieldMethodsClass.validate, |
|||
setValue: fieldMethodsClass.setValue, |
|||
getValue: fieldMethodsClass.getValue, |
|||
clearValue: fieldMethodsClass.clearValue, |
|||
}); |
|||
</script> |
@ -1,570 +1,31 @@ |
|||
<template> |
|||
<div style="height: 100%"> |
|||
<!-- <q-splitter v-model="splitterModel"> |
|||
<template #before> |
|||
<q-tabs v-model="tab" vertical class="text-teal"> |
|||
<q-tab name="mails" icon="mail" label="Mails" /> |
|||
<q-tab name="alarms" icon="alarm" label="Alarms" /> |
|||
<q-tab name="movies" icon="movie" label="Movies" /> |
|||
</q-tabs> |
|||
</template> |
|||
|
|||
<template #after> |
|||
<q-tab-panels v-model="tab" animated swipeable vertical transition-prev="jump-up" transition-next="jump-up"> |
|||
<q-tab-panel name="mails"> |
|||
|
|||
</q-tab-panel> |
|||
|
|||
<q-tab-panel name="alarms"> |
|||
<div class="h-full"> |
|||
<w-grid |
|||
ref="grid2" |
|||
:title="testGrid.title" |
|||
draggable |
|||
dense |
|||
:data-url="testGrid.tableDataUrl" |
|||
:checkbox-selection="true" |
|||
selection="multiple" |
|||
:query-form-cols-num="2" |
|||
:columns="testGrid.tableColumns" |
|||
:toolbar-actions="testGrid.toolbar" |
|||
:query-form-fields="testGrid.queryForm" |
|||
:editor="{ |
|||
form: { |
|||
colsNum: 1, |
|||
fields: [ |
|||
{ label: '登录名', name: 'loginName', type: 'w-text' }, |
|||
{ label: '用户名', name: 'userName', type: 'w-text' }, |
|||
{ label: '密码', name: 'password', type: 'w-text' }, |
|||
{ label: '是否可用1111', name: 'enable', type: 'w-checkbox' }, |
|||
{ |
|||
name: 'urlOpenType', |
|||
label: 'urlOpenType', |
|||
type: 'select', |
|||
options: Options.enum(UrlOpenTypeEnum, false), |
|||
defaultValue: 'NEW_WINDOW', |
|||
}, |
|||
], |
|||
}, |
|||
}" |
|||
:viewer="testGrid.view" |
|||
></w-grid> |
|||
</q-tab-panel> |
|||
|
|||
<q-tab-panel name="movies"> |
|||
<div class="text-h4 q-mb-md">Movies</div> |
|||
<w-form ref="form" :fields="[{ name: 'a', label: 'a', type: 'text' }]"></w-form> |
|||
</q-tab-panel> |
|||
</q-tab-panels> |
|||
</template> |
|||
</q-splitter> --> |
|||
<!-- <w-grid |
|||
ref="gridRef" |
|||
:title="testGrid.title" |
|||
draggable |
|||
:dense="state.dense" |
|||
:hide-bottom="false" |
|||
:data-url="testGrid.tableDataUrl" |
|||
:auto-fetch-data="true" |
|||
:checkbox-selection="true" |
|||
selection="multiple" |
|||
:query-form-cols-num="6" |
|||
:columns="testGrid.tableColumns" |
|||
:toolbar-actions="testGrid.toolbar" |
|||
:query-form-fields="testGrid.queryForm" |
|||
:editor="{ |
|||
form: { |
|||
colsNum: 1, |
|||
fields: [ |
|||
{ label: '登录名', name: 'loginName', type: 'w-text' }, |
|||
{ label: '用户名', name: 'userName', type: 'w-text' }, |
|||
{ label: '密码', name: 'password', type: 'w-text' }, |
|||
{ label: '是否可用1111', name: 'enable', type: 'w-checkbox' }, |
|||
{ |
|||
name: 'urlOpenType', |
|||
label: 'urlOpenType', |
|||
type: 'select', |
|||
options: Options.enum(UrlOpenTypeEnum, false), |
|||
defaultValue: 'NEW_WINDOW', |
|||
}, |
|||
], |
|||
}, |
|||
}" |
|||
:viewer="testGrid.view" |
|||
@update-ticked="updateTicked" |
|||
@row-click="rowClick" |
|||
@row-db-click="rowDbClick" |
|||
@after-request-data=" |
|||
() => { |
|||
} |
|||
" |
|||
></w-grid> --> |
|||
<w-grid |
|||
ref="applicationGridRef" |
|||
:title="$t('system.application.grid.title')" |
|||
:config-button="true" |
|||
selection="multiple" |
|||
:checkbox-selection="true" |
|||
:sort-no="true" |
|||
:draggable="true" |
|||
title="示例列表" |
|||
:data-url="Environment.apiContextPath('/api/system/application')" |
|||
:sort-by="['order']" |
|||
:query-form-cols-num="3" |
|||
db-click-operation="rowEdit" |
|||
:query-form-fields="[ |
|||
{ name: 'code', label: $t('code'), type: 'text' }, |
|||
{ name: 'name', label: $t('name'), type: 'text' }, |
|||
{ name: 'enable', label: $t('isEnable'), type: 'select', options: Options.yesNo() }, |
|||
]" |
|||
:toolbar-configure="{ noIcon: false }" |
|||
:toolbar-actions="[ |
|||
'query', |
|||
'refresh', |
|||
'separator', |
|||
'rowEdit', |
|||
'rowsEdit', |
|||
'separator', |
|||
'add', |
|||
'clone', |
|||
'edit', |
|||
'remove', |
|||
'separator', |
|||
'view', |
|||
'separator', |
|||
'export', |
|||
]" |
|||
:toolbar-actions="['add', 'edit']" |
|||
:columns="[ |
|||
{ name: 'order', label: $t('order'), type: 'number', attrs: { required: true } }, |
|||
{ name: 'code', label: $t('code'), type: 'text', attrs: { required: true } }, |
|||
{ name: 'code', label: '编码', type: 'w-text' }, |
|||
{ name: 'name', label: '名称', type: 'w-text' }, |
|||
{ |
|||
name: 'name', |
|||
label: $t('name'), |
|||
type: 'text', |
|||
format: (val, row) => { |
|||
return val; |
|||
}, |
|||
name: 'enable', |
|||
label: '状态', |
|||
format: Formater.enableTag(), |
|||
}, |
|||
{ width: 80, name: 'enable', label: $t('status'), format: Formater.enableTag(), type: 'checkbox' }, |
|||
{ width: 120, name: 'lastModifier', label: $t('lastModifier') }, |
|||
{ width: 120, name: 'lastModifyDate', label: $t('lastModifyDate'), format: Formater.dateOnly() }, |
|||
{ name: 'lastModifier', label: '最后修改人', align: 'center' }, |
|||
{ name: 'lastModifyDate', label: '最后修改日期', align: 'center' }, |
|||
]" |
|||
:editor="{ |
|||
dialog: { |
|||
width: '600px', |
|||
height: '300px', |
|||
}, |
|||
form: { |
|||
colsNum: 1, |
|||
fields: [ |
|||
{ name: 'code', label: $t('code'), type: 'text', required: true }, |
|||
{ name: 'name', label: $t('name'), type: 'text', required: true }, |
|||
{ name: 'description', label: $t('description'), type: 'textarea', rows: 1 }, |
|||
{ name: 'order', label: $t('order'), type: 'number' }, |
|||
{ name: 'enable', label: $t('enable'), type: 'checkbox', defaultValue: true }, |
|||
], |
|||
}, |
|||
}" |
|||
:viewer="{ |
|||
panel: { |
|||
columnNum: 1, |
|||
fields: [ |
|||
{ name: 'id', label: $t('id') }, |
|||
{ name: 'code', label: $t('code') }, |
|||
{ name: 'name', label: $t('name') }, |
|||
{ name: 'description', label: $t('description') }, |
|||
{ name: 'enable', label: $t('enable'), format: Formater.none() }, |
|||
{ name: 'order', label: $t('order') }, |
|||
{ name: 'dataComeFrom', label: $t('dataComeFrom') }, |
|||
{ name: 'creator', label: $t('creator') }, |
|||
{ name: 'createDate', label: $t('createDate') }, |
|||
{ name: 'lastModifier', label: $t('lastModifier') }, |
|||
{ name: 'lastModifyDate', label: $t('lastModifyDate'), format: Formater.none() }, |
|||
{ name: 'corporationCode', label: $t('corporationCode') }, |
|||
], |
|||
}, |
|||
}" |
|||
@row-click=" |
|||
(evt, row, index) => { |
|||
// console.info('rowclick'); |
|||
} |
|||
" |
|||
@before-request-data="() => {}" |
|||
@after-row-draggable=" |
|||
(grid, updateDatas) => { |
|||
// console.info('grid=====', grid); |
|||
// console.info('updateDatas======', updateDatas); |
|||
} |
|||
" |
|||
@after-editor-open=" |
|||
() => { |
|||
console.info('打开窗口'); |
|||
} |
|||
" |
|||
@row-click="rowClick" |
|||
> |
|||
</w-grid> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup lang="ts"> |
|||
import { ref, onMounted, nextTick, reactive, computed } from 'vue'; |
|||
import { axios, Environment, EnumTools, Options, Formater } from '@/platform'; |
|||
import EnableIcon from '@/platform/components/grid/EnableIcon.vue'; |
|||
import { IconEnum } from '@/platform/enums'; |
|||
|
|||
// :query-criteria="{ |
|||
// operator: 'equals', |
|||
// fieldName: 'code', |
|||
// value: 'A', |
|||
// }" |
|||
import { ref } from 'vue'; |
|||
import { Environment, Formater } from '@/platform'; |
|||
|
|||
const dialogRef = ref(); |
|||
const gridRef = ref(); |
|||
const grid2 = ref(); |
|||
const form = ref(); |
|||
const tab = ref('mails'); |
|||
const splitterModel = ref(10); |
|||
const UrlOpenTypeEnum = await EnumTools.fetch('io.sc.platform.system.enums.UrlOpenType'); |
|||
const updateTicked = (event, row) => { |
|||
console.info('grid.updateTicked.event====', event); |
|||
console.info('grid.updateTicked.row====', row); |
|||
}; |
|||
const state = reactive({ |
|||
dense: false, |
|||
}); |
|||
|
|||
const startY = ref(0); |
|||
const endY = ref(0); |
|||
|
|||
const rowClick = (evt, row, index) => { |
|||
// if (startY.value === 0) { |
|||
// startY.value = evt.clientY; |
|||
// } else if (evt.shiftKey && endY.value === 0) { |
|||
// endY.value = evt.clientY; |
|||
// } |
|||
// console.info('startY====', startY.value); |
|||
// console.info('endY====', endY.value); |
|||
// // 添加到选择中,同时清空 startY 与 endY |
|||
// if (startY.value > 0 && endY.value > 0) { |
|||
// console.info('添加到选择中,同时清空 startY 与 endY'); |
|||
// startY.value = 0; |
|||
// endY.value = 0; |
|||
// } |
|||
// startY.value = 0; |
|||
// endY.value = 0; |
|||
// console.info('grid.rowClick.row====', row); |
|||
|
|||
// tab.value = 'alarms'; |
|||
// nextTick(() => { |
|||
// grid2.value.getQueryForm().setFieldValue('loginName', row.id); |
|||
// }); |
|||
|
|||
// tab.value = 'movies'; |
|||
// nextTick(() => { |
|||
// form.value.setFieldValue('a', row.id); |
|||
// }); |
|||
console.info('grid.rowClick.row====', row); |
|||
}; |
|||
const rowDbClick = (evt, row, index) => { |
|||
console.info('grid.rowDbClick.row====', row); |
|||
}; |
|||
|
|||
// 获取元素的绝对位置坐标(像对于浏览器视区左上角) |
|||
const getElementViewPosition = (element) => { |
|||
//计算x坐标 |
|||
let actualLeft = element.offsetLeft; |
|||
let xcurrent = element.offsetParent; |
|||
while (xcurrent !== null) { |
|||
actualLeft += xcurrent.offsetLeft + xcurrent.clientLeft; |
|||
xcurrent = xcurrent.offsetParent; |
|||
} |
|||
let elementScrollLeft = document.documentElement.scrollLeft; |
|||
if (document.compatMode == 'BackCompat') { |
|||
elementScrollLeft = document.body.scrollLeft; |
|||
} |
|||
const left = actualLeft - elementScrollLeft; |
|||
|
|||
//计算y坐标 |
|||
let actualTop = element.offsetTop; |
|||
let ycurrent = element.offsetParent; |
|||
while (ycurrent !== null) { |
|||
actualTop += ycurrent.offsetTop + ycurrent.clientTop; |
|||
ycurrent = ycurrent.offsetParent; |
|||
} |
|||
let elementScrollTop = document.documentElement.scrollTop; |
|||
if (document.compatMode == 'BackCompat') { |
|||
elementScrollTop = document.body.scrollTop; |
|||
} |
|||
var right = actualTop - elementScrollTop; |
|||
//返回结果 |
|||
return { x: left, y: right }; |
|||
}; |
|||
|
|||
// const gridHeightComputed = computed(() => { |
|||
// // if (dialogRef?.value && gridRef?.value) { |
|||
// // const height = dialogRef.value.getContentHeight(); |
|||
// // const tableContentY = getElementViewPosition(gridRef.value.$el.getElementsByClassName('q-table__middle')[0]); |
|||
// // console.info('height==========', height); |
|||
// // console.info('gridRef==============', tableContentY); |
|||
// // if (height && tableContentY) { |
|||
// // return height.height - (tableContentY.y - height.y); |
|||
// // } |
|||
// // } |
|||
// if (dialogRef?.value && dialogRef.value.getContent()) { |
|||
// const height = dialogRef.value.getContent().clientHeight; |
|||
// console.info('dialogRef.value.getContent()====', height); |
|||
// if (height > 0) { |
|||
// return height; |
|||
// } |
|||
// } |
|||
// return 0; |
|||
// }); |
|||
const aaaaaaaaaaaaaaaa = ref(false); |
|||
const testGrid = { |
|||
hideBottom: false, |
|||
autoLoadData: false, |
|||
tableLeftColumnStickyNumber: 1, |
|||
title: '用户列表', |
|||
tableDataUrl: Environment.apiContextPath('api/system/user'), |
|||
queryCriteria: { |
|||
fieldName: 'loginName', |
|||
operator: 'contains', |
|||
value: '1', |
|||
}, |
|||
toolbar: [ |
|||
['query', 'separator', 'moreQuery'], |
|||
'reset', |
|||
{ |
|||
extend: 'refresh', |
|||
click: () => { |
|||
state.dense = !state.dense; |
|||
}, |
|||
}, |
|||
'separator', |
|||
{ |
|||
extend: 'resetDefaultValues', |
|||
icon: undefined, |
|||
label: 'aasdfFFF', |
|||
loadingIf: (selected, ticked, grid) => { |
|||
if (selected.length === 0) { |
|||
return true; |
|||
} |
|||
return false; |
|||
}, |
|||
// enableIf: (selected) => { |
|||
// if (selected && selected.length > 0) { |
|||
// return true; |
|||
// } |
|||
// return false; |
|||
// }, |
|||
// beforeClick: (selected, context, grid) => { |
|||
// console.info('先执行before'); |
|||
// context.aaa = '111'; |
|||
// }, |
|||
click: (args) => { |
|||
// grid.setQueryCriteria({ |
|||
// fieldName: 'loginName', |
|||
// operator: 'contains', |
|||
// value: 'admin', |
|||
// }); |
|||
console.info('args=====', args); |
|||
args._click(); |
|||
}, |
|||
afterClick: (selected, context, grid) => { |
|||
// grid.addEditFormRef.setFieldValue('userName', '李四'); |
|||
}, |
|||
}, |
|||
[ |
|||
{ |
|||
name: 'op', |
|||
icon: 'difference', |
|||
label: '操作', |
|||
}, |
|||
'add', |
|||
'edit', |
|||
'clone', |
|||
'remove', |
|||
'separator', |
|||
'view', |
|||
'export', |
|||
], |
|||
'separator', |
|||
], |
|||
tableShowSortNo: true, |
|||
queryForm: [ |
|||
{ label: '登录名', name: 'loginName', type: 'w-text' }, |
|||
{ label: '用户名', name: 'userName', type: 'w-text' }, |
|||
{ label: '描述', name: 'description', type: 'w-text' }, |
|||
{ label: '用户名', name: 'userName1', type: 'w-text' }, |
|||
{ label: '描述', name: 'description1', type: 'w-text' }, |
|||
{ |
|||
label: '是否可用', |
|||
name: 'enable', |
|||
type: 'select', |
|||
options: [{ label: '监管报表-G4B-1表内信用风险加权资产计算表(权重法)', value: '0a981b42-d0df-4f02-94c4-edc20620ba9f' }], |
|||
}, |
|||
// { label: '邮箱地址', name: 'email', type: 'w-text' }, |
|||
// { label: '电话', name: 'phone', type: 'w-text' }, |
|||
// { label: '手机号', name: 'mobile', type: 'w-number' }, |
|||
// { label: '最后修改人', name: 'lastModifier', type: 'w-text' }, |
|||
// { label: '最后修改时间', name: 'lastModifyDate', type: 'w-date' }, |
|||
], |
|||
tableColumns: [ |
|||
// { |
|||
// name: 'info', |
|||
// label: '用户信息', |
|||
// columns: [ |
|||
// { name: 'loginName', label: '登录名', align: 'right' }, |
|||
// { name: 'userName', label: '用户名' }, |
|||
// ], |
|||
// }, |
|||
{ name: 'loginName', label: '登录名', align: 'right' }, |
|||
{ name: 'userName', label: '用户名' }, |
|||
// { |
|||
// name: 'lxxx', |
|||
// label: '联系方式', |
|||
// columns: [ |
|||
// { |
|||
// name: 'email', |
|||
// label: '邮箱地址', |
|||
// columns: [ |
|||
// { width: 100, name: 'auc', label: 'auc' }, |
|||
// { width: 100, name: 'ar', label: 'ar' }, |
|||
// { width: 100, name: 'ks', label: 'ks' }, |
|||
// ], |
|||
// }, |
|||
// { |
|||
// name: 'tx', |
|||
// label: '通讯', |
|||
// columns: [ |
|||
// { name: 'phone', label: '电话' }, |
|||
// { name: 'mobile', label: '手机号' }, |
|||
// ], |
|||
// }, |
|||
// { |
|||
// name: 'qq', |
|||
// label: 'QQ', |
|||
// // columns: [ |
|||
// // { width: 100, name: 'aucQualitative', label: 'aucQualitative' }, |
|||
// // { width: 100, name: 'arQualitative', label: 'arQualitative' }, |
|||
// // { width: 100, name: 'ksQualitative', label: 'ksQualitative' }, |
|||
// // ], |
|||
// }, |
|||
// ], |
|||
// }, |
|||
{ name: 'email', label: '邮箱地址' }, |
|||
{ name: 'phone', label: '电话' }, |
|||
{ name: 'mobile', label: '手机号' }, |
|||
{ name: 'qq', label: 'QQ' }, |
|||
{ name: 'description', label: '描述', width: 400 }, |
|||
{ |
|||
name: 'enable', |
|||
label: '是否可用', |
|||
align: 'center', |
|||
width: 400, |
|||
format: (val, row) => { |
|||
return { |
|||
componentType: 'q-checkbox', |
|||
bindModelValue: true, |
|||
attrs: { |
|||
dense: true, |
|||
}, |
|||
}; |
|||
// return { |
|||
// componentType: 'q-icon', |
|||
// attrs: { |
|||
// name: val ? IconEnum.是状态 : IconEnum.否状态, |
|||
// color: val ? 'green' : 'red', |
|||
// size: 'xs', |
|||
// }, |
|||
// }; |
|||
}, |
|||
}, |
|||
// { name: 'loginName', label: '登录名', align: 'right' }, |
|||
// { name: 'userName', label: '用户名' }, |
|||
{ name: 'lastModifier', label: '最后修改人' }, |
|||
{ name: 'lastModifyDate', label: '最后修改时间' }, |
|||
], |
|||
addEdit: { |
|||
dialog: {}, |
|||
form: { |
|||
colsNum: 1, |
|||
fields: [ |
|||
{ label: '登录名', name: 'loginName', type: 'w-text' }, |
|||
{ label: '用户名', name: 'userName', type: 'w-text' }, |
|||
{ label: '密码', name: 'password', type: 'w-text' }, |
|||
{ label: '是否可用1111', name: 'enable', type: 'w-checkbox' }, |
|||
{ |
|||
name: 'urlOpenType', |
|||
label: 'urlOpenType', |
|||
type: 'select', |
|||
options: Options.enum(UrlOpenTypeEnum, false), |
|||
defaultValue: 'NEW_WINDOW', |
|||
}, |
|||
], |
|||
}, |
|||
}, |
|||
view: { |
|||
panel: { |
|||
columnNum: 2, |
|||
fields: [ |
|||
{ name: 'id', label: '主键' }, |
|||
{ name: 'loginName', label: '登录名' }, |
|||
{ name: 'userName', label: '用户名' }, |
|||
{ name: 'description', label: '描述' }, |
|||
{ |
|||
name: 'enable', |
|||
label: '是否可用', |
|||
}, |
|||
{ name: 'email', label: '邮箱地址' }, |
|||
{ name: 'phone', label: '电话' }, |
|||
{ name: 'mobile', label: '手机号' }, |
|||
{ name: 'lastModifier', label: '最后修改人' }, |
|||
{ name: 'lastModifyDate', label: '最后修改时间' }, |
|||
], |
|||
}, |
|||
}, |
|||
}; |
|||
|
|||
onMounted(() => { |
|||
// gridRef.value.setLocalData([ |
|||
// { |
|||
// loginName: 'admin1', |
|||
// }, |
|||
// { |
|||
// loginName: 'admin2', |
|||
// }, |
|||
// { |
|||
// loginName: 'admin3', |
|||
// }, |
|||
// { |
|||
// loginName: 'admin4', |
|||
// }, |
|||
// { |
|||
// loginName: 'admin5', |
|||
// }, |
|||
// { |
|||
// loginName: 'admin6', |
|||
// }, |
|||
// { |
|||
// loginName: 'admin7', |
|||
// }, |
|||
// { |
|||
// loginName: 'admin8', |
|||
// }, |
|||
// { |
|||
// loginName: 'admin9', |
|||
// }, |
|||
// { |
|||
// loginName: 'admin10', |
|||
// }, |
|||
// { |
|||
// loginName: 'admin11', |
|||
// }, |
|||
// { |
|||
// loginName: 'admin12', |
|||
// }, |
|||
// { |
|||
// loginName: 'admin13', |
|||
// }, |
|||
// ]); |
|||
}); |
|||
const rowClick = () => {}; |
|||
</script> |
|||
|
@ -0,0 +1,232 @@ |
|||
{ |
|||
"enable": true, |
|||
"url": "/api/rwa/params/isc/fetchParams?pageable=false&sortBy=sortNo", |
|||
"method": "get", |
|||
"response": { |
|||
"code" : 200, |
|||
"messageI18nKey" : "success", |
|||
"message" : "success", |
|||
"data" : [ { |
|||
"jpaVersion" : null, |
|||
"dataComeFrom" : "INPUT", |
|||
"creator" : "admin", |
|||
"createDate" : "2023-09-05 02:02:14", |
|||
"lastModifier" : "admin", |
|||
"lastModifyDate" : "2023-09-05 02:02:14", |
|||
"corporationCode" : null, |
|||
"id" : "2268c3e2-c03f-4d8a-8bcd-e37d24cf955e", |
|||
"name" : "银行参数", |
|||
"parent" : null, |
|||
"children" : [ ], |
|||
"icon" : "folder", |
|||
"isFolder" : true, |
|||
"sortNo" : null, |
|||
"isDefault" : false, |
|||
"pageType" : null, |
|||
"templateId" : null, |
|||
"routeName" : null, |
|||
"routeQuery" : null |
|||
}, { |
|||
"jpaVersion" : null, |
|||
"dataComeFrom" : "INPUT", |
|||
"creator" : "admin", |
|||
"createDate" : "2023-08-30 08:00:00", |
|||
"lastModifier" : "admin", |
|||
"lastModifyDate" : "2023-08-30 08:00:00", |
|||
"corporationCode" : null, |
|||
"id" : "BIII", |
|||
"name" : "BIII参数", |
|||
"parent" : null, |
|||
"children" : [ { |
|||
"jpaVersion" : null, |
|||
"dataComeFrom" : "INPUT", |
|||
"creator" : "admin", |
|||
"createDate" : "2024-02-26 17:34:22", |
|||
"lastModifier" : "admin", |
|||
"lastModifyDate" : "2024-02-26 17:34:22", |
|||
"corporationCode" : "_PRIMARY_", |
|||
"id" : "478b6c43-ca5b-45c4-a0cb-14715f45c98c", |
|||
"name" : "信用风险-表内风险权重参数表", |
|||
"parent" : "BIII", |
|||
"ticked" : true, |
|||
"children" : [ ], |
|||
"icon" : "calendar_month", |
|||
"isFolder" : false, |
|||
"sortNo" : 100, |
|||
"isDefault" : true, |
|||
"pageType" : "TEMPLATE", |
|||
"templateId" : "47442edb-7b0d-4dc4-ab71-755ddbae71bf", |
|||
"routeName" : null, |
|||
"routeQuery" : null |
|||
}, { |
|||
"jpaVersion" : null, |
|||
"dataComeFrom" : "INPUT", |
|||
"creator" : null, |
|||
"createDate" : null, |
|||
"lastModifier" : "admin", |
|||
"lastModifyDate" : "2024-02-27 15:41:34", |
|||
"corporationCode" : "_PRIMARY_", |
|||
"id" : "BWFXQZ", |
|||
"name" : "信用风险-表外主体权重参数表", |
|||
"parent" : "BIII", |
|||
"children" : [ ], |
|||
"icon" : "calendar_today", |
|||
"isFolder" : false, |
|||
"sortNo" : 200, |
|||
"isDefault" : false, |
|||
"pageType" : "TEMPLATE", |
|||
"templateId" : "1b42b129-b683-4ac0-a8dc-3d39db1eb836", |
|||
"routeName" : null, |
|||
"routeQuery" : null |
|||
} ], |
|||
"icon" : "folder", |
|||
"isFolder" : true, |
|||
"sortNo" : 100, |
|||
"isDefault" : false, |
|||
"pageType" : null, |
|||
"templateId" : null, |
|||
"routeName" : null, |
|||
"routeQuery" : null |
|||
}, { |
|||
"jpaVersion" : null, |
|||
"dataComeFrom" : "INPUT", |
|||
"creator" : "admin", |
|||
"createDate" : "2024-02-28 13:56:36", |
|||
"lastModifier" : "admin", |
|||
"lastModifyDate" : "2024-02-28 13:56:36", |
|||
"corporationCode" : "_PRIMARY_", |
|||
"id" : "bc56db9d-c4ad-4d66-9d55-7ae1a9ad3af3", |
|||
"name" : "交易对手信用风险", |
|||
"parent" : null, |
|||
"children" : [ { |
|||
"jpaVersion" : null, |
|||
"dataComeFrom" : "INPUT", |
|||
"creator" : "admin", |
|||
"createDate" : "2024-02-28 14:03:45", |
|||
"lastModifier" : "admin", |
|||
"lastModifyDate" : "2024-02-28 14:03:45", |
|||
"corporationCode" : "_PRIMARY_", |
|||
"id" : "fac9819a-84a7-46bd-9e89-47e07ebeb31b", |
|||
"name" : "交易对手信用风险设置", |
|||
"parent" : "bc56db9d-c4ad-4d66-9d55-7ae1a9ad3af3", |
|||
"children" : [ ], |
|||
"icon" : "settings_suggest", |
|||
"isFolder" : false, |
|||
"sortNo" : 100, |
|||
"isDefault" : false, |
|||
"pageType" : "TEMPLATE", |
|||
"templateId" : "61da07af-351f-4c70-9e58-0ab99ca1d730", |
|||
"routeName" : null, |
|||
"routeQuery" : null |
|||
}, { |
|||
"jpaVersion" : null, |
|||
"dataComeFrom" : "INPUT", |
|||
"creator" : "admin", |
|||
"createDate" : "2024-02-28 14:55:57", |
|||
"lastModifier" : "admin", |
|||
"lastModifyDate" : "2024-02-28 14:55:57", |
|||
"corporationCode" : "_PRIMARY_", |
|||
"id" : "2389c168-12c5-4955-b31f-5090f9dcea4b", |
|||
"name" : "SACCR监管参数配置", |
|||
"parent" : "bc56db9d-c4ad-4d66-9d55-7ae1a9ad3af3", |
|||
"children" : [ ], |
|||
"icon" : "settings_applications", |
|||
"isFolder" : false, |
|||
"sortNo" : 200, |
|||
"isDefault" : false, |
|||
"pageType" : "TEMPLATE", |
|||
"templateId" : "df6de052-7f56-42bd-895b-ca09088e0906", |
|||
"routeName" : null, |
|||
"routeQuery" : null |
|||
}, { |
|||
"jpaVersion" : null, |
|||
"dataComeFrom" : "INPUT", |
|||
"creator" : null, |
|||
"createDate" : null, |
|||
"lastModifier" : "admin", |
|||
"lastModifyDate" : "2024-02-28 16:13:48", |
|||
"corporationCode" : "_PRIMARY_", |
|||
"id" : "ec48aefe-1181-4764-9a97-b149f20b520e", |
|||
"name" : "CVA行业类别映射", |
|||
"parent" : "bc56db9d-c4ad-4d66-9d55-7ae1a9ad3af3", |
|||
"children" : [ ], |
|||
"icon" : "linear_scale", |
|||
"isFolder" : false, |
|||
"sortNo" : 300, |
|||
"isDefault" : false, |
|||
"pageType" : "TEMPLATE", |
|||
"templateId" : "125dc90f-15cb-4b82-961b-1b7361f0df5e", |
|||
"routeName" : null, |
|||
"routeQuery" : null |
|||
}, { |
|||
"jpaVersion" : null, |
|||
"dataComeFrom" : "INPUT", |
|||
"creator" : null, |
|||
"createDate" : null, |
|||
"lastModifier" : "admin", |
|||
"lastModifyDate" : "2024-02-28 16:31:40", |
|||
"corporationCode" : "_PRIMARY_", |
|||
"id" : "a315ede8-3438-4d00-a60a-c9ef2babc0b1", |
|||
"name" : "货币优先顺序", |
|||
"parent" : "bc56db9d-c4ad-4d66-9d55-7ae1a9ad3af3", |
|||
"children" : [ ], |
|||
"icon" : "currency_yen", |
|||
"isFolder" : false, |
|||
"sortNo" : 400, |
|||
"isDefault" : false, |
|||
"pageType" : "TEMPLATE", |
|||
"templateId" : "3fcee541-43f6-480e-827b-6cf021f748eb", |
|||
"routeName" : null, |
|||
"routeQuery" : null |
|||
}, { |
|||
"jpaVersion" : null, |
|||
"dataComeFrom" : "INPUT", |
|||
"creator" : "admin", |
|||
"createDate" : "2024-02-28 16:45:56", |
|||
"lastModifier" : "admin", |
|||
"lastModifyDate" : "2024-02-28 16:45:56", |
|||
"corporationCode" : "_PRIMARY_", |
|||
"id" : "8865a5dd-0a88-4362-9ba9-192009072ad0", |
|||
"name" : "CVA评级等级映射", |
|||
"parent" : "bc56db9d-c4ad-4d66-9d55-7ae1a9ad3af3", |
|||
"children" : [ ], |
|||
"icon" : "format_list_numbered", |
|||
"isFolder" : false, |
|||
"sortNo" : 500, |
|||
"isDefault" : false, |
|||
"pageType" : "TEMPLATE", |
|||
"templateId" : "637eea6b-1fcf-4977-a56b-9653b0703c31", |
|||
"routeName" : null, |
|||
"routeQuery" : null |
|||
}, { |
|||
"jpaVersion" : null, |
|||
"dataComeFrom" : "INPUT", |
|||
"creator" : "admin", |
|||
"createDate" : "2024-02-28 17:08:39", |
|||
"lastModifier" : "admin", |
|||
"lastModifyDate" : "2024-02-28 17:08:39", |
|||
"corporationCode" : "_PRIMARY_", |
|||
"id" : "62021407-ac21-4fde-a37d-e53865b94aa5", |
|||
"name" : "CVA权重映射", |
|||
"parent" : "bc56db9d-c4ad-4d66-9d55-7ae1a9ad3af3", |
|||
"children" : [ ], |
|||
"icon" : "percent", |
|||
"isFolder" : false, |
|||
"sortNo" : 600, |
|||
"isDefault" : false, |
|||
"pageType" : "TEMPLATE", |
|||
"templateId" : "dacd1de2-8492-4123-b1fb-f8abb4f6346b", |
|||
"routeName" : null, |
|||
"routeQuery" : null |
|||
} ], |
|||
"icon" : "folder", |
|||
"isFolder" : true, |
|||
"sortNo" : 300, |
|||
"isDefault" : false, |
|||
"pageType" : null, |
|||
"templateId" : null, |
|||
"routeName" : null, |
|||
"routeQuery" : null |
|||
} ] |
|||
} |
|||
} |
@ -0,0 +1,5 @@ |
|||
dependencies { |
|||
api( |
|||
"com.oceanbase:oceanbase-client:2.4.0", |
|||
) |
|||
} |
@ -0,0 +1,10 @@ |
|||
{ |
|||
"installerEnable" : true, |
|||
"type" : "OceanBase", |
|||
"version" : "2.4", |
|||
"driver" : "com.oceanbase.jdbc.Driver", |
|||
"url" : "jdbc:oceanbase://${host}:${port}/${database}", |
|||
"urlSample" : "jdbc:oceanbase://localhost:2883/shemaname?pool=false", |
|||
"hibernateDialect" : "org.hibernate.dialect.Oracle10gDialect", |
|||
"validationQuery" : "select 1 from dual" |
|||
} |
Loading…
Reference in new issue