Browse Source

synchronize vben admin changes

pull/744/head
cKey 3 years ago
parent
commit
b52d4f71e2
  1. 1
      apps/vue/build/vite/plugin/styleImport.ts
  2. 2
      apps/vue/package.json
  3. 9
      apps/vue/src/components/Button/src/props.ts
  4. 4
      apps/vue/src/components/Cropper/src/CropperAvatar.vue
  5. 24
      apps/vue/src/components/Excel/src/Export2Excel.ts
  6. 4
      apps/vue/src/components/Excel/src/ImportExcel.vue
  7. 12
      apps/vue/src/components/Form/src/BasicForm.vue
  8. 4
      apps/vue/src/components/Form/src/TabForm.vue
  9. 9
      apps/vue/src/components/Form/src/components/ApiSelect.vue
  10. 9
      apps/vue/src/components/Form/src/components/ApiTransfer.vue
  11. 7
      apps/vue/src/components/Form/src/components/FormItem.vue
  12. 9
      apps/vue/src/components/Form/src/hooks/useAdvanced.ts
  13. 4
      apps/vue/src/components/Form/src/hooks/useForm.ts
  14. 24
      apps/vue/src/components/Form/src/hooks/useFormEvents.ts
  15. 13
      apps/vue/src/components/Form/src/hooks/useFormValues.ts
  16. 4
      apps/vue/src/components/Form/src/props.ts
  17. 7
      apps/vue/src/components/Form/src/types/form.ts
  18. 2
      apps/vue/src/components/Menu/src/props.ts
  19. 10
      apps/vue/src/components/Preview/src/Functional.vue
  20. 3
      apps/vue/src/components/Table/src/BasicTable.vue
  21. 6
      apps/vue/src/components/Table/src/componentMap.ts
  22. 12
      apps/vue/src/components/Table/src/components/TableImg.vue
  23. 4
      apps/vue/src/components/Table/src/components/editable/EditableCell.vue
  24. 59
      apps/vue/src/components/Table/src/components/settings/ColumnSetting.vue
  25. 2
      apps/vue/src/components/Table/src/hooks/useCustomRow.ts
  26. 4
      apps/vue/src/components/Table/src/hooks/useRowSelection.ts
  27. 3
      apps/vue/src/components/Table/src/hooks/useTable.ts
  28. 5
      apps/vue/src/components/Table/src/types/componentType.ts
  29. 3
      apps/vue/src/components/Table/src/types/table.ts
  30. 2
      apps/vue/src/components/Tinymce/src/Editor.vue
  31. 4
      apps/vue/src/components/Tree/index.ts
  32. 76
      apps/vue/src/components/Tree/src/BasicTree.vue
  33. 14
      apps/vue/src/components/Tree/src/components/TreeHeader.vue
  34. 2
      apps/vue/src/components/Tree/src/hooks/useTree.ts
  35. 108
      apps/vue/src/components/Tree/src/props.ts
  36. 1
      apps/vue/src/components/Tree/src/types/tree.ts
  37. 54
      apps/vue/src/components/Tree/src/typing.ts
  38. 2
      apps/vue/src/components/Upload/src/props.ts
  39. 10
      apps/vue/src/components/Verify/src/props.ts
  40. 8
      apps/vue/src/design/ant/index.less
  41. 5
      apps/vue/src/design/ant/input.less
  42. 8
      apps/vue/src/hooks/web/useECharts.ts
  43. 7
      apps/vue/src/layouts/default/header/components/FullScreen.vue
  44. 2
      apps/vue/src/layouts/default/setting/components/ThemeColorPicker.vue
  45. 2
      apps/vue/src/layouts/default/setting/components/TypePicker.vue
  46. 2
      apps/vue/src/locales/lang/en/layout.ts
  47. 2
      apps/vue/src/router/constant.ts
  48. 1
      apps/vue/src/store/modules/multipleTab.ts
  49. 11
      apps/vue/src/utils/dateUtil.ts
  50. 6
      apps/vue/src/utils/http/axios/index.ts
  51. 6
      apps/vue/src/utils/index.ts
  52. 3
      apps/vue/src/utils/is.ts
  53. 4
      apps/vue/src/views/account/setting/BaseSetting.vue
  54. 3
      apps/vue/src/views/oss-management/objects/components/FileList.vue
  55. 2
      apps/vue/src/views/platform/menu/hooks/useMenuFormContext.ts

1
apps/vue/build/vite/plugin/styleImport.ts

