将开源版本的修改打补丁应用到商业版
This commit is contained in:
@@ -0,0 +1,158 @@
|
||||
<template>
|
||||
<div class="JSelectDept">
|
||||
<JSelectBiz @change="handleSelectChange" @handleOpen="handleOpen" :loading="loadingEcho" v-bind="attrs" />
|
||||
|
||||
<a-form-item v-show="false">
|
||||
<SzDeptSelectModal
|
||||
@register="regModal"
|
||||
@getSelectResult="setValue"
|
||||
v-bind="getBindValue"
|
||||
:rowKey="rowKey"
|
||||
:labelKey="labelKey"
|
||||
@close="handleClose"
|
||||
/>
|
||||
</a-form-item>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref, reactive, watchEffect, watch, provide, unref, toRaw } from 'vue';
|
||||
import SzDeptSelectModal from './modal/SzDeptSelectModal.vue';
|
||||
import JSelectBiz from '@/components/Form/src/jeecg/components/base/JSelectBiz.vue';
|
||||
import { useModal } from '/@/components/Modal';
|
||||
import { propTypes } from '/@/utils/propTypes';
|
||||
import { useAttrs } from '/@/hooks/core/useAttrs';
|
||||
import { SelectValue } from 'ant-design-vue/es/select';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'SzSelectDept',
|
||||
components: {
|
||||
SzDeptSelectModal,
|
||||
JSelectBiz,
|
||||
},
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
// 外部 v-model 绑定的值(ID字符串或数组)
|
||||
value: propTypes.oneOfType([propTypes.string, propTypes.array]),
|
||||
// 显示文本的字段名
|
||||
labelKey: {
|
||||
type: String,
|
||||
default: 'departName',
|
||||
},
|
||||
// 存储值的字段名
|
||||
rowKey: {
|
||||
type: String,
|
||||
default: 'id',
|
||||
},
|
||||
// 是否允许多选
|
||||
multiple: propTypes.bool.def(true),
|
||||
},
|
||||
emits: ['options-change', 'change', 'update:value', 'select'],
|
||||
setup(props, { emit }) {
|
||||
const [regModal, { openModal }] = useModal();
|
||||
const attrs = useAttrs();
|
||||
|
||||
const selectOptions = ref<SelectValue>([]); // 存储 [{id, departName}]
|
||||
const selectValues = reactive<Recordable>({ value: [] }); // 存储 [id]
|
||||
const loadingEcho = ref<boolean>(false);
|
||||
let tempSave: any = [];
|
||||
|
||||
// 依赖注入给 JSelectBiz 组件使用,用于显示标签和加载状态
|
||||
provide('selectOptions', selectOptions);
|
||||
provide('selectValues', selectValues);
|
||||
provide('loadingEcho', loadingEcho);
|
||||
|
||||
/**
|
||||
* 监听外部 value 变化进行初始化
|
||||
*/
|
||||
watchEffect(() => {
|
||||
tempSave = [];
|
||||
if (props.value) {
|
||||
initValue();
|
||||
} else {
|
||||
selectValues.value = [];
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* 初始化值:将字符串转为数组
|
||||
*/
|
||||
function initValue() {
|
||||
let val = props.value ? props.value : [];
|
||||
if (typeof val === 'string' && val !== 'null' && val !== 'undefined') {
|
||||
selectValues.value = val.split(',');
|
||||
tempSave = val.split(',');
|
||||
} else {
|
||||
selectValues.value = Array.isArray(val) ? val : [];
|
||||
tempSave = cloneDeep(selectValues.value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 【关键】接收弹窗传回的精简数据
|
||||
* @param options 格式:[{id: 'xxx', departName: 'xxx'}]
|
||||
* @param values 格式:['xxx']
|
||||
*/
|
||||
function setValue(options, values) {
|
||||
// 将后端字段 [id, departName] 转换为 a-select 认识的 [value, label]
|
||||
selectOptions.value = options.map((item) => ({
|
||||
label: item.departName, // 这一步让框里显示出名字
|
||||
value: item.id, // 这一步让值对应上
|
||||
}));
|
||||
|
||||
selectValues.value = values;
|
||||
send(values);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送数据给父组件
|
||||
*/
|
||||
const send = (values) => {
|
||||
let result = typeof props.value === 'string' ? values.join(',') : values;
|
||||
emit('update:value', result);
|
||||
emit('change', result);
|
||||
};
|
||||
|
||||
function handleOpen() {
|
||||
openModal(true, { isUpdate: false });
|
||||
}
|
||||
|
||||
function handleClose() {
|
||||
if (tempSave.length) {
|
||||
selectValues.value = cloneDeep(tempSave);
|
||||
} else {
|
||||
send(tempSave);
|
||||
}
|
||||
}
|
||||
|
||||
function handleSelectChange(values) {
|
||||
tempSave = cloneDeep(values);
|
||||
send(tempSave);
|
||||
}
|
||||
|
||||
const getBindValue = Object.assign({}, unref(props), unref(attrs));
|
||||
|
||||
return {
|
||||
attrs,
|
||||
selectOptions,
|
||||
selectValues,
|
||||
loadingEcho,
|
||||
getBindValue,
|
||||
regModal,
|
||||
setValue,
|
||||
handleOpen,
|
||||
handleClose,
|
||||
handleSelectChange,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.JSelectDept {
|
||||
> .ant-form-item {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,12 @@
|
||||
// 1. 修改引入路径,Jeecg 使用的是 defHttp
|
||||
import { defHttp } from '@/utils/http/axios';
|
||||
|
||||
// 根据部门+角色+密级筛选用户
|
||||
export function queryDept(params) {
|
||||
return defHttp.get({
|
||||
// 2. 注意:Jeecg 默认配置了 baseUrl,通常不需要写 /jeecg-boot 前缀
|
||||
url: '/sys/sysDepart/querySecondLevelDepts',
|
||||
// 3. GET 请求的参数 key 是 params,而不是 data
|
||||
params,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,245 @@
|
||||
<template>
|
||||
<div>
|
||||
<BasicModal
|
||||
v-bind="$attrs"
|
||||
@register="register"
|
||||
:title="modalTitle"
|
||||
:width="showSelected ? '1200px' : '900px'"
|
||||
wrapClassName="j-user-select-modal"
|
||||
@ok="handleOk"
|
||||
@cancel="handleCancel"
|
||||
:maxHeight="maxHeight"
|
||||
:centered="true"
|
||||
destroyOnClose
|
||||
@visible-change="visibleChange"
|
||||
>
|
||||
<a-row>
|
||||
<a-col :span="showSelected ? 18 : 24">
|
||||
<BasicTable
|
||||
ref="tableRef"
|
||||
:columns="columns"
|
||||
:scroll="tableScroll"
|
||||
v-bind="getBindValue"
|
||||
:useSearchForm="true"
|
||||
:formConfig="formConfig"
|
||||
:api="queryDept"
|
||||
:searchInfo="searchInfo"
|
||||
:rowSelection="rowSelection"
|
||||
:indexColumnProps="indexColumnProps"
|
||||
:afterFetch="afterFetch"
|
||||
:beforeFetch="beforeFetch"
|
||||
>
|
||||
<template #tableTitle></template>
|
||||
</BasicTable>
|
||||
</a-col>
|
||||
|
||||
<a-col :span="showSelected ? 6 : 0" v-if="showSelected" style="padding-left: 10px">
|
||||
<BasicTable v-bind="selectedTable" :dataSource="selectRows">
|
||||
<template #action="{ record }">
|
||||
<a href="javascript:void(0)" @click="handleDeleteSelected(record)">
|
||||
<Icon icon="ant-design:delete-outlined" style="color: #ff4d4f"></Icon>
|
||||
</a>
|
||||
</template>
|
||||
</BasicTable>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</BasicModal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, unref, ref, watch, h } from 'vue';
|
||||
import { BasicModal, useModalInner } from '@/components/Modal';
|
||||
import { queryDept } from '../dept';
|
||||
import { createAsyncComponent } from '@/utils/factory/createAsyncComponent';
|
||||
import { useSelectBiz } from '@/components/Form/src/jeecg/hooks/useSelectBiz';
|
||||
import { useAttrs } from '@/hooks/core/useAttrs';
|
||||
import { selectProps } from '@/components/Form/src/jeecg/props/props';
|
||||
import { Icon } from '@/components/Icon';
|
||||
import { JDictSelectTag } from "@/components/Form";
|
||||
import { render } from "@/utils/common/renderUtils";
|
||||
|
||||
export default defineComponent({
|
||||
name: 'SzDeptSelectModal',
|
||||
components: {
|
||||
BasicModal,
|
||||
Icon,
|
||||
BasicTable: createAsyncComponent(() => import('/src/components/Table/src/BasicTable.vue'), {
|
||||
loading: true,
|
||||
}),
|
||||
},
|
||||
props: {
|
||||
...selectProps,
|
||||
modalTitle: {
|
||||
type: String,
|
||||
default: '选择部门',
|
||||
},
|
||||
},
|
||||
emits: ['register', 'getSelectResult', 'close'],
|
||||
setup(props, { emit }) {
|
||||
const tableScroll = ref<any>({ x: false });
|
||||
const tableRef = ref();
|
||||
const maxHeight = ref(600);
|
||||
|
||||
// 内部状态注册
|
||||
const [register, { closeModal }] = useModalInner(() => {
|
||||
if (window.innerWidth < 900) {
|
||||
tableScroll.value = { x: 900 };
|
||||
} else {
|
||||
tableScroll.value = { x: false };
|
||||
}
|
||||
// 延迟设置选中行,确保 table 渲染完成
|
||||
setTimeout(() => {
|
||||
if (tableRef.value) {
|
||||
tableRef.value.setSelectedRowKeys(selectValues['value'] || []);
|
||||
}
|
||||
}, 300);
|
||||
});
|
||||
|
||||
const attrs = useAttrs();
|
||||
|
||||
// 基础配置
|
||||
const config = {
|
||||
canResize: false,
|
||||
bordered: true,
|
||||
size: 'small',
|
||||
rowKey: 'id', // 必须确保后端返回 id 字段
|
||||
labelKey: 'departName',
|
||||
};
|
||||
|
||||
const getBindValue = Object.assign({}, unref(props), unref(attrs), config);
|
||||
|
||||
// 使用 Jeecg 核心 Hook
|
||||
const [{ rowSelection, visibleChange, selectValues, indexColumnProps, getSelectResult, handleDeleteSelected, selectRows, showSelected }] =
|
||||
useSelectBiz(queryDept, getBindValue, emit);
|
||||
|
||||
const searchInfo = ref(props.params);
|
||||
|
||||
// 监听外部 keys 变化同步给 table
|
||||
watch(rowSelection.selectedRowKeys, (newVal) => {
|
||||
if (tableRef.value) {
|
||||
tableRef.value.setSelectedRowKeys(newVal);
|
||||
}
|
||||
});
|
||||
|
||||
// 搜索表单配置
|
||||
const formConfig = {
|
||||
// 在这里增加 labelWidth
|
||||
labelWidth: 65,
|
||||
baseColProps: { xs: 24, sm: 12, md: 8, lg: 8, xl: 8, xxl: 8 },
|
||||
schemas: [
|
||||
{
|
||||
label: '部门类别',
|
||||
field: 'departType',
|
||||
// 也可以在具体的 schema 里单独控制
|
||||
// labelWidth: 100,
|
||||
component: 'JDictSelectTag',
|
||||
componentProps: {
|
||||
dictCode: 'depart_type',
|
||||
|
||||
placeholder: '请选择部门类别',
|
||||
|
||||
stringToNumber: true,
|
||||
|
||||
'onUpdate:value': (val) => {
|
||||
// 这里的 val 就是选中的值
|
||||
console.log('监听到值改变:', val);
|
||||
// 触发 Table 刷新
|
||||
tableRef.value?.reload();
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
// 主表列定义
|
||||
const columns = [
|
||||
{ title: '部门名称', dataIndex: 'departName', width: 180, align: 'left' },
|
||||
{ title: '机构编码', dataIndex: 'orgCode', width: 120 },
|
||||
{
|
||||
title: '机构类型',
|
||||
dataIndex: 'departType',
|
||||
width: 100,
|
||||
customRender: ({ text }) => {
|
||||
return render.renderDict(text, 'depart_type');
|
||||
},
|
||||
},
|
||||
{ title: '排序', dataIndex: 'departOrder', width: 80 },
|
||||
];
|
||||
|
||||
// 右侧已选表配置
|
||||
const selectedTable = {
|
||||
pagination: false,
|
||||
showIndexColumn: false,
|
||||
scroll: { y: 390 },
|
||||
size: 'small',
|
||||
canResize: false,
|
||||
bordered: true,
|
||||
rowKey: 'id',
|
||||
columns: [
|
||||
{ title: '部门名称', dataIndex: 'departName', width: 100 },
|
||||
{ title: '操作', dataIndex: 'action', align: 'center', width: 40, slots: { customRender: 'action' } },
|
||||
],
|
||||
};
|
||||
|
||||
/**
|
||||
* 【修改后的 handleOk】
|
||||
* 只提取 id 和 departName
|
||||
*/
|
||||
function handleOk() {
|
||||
// 直接从 tableRef 获取选中的原始行数据,避免 label 为 undefined 的问题
|
||||
const rows = tableRef.value.getSelectRows();
|
||||
|
||||
// 1. 提取精简的对象列表
|
||||
const options = rows.map((item) => ({
|
||||
id: item.id,
|
||||
departName: item.departName,
|
||||
}));
|
||||
|
||||
// 2. 提取 ID 列表
|
||||
const values = rows.map((item) => item.id);
|
||||
|
||||
console.log('确定选择内容:', options);
|
||||
|
||||
// 3. 向上抛出事件
|
||||
emit('getSelectResult', options, values);
|
||||
closeModal();
|
||||
}
|
||||
|
||||
function afterFetch(record) {
|
||||
return record;
|
||||
}
|
||||
|
||||
function beforeFetch(params) {
|
||||
return Object.assign({ column: 'createTime', order: 'desc' }, params);
|
||||
}
|
||||
|
||||
const handleCancel = () => {
|
||||
emit('close');
|
||||
};
|
||||
|
||||
return {
|
||||
handleOk,
|
||||
searchInfo,
|
||||
register,
|
||||
indexColumnProps,
|
||||
visibleChange,
|
||||
getBindValue,
|
||||
queryDept, // 必须暴露给 template 中的 :api
|
||||
formConfig,
|
||||
columns,
|
||||
rowSelection,
|
||||
selectRows,
|
||||
showSelected,
|
||||
selectedTable,
|
||||
handleDeleteSelected,
|
||||
tableScroll,
|
||||
tableRef,
|
||||
afterFetch,
|
||||
handleCancel,
|
||||
maxHeight,
|
||||
beforeFetch,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
Reference in New Issue
Block a user