mirror of
https://github.com/tencentmusic/supersonic.git
synced 2026-04-21 22:34:28 +08:00
[improvement][semantic-fe] Adding the ability to filter dimensions based on whether they are tags or not. (#417)
* [improvement][semantic-fe] Add model alias setting & Add view permission restrictions to the model permission management tab. [improvement][semantic-fe] Add permission control to the action buttons for the main domain; apply high sensitivity filtering to the authorization of metrics/dimensions. [improvement][semantic-fe] Optimize the editing mode in the dimension/metric/datasource components to use the modelId stored in the database for data, instead of relying on the data from the state manager. * [improvement][semantic-fe] Add time granularity setting in the data source configuration. * [improvement][semantic-fe] Dictionary import for dimension values supported in Q&A visibility * [improvement][semantic-fe] Modification of data source creation prompt wording" * [improvement][semantic-fe] metric market experience optimization * [improvement][semantic-fe] enhance the analysis of metric trends * [improvement][semantic-fe] optimize the presentation of metric trend permissions * [improvement][semantic-fe] add metric trend download functionality * [improvement][semantic-fe] fix the dimension initialization issue in metric correlation * [improvement][semantic-fe] Fix the issue of database changes not taking effect when creating based on an SQL data source. * [improvement][semantic-fe] Optimizing pagination logic and some CSS styles * [improvement][semantic-fe] Fixing the API for the indicator list by changing "current" to "pageNum" * [improvement][semantic-fe] Fixing the default value setting for the indicator list * [improvement][semantic-fe] Adding batch operations for indicators/dimensions/models * [improvement][semantic-fe] Replacing the single status update API for indicators/dimensions with a batch update API * [improvement][semantic-fe] Redesigning the indicator homepage to incorporate trend charts and table functionality for indicators * [improvement][semantic-fe] Optimizing the logic for setting dimension values and editing data sources, and adding system settings functionality * [improvement][semantic-fe] Upgrading antd version to 5.x, extracting the batch operation button component, optimizing the interaction for system settings, and expanding the configuration generation types for list-to-select component. * [improvement][semantic-fe] Adding the ability to filter dimensions based on whether they are tags or not.
This commit is contained in:
@@ -163,7 +163,7 @@ const DefaultSettingForm: ForwardRefRenderFunction<any, Props> = (
|
||||
</FormItem>
|
||||
|
||||
{chatConfigType === ChatConfigType.DETAIL && (
|
||||
<FormItem name="dataItemIds" label="展示维度/指标">
|
||||
<FormItem name="dataItemIds" label="圈选结果展示字段">
|
||||
<Select
|
||||
mode="multiple"
|
||||
allowClear
|
||||
@@ -176,63 +176,11 @@ const DefaultSettingForm: ForwardRefRenderFunction<any, Props> = (
|
||||
}
|
||||
return false;
|
||||
}}
|
||||
placeholder="请选择展示维度/指标信息"
|
||||
placeholder="请选择圈选结果展示字段"
|
||||
options={dataItemListOptions}
|
||||
/>
|
||||
</FormItem>
|
||||
)}
|
||||
{chatConfigType === ChatConfigType.AGG && (
|
||||
<>
|
||||
{/* <FormItem
|
||||
name="metricIds"
|
||||
label={
|
||||
<FormItemTitle
|
||||
title={'指标'}
|
||||
subTitle={'问答搜索结果选择中,如果没有指定指标,将会采用默认指标进行展示'}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Select
|
||||
mode="multiple"
|
||||
allowClear
|
||||
style={{ width: '100%' }}
|
||||
filterOption={(inputValue: string, item: any) => {
|
||||
const { label } = item;
|
||||
if (label.includes(inputValue)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}}
|
||||
placeholder="请选择展示指标信息"
|
||||
options={metricListOptions}
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem
|
||||
name="ratioMetricIds"
|
||||
label={
|
||||
<FormItemTitle
|
||||
title={'同环比指标'}
|
||||
subTitle={'问答搜索含有指定的指标,将会同时计算该指标最后一天的同环比'}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Select
|
||||
mode="multiple"
|
||||
allowClear
|
||||
style={{ width: '100%' }}
|
||||
filterOption={(inputValue: string, item: any) => {
|
||||
const { label } = item;
|
||||
if (label.includes(inputValue)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}}
|
||||
placeholder="请选择同环比指标"
|
||||
options={metricListOptions}
|
||||
/>
|
||||
</FormItem> */}
|
||||
</>
|
||||
)}
|
||||
<FormItem
|
||||
label={
|
||||
<FormItemTitle
|
||||
|
||||
@@ -1,19 +1,13 @@
|
||||
import { Table, Transfer, Checkbox, Button, Space, message, Tooltip } from 'antd';
|
||||
import { Table, Transfer } from 'antd';
|
||||
import type { ColumnsType, TableRowSelection } from 'antd/es/table/interface';
|
||||
import type { TransferItem } from 'antd/es/transfer';
|
||||
import type { CheckboxChangeEvent } from 'antd/es/checkbox';
|
||||
import difference from 'lodash/difference';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import React from 'react';
|
||||
import { connect } from 'umi';
|
||||
import type { StateType } from '../../model';
|
||||
import type { IChatConfig } from '../../data';
|
||||
import DimensionValueSettingModal from './DimensionValueSettingModal';
|
||||
import TransTypeTag from '../TransTypeTag';
|
||||
import TableTitleTooltips from '../../components/TableTitleTooltips';
|
||||
import { RedoOutlined } from '@ant-design/icons';
|
||||
import { SemanticNodeType, DictTaskState, TransType } from '../../enum';
|
||||
import { createDictTask, searchDictLatestTaskList } from '@/pages/SemanticModel/service';
|
||||
import styles from '../style.less';
|
||||
import { SemanticNodeType, TransType } from '../../enum';
|
||||
interface RecordType {
|
||||
id: number;
|
||||
key: string;
|
||||
@@ -29,105 +23,14 @@ type Props = {
|
||||
[key: string]: any;
|
||||
};
|
||||
|
||||
type TaskStateMap = Record<string, DictTaskState>;
|
||||
// type TaskStateMap = Record<string, DictTaskState>;
|
||||
|
||||
const DimensionMetricVisibleTableTransfer: React.FC<Props> = ({
|
||||
domainManger,
|
||||
// domainManger,
|
||||
knowledgeInfosMap,
|
||||
onKnowledgeInfosMapChange,
|
||||
// onKnowledgeInfosMapChange,
|
||||
...restProps
|
||||
}) => {
|
||||
// const { selectModelId: modelId } = domainManger;
|
||||
// const [dimensionValueSettingModalVisible, setDimensionValueSettingModalVisible] =
|
||||
// useState<boolean>(false);
|
||||
// const [currentRecord, setCurrentRecord] = useState<RecordType>({} as RecordType);
|
||||
// const [currentDimensionSettingFormData, setCurrentDimensionSettingFormData] =
|
||||
// useState<IChatConfig.IKnowledgeConfig>();
|
||||
|
||||
// const [recordLoadingMap, setRecordLoadingMap] = useState<Record<string, boolean>>({});
|
||||
|
||||
// const [taskStateMap, setTaskStateMap] = useState<TaskStateMap>({});
|
||||
|
||||
// useEffect(() => {
|
||||
// queryDictLatestTaskList();
|
||||
// }, []);
|
||||
|
||||
// const updateKnowledgeInfosMap = (record: RecordType, updateData: Record<string, any>) => {
|
||||
// const { bizName, id } = record;
|
||||
// const knowledgeMap = {
|
||||
// ...knowledgeInfosMap,
|
||||
// };
|
||||
// const target = knowledgeMap[bizName];
|
||||
// if (target) {
|
||||
// knowledgeMap[bizName] = {
|
||||
// ...target,
|
||||
// ...updateData,
|
||||
// };
|
||||
// } else {
|
||||
// knowledgeMap[bizName] = {
|
||||
// itemId: id,
|
||||
// bizName,
|
||||
// ...updateData,
|
||||
// };
|
||||
// }
|
||||
// onKnowledgeInfosMapChange?.(knowledgeMap);
|
||||
// };
|
||||
|
||||
// const queryDictLatestTaskList = async () => {
|
||||
// const { code, data } = await searchDictLatestTaskList({
|
||||
// modelId,
|
||||
// });
|
||||
// if (code !== 200) {
|
||||
// message.error('获取字典导入任务失败!');
|
||||
// return;
|
||||
// }
|
||||
// const tastMap = data.reduce(
|
||||
// (stateMap: TaskStateMap, item: { dimId: number; status: DictTaskState }) => {
|
||||
// const { dimId, status } = item;
|
||||
// stateMap[dimId] = status;
|
||||
// return stateMap;
|
||||
// },
|
||||
// {},
|
||||
// );
|
||||
// setTaskStateMap(tastMap);
|
||||
// };
|
||||
|
||||
// const createDictTaskQuery = async (recordData: RecordType) => {
|
||||
// setRecordLoadingMap({
|
||||
// ...recordLoadingMap,
|
||||
// [recordData.id]: true,
|
||||
// });
|
||||
// const { code } = await createDictTask({
|
||||
// updateMode: 'REALTIME_ADD',
|
||||
// modelAndDimPair: {
|
||||
// [modelId]: [recordData.id],
|
||||
// },
|
||||
// });
|
||||
// setRecordLoadingMap({
|
||||
// ...recordLoadingMap,
|
||||
// [recordData.id]: false,
|
||||
// });
|
||||
// if (code !== 200) {
|
||||
// message.error('字典导入任务创建失败!');
|
||||
// return;
|
||||
// }
|
||||
// setTimeout(() => {
|
||||
// queryDictLatestTaskList();
|
||||
// }, 2000);
|
||||
// };
|
||||
|
||||
// const deleteDictTask = async (recordData: RecordType) => {
|
||||
// const { code } = await createDictTask({
|
||||
// updateMode: 'REALTIME_DELETE',
|
||||
// modelAndDimPair: {
|
||||
// [modelId]: [recordData.id],
|
||||
// },
|
||||
// });
|
||||
// if (code !== 200) {
|
||||
// message.error('删除字典导入任务创建失败!');
|
||||
// }
|
||||
// };
|
||||
|
||||
let rightColumns: ColumnsType<RecordType> = [
|
||||
{
|
||||
dataIndex: 'name',
|
||||
@@ -141,104 +44,6 @@ const DimensionMetricVisibleTableTransfer: React.FC<Props> = ({
|
||||
return <TransTypeTag type={type} />;
|
||||
},
|
||||
},
|
||||
// {
|
||||
// dataIndex: 'y',
|
||||
// title: (
|
||||
// <TableTitleTooltips
|
||||
// title="维度值可见"
|
||||
// tooltips="勾选可见后,维度值将在搜索时可以被联想出来"
|
||||
// />
|
||||
// ),
|
||||
// width: 120,
|
||||
// render: (_: any, record: RecordType) => {
|
||||
// const { type, bizName } = record;
|
||||
// return type === TransType.DIMENSION ? (
|
||||
// <Checkbox
|
||||
// checked={knowledgeInfosMap?.[bizName]?.searchEnable}
|
||||
// onChange={(e: CheckboxChangeEvent) => {
|
||||
// updateKnowledgeInfosMap(record, { searchEnable: e.target.checked });
|
||||
// if (!e.target.checked) {
|
||||
// deleteDictTask(record);
|
||||
// }
|
||||
// }}
|
||||
// onClick={(event) => {
|
||||
// event.stopPropagation();
|
||||
// }}
|
||||
// />
|
||||
// ) : (
|
||||
// <></>
|
||||
// );
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// dataIndex: 'taskState',
|
||||
// width: 130,
|
||||
// title: (
|
||||
// <Space>
|
||||
// 导入字典状态
|
||||
// <span
|
||||
// className={styles.taskStateRefreshIcon}
|
||||
// onClick={() => {
|
||||
// queryDictLatestTaskList();
|
||||
// }}
|
||||
// >
|
||||
// <Tooltip title="刷新字典任务状态">
|
||||
// <RedoOutlined />
|
||||
// </Tooltip>
|
||||
// </span>
|
||||
// </Space>
|
||||
// ),
|
||||
// render: (_, record) => {
|
||||
// const { id, type } = record;
|
||||
// const target = taskStateMap[id];
|
||||
// if (type === TransType.DIMENSION && target) {
|
||||
// return DictTaskState[target] || '未知状态';
|
||||
// }
|
||||
// return '--';
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// title: '操作',
|
||||
// dataIndex: 'x',
|
||||
// render: (_: any, record: RecordType) => {
|
||||
// const { type, bizName, id } = record;
|
||||
// return type === TransType.DIMENSION ? (
|
||||
// <Space>
|
||||
// <Button
|
||||
// style={{ padding: 0 }}
|
||||
// key="importDictBtn"
|
||||
// type="link"
|
||||
// disabled={!knowledgeInfosMap?.[bizName]?.searchEnable}
|
||||
// loading={!!recordLoadingMap[id]}
|
||||
// onClick={(event) => {
|
||||
// createDictTaskQuery(record);
|
||||
// event.stopPropagation();
|
||||
// }}
|
||||
// >
|
||||
// 导入字典
|
||||
// </Button>
|
||||
// <Button
|
||||
// style={{ padding: 0 }}
|
||||
// key="editable"
|
||||
// type="link"
|
||||
// disabled={!knowledgeInfosMap?.[bizName]?.searchEnable}
|
||||
// onClick={(event) => {
|
||||
// setCurrentRecord(record);
|
||||
// setCurrentDimensionSettingFormData(
|
||||
// knowledgeInfosMap?.[bizName]?.knowledgeAdvancedConfig,
|
||||
// );
|
||||
// setDimensionValueSettingModalVisible(true);
|
||||
// event.stopPropagation();
|
||||
// }}
|
||||
// >
|
||||
// 可见维度值设置
|
||||
// </Button>
|
||||
// </Space>
|
||||
// ) : (
|
||||
// <></>
|
||||
// );
|
||||
// },
|
||||
// },
|
||||
];
|
||||
|
||||
const leftColumns: ColumnsType<RecordType> = [
|
||||
@@ -299,17 +104,6 @@ const DimensionMetricVisibleTableTransfer: React.FC<Props> = ({
|
||||
);
|
||||
}}
|
||||
</Transfer>
|
||||
{/* <DimensionValueSettingModal
|
||||
visible={dimensionValueSettingModalVisible}
|
||||
initialValues={currentDimensionSettingFormData}
|
||||
onSubmit={(formValues) => {
|
||||
updateKnowledgeInfosMap(currentRecord, { knowledgeAdvancedConfig: formValues });
|
||||
setDimensionValueSettingModalVisible(false);
|
||||
}}
|
||||
onCancel={() => {
|
||||
setDimensionValueSettingModalVisible(false);
|
||||
}}
|
||||
/> */}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -209,7 +209,7 @@ const DimensionValueSettingForm: ForwardRefRenderFunction<any, Props> = (
|
||||
className={styles.form}
|
||||
>
|
||||
<FormItem
|
||||
style={{ marginTop: 15, marginBottom: -30 }}
|
||||
style={{ marginTop: 15 }}
|
||||
label={
|
||||
<FormItemTitle
|
||||
title={
|
||||
@@ -272,11 +272,11 @@ const DimensionValueSettingForm: ForwardRefRenderFunction<any, Props> = (
|
||||
</FormItem>
|
||||
{dimensionVisible && (
|
||||
<>
|
||||
<Divider
|
||||
{/* <Divider
|
||||
style={{
|
||||
marginBottom: 35,
|
||||
}}
|
||||
/>
|
||||
/> */}
|
||||
<div style={{ padding: 20, border: '1px solid #eee', borderRadius: 10 }}>
|
||||
<div
|
||||
style={{
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
import { useEffect, useState, forwardRef, useImperativeHandle } from 'react';
|
||||
import type { ForwardRefRenderFunction } from 'react';
|
||||
import { message, Form, Input, Select, Button } from 'antd';
|
||||
import { updateModel } from '../../service';
|
||||
import type { ISemantic } from '../../data';
|
||||
import { formLayout } from '@/components/FormHelper/utils';
|
||||
import styles from '../style.less';
|
||||
|
||||
type Props = {
|
||||
modelData?: ISemantic.IModelItem;
|
||||
dimensionList: ISemantic.IDimensionList;
|
||||
modelId: number;
|
||||
onSubmit: () => void;
|
||||
};
|
||||
|
||||
const FormItem = Form.Item;
|
||||
|
||||
const EntityCreateForm: ForwardRefRenderFunction<any, Props> = (
|
||||
{ modelData, dimensionList, modelId, onSubmit },
|
||||
ref,
|
||||
) => {
|
||||
const [form] = Form.useForm();
|
||||
const [dimensionListOptions, setDimensionListOptions] = useState<any>([]);
|
||||
const getFormValidateFields = async () => {
|
||||
return await form.validateFields();
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
form.resetFields();
|
||||
if (!modelData?.entity) {
|
||||
return;
|
||||
}
|
||||
const { entity } = modelData;
|
||||
form.setFieldsValue({
|
||||
...entity,
|
||||
name: entity.names.join(','),
|
||||
});
|
||||
}, [modelData]);
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
getFormValidateFields,
|
||||
}));
|
||||
|
||||
useEffect(() => {
|
||||
const dimensionEnum = dimensionList.map((item: ISemantic.IDimensionItem) => {
|
||||
return {
|
||||
label: item.name,
|
||||
value: item.id,
|
||||
};
|
||||
});
|
||||
setDimensionListOptions(dimensionEnum);
|
||||
}, [dimensionList]);
|
||||
|
||||
const saveEntity = async () => {
|
||||
const values = await form.validateFields();
|
||||
const { name = '' } = values;
|
||||
const { code, msg, data } = await updateModel({
|
||||
...modelData,
|
||||
entity: {
|
||||
...values,
|
||||
names: name.split(','),
|
||||
},
|
||||
id: modelId,
|
||||
modelId,
|
||||
});
|
||||
|
||||
if (code === 200) {
|
||||
form.setFieldValue('id', data);
|
||||
onSubmit?.();
|
||||
message.success('保存成功');
|
||||
return;
|
||||
}
|
||||
message.error(msg);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form {...formLayout} form={form} layout="vertical" className={styles.form}>
|
||||
<FormItem hidden={true} name="id" label="ID">
|
||||
<Input placeholder="id" />
|
||||
</FormItem>
|
||||
<FormItem name="name" label="实体别名">
|
||||
<Input placeholder="请输入实体别名,多个名称以英文逗号分隔" />
|
||||
</FormItem>
|
||||
<FormItem name="entityId" label="唯一标识">
|
||||
<Select
|
||||
allowClear
|
||||
style={{ width: '100%' }}
|
||||
// filterOption={(inputValue: string, item: any) => {
|
||||
// const { label } = item;
|
||||
// if (label.includes(inputValue)) {
|
||||
// return true;
|
||||
// }
|
||||
// return false;
|
||||
// }}
|
||||
placeholder="请选择主体标识"
|
||||
options={dimensionListOptions}
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
saveEntity();
|
||||
}}
|
||||
>
|
||||
保 存
|
||||
</Button>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default forwardRef(EntityCreateForm);
|
||||
@@ -1,67 +0,0 @@
|
||||
import { message, Space } from 'antd';
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import type { Dispatch } from 'umi';
|
||||
import { connect } from 'umi';
|
||||
import type { StateType } from '../../model';
|
||||
import { getModelDetail } from '../../service';
|
||||
import ProCard from '@ant-design/pro-card';
|
||||
import EntityCreateForm from './EntityCreateForm';
|
||||
import type { ISemantic } from '../../data';
|
||||
|
||||
type Props = {
|
||||
dispatch: Dispatch;
|
||||
domainManger: StateType;
|
||||
};
|
||||
|
||||
const EntitySettingSection: React.FC<Props> = ({ domainManger }) => {
|
||||
const { dimensionList, selectModelId: modelId } = domainManger;
|
||||
|
||||
const [modelData, setModelData] = useState<ISemantic.IModelItem>();
|
||||
|
||||
const entityCreateRef = useRef<any>({});
|
||||
|
||||
const queryDomainData: any = async () => {
|
||||
const { code, data } = await getModelDetail({
|
||||
modelId,
|
||||
});
|
||||
|
||||
if (code === 200) {
|
||||
setModelData(data);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
message.error('获取问答设置信息失败');
|
||||
};
|
||||
|
||||
const initPage = async () => {
|
||||
queryDomainData();
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
initPage();
|
||||
}, [modelId]);
|
||||
|
||||
return (
|
||||
<div style={{ width: 800, margin: '20px auto' }}>
|
||||
<Space direction="vertical" style={{ width: '100%' }} size={20}>
|
||||
{
|
||||
<ProCard title="实体" bordered>
|
||||
<EntityCreateForm
|
||||
ref={entityCreateRef}
|
||||
modelId={Number(modelId)}
|
||||
modelData={modelData}
|
||||
dimensionList={dimensionList}
|
||||
onSubmit={() => {
|
||||
queryDomainData();
|
||||
}}
|
||||
/>
|
||||
</ProCard>
|
||||
}
|
||||
</Space>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
export default connect(({ domainManger }: { domainManger: StateType }) => ({
|
||||
domainManger,
|
||||
}))(EntitySettingSection);
|
||||
Reference in New Issue
Block a user