v3.8.2 版本前端代码

This commit is contained in:
JEECG
2025-07-30 18:25:58 +08:00
parent e6edde963a
commit 219869f4c0
84 changed files with 3587 additions and 1964 deletions

View File

@ -7,6 +7,7 @@
<a-menu :class="[`${prefixCls}-menu`]" :selectedKeys="selectedKeys">
<template v-for="item in dropMenuList" :key="`${item.event}`">
<a-menu-item
v-if="!item.hide"
v-bind="getAttr(item.event)"
@click="handleClickMenu(item)"
:disabled="item.disabled"

View File

@ -5,5 +5,7 @@ export interface DropMenu {
event: string | number;
text: string;
disabled?: boolean;
// 是否隐藏
hide?: boolean;
divider?: boolean;
}

View File

@ -11,6 +11,7 @@
:allDefaultValues="defaultValueRef"
:formModel="formModel"
:formName="getBindValue.name"
:source="getBindValue.source"
:setFormModel="setFormModel"
:validateFields="validateFields"
:clearValidate="clearValidate"
@ -126,7 +127,15 @@
};
});
const getBindValue = computed(() => ({ ...attrs, ...props, ...unref(getProps) } as Recordable));
const getBindValue = computed(() => {
const bindValue = { ...attrs, ...props, ...unref(getProps) } as Recordable;
// update-begin--author:liaozhiyang---date:20250630---for【issues/8484】分类字典中的新增弹窗的label点击会触发查询区域的input
if (bindValue.name === undefined && bindValue.source === 'table-query') {
bindValue.name = 'top-query-form';
}
// update-end--author:liaozhiyang---date:20250630---for【issues/8484】分类字典中的新增弹窗的label点击会触发查询区域的input
return bindValue;
});
const getSchema = computed((): FormSchema[] => {
const schemas: FormSchema[] = unref(schemaRef) || (unref(getProps).schemas as any);
@ -302,6 +311,22 @@
}
}
/**
* 获取 componentProps处理可能是函数的情况
* @param schema
*/
function getSchemaComponentProps(schema: FormSchema) {
if (typeof schema.componentProps === 'function') {
return schema.componentProps({
schema,
tableAction: props.tableAction,
formActionType,
formModel,
})
}
return schema.componentProps
}
const formActionType: Partial<FormActionType> = {
getFieldsValue,
setFieldsValue,
@ -318,6 +343,7 @@
validate,
submit: handleSubmit,
scrollToField: scrollToField,
getSchemaComponentProps,
};
onMounted(() => {

View File

@ -66,6 +66,7 @@ import JEllipsis from './jeecg/components/JEllipsis.vue';
import JSelectUserByDept from './jeecg/components/JSelectUserByDept.vue';
import JSelectUserByDepartment from './jeecg/components/JSelectUserByDepartment.vue';
import JLinkTableCard from './jeecg/components/JLinkTableCard/JLinkTableCard.vue';
import JUpload from './jeecg/components/JUpload/JUpload.vue';
import JSearchSelect from './jeecg/components/JSearchSelect.vue';
import JAddInput from './jeecg/components/JAddInput.vue';

View File

@ -190,7 +190,7 @@
} finally {
loading.value = false;
//--@updateBy-begin----author:liusq---date:20210914------for:判断选择模式multiple多选情况下的value值空的情况下需要设置为数组------
unref(attrs).mode == 'multiple' && !Array.isArray(unref(state)) && setState([]);
['multiple', 'tags'].includes(unref(attrs).mode) && !Array.isArray(unref(state)) && setState([]);
//--@updateBy-end----author:liusq---date:20210914------for:判断选择模式multiple多选情况下的value值空的情况下需要设置为数组------
//update-begin---author:wangshuai ---date:20230505 for初始化value值如果是多选字符串的情况下显示不出来------------
@ -202,7 +202,7 @@
function initValue() {
let value = props.value;
// update-begin--author:liaozhiyang---date:20250407---for【issues/8037】初始化值单选的值被错误地写入数组值
if (unref(attrs).mode == 'multiple') {
if (['multiple', 'tags'].includes(unref(attrs).mode)) {
if (value && typeof value === 'string' && value != 'null' && value != 'undefined') {
state.value = value.split(',');
} else if (isNumber(value)) {

View File

@ -66,6 +66,10 @@
default: '',
},
// update-end--author:liaozhiyang---date:20240625---for【TV360X-1511】blur不生效
source: {
type: String,
default: '',
},
},
setup(props, { slots }) {
const { t } = useI18n();
@ -506,7 +510,7 @@
<div style="display:flex">
{/* author: sunjianlei for: 【VUEN-744】此处加上 width: 100%; 因为要防止组件宽度超出 FormItem */}
{/* update-begin--author:liaozhiyang---date:20240510---for【TV360X-719】表单校验不通过项滚动到可视区内 */}
<Middleware formName={props.formName} fieldName={field}>{getContent()}</Middleware>
<Middleware formName={props.formName} fieldName={field} source={props.source}>{getContent()}</Middleware>
{/* update-end--author:liaozhiyang---date:20240510---for【TV360X-719】表单校验不通过项滚动到可视区内 */}
{showSuffix && <span class="suffix">{getSuffix}</span>}
</div>

View File

@ -8,8 +8,8 @@
import { ref } from 'vue';
// update-begin--author:liaozhiyang---date:20240625---for【TV360X-1511】blur不生效
const formItemId = ref(null);
const props = defineProps(['formName', 'fieldName']);
if (props.formName && props.fieldName) {
const props = defineProps(['formName', 'fieldName', 'source']);
if (props.formName && props.fieldName && props.source !== 'table-query') {
formItemId.value = `${props.formName}_${props.fieldName}`;
}
// update-end--author:liaozhiyang---date:20240625---for【TV360X-1511】blur不生效

View File

@ -137,7 +137,7 @@ export function useForm(props?: Props): UseFormReturnType {
let values = form.validate(nameList).then((values) => {
for (let key in values) {
if (values[key] instanceof Array) {
let valueType = getValueTypeBySchema(form.getSchemaByField(key)!);
let valueType = getValueTypeBySchema(form.getSchemaByField(key)!, form);
if (valueType === 'string') {
values[key] = values[key].join(',');
}

View File

@ -595,6 +595,9 @@
flex: 1;
border-right: 1px solid #e8e8e8;
.search-box {
:deep(.ant-input-affix-wrapper) {
border-color: #d9d9d9 !important;
}
margin: 0 16px 16px 16px;
}
:deep(.ant-breadcrumb) {

View File

@ -24,7 +24,7 @@
v-bind="getBindValue"
:useSearchForm="true"
:formConfig="formConfig"
:api="getUserList"
:api="hasCustomApi ? customListApi : getUserList"
:searchInfo="searchInfo"
:rowSelection="rowSelection"
:indexColumnProps="indexColumnProps"
@ -54,7 +54,7 @@
</div>
</template>
<script lang="ts">
import { defineComponent, unref, ref, watch } from 'vue';
import { defineComponent, unref, ref, watch, computed } from 'vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { getUserList } from '/@/api/common/api';
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
@ -85,6 +85,11 @@
default: [],
},
//update-end---author:wangshuai ---date:20230703 for【QQYUN-5685】5、离职人员可以选自己------------
// 查询table数据使用的自定义接口
customListApi: {type: Function},
// 自定义接口的查询条件是否使用 JInput
customApiJInput: {type: Boolean, default: true},
},
emits: ['register', 'getSelectResult', 'close'],
setup(props, { emit, refs }) {
@ -93,6 +98,8 @@
const tableRef = ref();
const maxHeight = ref(600);
const hasCustomApi = computed(() => typeof props.customListApi === 'function');
//注册弹框
const [register, { closeModal }] = useModalInner(() => {
if (window.innerWidth < 900) {
@ -156,12 +163,12 @@
{
label: '账号',
field: 'username',
component: 'JInput',
component: (hasCustomApi.value && !props.customApiJInput) ? 'Input' : 'JInput',
},
{
label: '姓名',
field: 'realname',
component: 'JInput',
component: (hasCustomApi.value && !props.customApiJInput) ? 'Input' : 'JInput',
},
],
};
@ -300,6 +307,7 @@
handleCancel,
maxHeight,
beforeFetch,
hasCustomApi,
};
},
});

View File

@ -41,6 +41,7 @@ export interface FormActionType {
validateFields: (nameList?: NamePath[], options?: ValidateOptions) => Promise<any>;
validate: (nameList?: NamePath[]) => Promise<any>;
scrollToField: (name: NamePath, options?: ScrollOptions) => Promise<void>;
getSchemaComponentProps: (schema: FormSchema) => Recordable
}
export type RegisterFn = (formInstance: FormActionType) => void;

View File

@ -143,6 +143,11 @@
function scaleFunc(num: number) {
if (imgState.imgScale <= 0.2 && num < 0) return;
imgState.imgScale += num;
// update-begin--author:liaozhiyang---date:20250722---for【QQYUN-13162】图片预览点击缩小一下就没了
if (imgState.imgScale < 0.2) {
imgState.imgScale = 0.2;
}
// update-end--author:liaozhiyang---date:20250722---for【QQYUN-13162】图片预览点击缩小一下就没了
}
// 旋转图片

View File

@ -4,6 +4,7 @@
:class="{ 'table-search-area-hidden': !getBindValues.formConfig?.schemas?.length }"
submitOnReset
v-bind="getFormProps"
source="table-query"
v-if="getBindValues.useSearchForm"
:tableAction="tableAction"
@register="registerForm"
@ -214,7 +215,7 @@
onChange && isFunction(onChange) && onChange.call(undefined, ...args);
}
const { getViewColumns, getColumns, setCacheColumnsByField, setColumns, getColumnsRef, getCacheColumns } = useColumns(
const { getViewColumns, getColumns, getRefColumns, setCacheColumnsByField, setColumns, getColumnsRef, getCacheColumns } = useColumns(
getProps,
getPaginationInfo,
// update-begin--author:sunjianlei---date:220230630---for【QQYUN-5571】自封装选择列解决数据行选择卡顿问题
@ -367,6 +368,9 @@
getRowSelection,
getPaginationRef: getPagination,
getColumns,
// update-begin--author:liaozhiyang---date:20250722---for【issues/8529】setColumns后列配置没联动更新
getColumnsRef: () => getColumnsRef,
// update-end--author:liaozhiyang---date:20250722---for【issues/8529】setColumns后列配置没联动更新
getCacheColumns,
emit,
updateTableData,

View File

@ -49,6 +49,7 @@
},
setup(props) {
const table = useTableContext();
const getColumnsRef = table.getColumnsRef();
const tableFooter = ref<any>(null);
const getDataSource = computed((): Recordable[] => {
const { summaryFunc, summaryData } = props;
@ -71,7 +72,10 @@
const getColumns = computed(() => {
const dataSource = unref(getDataSource);
let columns: BasicColumn[] = cloneDeep(table.getColumns());
// update-begin--author:liaozhiyang---date:20250729---for【issues/8502】权限列不显示后表尾行合计栏还显示导致对不齐
const allColumns = unref(getColumnsRef);
let columns: BasicColumn[] = cloneDeep(table.getColumns({ ignoreAuth: true, ignoreIfShow: true }));
// update-end--author:liaozhiyang---date:20250729---for【issues/8502】权限列不显示后表尾行合计栏还显示导致对不齐
// update-begin--author:liaozhiyang---date:220230804---for【issues/638】表格合计列自定义隐藏或展示时合计栏会错位
columns = columns.filter((item) => !item.defaultHidden);
// update-begin--author:liaozhiyang---date:220230804---for【issues/638】表格合计列自定义隐藏或展示时合计栏会错位

View File

@ -148,7 +148,27 @@
const options: LabelValueOptions = editComponentProps?.options ?? (unref(optionsRef) || []);
const option = options.find((item) => `${item.value}` === `${value}`);
// update-begin---author:liaozhiyang---date:2025-07-28---for:【QQYUN-13251】表格可编辑单元格apiSelect多选不翻译 ---
if (['tags', 'multiple'].includes(editComponentProps?.mode)) {
const result = options
.filter((item) => {
let v = value;
if (isString(value)) {
v = value.split(',');
} else if (isNumber(value)) {
v = [value];
}
if (v.includes(item.value)) {
return true;
}
})
.map((item) => item.label);
if (result.length) {
return result.join(',');
}
return value;
}
// update-end---author:liaozhiyang---date:2025-07-28---for:【QQYUN-13251】表格可编辑单元格apiSelect多选不翻译 ---
return option?.label ?? value;
});

View File

@ -151,6 +151,9 @@
// nextTick(() => popoverVisible.value = false);
// update-end--author:sunjianlei---date:20221101---for: 修复第一次进入时列表配置不能拖拽
const defaultRowSelection = omit(table.getRowSelection(), 'selectedRowKeys');
// update-begin--author:liaozhiyang---date:20250722---for【issues/8529】setColumns后列配置没联动更新
const getColumnsRef = table.getColumnsRef();
// update-end--author:liaozhiyang---date:20250722---for【issues/8529】setColumns后列配置没联动更新
let inited = false;
const cachePlainOptions = ref<Options[]>([]);
@ -219,7 +222,7 @@
checkSelect.value = !!values.rowSelection;
});
// update-begin--author:liaozhiyang---date:20240724---for【issues/6908】多语言无刷新切换时BasicColumn和FormSchema里面的值不能正常切换
watch(localeStore, () => {
watch([localeStore, getColumnsRef], () => {
const columns = getColumns();
plainOptions.value = columns;
plainSortOptions.value = columns;
@ -230,7 +233,7 @@
function getColumns() {
const ret: Options[] = [];
// update-begin--author:liaozhiyang---date:20250403---for【issues/7996】表格列组件取消所有或者只勾选中间显示非预期
let t = table.getColumns({ ignoreIndex: true, ignoreAction: true });
let t = table.getColumns({ ignoreIndex: true, ignoreAction: true, ignoreAuth: true, ignoreIfShow: true });
if (!t.length) {
t = table.getCacheColumns();
}
@ -249,7 +252,7 @@
const columns = getColumns();
const checkList = table
.getColumns({ ignoreAction: true, ignoreIndex: true })
.getColumns({ ignoreAction: true, ignoreIndex: true, ignoreAuth: true, ignoreIfShow: true })
.map((item) => {
if (item.defaultHidden) {
return '';
@ -341,7 +344,7 @@
// state.checkedList = [...state.defaultCheckList];
// update-begin--author:liaozhiyang---date:20231103---for【issues/825】tabel的列设置隐藏列保存后切换路由问题[重置没勾选]
state.checkedList = table
.getColumns({ ignoreAction: true })
.getColumns({ ignoreAction: true, ignoreAuth: true, ignoreIfShow: true })
.map((item) => {
return item.dataIndex || item.title;
})

View File

@ -285,7 +285,7 @@ export function useColumns(
// update-end--author:sunjianlei---date:20220523---for: 【VUEN-1089】合并vben最新版代码解决表格字段排序问题
function getColumns(opt?: GetColumnsParams) {
const { ignoreIndex, ignoreAction, sort } = opt || {};
const { ignoreIndex, ignoreAction, ignoreAuth, ignoreIfShow, sort } = opt || {};
let columns = toRaw(unref(getColumnsRef));
if (ignoreIndex) {
columns = columns.filter((item) => item.flag !== INDEX_COLUMN_FLAG);
@ -297,7 +297,27 @@ export function useColumns(
// 过滤自定义选择列
columns = columns.filter((item) => item.key !== CUS_SEL_COLUMN_KEY);
// update-enb--author:sunjianlei---date:220230630---for【QQYUN-5571】自封装选择列解决数据行选择卡顿问题
// update-begin--author:liaozhiyang---date:20250729---for【issues/8502】解决权限列在列表中不显示列配置中还显示
if (ignoreAuth) {
columns = columns.filter((item) => {
if (item.auth) {
return hasPermission(item.auth);
}
return true;
});
}
if (ignoreIfShow) {
columns = columns.filter((item) => {
if (isBoolean(item.ifShow)) {
return item.ifShow;
}
if (isFunction(item.ifShow)) {
return item.ifShow(item);
}
return true;
});
}
// update-end--author:liaozhiyang---date:20250729---for【issues/8502】解决权限列在列表中不显示列配置中还显示
if (sort) {
columns = sortFixedColumn(columns);
}

View File

@ -1,4 +1,4 @@
import type { VNodeChild } from 'vue';
import type { VNodeChild, ComputedRef } from 'vue';
import type { PaginationProps } from './pagination';
import type { FormProps } from '/@/components/Form';
import type { TableRowSelection as ITableRowSelection } from 'ant-design-vue/lib/table/interface';
@ -80,6 +80,10 @@ export interface FetchParams {
export interface GetColumnsParams {
ignoreIndex?: boolean;
ignoreAction?: boolean;
// update-begin--author:liaozhiyang---date:20250729---for【issues/8502】解决权限列在列表中不显示列配置中还显示
ignoreAuth?: boolean;
ignoreIfShow?: boolean | ((column: BasicColumn) => boolean);
// update-end--author:liaozhiyang---date:20250729---for【issues/8502】解决权限列在列表中不显示列配置中还显示
sort?: boolean;
}
@ -116,6 +120,7 @@ export interface TableActionType {
setShowPagination: (show: boolean) => Promise<void>;
getShowPagination: () => boolean;
setCacheColumnsByField?: (dataIndex: string | undefined, value: BasicColumn) => void;
getColumnsRef: () => ComputedRef<BasicColumn[]>;
}
export interface FetchSetting {

View File

@ -151,6 +151,28 @@
toolbar,
menubar: false,
plugins,
// 添加以下粘贴相关配置
paste_data_images: true, // 允许粘贴图片
paste_as_text: false, // 不以纯文本粘贴
paste_retain_style_properties: 'all', // 保留所有样式属性
paste_webkit_styles: 'all', // 保留webkit样式
paste_merge_formats: true, // 合并格式
paste_block_drop: true, // 允许拖放粘贴
paste_preprocess: (plugin, args) => {
// 可以在这里对粘贴的内容进行预处理
//console.log('粘贴的内容:', args.content);
},
paste_postprocess: (plugin, args) => {
// 可以在这里对粘贴的内容进行后处理
//console.log('处理后的内容:', args.node);
},
// 放宽内容过滤规则
valid_elements: '*[*]',
extended_valid_elements: '*[*]',
valid_children: '+body[style]',
allow_conditional_comments: true,
allow_html_in_named_anchor: true,
language_url: publicPath + 'resource/tinymce/langs/' + langName.value + '.js',
language: langName.value,
branding: false,

View File

@ -10,10 +10,10 @@ export const plugins = [
export const toolbar =
'fullscreen code preview | undo redo | bold italic underline strikethrough | fontselect fontsizeselect formatselect | alignleft aligncenter alignright alignjustify | outdent indent lineheight|subscript superscript blockquote| numlist bullist checklist | forecolor backcolor casechange permanentpen formatpainter removeformat | pagebreak | charmap emoticons | insertfile image media pageembed link anchor codesample insertdatetime hr| a11ycheck ltr rtl';
export const simplePlugins = 'lists image link fullscreen';
export const simplePlugins = 'lists image link fullscreen paste';
export const simpleToolbar = [
'undo redo styles bold italic alignleft aligncenter alignright alignjustify bullist numlist outdent indent lists image link fullscreen',
'undo redo styles forecolor fontsize bold italic alignleft aligncenter alignright alignjustify bullist numlist outdent indent lists image link fullscreen',
];
export const menubar = 'file edit insert view format table';