123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344 |
- import {
- DeleteOutlined,
- PlusOutlined,
- } from "@ant-design/icons";
- import {
- Col,
- Row,
- Form,
- Input,
- Select,
- Button,
- Tooltip,
- Popover,
- Popconfirm,
- } from "antd";
- import React, { useEffect, useState } from "react";
- import CustomColorPicker from "@/components/CustomColorPicker";
- import { ColumnItem as ColumnItemType, TableItemType } from "@/type";
- import { TABLE_TYPE_OPTIONS } from "@/constants";
- import { createColumn } from "@/utils";
- import { useModel } from "umi";
- import { DndContext } from "@dnd-kit/core";
- import type { DragEndEvent } from "@dnd-kit/core";
- import {
- SortableContext,
- arrayMove,
- verticalListSortingStrategy,
- } from "@dnd-kit/sortable";
- import { restrictToParentElement } from "@dnd-kit/modifiers";
- import ColumnItem from "./ColumnItem";
- import LangInput from "@/components/LangInput";
- import LangInputTextarea from "@/components/LangInputTextarea";
- import { validateAliasName, validateTableCode } from "@/utils/validator";
- export default function TableItem({
- data,
- onChange,
- active,
- setActive,
- }: {
- data: TableItemType;
- onChange: (data: TableItemType) => void;
- active?: string;
- setActive: (active: string) => void;
- }) {
- const { tableColumnList = [] } = data;
- const { addTable, deleteTable } = useModel("erModel");
- const [list, setList] = useState(tableColumnList);
- const [table, setTable] = React.useState(data?.table);
- useEffect(() => {
- setList(tableColumnList);
- }, [tableColumnList]);
- const handleTableChange = (key: string, value: any) => {
- onChange({
- tableColumnList,
- table: { ...table, [key]: value },
- isTable: true,
- });
- setTable({ ...table, [key]: value });
- };
- const handleChangeColumn = (index: number, key: string, value: any) => {
- const data = tableColumnList[index];
- const newData = { ...data, [key]: value };
- setList(tableColumnList.map((item, i) => (i === index ? newData : item)));
- onChange({
- isTable: true,
- table,
- tableColumnList: tableColumnList.map((item, i) => {
- if (index === i) {
- return { ...item, [key]: value };
- }
- return item;
- }),
- });
- };
- // 添加表
- const handleAddChildTable = () => {
- addTable(table.id);
- };
- // 添加字段
- const handleAddColumn = () => {
- const newColumn: ColumnItemType = createColumn(
- table.id,
- tableColumnList.length + 1
- );
- onChange({
- table,
- tableColumnList: [...tableColumnList, newColumn],
- isTable: true,
- });
- };
- const handleDeleteColumn = (columnId: string) => {
- onChange({
- table,
- tableColumnList: tableColumnList.filter((item) => item.id !== columnId),
- isTable: true,
- });
- };
- const handleDragEnd = (dragItem: DragEndEvent) => {
- const { active, over } = dragItem;
- if (!active || !over) return; // 处理边界情况
- const activeIndex = tableColumnList.findIndex(
- (item) => item.id === active.id
- );
- const overIndex = tableColumnList.findIndex((item) => item.id === over.id);
- const newList = arrayMove(tableColumnList, activeIndex, overIndex);
- setList(newList);
- onChange({
- table,
- tableColumnList: newList,
- isTable: true,
- });
- };
- return (
- <div
- className="
- w-full
- border-l-solid
- border-l-[#e6e6e6]
- border-l-[4px]
- border-b-solid
- border-b-[#e4e4e4]
- border-b-[1px]
- m-b-4px
- p-l-16px"
- style={{
- borderLeftColor: table.style?.color || "#eee",
- marginLeft: table.parentBusinessTableId ? 10 : 0,
- }}
- >
- <div
- className="
- header
- flex
- items-center
- justify-between
- leading-[40px]
- px-[10px]
- hover:bg-[#fafafa]
- cursor-pointer
- m-b-[10px]"
- onClick={() => setActive(active === table.id ? "" : table.id)}
- >
- <div className="font-bold truncate flex-1">
- {table.schemaName}(
- {table?.langNameList?.find((item) => item.name === "zh-CN")?.value})
- </div>
- <div>
- <Popover
- trigger="click"
- placement="right"
- content={
- <div className="w-200px" onClick={(e) => e.stopPropagation()}>
- <Form layout="vertical" initialValues={table}>
- <Form.Item label="表名称" name="langNameList">
- <LangInput
- value={table.langNameList}
- onChange={(lang) => {
- handleTableChange("langNameList", lang);
- }}
- />
- </Form.Item>
- <Form.Item label="描述" name="langDescriptionList">
- <LangInputTextarea
- value={table.langDescriptionList}
- onChange={(lang) => {
- handleTableChange("langDescriptionList", lang);
- }}
- />
- </Form.Item>
- </Form>
- </div>
- }
- >
- <i
- className="iconfont icon-shezhi mr-[10px] cursor-pointer"
- onClick={(e) => e.stopPropagation()}
- />
- </Popover>
- <i
- className="iconfont icon-open inline-block"
- style={{
- transform:
- active === table.id ? "rotate(180deg)" : "rotate(0deg)",
- transition: "all 0.3s",
- }}
- />
- </div>
- </div>
- <div
- className="content overflow-hidden"
- style={{
- display: "grid",
- gridTemplateRows: active === table.id ? "1fr" : "0fr",
- transition: "all 0.3s",
- }}
- >
- <div className="overflow-hidden">
- <Form
- layout="horizontal"
- labelCol={{ span: 8 }}
- initialValues={table}
- >
- <Form.Item
- label="类型"
- labelCol={{ span: 4 }}
- wrapperCol={{ span: 21 }}
- >
- <Select
- placeholder="请选择"
- options={TABLE_TYPE_OPTIONS}
- value={table.type}
- disabled
- onChange={(val) => handleTableChange("type", val)}
- />
- </Form.Item>
- <Row gutter={8}>
- <Col span={12}>
- <Form.Item
- label="编码"
- name="schemaName"
- rules={[
- { required: true, message: "请输入编码" },
- validateTableCode,
- ]}
- >
- <Tooltip title={table.schemaName}>
- <Input
- placeholder="请输入"
- value={table.schemaName}
- onChange={(e) =>
- handleTableChange("schemaName", e.target.value)
- }
- />
- </Tooltip>
- </Form.Item>
- </Col>
- <Col span={12}>
- <Form.Item
- label="别名"
- name="aliasName"
- rules={[
- { required: true, message: "请输入编码" },
- validateAliasName,
- ]}
- >
- <Tooltip title={table.aliasName}>
- <Input
- placeholder="请输入"
- value={table.aliasName}
- onChange={(e) =>
- handleTableChange("aliasName", e.target.value)
- }
- />
- </Tooltip>
- </Form.Item>
- </Col>
- </Row>
- </Form>
- <div className="flex justify-between m-b-10px">
- <CustomColorPicker
- color={table.style?.background}
- onChange={(color) =>
- handleTableChange("style", { ...table.style, color })
- }
- >
- <div
- className="rounded-4px cus-btn w-32px h-32px bg-#eee flex-none cursor-pointer shadow-inner"
- style={{ background: table.style?.color || "#eee" }}
- ></div>
- </CustomColorPicker>
- <div className="flex gap-4px">
- {!table.parentBusinessTableId && (
- <Button
- type="primary"
- className="w-50px"
- onClick={handleAddChildTable}
- >
- 子表
- </Button>
- )}
- <Button
- type="primary"
- className="w-50px"
- onClick={handleAddColumn}
- >
- 字段
- </Button>
- <Popconfirm
- okType="primary"
- title="确定删除该表?"
- okText="确定"
- cancelText="取消"
- onConfirm={() => deleteTable(table.id)}
- >
- <div className="rounded-4px cus-btn w-32px h-32px bg-#eee flex-none text-center leading-32px color-red cursor-pointer">
- <DeleteOutlined />
- </div>
- </Popconfirm>
- </div>
- </div>
- <div className="column-content border-solid border-1px border-#e4e4e4 border-x-none p-y-10px">
- {/* 字段内容 */}
- <DndContext
- onDragEnd={handleDragEnd}
- modifiers={[restrictToParentElement]}
- >
- <SortableContext
- items={list.map((item) => item.id)}
- strategy={verticalListSortingStrategy}
- >
- {list.map((column, index) => {
- return (
- <ColumnItem
- key={column.id}
- column={column}
- onChange={(key, val) =>
- handleChangeColumn(index, key, val)
- }
- onDelete={handleDeleteColumn}
- />
- );
- })}
- </SortableContext>
- </DndContext>
- </div>
- </div>
- </div>
- </div>
- );
- }
|