@ -49,6 +49,7 @@ export function configStyleImportPlugin(_isBuild: boolean) {
// 这里是需要额外引入样式的子组件列表 // 这里是需要额外引入样式的子组件列表
// 单独引入子组件时需引入组件样式,否则会在打包后导致子组件样式丢失 // 单独引入子组件时需引入组件样式,否则会在打包后导致子组件样式丢失
const replaceList = { const replaceList = {
textarea: 'input',
'typography-text': 'typography', 'typography-text': 'typography',
'typography-title': 'typography', 'typography-title': 'typography',
'typography-paragraph': 'typography', 'typography-paragraph': 'typography',

2
apps/vue/package.json

@ -149,7 +149,7 @@
"vite-plugin-vue-setup-extend": "^0.4.0", "vite-plugin-vue-setup-extend": "^0.4.0",
"vite-plugin-windicss": "^1.8.4", "vite-plugin-windicss": "^1.8.4",
"vue-eslint-parser": "^8.3.0", "vue-eslint-parser": "^8.3.0",
"vue-tsc": "^0.33.9" "vue-tsc": "^1.0.9"
}, },
"resolutions": { "resolutions": {
"bin-wrapper": "npm:bin-wrapper-china", "bin-wrapper": "npm:bin-wrapper-china",

9
apps/vue/src/components/Button/src/props.ts

@ -1,5 +1,12 @@
const validColors = ['error', 'warning', 'success', ''] as const;
type ButtonColorType = typeof validColors[number];
export const buttonProps = { export const buttonProps = {
color: { type: String, validator: (v) => ['error', 'warning', 'success', ''].includes(v) }, color: {
type: String as PropType<ButtonColorType>,
validator: (v) => validColors.includes(v),
default: '',
},
loading: { type: Boolean }, loading: { type: Boolean },
disabled: { type: Boolean }, disabled: { type: Boolean },
/** /**

4
apps/vue/src/components/Cropper/src/CropperAvatar.vue

@ -92,9 +92,9 @@
}, },
); );
function handleUploadSuccess({ source }) { function handleUploadSuccess({ source, data }) {
sourceValue.value = source; sourceValue.value = source;
emits('change', source); emits('change', { source, data });
createMessage.success(t('component.cropper.uploadSuccess')); createMessage.success(t('component.cropper.uploadSuccess'));
} }

24
apps/vue/src/components/Excel/src/Export2Excel.ts

@ -6,6 +6,28 @@ const { utils, writeFile } = xlsx;
const DEF_FILE_NAME = 'excel-list.xlsx'; const DEF_FILE_NAME = 'excel-list.xlsx';
/**
* @param data source data
* @param worksheet worksheet object
* @param min min width
*/
function setColumnWidth(data, worksheet, min = 3) {
const obj = {};
worksheet['!cols'] = [];
data.forEach((item) => {
Object.keys(item).forEach((key) => {
const cur = item[key];
const length = cur?.length ?? min;
obj[key] = Math.max(length, obj[key] ?? min);
});
});
Object.keys(obj).forEach((key) => {
worksheet['!cols'].push({
wch: obj[key],
});
});
}
export function jsonToSheetXlsx<T = any>({ export function jsonToSheetXlsx<T = any>({
data, data,
header, header,
@ -20,7 +42,7 @@ export function jsonToSheetXlsx<T = any>({
} }
const worksheet = utils.json_to_sheet(arrData, json2sheetOpts); const worksheet = utils.json_to_sheet(arrData, json2sheetOpts);
setColumnWidth(arrData, worksheet);
/* add worksheet to workbook */ /* add worksheet to workbook */
const workbook: WorkBook = { const workbook: WorkBook = {
SheetNames: [filename], SheetNames: [filename],

4
apps/vue/src/components/Excel/src/ImportExcel.vue

@ -137,8 +137,10 @@
* @description: 触发选择文件管理器 * @description: 触发选择文件管理器
*/ */
function handleInputClick(e: Event) { function handleInputClick(e: Event) {
const files = e && (e.target as HTMLInputElement).files; const target = e && (e.target as HTMLInputElement);
const files = target?.files;
const rawFile = files && files[0]; // only setting files[0] const rawFile = files && files[0]; // only setting files[0]
target.value = '';
if (!rawFile) return; if (!rawFile) return;
upload(rawFile); upload(rawFile);
} }

12
apps/vue/src/components/Form/src/BasicForm.vue

@ -10,6 +10,7 @@
<slot name="formHeader"></slot> <slot name="formHeader"></slot>
<template v-for="schema in getSchema" :key="schema.field"> <template v-for="schema in getSchema" :key="schema.field">
<FormItem <FormItem
:isAdvanced="fieldsIsAdvancedMap[schema.field]"
:tableAction="tableAction" :tableAction="tableAction"
:formActionType="formActionType" :formActionType="formActionType"
:schema="schema" :schema="schema"
@ -117,9 +118,9 @@
const getSchema = computed((): FormSchema[] => { const getSchema = computed((): FormSchema[] => {
const schemas: FormSchema[] = unref(schemaRef) || (unref(getProps).schemas as any); const schemas: FormSchema[] = unref(schemaRef) || (unref(getProps).schemas as any);
for (const schema of schemas) { for (const schema of schemas) {
const { defaultValue, component } = schema; const { defaultValue, component, isHandleDateDefaultValue = true } = schema;
// handle date type // handle date type
if (defaultValue && dateItemType.includes(component)) { if (isHandleDateDefaultValue && defaultValue && dateItemType.includes(component)) {
if (!Array.isArray(defaultValue)) { if (!Array.isArray(defaultValue)) {
schema.defaultValue = dateUtil(defaultValue); schema.defaultValue = dateUtil(defaultValue);
} else { } else {
@ -138,7 +139,7 @@
} }
}); });
const { handleToggleAdvanced } = useAdvanced({ const { handleToggleAdvanced, fieldsIsAdvancedMap } = useAdvanced({
advanceState, advanceState,
emit, emit,
getProps, getProps,
@ -171,7 +172,7 @@
updateSchema, updateSchema,
resetSchema, resetSchema,
appendSchemaByField, appendSchemaByField,
removeSchemaByFiled, removeSchemaByField,
resetFields, resetFields,
scrollToField, scrollToField,
} = useFormEvents({ } = useFormEvents({
@ -265,7 +266,7 @@
updateSchema, updateSchema,
resetSchema, resetSchema,
setProps, setProps,
removeSchemaByFiled, removeSchemaByField,
appendSchemaByField, appendSchemaByField,
clearValidate, clearValidate,
validateFields, validateFields,
@ -296,6 +297,7 @@
getFormActionBindProps: computed( getFormActionBindProps: computed(
(): Recordable => ({ ...getProps.value, ...advanceState }), (): Recordable => ({ ...getProps.value, ...advanceState }),
), ),
fieldsIsAdvancedMap,
...formActionType, ...formActionType,
}; };
}, },

4
apps/vue/src/components/Form/src/TabForm.vue

@ -214,7 +214,7 @@
updateSchema, updateSchema,
resetSchema, resetSchema,
appendSchemaByField, appendSchemaByField,
removeSchemaByFiled, removeSchemaByField,
resetFields, resetFields,
scrollToField, scrollToField,
} = useFormEvents({ } = useFormEvents({
@ -319,7 +319,7 @@
updateSchema, updateSchema,
resetSchema, resetSchema,
setProps, setProps,
removeSchemaByFiled, removeSchemaByField,
appendSchemaByField, appendSchemaByField,
clearValidate, clearValidate,
validateFields, validateFields,

9
apps/vue/src/components/Form/src/components/ApiSelect.vue

@ -59,7 +59,7 @@
immediate: propTypes.bool.def(true), immediate: propTypes.bool.def(true),
alwaysLoad: propTypes.bool.def(false), alwaysLoad: propTypes.bool.def(false),
}, },
emits: ['options-change', 'change'], emits: ['options-change', 'change', 'update:value'],
setup(props, { emit }) { setup(props, { emit }) {
const options = ref<OptionsItem[]>([]); const options = ref<OptionsItem[]>([]);
const loading = ref(false); const loading = ref(false);
@ -91,6 +91,13 @@
props.immediate && !props.alwaysLoad && fetch(); props.immediate && !props.alwaysLoad && fetch();
}); });
watch(
() => state.value,
(v) => {
emit('update:value', v);
},
);
watch( watch(
() => props.params, () => props.params,
() => { () => {

9
apps/vue/src/components/Form/src/components/ApiTransfer.vue

@ -1,7 +1,6 @@
<template> <template>
<Transfer <Transfer
:data-source="getdataSource" :data-source="getdataSource"
show-search
:filter-option="filterOption" :filter-option="filterOption"
:render="(item) => item.title" :render="(item) => item.title"
:showSelectAll="showSelectAll" :showSelectAll="showSelectAll"
@ -24,13 +23,13 @@
name: 'ApiTransfer', name: 'ApiTransfer',
components: { Transfer }, components: { Transfer },
props: { props: {
value: { type: Array<string> }, value: { type: Array as PropType<Array<string>> },
api: { api: {
type: Function as PropType<(arg?: Recordable) => Promise<TransferItem[]>>, type: Function as PropType<(arg?: Recordable) => Promise<TransferItem[]>>,
default: null, default: null,
}, },
params: { type: Object }, params: { type: Object },
dataSource: { type: Array<TransferItem> }, dataSource: { type: Array as PropType<Array<TransferItem>> },
immediate: propTypes.bool.def(true), immediate: propTypes.bool.def(true),
alwaysLoad: propTypes.bool.def(false), alwaysLoad: propTypes.bool.def(false),
afterFetch: { type: Function as PropType<Fn> }, afterFetch: { type: Function as PropType<Fn> },
@ -42,9 +41,9 @@
filterOption: { filterOption: {
type: Function as PropType<(inputValue: string, item: TransferItem) => boolean>, type: Function as PropType<(inputValue: string, item: TransferItem) => boolean>,
}, },
selectedKeys: { type: Array<string> }, selectedKeys: { type: Array as PropType<Array<string>> },
showSelectAll: { type: Boolean, default: false }, showSelectAll: { type: Boolean, default: false },
targetKeys: { type: Array<string> }, targetKeys: { type: Array as PropType<Array<string>> },
}, },
emits: ['options-change', 'change'], emits: ['options-change', 'change'],
setup(props, { attrs, emit }) { setup(props, { attrs, emit }) {

7
apps/vue/src/components/Form/src/components/FormItem.vue

@ -43,6 +43,9 @@
formActionType: { formActionType: {
type: Object as PropType<FormActionType>, type: Object as PropType<FormActionType>,
}, },
isAdvanced: {
type: Boolean,
},
}, },
setup(props, { slots }) { setup(props, { slots }) {
const { t } = useI18n(); const { t } = useI18n();
@ -102,8 +105,8 @@
const { show, ifShow } = props.schema; const { show, ifShow } = props.schema;
const { showAdvancedButton } = props.formProps; const { showAdvancedButton } = props.formProps;
const itemIsAdvanced = showAdvancedButton const itemIsAdvanced = showAdvancedButton
? isBoolean(props.schema.isAdvanced) ? isBoolean(props.isAdvanced)
? props.schema.isAdvanced ? props.isAdvanced
: true : true
: true; : true;

9
apps/vue/src/components/Form/src/hooks/useAdvanced.ts

@ -2,7 +2,7 @@ import type { ColEx } from '../types';
import type { AdvanceState } from '../types/hooks'; import type { AdvanceState } from '../types/hooks';
import type { ComputedRef, Ref } from 'vue'; import type { ComputedRef, Ref } from 'vue';
import type { FormProps, FormSchema } from '../types/form'; import type { FormProps, FormSchema } from '../types/form';
import { computed, unref, watch } from 'vue'; import { computed, unref, watch, shallowReactive } from 'vue';
import { isBoolean, isFunction, isNumber, isObject } from '/@/utils/is'; import { isBoolean, isFunction, isNumber, isObject } from '/@/utils/is';
import { useBreakpoint } from '/@/hooks/event/useBreakpoint'; import { useBreakpoint } from '/@/hooks/event/useBreakpoint';
import { useDebounceFn } from '@vueuse/core'; import { useDebounceFn } from '@vueuse/core';
@ -111,6 +111,8 @@ export default function ({
} }
} }
const fieldsIsAdvancedMap = shallowReactive({});
function updateAdvanced() { function updateAdvanced() {
let itemColSum = 0; let itemColSum = 0;
let realItemColSum = 0; let realItemColSum = 0;
@ -146,7 +148,8 @@ export default function ({
if (isAdvanced) { if (isAdvanced) {
realItemColSum = itemColSum; realItemColSum = itemColSum;
} }
schema.isAdvanced = isAdvanced;
fieldsIsAdvancedMap[schema.field] = isAdvanced;
} }
} }
@ -161,5 +164,5 @@ export default function ({
advanceState.isAdvanced = !advanceState.isAdvanced; advanceState.isAdvanced = !advanceState.isAdvanced;
} }
return { handleToggleAdvanced }; return { handleToggleAdvanced, fieldsIsAdvancedMap };
} }

4
apps/vue/src/components/Form/src/hooks/useForm.ts

@ -79,8 +79,8 @@ export function useForm(props?: Props): UseFormReturnType {
}); });
}, },
removeSchemaByFiled: async (field: string | string[]) => { removeSchemaByField: async (field: string | string[]) => {
unref(formRef)?.removeSchemaByFiled(field); unref(formRef)?.removeSchemaByField(field);
}, },
// TODO promisify // TODO promisify

24
apps/vue/src/components/Form/src/hooks/useFormEvents.ts

@ -2,7 +2,15 @@ import type { ComputedRef, Ref } from 'vue';
import type { FormProps, FormSchema, FormActionType } from '../types/form'; import type { FormProps, FormSchema, FormActionType } from '../types/form';
import type { NamePath } from 'ant-design-vue/lib/form/interface'; import type { NamePath } from 'ant-design-vue/lib/form/interface';
import { unref, toRaw, nextTick } from 'vue'; import { unref, toRaw, nextTick } from 'vue';
import { isArray, isFunction, isObject, isString, isDef, isNullOrUnDef } from '/@/utils/is'; import {
isArray,
isFunction,
isObject,
isString,
isDef,
isNullOrUnDef,
isEmpty,
} from '/@/utils/is';
import { deepMerge } from '/@/utils'; import { deepMerge } from '/@/utils';
import { dateItemType, handleInputNumberValue, defaultValueComponents } from '../helper'; import { dateItemType, handleInputNumberValue, defaultValueComponents } from '../helper';
import { dateUtil } from '/@/utils/dateUtil'; import { dateUtil } from '/@/utils/dateUtil';
@ -94,7 +102,7 @@ export function useFormEvents({
} else { } else {
nestKeyArray.forEach((nestKey: string) => { nestKeyArray.forEach((nestKey: string) => {
try { try {
const value = eval('values' + delimiter + nestKey); const value = nestKey.split('.').reduce((out, item) => out[item], values);
if (isDef(value)) { if (isDef(value)) {
formModel[nestKey] = value; formModel[nestKey] = value;
validKeys.push(nestKey); validKeys.push(nestKey);
@ -114,7 +122,7 @@ export function useFormEvents({
/** /**
* @description: Delete based on field name * @description: Delete based on field name
*/ */
async function removeSchemaByFiled(fields: string | string[]): Promise<void> { async function removeSchemaByField(fields: string | string[]): Promise<void> {
const schemaList: FormSchema[] = cloneDeep(unref(getSchema)); const schemaList: FormSchema[] = cloneDeep(unref(getSchema));
if (!fields) { if (!fields) {
return; return;
@ -125,7 +133,7 @@ export function useFormEvents({
fieldList = [fields]; fieldList = [fields];
} }
for (const field of fieldList) { for (const field of fieldList) {
_removeSchemaByFiled(field, schemaList); _removeSchemaByField(field, schemaList);
} }
schemaRef.value = schemaList; schemaRef.value = schemaList;
} }
@ -133,7 +141,7 @@ export function useFormEvents({
/** /**
* @description: Delete based on field name * @description: Delete based on field name
*/ */
function _removeSchemaByFiled(field: string, schemaList: FormSchema[]): void { function _removeSchemaByField(field: string, schemaList: FormSchema[]): void {
if (isString(field)) { if (isString(field)) {
const index = schemaList.findIndex((schema) => schema.field === field); const index = schemaList.findIndex((schema) => schema.field === field);
if (index !== -1) { if (index !== -1) {
@ -239,7 +247,9 @@ export function useFormEvents({
Reflect.has(item, 'field') && Reflect.has(item, 'field') &&
item.field && item.field &&
!isNullOrUnDef(item.defaultValue) && !isNullOrUnDef(item.defaultValue) &&
!(item.field in currentFieldsValue) (!(item.field in currentFieldsValue) ||
isNullOrUnDef(currentFieldsValue[item.field]) ||
isEmpty(currentFieldsValue[item.field]))
) { ) {
obj[item.field] = item.defaultValue; obj[item.field] = item.defaultValue;
} }
@ -308,7 +318,7 @@ export function useFormEvents({
updateSchema, updateSchema,
resetSchema, resetSchema,
appendSchemaByField, appendSchemaByField,
removeSchemaByFiled, removeSchemaByField,
resetFields, resetFields,
setFieldsValue, setFieldsValue,
scrollToField, scrollToField,

13
apps/vue/src/components/Form/src/hooks/useFormValues.ts

@ -97,14 +97,21 @@ export function useFormValues({
} }
for (const [field, [startTimeKey, endTimeKey], format = 'YYYY-MM-DD'] of fieldMapToTime) { for (const [field, [startTimeKey, endTimeKey], format = 'YYYY-MM-DD'] of fieldMapToTime) {
if (!field || !startTimeKey || !endTimeKey || !values[field]) { if (!field || !startTimeKey || !endTimeKey) {
continue;
}
// If the value to be converted is empty, remove the field
if (!values[field]) {
Reflect.deleteProperty(values, field);
continue; continue;
} }
const [startTime, endTime]: string[] = values[field]; const [startTime, endTime]: string[] = values[field];
values[startTimeKey] = dateUtil(startTime).format(format); const [startTimeFormat, endTimeFormat] = Array.isArray(format) ? format : [format, format];
values[endTimeKey] = dateUtil(endTime).format(format);
values[startTimeKey] = dateUtil(startTime).format(startTimeFormat);
values[endTimeKey] = dateUtil(endTime).format(endTimeFormat);
Reflect.deleteProperty(values, field); Reflect.deleteProperty(values, field);
} }

4
apps/vue/src/components/Form/src/props.ts

@ -9,7 +9,7 @@ import { propTypes } from '/@/utils/propTypes';
export const basicProps = { export const basicProps = {
model: { model: {
type: Object as PropType<Recordable>, type: Object as PropType<Recordable>,
default: {}, default: () => ({}),
}, },
// 标签宽度 固定宽度 // 标签宽度 固定宽度
labelWidth: { labelWidth: {
@ -45,7 +45,7 @@ export const basicProps = {
// 禁用表单 // 禁用表单
disabled: propTypes.bool, disabled: propTypes.bool,
emptySpan: { emptySpan: {
type: [Number, Object] as PropType<number>, type: [Number, Object] as PropType<number | Recordable>,
default: 0, default: 0,
}, },
// 是否显示收起展开按钮 // 是否显示收起展开按钮

7
apps/vue/src/components/Form/src/types/form.ts

@ -7,7 +7,7 @@ import type { TableActionType } from '/@/components/Table/src/types/table';
import type { CSSProperties } from 'vue'; import type { CSSProperties } from 'vue';
import type { RowProps } from 'ant-design-vue/lib/grid/Row'; import type { RowProps } from 'ant-design-vue/lib/grid/Row';
export type FieldMapToTime = [string, [string, string], string?][]; export type FieldMapToTime = [string, [string, string], (string | [string, string])?][];
export type Rule = RuleObject & { export type Rule = RuleObject & {
trigger?: 'blur' | 'change' | ['change', 'blur']; trigger?: 'blur' | 'change' | ['change', 'blur'];
@ -33,7 +33,7 @@ export interface FormActionType {
updateSchema: (data: Partial<FormSchema> | Partial<FormSchema>[]) => Promise<void>; updateSchema: (data: Partial<FormSchema> | Partial<FormSchema>[]) => Promise<void>;
resetSchema: (data: Partial<FormSchema> | Partial<FormSchema>[]) => Promise<void>; resetSchema: (data: Partial<FormSchema> | Partial<FormSchema>[]) => Promise<void>;
setProps: (formProps: Partial<FormProps>) => Promise<void>; setProps: (formProps: Partial<FormProps>) => Promise<void>;
removeSchemaByFiled: (field: string | string[]) => Promise<void>; removeSchemaByField: (field: string | string[]) => Promise<void>;
appendSchemaByField: ( appendSchemaByField: (
schema: FormSchema, schema: FormSchema,
prefixField: string | undefined, prefixField: string | undefined,
@ -187,6 +187,9 @@ export interface FormSchema {
// 默认值 // 默认值
defaultValue?: any; defaultValue?: any;
// 是否自动处理与时间相关组件的默认值
isHandleDateDefaultValue?: boolean;
isAdvanced?: boolean; isAdvanced?: boolean;
// Matching details components // Matching details components

2
apps/vue/src/components/Menu/src/props.ts

@ -41,7 +41,7 @@ export const basicProps = {
export const itemProps = { export const itemProps = {
item: { item: {
type: Object as PropType<Menu>, type: Object as PropType<Menu>,
default: {}, default: () => ({}),
}, },
level: propTypes.number, level: propTypes.number,
theme: propTypes.oneOf(['dark', 'light']), theme: propTypes.oneOf(['dark', 'light']),

10
apps/vue/src/components/Preview/src/Functional.vue

@ -141,8 +141,16 @@
} }
// //
function scaleFunc(num: number) { function scaleFunc(num: number) {
//
const MIN_SCALE = 0.02;
//
const GRA = 0.1;
if (imgState.imgScale <= 0.2 && num < 0) return; if (imgState.imgScale <= 0.2 && num < 0) return;
imgState.imgScale += num; imgState.imgScale += num * GRA;
// scale < 0
if (imgState.imgScale < 0) {
imgState.imgScale = MIN_SCALE;
}
} }
// //

3
apps/vue/src/components/Table/src/BasicTable.vue

@ -163,6 +163,7 @@
getRowSelection, getRowSelection,
getRowSelectionRef, getRowSelectionRef,
getSelectRows, getSelectRows,
setSelectedRows,
clearSelectedRowKeys, clearSelectedRowKeys,
getSelectRowKeys, getSelectRowKeys,
deleteSelectRowByKey, deleteSelectRowByKey,
@ -328,6 +329,7 @@
const tableAction: TableActionType = { const tableAction: TableActionType = {
reload, reload,
getSelectRows, getSelectRows,
setSelectedRows,
clearSelectedRowKeys, clearSelectedRowKeys,
getSelectRowKeys, getSelectRowKeys,
deleteSelectRowByKey, deleteSelectRowByKey,
@ -439,6 +441,7 @@
padding: 16px; padding: 16px;
.ant-form { .ant-form {
width: 100%;
padding: 12px 10px 6px; padding: 12px 10px 6px;
margin-bottom: 16px; margin-bottom: 16px;
background-color: @component-background; background-color: @component-background;

6
apps/vue/src/components/Table/src/componentMap.ts

@ -8,9 +8,10 @@ import {
DatePicker, DatePicker,
TimePicker, TimePicker,
AutoComplete, AutoComplete,
Radio,
} from 'ant-design-vue'; } from 'ant-design-vue';
import type { ComponentType } from './types/componentType'; import type { ComponentType } from './types/componentType';
import { ApiSelect, ApiTreeSelect } from '/@/components/Form'; import { ApiSelect, ApiTreeSelect, RadioButtonGroup, ApiRadioGroup } from '/@/components/Form';
const componentMap = new Map<ComponentType, Component>(); const componentMap = new Map<ComponentType, Component>();
@ -24,6 +25,9 @@ componentMap.set('Switch', Switch);
componentMap.set('Checkbox', Checkbox); componentMap.set('Checkbox', Checkbox);
componentMap.set('DatePicker', DatePicker); componentMap.set('DatePicker', DatePicker);
componentMap.set('TimePicker', TimePicker); componentMap.set('TimePicker', TimePicker);
componentMap.set('RadioGroup', Radio.Group);
componentMap.set('RadioButtonGroup', RadioButtonGroup);
componentMap.set('ApiRadioGroup', ApiRadioGroup);
export function add(compName: ComponentType, component: Component) { export function add(compName: ComponentType, component: Component) {
componentMap.set(compName, component); componentMap.set(compName, component);

12
apps/vue/src/components/Table/src/components/TableImg.vue

@ -9,7 +9,7 @@
<div class="img-div"> <div class="img-div">
<PreviewGroup> <PreviewGroup>
<template v-for="(img, index) in imgList" :key="img"> <template v-for="(img, index) in imgList" :key="img">
<Image <AImage
:width="size" :width="size"
:style="{ :style="{
display: index === 0 ? '' : 'none !important', display: index === 0 ? '' : 'none !important',
@ -22,9 +22,9 @@
</Badge> </Badge>
<PreviewGroup v-else> <PreviewGroup v-else>
<template v-for="(img, index) in imgList" :key="img"> <template v-for="(img, index) in imgList" :key="img">
<Image <AImage
:width="size" :width="size"
:style="{ marginLeft: index === 0 ? 0 : margin }" :style="{ marginLeft: index === 0 ? 0 : margin + 'px' }"
:src="srcPrefix + img" :src="srcPrefix + img"
/> />
</template> </template>
@ -40,7 +40,7 @@
export default defineComponent({ export default defineComponent({
name: 'TableImage', name: 'TableImage',
components: { Image, PreviewGroup: Image.PreviewGroup, Badge }, components: { AImage: Image, PreviewGroup: Image.PreviewGroup, Badge },
props: { props: {
imgList: propTypes.arrayOf(propTypes.string), imgList: propTypes.arrayOf(propTypes.string),
size: propTypes.number.def(40), size: propTypes.number.def(40),
@ -52,6 +52,10 @@
margin: propTypes.number.def(4), margin: propTypes.number.def(4),
// srcimgList // srcimgList
srcPrefix: propTypes.string.def(''), srcPrefix: propTypes.string.def(''),
// fallback,
fallback: propTypes.string.def(
'data:image/png;base64,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',
),
}, },
setup(props) { setup(props) {
const getWrapStyle = computed((): CSSProperties => { const getWrapStyle = computed((): CSSProperties => {

4
apps/vue/src/components/Table/src/components/editable/EditableCell.vue

@ -121,7 +121,7 @@
} }
const component = unref(getComponent); const component = unref(getComponent);
if (!component.includes('Select')) { if (!component.includes('Select') && !component.includes('Radio')) {
return value; return value;
} }
@ -152,7 +152,7 @@
}); });
watchEffect(() => { watchEffect(() => {
defaultValueRef.value = props.value; //defaultValueRef.value = props.value;
currentValueRef.value = props.value; currentValueRef.value = props.value;
}); });

59
apps/vue/src/components/Table/src/components/settings/ColumnSetting.vue

@ -14,7 +14,7 @@
<div :class="`${prefixCls}__popover-title`"> <div :class="`${prefixCls}__popover-title`">
<Checkbox <Checkbox
:indeterminate="indeterminate" :indeterminate="indeterminate"
v-model:checked="checkAll" v-model:checked="state.checkAll"
@change="onCheckAllChange" @change="onCheckAllChange"
> >
{{ t('component.table.settingColumnShow') }} {{ t('component.table.settingColumnShow') }}
@ -44,7 +44,7 @@
<template #content> <template #content>
<ScrollContainer> <ScrollContainer>
<CheckboxGroup v-model:value="checkedList" @change="onChange" ref="columnListRef"> <CheckboxGroup v-model:value="state.checkedList" @change="onChange" ref="columnListRef">
<template v-for="item in plainOptions" :key="item.value"> <template v-for="item in plainOptions" :key="item.value">
<div :class="`${prefixCls}__check-item`" v-if="!('ifShow' in item && !item.ifShow)"> <div :class="`${prefixCls}__check-item`" v-if="!('ifShow' in item && !item.ifShow)">
<DragOutlined class="table-column-drag-icon" /> <DragOutlined class="table-column-drag-icon" />
@ -66,7 +66,7 @@
`${prefixCls}__fixed-left`, `${prefixCls}__fixed-left`,
{ {
active: item.fixed === 'left', active: item.fixed === 'left',
disabled: !checkedList.includes(item.value), disabled: !state.checkedList.includes(item.value),
}, },
]" ]"
@click="handleColumnFixed(item, 'left')" @click="handleColumnFixed(item, 'left')"
@ -87,7 +87,7 @@
`${prefixCls}__fixed-right`, `${prefixCls}__fixed-right`,
{ {
active: item.fixed === 'right', active: item.fixed === 'right',
disabled: !checkedList.includes(item.value), disabled: !state.checkedList.includes(item.value),
}, },
]" ]"
@click="handleColumnFixed(item, 'right')" @click="handleColumnFixed(item, 'right')"
@ -102,13 +102,12 @@
</Popover> </Popover>
</Tooltip> </Tooltip>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import type { BasicColumn, ColumnChangeParam } from '../../types/table'; import type { BasicColumn, ColumnChangeParam } from '../../types/table';
import { import {
defineComponent, useAttrs,
ref, ref,
reactive, reactive,
toRefs,
watchEffect, watchEffect,
nextTick, nextTick,
unref, unref,
@ -142,22 +141,9 @@
fixed?: boolean | 'left' | 'right'; fixed?: boolean | 'left' | 'right';
} }
export default defineComponent({ const CheckboxGroup = Checkbox.Group;
name: 'ColumnSetting', const emits = defineEmits(['columns-change']);
components: {
SettingOutlined,
Popover,
Tooltip,
Checkbox,
CheckboxGroup: Checkbox.Group,
DragOutlined,
ScrollContainer,
Divider,
Icon,
},
emits: ['columns-change'],
setup(_, { emit, attrs }) {
const { t } = useI18n(); const { t } = useI18n();
const table = useTableContext(); const table = useTableContext();
@ -218,7 +204,7 @@
const columns = getColumns(); const columns = getColumns();
const checkList = table const checkList = table
.getColumns({ ignoreAction: true }) .getColumns({ ignoreAction: true, ignoreIndex: true })
.map((item) => { .map((item) => {
if (item.defaultHidden) { if (item.defaultHidden) {
return ''; return '';
@ -389,38 +375,15 @@
return { dataIndex: col.value, fixed: col.fixed, visible }; return { dataIndex: col.value, fixed: col.fixed, visible };
}); });
emit('columns-change', data); emits('columns-change', data);
} }
function getPopupContainer() { function getPopupContainer() {
const attrs = useAttrs();
return isFunction(attrs.getPopupContainer) return isFunction(attrs.getPopupContainer)
? attrs.getPopupContainer() ? attrs.getPopupContainer()
: getParentContainer(); : getParentContainer();
} }
return {
t,
...toRefs(state),
indeterminate,
onCheckAllChange,
onChange,
plainOptions,
reset,
prefixCls,
columnListRef,
handleVisibleChange,
checkIndex,
checkSelect,
checkDrag,
handleIndexCheckChange,
handleSelectCheckChange,
handleDragChange,
defaultRowSelection,
handleColumnFixed,
getPopupContainer,
};
},
});
</script> </script>
<style lang="less"> <style lang="less">
@prefix-cls: ~'@{namespace}-basic-column-setting'; @prefix-cls: ~'@{namespace}-basic-column-setting';

2
apps/vue/src/components/Table/src/hooks/useCustomRow.ts

@ -40,7 +40,7 @@ export function useCustomRow(
function handleClick() { function handleClick() {
const { rowSelection, rowKey, clickToRowSelect } = unref(propsRef); const { rowSelection, rowKey, clickToRowSelect } = unref(propsRef);
if (!rowSelection || !clickToRowSelect) return; if (!rowSelection || !clickToRowSelect) return;
const keys = getSelectRowKeys(); const keys = getSelectRowKeys() || [];
const key = getKey(record, rowKey, unref(getAutoCreateKey)); const key = getKey(record, rowKey, unref(getAutoCreateKey));
if (!key) return; if (!key) return;

4
apps/vue/src/components/Table/src/hooks/useRowSelection.ts

@ -66,13 +66,13 @@ export function useRowSelection(
selectedRowKeysRef.value = rowKeys; selectedRowKeysRef.value = rowKeys;
const allSelectedRows = findNodeAll( const allSelectedRows = findNodeAll(
toRaw(unref(tableData)).concat(toRaw(unref(selectedRowRef))), toRaw(unref(tableData)).concat(toRaw(unref(selectedRowRef))),
(item) => rowKeys.includes(item[unref(getRowKey) as string]), (item) => rowKeys?.includes(item[unref(getRowKey) as string]),
{ {
children: propsRef.value.childrenColumnName ?? 'children', children: propsRef.value.childrenColumnName ?? 'children',
}, },
); );
const trueSelectedRows: any[] = []; const trueSelectedRows: any[] = [];
rowKeys.forEach((key: string) => { rowKeys?.forEach((key: string) => {
const found = allSelectedRows.find((item) => item[unref(getRowKey) as string] === key); const found = allSelectedRows.find((item) => item[unref(getRowKey) as string] === key);
found && trueSelectedRows.push(found); found && trueSelectedRows.push(found);
}); });

3
apps/vue/src/components/Table/src/hooks/useTable.ts

@ -76,6 +76,9 @@ export function useTable(tableProps?: Props): [
redoHeight: () => { redoHeight: () => {
getTableInstance().redoHeight(); getTableInstance().redoHeight();
}, },
setSelectedRows: (rows: Recordable[]) => {
return toRaw(getTableInstance().setSelectedRows(rows));
},
setLoading: (loading: boolean) => { setLoading: (loading: boolean) => {
getTableInstance().setLoading(loading); getTableInstance().setLoading(loading);
}, },

5
apps/vue/src/components/Table/src/types/componentType.ts

@ -8,4 +8,7 @@ export type ComponentType =
| 'Checkbox' | 'Checkbox'
| 'Switch' | 'Switch'
| 'DatePicker' | 'DatePicker'
| 'TimePicker'; | 'TimePicker'
| 'RadioGroup'
| 'RadioButtonGroup'
| 'ApiRadioGroup';

3
apps/vue/src/components/Table/src/types/table.ts

@ -85,10 +85,11 @@ export type SizeType = 'default' | 'middle' | 'small' | 'large';
export interface TableActionType { export interface TableActionType {
reload: (opt?: FetchParams) => Promise<void>; reload: (opt?: FetchParams) => Promise<void>;
setSelectedRows: (rows: Recordable[]) => void;
getSelectRows: <T = Recordable>() => T[]; getSelectRows: <T = Recordable>() => T[];
clearSelectedRowKeys: () => void; clearSelectedRowKeys: () => void;
expandAll: () => void; expandAll: () => void;
expandRows: (keys: string[]) => void; expandRows: (keys: string[] | number[]) => void;
collapseAll: () => void; collapseAll: () => void;
scrollTo: (pos: string) => void; // pos: id | "top" | "bottom" scrollTo: (pos: string) => void; // pos: id | "top" | "bottom"
getSelectRowKeys: () => string[]; getSelectRowKeys: () => string[];

2
apps/vue/src/components/Tinymce/src/Editor.vue

@ -76,7 +76,7 @@
const tinymceProps = { const tinymceProps = {
options: { options: {
type: Object as PropType<Partial<RawEditorSettings>>, type: Object as PropType<Partial<RawEditorSettings>>,
default: {}, default: () => ({}),
}, },
value: { value: {
type: String, type: String,

4
apps/vue/src/components/Tree/index.ts

@ -1,6 +1,6 @@
import BasicTree from './src/Tree.vue'; import BasicTree from './src/BasicTree.vue';
import './style'; import './style';
export { BasicTree }; export { BasicTree };
export type { ContextMenuItem } from '/@/hooks/web/useContextMenu'; export type { ContextMenuItem } from '/@/hooks/web/useContextMenu';
export * from './src/tree'; export * from './src/types/tree';

76
apps/vue/src/components/Tree/src/Tree.vue → apps/vue/src/components/Tree/src/BasicTree.vue

@ -1,7 +1,13 @@
<script lang="tsx"> <script lang="tsx">
import type { CSSProperties } from 'vue'; import type { CSSProperties } from 'vue';
import type { FieldNames, TreeState, TreeItem, KeyType, CheckKeys, TreeActionType } from './tree'; import type {
FieldNames,
TreeState,
TreeItem,
KeyType,
CheckKeys,
TreeActionType,
} from './types/tree';
import { import {
defineComponent, defineComponent,
reactive, reactive,
@ -13,7 +19,7 @@
watch, watch,
onMounted, onMounted,
} from 'vue'; } from 'vue';
import TreeHeader from './TreeHeader.vue'; import TreeHeader from './components/TreeHeader.vue';
import { Tree, Spin, Empty } from 'ant-design-vue'; import { Tree, Spin, Empty } from 'ant-design-vue';
import { TreeIcon } from './TreeIcon'; import { TreeIcon } from './TreeIcon';
import { ScrollContainer } from '/@/components/Container'; import { ScrollContainer } from '/@/components/Container';
@ -21,12 +27,11 @@
import { isArray, isBoolean, isEmpty, isFunction } from '/@/utils/is'; import { isArray, isBoolean, isEmpty, isFunction } from '/@/utils/is';
import { extendSlots, getSlot } from '/@/utils/helper/tsxHelper'; import { extendSlots, getSlot } from '/@/utils/helper/tsxHelper';
import { filter, treeToList, eachTree } from '/@/utils/helper/treeHelper'; import { filter, treeToList, eachTree } from '/@/utils/helper/treeHelper';
import { useTree } from './useTree'; import { useTree } from './hooks/useTree';
import { useContextMenu } from '/@/hooks/web/useContextMenu'; import { useContextMenu } from '/@/hooks/web/useContextMenu';
import { CreateContextOptions } from '/@/components/ContextMenu'; import { CreateContextOptions } from '/@/components/ContextMenu';
import { treeEmits, treeProps } from './tree'; import { treeEmits, treeProps } from './types/tree';
import { createBEM } from '/@/utils/bem'; import { createBEM } from '/@/utils/bem';
export default defineComponent({ export default defineComponent({
name: 'BasicTree', name: 'BasicTree',
inheritAttrs: false, inheritAttrs: false,
@ -34,24 +39,19 @@
emits: treeEmits, emits: treeEmits,
setup(props, { attrs, slots, emit, expose }) { setup(props, { attrs, slots, emit, expose }) {
const [bem] = createBEM('tree'); const [bem] = createBEM('tree');
const state = reactive<TreeState>({ const state = reactive<TreeState>({
checkStrictly: props.checkStrictly, checkStrictly: props.checkStrictly,
expandedKeys: props.expandedKeys || [], expandedKeys: props.expandedKeys || [],
selectedKeys: props.selectedKeys || [], selectedKeys: props.selectedKeys || [],
checkedKeys: props.checkedKeys || [], checkedKeys: props.checkedKeys || [],
}); });
const searchState = reactive({ const searchState = reactive({
startSearch: false, startSearch: false,
searchText: '', searchText: '',
searchData: [] as TreeItem[], searchData: [] as TreeItem[],
}); });
const treeDataRef = ref<TreeItem[]>([]); const treeDataRef = ref<TreeItem[]>([]);
const [createContextMenu] = useContextMenu(); const [createContextMenu] = useContextMenu();
const getFieldNames = computed((): Required<FieldNames> => { const getFieldNames = computed((): Required<FieldNames> => {
const { fieldNames } = props; const { fieldNames } = props;
return { return {
@ -61,7 +61,6 @@
...fieldNames, ...fieldNames,
}; };
}); });
const getBindValues = computed(() => { const getBindValues = computed(() => {
let propsData = { let propsData = {
blockNode: true, blockNode: true,
@ -83,16 +82,15 @@
onCheck: (v: CheckKeys, e) => { onCheck: (v: CheckKeys, e) => {
let currentValue = toRaw(state.checkedKeys) as KeyType[]; let currentValue = toRaw(state.checkedKeys) as KeyType[];
if (isArray(currentValue) && searchState.startSearch) { if (isArray(currentValue) && searchState.startSearch) {
const { key } = unref(getFieldNames); const value = e.node.eventKey;
currentValue = difference(currentValue, getChildrenKeys(e.node.$attrs.node[key])); currentValue = difference(currentValue, getChildrenKeys(value));
if (e.checked) { if (e.checked) {
currentValue.push(e.node.$attrs.node[key]); currentValue.push(value);
} }
state.checkedKeys = currentValue; state.checkedKeys = currentValue;
} else { } else {
state.checkedKeys = v; state.checkedKeys = v;
} }
const rawVal = toRaw(state.checkedKeys); const rawVal = toRaw(state.checkedKeys);
emit('update:value', rawVal); emit('update:value', rawVal);
emit('check', rawVal, e); emit('check', rawVal, e);
@ -101,15 +99,12 @@
}; };
return omit(propsData, 'treeData', 'class'); return omit(propsData, 'treeData', 'class');
}); });
const getTreeData = computed((): TreeItem[] => const getTreeData = computed((): TreeItem[] =>
searchState.startSearch ? searchState.searchData : unref(treeDataRef), searchState.startSearch ? searchState.searchData : unref(treeDataRef),
); );
const getNotFound = computed((): boolean => { const getNotFound = computed((): boolean => {
return !getTreeData.value || getTreeData.value.length === 0; return !getTreeData.value || getTreeData.value.length === 0;
}); });
const { const {
deleteNodeByKey, deleteNodeByKey,
insertNodeByKey, insertNodeByKey,
@ -121,7 +116,6 @@
getEnabledKeys, getEnabledKeys,
getSelectedNode, getSelectedNode,
} = useTree(treeDataRef, getFieldNames); } = useTree(treeDataRef, getFieldNames);
function getIcon(params: Recordable, icon?: string) { function getIcon(params: Recordable, icon?: string) {
if (!icon) { if (!icon) {
if (props.renderIcon && isFunction(props.renderIcon)) { if (props.renderIcon && isFunction(props.renderIcon)) {
@ -130,11 +124,9 @@
} }
return icon; return icon;
} }
async function handleRightClick({ event, node }: Recordable) { async function handleRightClick({ event, node }: Recordable) {
const { rightMenuList: menuList = [], beforeRightClick } = props; const { rightMenuList: menuList = [], beforeRightClick } = props;
let contextMenuOptions: CreateContextOptions = { event, items: [] }; let contextMenuOptions: CreateContextOptions = { event, items: [] };
if (beforeRightClick && isFunction(beforeRightClick)) { if (beforeRightClick && isFunction(beforeRightClick)) {
let result = await beforeRightClick(node, event); let result = await beforeRightClick(node, event);
if (Array.isArray(result)) { if (Array.isArray(result)) {
@ -149,42 +141,33 @@
contextMenuOptions.items = contextMenuOptions.items.filter((item) => !item.hidden); contextMenuOptions.items = contextMenuOptions.items.filter((item) => !item.hidden);
createContextMenu(contextMenuOptions); createContextMenu(contextMenuOptions);
} }
function setExpandedKeys(keys: KeyType[]) { function setExpandedKeys(keys: KeyType[]) {
state.expandedKeys = keys; state.expandedKeys = keys;
} }
function getExpandedKeys() { function getExpandedKeys() {
return state.expandedKeys; return state.expandedKeys;
} }
function setSelectedKeys(keys: KeyType[]) { function setSelectedKeys(keys: KeyType[]) {
state.selectedKeys = keys; state.selectedKeys = keys;
} }
function getSelectedKeys() { function getSelectedKeys() {
return state.selectedKeys; return state.selectedKeys;
} }
function setCheckedKeys(keys: CheckKeys) { function setCheckedKeys(keys: CheckKeys) {
state.checkedKeys = keys; state.checkedKeys = keys;
} }
function getCheckedKeys() { function getCheckedKeys() {
return state.checkedKeys; return state.checkedKeys;
} }
function checkAll(checkAll: boolean) { function checkAll(checkAll: boolean) {
state.checkedKeys = checkAll ? getEnabledKeys() : ([] as KeyType[]); state.checkedKeys = checkAll ? getEnabledKeys() : ([] as KeyType[]);
} }
function expandAll(expandAll: boolean) { function expandAll(expandAll: boolean) {
state.expandedKeys = expandAll ? getAllKeys() : ([] as KeyType[]); state.expandedKeys = expandAll ? getAllKeys() : ([] as KeyType[]);
} }
function onStrictlyChange(strictly: boolean) { function onStrictlyChange(strictly: boolean) {
state.checkStrictly = strictly; state.checkStrictly = strictly;
} }
watch( watch(
() => props.searchValue, () => props.searchValue,
(val) => { (val) => {
@ -196,7 +179,6 @@
immediate: true, immediate: true,
}, },
); );
watch( watch(
() => props.treeData, () => props.treeData,
(val) => { (val) => {
@ -205,7 +187,6 @@
} }
}, },
); );
function handleSearch(searchValue: string) { function handleSearch(searchValue: string) {
if (searchValue !== searchState.searchText) searchState.searchText = searchValue; if (searchValue !== searchState.searchText) searchState.searchText = searchValue;
emit('update:searchValue', searchValue); emit('update:searchValue', searchValue);
@ -217,7 +198,6 @@
unref(props); unref(props);
searchState.startSearch = true; searchState.startSearch = true;
const { title: titleField, key: keyField } = unref(getFieldNames); const { title: titleField, key: keyField } = unref(getFieldNames);
const matchedKeys: string[] = []; const matchedKeys: string[] = [];
searchState.searchData = filter( searchState.searchData = filter(
unref(treeDataRef), unref(treeDataRef),
@ -232,7 +212,6 @@
}, },
unref(getFieldNames), unref(getFieldNames),
); );
if (expandOnSearch) { if (expandOnSearch) {
const expandKeys = treeToList(searchState.searchData).map((val) => { const expandKeys = treeToList(searchState.searchData).map((val) => {
return val[keyField]; return val[keyField];
@ -241,16 +220,13 @@
setExpandedKeys(expandKeys); setExpandedKeys(expandKeys);
} }
} }
if (checkOnSearch && checkable && matchedKeys.length) { if (checkOnSearch && checkable && matchedKeys.length) {
setCheckedKeys(matchedKeys); setCheckedKeys(matchedKeys);
} }
if (selectedOnSearch && matchedKeys.length) { if (selectedOnSearch && matchedKeys.length) {
setSelectedKeys(matchedKeys); setSelectedKeys(matchedKeys);
} }
} }
function handleClickNode(key: string, children: TreeItem[]) { function handleClickNode(key: string, children: TreeItem[]) {
if (!props.clickRowToExpand || !children || children.length === 0) return; if (!props.clickRowToExpand || !children || children.length === 0) return;
if (!state.expandedKeys.includes(key)) { if (!state.expandedKeys.includes(key)) {
@ -264,11 +240,9 @@
setExpandedKeys(keys); setExpandedKeys(keys);
} }
} }
watchEffect(() => { watchEffect(() => {
treeDataRef.value = props.treeData as TreeItem[]; treeDataRef.value = props.treeData as TreeItem[];
}); });
onMounted(() => { onMounted(() => {
const level = parseInt(props.defaultExpandLevel); const level = parseInt(props.defaultExpandLevel);
if (level > 0) { if (level > 0) {
@ -277,19 +251,15 @@
expandAll(true); expandAll(true);
} }
}); });
watchEffect(() => { watchEffect(() => {
state.expandedKeys = props.expandedKeys; state.expandedKeys = props.expandedKeys;
}); });
watchEffect(() => { watchEffect(() => {
state.selectedKeys = props.selectedKeys; state.selectedKeys = props.selectedKeys;
}); });
watchEffect(() => { watchEffect(() => {
state.checkedKeys = props.checkedKeys; state.checkedKeys = props.checkedKeys;
}); });
watch( watch(
() => props.value, () => props.value,
() => { () => {
@ -297,7 +267,6 @@
}, },
{ immediate: true }, { immediate: true },
); );
watch( watch(
() => state.checkedKeys, () => state.checkedKeys,
() => { () => {
@ -306,11 +275,9 @@
emit('change', v); emit('change', v);
}, },
); );
watchEffect(() => { watchEffect(() => {
state.checkStrictly = props.checkStrictly; state.checkStrictly = props.checkStrictly;
}); });
const instance: TreeActionType = { const instance: TreeActionType = {
setExpandedKeys, setExpandedKeys,
getExpandedKeys, getExpandedKeys,
@ -335,7 +302,6 @@
return searchState.searchText; return searchState.searchText;
}, },
}; };
function renderAction(node: TreeItem) { function renderAction(node: TreeItem) {
const { actionList } = props; const { actionList } = props;
if (!actionList || actionList.length === 0) return; if (!actionList || actionList.length === 0) return;
@ -346,9 +312,7 @@
} else if (isBoolean(item.show)) { } else if (isBoolean(item.show)) {
nodeShow = item.show; nodeShow = item.show;
} }
if (!nodeShow) return null; if (!nodeShow) return null;
return ( return (
<span key={index} class={bem('action')}> <span key={index} class={bem('action')}>
{item.render(node)} {item.render(node)}
@ -356,7 +320,6 @@
); );
}); });
} }
const treeData = computed(() => { const treeData = computed(() => {
const data = cloneDeep(getTreeData.value); const data = cloneDeep(getTreeData.value);
eachTree(data, (item, _parent) => { eachTree(data, (item, _parent) => {
@ -367,15 +330,12 @@
key: keyField, key: keyField,
children: childrenField, children: childrenField,
} = unref(getFieldNames); } = unref(getFieldNames);
const icon = getIcon(item, item.icon); const icon = getIcon(item, item.icon);
const title = get(item, titleField); const title = get(item, titleField);
const searchIdx = searchText ? title.indexOf(searchText) : -1; const searchIdx = searchText ? title.indexOf(searchText) : -1;
const isHighlight = const isHighlight =
searchState.startSearch && !isEmpty(searchText) && highlight && searchIdx !== -1; searchState.startSearch && !isEmpty(searchText) && highlight && searchIdx !== -1;
const highlightStyle = `color: ${isBoolean(highlight) ? '#f50' : highlight}`; const highlightStyle = `color: ${isBoolean(highlight) ? '#f50' : highlight}`;
const titleDom = isHighlight ? ( const titleDom = isHighlight ? (
<span class={unref(getBindValues)?.blockNode ? `${bem('content')}` : ''}> <span class={unref(getBindValues)?.blockNode ? `${bem('content')}` : ''}>
<span>{title.substr(0, searchIdx)}</span> <span>{title.substr(0, searchIdx)}</span>
@ -405,9 +365,7 @@
}); });
return data; return data;
}); });
expose(instance); expose(instance);
return () => { return () => {
const { title, helpMessage, toolbar, search, checkable } = props; const { title, helpMessage, toolbar, search, checkable } = props;
const showTitle = title || toolbar || search || slots.headerTitle; const showTitle = title || toolbar || search || slots.headerTitle;
@ -430,7 +388,11 @@
{extendSlots(slots)} {extendSlots(slots)}
</TreeHeader> </TreeHeader>
)} )}
<Spin spinning={unref(props.loading)} tip="加载中..."> <Spin
wrapperClassName={unref(props.treeWrapperClassName)}
spinning={unref(props.loading)}
tip="加载中..."
>
<ScrollContainer style={scrollStyle} v-show={!unref(getNotFound)}> <ScrollContainer style={scrollStyle} v-show={!unref(getNotFound)}>
<Tree {...unref(getBindValues)} showIcon={false} treeData={treeData.value} /> <Tree {...unref(getBindValues)} showIcon={false} treeData={treeData.value} />
</ScrollContainer> </ScrollContainer>

14
apps/vue/src/components/Tree/src/TreeHeader.vue → apps/vue/src/components/Tree/src/components/TreeHeader.vue

@ -40,12 +40,9 @@
import { useI18n } from '/@/hooks/web/useI18n'; import { useI18n } from '/@/hooks/web/useI18n';
import { useDebounceFn } from '@vueuse/core'; import { useDebounceFn } from '@vueuse/core';
import { createBEM } from '/@/utils/bem'; import { createBEM } from '/@/utils/bem';
import { ToolbarEnum } from './tree'; import { ToolbarEnum } from '../types/tree';
const searchValue = ref(''); const searchValue = ref('');
const [bem] = createBEM('tree-header'); const [bem] = createBEM('tree-header');
const props = defineProps({ const props = defineProps({
helpMessage: { helpMessage: {
type: [String, Array] as PropType<string | string[]>, type: [String, Array] as PropType<string | string[]>,
@ -81,10 +78,8 @@
}, },
} as const); } as const);
const emit = defineEmits(['strictly-change', 'search']); const emit = defineEmits(['strictly-change', 'search']);
const slots = useSlots(); const slots = useSlots();
const { t } = useI18n(); const { t } = useI18n();
const getInputSearchCls = computed(() => { const getInputSearchCls = computed(() => {
const titleExists = slots.headerTitle || props.title; const titleExists = slots.headerTitle || props.title;
return [ return [
@ -95,7 +90,6 @@
}, },
]; ];
}); });
const toolbarList = computed(() => { const toolbarList = computed(() => {
const { checkable } = props; const { checkable } = props;
const defaultToolbarList = [ const defaultToolbarList = [
@ -106,7 +100,6 @@
divider: checkable, divider: checkable,
}, },
]; ];
return checkable return checkable
? [ ? [
{ label: t('component.tree.selectAll'), value: ToolbarEnum.SELECT_ALL }, { label: t('component.tree.selectAll'), value: ToolbarEnum.SELECT_ALL },
@ -121,7 +114,6 @@
] ]
: defaultToolbarList; : defaultToolbarList;
}); });
function handleMenuClick(e: { key: ToolbarEnum }) { function handleMenuClick(e: { key: ToolbarEnum }) {
const { key } = e; const { key } = e;
switch (key) { switch (key) {
@ -145,20 +137,16 @@
break; break;
} }
} }
function emitChange(value?: string): void { function emitChange(value?: string): void {
emit('search', value); emit('search', value);
} }
const debounceEmitChange = useDebounceFn(emitChange, 200); const debounceEmitChange = useDebounceFn(emitChange, 200);
watch( watch(
() => searchValue.value, () => searchValue.value,
(v) => { (v) => {
debounceEmitChange(v); debounceEmitChange(v);
}, },
); );
watch( watch(
() => props.searchText, () => props.searchText,
(v) => { (v) => {

2
apps/vue/src/components/Tree/src/useTree.ts → apps/vue/src/components/Tree/src/hooks/useTree.ts

@ -1,4 +1,4 @@
import type { InsertNodeParams, KeyType, FieldNames, TreeItem } from './tree'; import type { InsertNodeParams, KeyType, FieldNames, TreeItem } from '../types/tree';
import type { Ref, ComputedRef } from 'vue'; import type { Ref, ComputedRef } from 'vue';
import type { TreeDataItem } from 'ant-design-vue/es/tree/Tree'; import type { TreeDataItem } from 'ant-design-vue/es/tree/Tree';

108
apps/vue/src/components/Tree/src/props.ts

@ -1,108 +0,0 @@
import type { PropType } from 'vue';
import type {
ReplaceFields,
ActionItem,
Keys,
CheckKeys,
ContextMenuOptions,
TreeItem,
} from './typing';
import type { ContextMenuItem } from '/@/hooks/web/useContextMenu';
import type { TreeDataItem } from 'ant-design-vue/es/tree/Tree';
import { propTypes } from '/@/utils/propTypes';
export const basicProps = {
value: {
type: [Object, Array] as PropType<Keys | CheckKeys>,
},
renderIcon: {
type: Function as PropType<(params: Recordable) => string>,
},
helpMessage: {
type: [String, Array] as PropType<string | string[]>,
default: '',
},
title: propTypes.string,
toolbar: propTypes.bool,
search: propTypes.bool,
searchValue: propTypes.string,
checkStrictly: propTypes.bool,
clickRowToExpand: propTypes.bool.def(true),
checkable: propTypes.bool.def(false),
defaultExpandLevel: {
type: [String, Number] as PropType<string | number>,
default: '',
},
defaultExpandAll: propTypes.bool.def(false),
replaceFields: {
type: Object as PropType<ReplaceFields>,
},
treeData: {
type: Array as PropType<TreeDataItem[]>,
},
actionList: {
type: Array as PropType<ActionItem[]>,
default: () => [],
},
expandedKeys: {
type: Array as PropType<Keys>,
default: () => [],
},
selectedKeys: {
type: Array as PropType<Keys>,
default: () => [],
},
checkedKeys: {
type: Array as PropType<CheckKeys>,
default: () => [],
},
beforeRightClick: {
type: Function as PropType<(...arg: any) => ContextMenuItem[] | ContextMenuOptions>,
default: null,
},
rightMenuList: {
type: Array as PropType<ContextMenuItem[]>,
},
// 自定义数据过滤判断方法(注: 不是整个过滤方法,而是内置过滤的判断方法,用于增强原本仅能通过title进行过滤的方式)
filterFn: {
type: Function as PropType<
(searchValue: any, node: TreeItem, replaceFields: ReplaceFields) => boolean
>,
default: null,
},
// 高亮搜索值,仅高亮具体匹配值(通过title)值为true时使用默认色值,值为#xxx时使用此值替代且高亮开启
highlight: {
type: [Boolean, String] as PropType<Boolean | String>,
default: false,
},
// 搜索完成时自动展开结果
expandOnSearch: propTypes.bool.def(false),
// 搜索完成自动选中所有结果,当且仅当 checkable===true 时生效
checkOnSearch: propTypes.bool.def(false),
// 搜索完成自动select所有结果
selectedOnSearch: propTypes.bool.def(false),
};
export const treeNodeProps = {
actionList: {
type: Array as PropType<ActionItem[]>,
default: () => [],
},
replaceFields: {
type: Object as PropType<ReplaceFields>,
},
treeData: {
type: Array as PropType<TreeDataItem[]>,
default: () => [],
},
};

1
apps/vue/src/components/Tree/src/tree.ts → apps/vue/src/components/Tree/src/types/tree.ts

@ -134,6 +134,7 @@ export const treeProps = buildProps({
type: Boolean, type: Boolean,
default: false, default: false,
}, },
treeWrapperClassName: String
}); });
export type TreeProps = ExtractPropTypes<typeof treeProps>; export type TreeProps = ExtractPropTypes<typeof treeProps>;

54
apps/vue/src/components/Tree/src/typing.ts

@ -1,54 +0,0 @@
import type { TreeDataItem, CheckEvent as CheckEventOrigin } from 'ant-design-vue/es/tree/Tree';
import { ContextMenuItem } from '/@/hooks/web/useContextMenu';
export interface ActionItem {
render: (record: Recordable) => any;
show?: boolean | ((record: Recordable) => boolean);
}
export interface TreeItem extends TreeDataItem {
icon?: any;
}
export interface ReplaceFields {
children?: string;
title?: string;
key?: string;
}
export type Keys = (string | number)[];
export type CheckKeys =
| (string | number)[]
| { checked: (string | number)[]; halfChecked: (string | number)[] };
export interface TreeActionType {
checkAll: (checkAll: boolean) => void;
expandAll: (expandAll: boolean) => void;
setExpandedKeys: (keys: Keys) => void;
getExpandedKeys: () => Keys;
setSelectedKeys: (keys: Keys) => void;
getSelectedKeys: () => Keys;
setCheckedKeys: (keys: CheckKeys) => void;
getCheckedKeys: () => CheckKeys;
filterByLevel: (level: number) => void;
insertNodeByKey: (opt: InsertNodeParams) => void;
insertNodesByKey: (opt: InsertNodeParams) => void;
deleteNodeByKey: (key: string) => void;
updateNodeByKey: (key: string, node: Omit<TreeDataItem, 'key'>) => void;
setSearchValue: (value: string) => void;
getSearchValue: () => string;
}
export interface InsertNodeParams {
parentKey: string | null;
node: TreeDataItem;
list?: TreeDataItem[];
push?: 'push' | 'unshift';
}
export interface ContextMenuOptions {
icon?: string;
styles?: any;
items?: ContextMenuItem[];
}
export type CheckEvent = CheckEventOrigin;

2
apps/vue/src/components/Upload/src/props.ts

@ -27,7 +27,7 @@ export const basicProps = {
}, },
uploadParams: { uploadParams: {
type: Object as PropType<any>, type: Object as PropType<any>,
default: {}, default: () => ({}),
}, },
api: { api: {
type: Function as PropType<PromiseFn>, type: Function as PropType<PromiseFn>,

10
apps/vue/src/components/Verify/src/props.ts

@ -38,19 +38,19 @@ export const basicProps = {
wrapStyle: { wrapStyle: {
type: Object as PropType<any>, type: Object as PropType<any>,
default: {}, default: () => ({}),
}, },
contentStyle: { contentStyle: {
type: Object as PropType<any>, type: Object as PropType<any>,
default: {}, default: () => ({}),
}, },
barStyle: { barStyle: {
type: Object as PropType<any>, type: Object as PropType<any>,
default: {}, default: () => ({}),
}, },
actionStyle: { actionStyle: {
type: Object as PropType<any>, type: Object as PropType<any>,
default: {}, default: () => ({}),
}, },
}; };
@ -67,7 +67,7 @@ export const rotateProps = {
imgWrapStyle: { imgWrapStyle: {
type: Object as PropType<any>, type: Object as PropType<any>,
default: {}, default: () => ({}),
}, },
minDegree: { minDegree: {

8
apps/vue/src/design/ant/index.less

@ -57,3 +57,11 @@ span.anticon:not(.app-iconify) {
border-top: 0 !important; border-top: 0 !important;
border-left: 0 !important; border-left: 0 !important;
} }
.ant-form-item-control-input-content {
> div {
> div {
max-width: 100%;
}
}
}

5
apps/vue/src/design/ant/input.less

@ -2,9 +2,10 @@
// input // input
.ant-input { .ant-input {
&-number { &-number,
width: 100% !important; &-number-group-wrapper {
min-width: 110px; min-width: 110px;
width: 100% !important;
max-width: 100%; max-width: 100%;
} }
} }

8
apps/vue/src/hooks/web/useECharts.ts

@ -8,6 +8,7 @@ import { useEventListener } from '/@/hooks/event/useEventListener';
import { useBreakpoint } from '/@/hooks/event/useBreakpoint'; import { useBreakpoint } from '/@/hooks/event/useBreakpoint';
import echarts from '/@/utils/lib/echarts'; import echarts from '/@/utils/lib/echarts';
import { useRootSetting } from '/@/hooks/setting/useRootSetting'; import { useRootSetting } from '/@/hooks/setting/useRootSetting';
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
export function useECharts( export function useECharts(
elRef: Ref<HTMLDivElement>, elRef: Ref<HTMLDivElement>,
@ -18,6 +19,7 @@ export function useECharts(
const getDarkMode = computed(() => { const getDarkMode = computed(() => {
return theme === 'default' ? getSysDarkMode.value : theme; return theme === 'default' ? getSysDarkMode.value : theme;
}); });
const { getCollapsed } = useMenuSetting();
let chartInstance: echarts.ECharts | null = null; let chartInstance: echarts.ECharts | null = null;
let resizeFn: Fn = resize; let resizeFn: Fn = resize;
const cacheOptions = ref({}) as Ref<EChartsOption>; const cacheOptions = ref({}) as Ref<EChartsOption>;
@ -99,6 +101,12 @@ export function useECharts(
}, },
); );
watch(getCollapsed, (_) => {
useTimeoutFn(() => {
resizeFn();
}, 300);
});
tryOnUnmounted(() => { tryOnUnmounted(() => {
if (!chartInstance) return; if (!chartInstance) return;
removeResizeFn(); removeResizeFn();

7
apps/vue/src/layouts/default/header/components/FullScreen.vue

@ -20,6 +20,13 @@
setup() { setup() {
const { t } = useI18n(); const { t } = useI18n();
const { toggle, isFullscreen } = useFullscreen(); const { toggle, isFullscreen } = useFullscreen();
//
isFullscreen.value = !!(
document.fullscreenElement ||
document.webkitFullscreenElement ||
document.mozFullScreenElement ||
document.msFullscreenElement
);
const getTitle = computed(() => { const getTitle = computed(() => {
return unref(isFullscreen) return unref(isFullscreen)

2
apps/vue/src/layouts/default/setting/components/ThemeColorPicker.vue

@ -31,7 +31,7 @@
props: { props: {
colorList: { colorList: {
type: Array as PropType<string[]>, type: Array as PropType<string[]>,
defualt: [], default: () => [],
}, },
event: { event: {
type: Number as PropType<HandlerEnum>, type: Number as PropType<HandlerEnum>,

2
apps/vue/src/layouts/default/setting/components/TypePicker.vue

@ -31,7 +31,7 @@
props: { props: {
menuTypeList: { menuTypeList: {
type: Array as PropType<typeof menuTypeList>, type: Array as PropType<typeof menuTypeList>,
defualt: () => [], default: () => [],
}, },
handler: { handler: {
type: Function as PropType<Fn>, type: Function as PropType<Fn>,

2
apps/vue/src/locales/lang/en/layout.ts

@ -3,7 +3,7 @@ export default {
header: { header: {
// user dropdown // user dropdown
dropdownItemDoc: 'Document', dropdownItemDoc: 'Document',
dropdownItemLoginOut: 'Login Out', dropdownItemLoginOut: 'Log Out',
tooltipErrorLog: 'Error log', tooltipErrorLog: 'Error log',
tooltipLock: 'Lock screen', tooltipLock: 'Lock screen',

2
apps/vue/src/router/constant.ts

@ -18,7 +18,7 @@ export const getParentLayout = (_name?: string) => {
return () => return () =>
new Promise((resolve) => { new Promise((resolve) => {
resolve({ resolve({
name: PARENT_LAYOUT_NAME, name: _name || PARENT_LAYOUT_NAME,
}); });
}); });
}; };

1
apps/vue/src/store/modules/multipleTab.ts

@ -187,6 +187,7 @@ export const useMultipleTabStore = defineStore({
if (path !== tab.path) { if (path !== tab.path) {
// Closed is not the activation tab // Closed is not the activation tab
close(tab); close(tab);
this.updateCacheTab();
return; return;
} }

11
apps/vue/src/utils/dateUtil.ts

@ -6,17 +6,12 @@ import dayjs from 'dayjs';
const DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss'; const DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss';
const DATE_FORMAT = 'YYYY-MM-DD'; const DATE_FORMAT = 'YYYY-MM-DD';
export function formatToDateTime( export function formatToDateTime(date?: dayjs.ConfigType, format = DATE_TIME_FORMAT): string{
date: string | Date | dayjs.Dayjs | undefined = undefined,
format = DATE_TIME_FORMAT,
): string {
return dayjs(date).format(format); return dayjs(date).format(format);
} }
export function formatToDate( export function formatToDate(date?: dayjs.ConfigType, format = DATE_FORMAT): string {
date: string | Date | dayjs.Dayjs | undefined = undefined, if (typeof date === 'number') date *= 1000;
format = DATE_FORMAT,
): string {
return dayjs(date).format(format); return dayjs(date).format(format);
} }

6
apps/vue/src/utils/http/axios/index.ts

@ -16,6 +16,7 @@ import { setObjToUrlParams, deepMerge } from '/@/utils';
import { useErrorLogStoreWithOut } from '/@/store/modules/errorLog'; import { useErrorLogStoreWithOut } from '/@/store/modules/errorLog';
import { joinTimestamp, formatRequestDate } from './helper'; import { joinTimestamp, formatRequestDate } from './helper';
import { useLocaleStoreWithOut } from '/@/store/modules/locale'; import { useLocaleStoreWithOut } from '/@/store/modules/locale';
import axios from 'axios';
const globSetting = useGlobSetting(); const globSetting = useGlobSetting();
const urlPrefix = globSetting.urlPrefix; const urlPrefix = globSetting.urlPrefix;
@ -153,6 +154,11 @@ const transform: AxiosTransform = {
// const { t } = useI18n(); // const { t } = useI18n();
const errorLogStore = useErrorLogStoreWithOut(); const errorLogStore = useErrorLogStoreWithOut();
errorLogStore.addAjaxErrorInfo(error); errorLogStore.addAjaxErrorInfo(error);
if (axios.isCancel(error)) {
return Promise.reject(error);
}
const resMessage = checkResponse(error.response); const resMessage = checkResponse(error.response);
return Promise.reject(resMessage ?? error); return Promise.reject(resMessage ?? error);
}, },

6
apps/vue/src/utils/index.ts

@ -3,6 +3,7 @@ import type { App, Plugin } from 'vue';
import { unref } from 'vue'; import { unref } from 'vue';
import { isObject } from '/@/utils/is'; import { isObject } from '/@/utils/is';
import { cloneDeep } from 'lodash-es';
export const noop = () => {}; export const noop = () => {};
@ -34,10 +35,11 @@ export function setObjToUrlParams(baseUrl: string, obj: any): string {
export function deepMerge<T = any>(src: any = {}, target: any = {}): T { export function deepMerge<T = any>(src: any = {}, target: any = {}): T {
let key: string; let key: string;
const res: any = cloneDeep(src)
for (key in target) { for (key in target) {
src[key] = isObject(src[key]) ? deepMerge(src[key], target[key]) : (src[key] = target[key]); res[key] = isObject(res[key]) ? deepMerge(res[key], target[key]) : (res[key] = target[key]);
} }
return src; return res;
} }
export function openWindow( export function openWindow(

3
apps/vue/src/utils/is.ts

@ -107,8 +107,7 @@ export function isPhone(val: string) {
} }
export function isUrl(path: string): boolean { export function isUrl(path: string): boolean {
const reg = const reg = /^http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?/;
/^(((^https?:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)$/;
return isMatch(reg, path); return isMatch(reg, path);
} }

4
apps/vue/src/views/account/setting/BaseSetting.vue

@ -97,9 +97,9 @@
}); });
} }
function updateAvatar(src: string) { function updateAvatar({ source }) {
const userinfo = userStore.getUserInfo; const userinfo = userStore.getUserInfo;
userinfo.avatar = src; userinfo.avatar = source;
userStore.setUserInfo(userinfo); userStore.setUserInfo(userinfo);
} }

3
apps/vue/src/views/oss-management/objects/components/FileList.vue

@ -99,9 +99,6 @@
// , // ,
clickToRowSelect: false, clickToRowSelect: false,
clearSelectOnPageChange: true, clearSelectOnPageChange: true,
tableSetting: {
redo: false,
},
bordered: true, bordered: true,
showIndexColumn: false, showIndexColumn: false,
canResize: false, canResize: false,

2
apps/vue/src/views/platform/menu/hooks/useMenuFormContext.ts

@ -223,7 +223,7 @@ export function useMenuFormContext({ menuModel, formElRef, framework }: UseMenuF
const schemas = unref(getFormSchemas); const schemas = unref(getFormSchemas);
const metaSchemas= schemas.filter((x) => x.tab === tabKey); const metaSchemas= schemas.filter((x) => x.tab === tabKey);
metaSchemas.forEach((x) => { metaSchemas.forEach((x) => {
formEl?.removeSchemaByFiled(x.field); formEl?.removeSchemaByField(x.field);
const index = schemas.findIndex((s) => s.field === x.field); const index = schemas.findIndex((s) => s.field === x.field);
if (index) { if (index) {
schemas.splice(index, 1); schemas.splice(index, 1);

Loading…
Cancel
Save