123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274 |
- import React, { useMemo, useState } from "react";
- import { HolderOutlined } from "@ant-design/icons";
- import {
- Button,
- Form,
- Input,
- InputNumber,
- Popover,
- Row,
- Col,
- Tooltip,
- Select,
- } from "antd";
- import { ColumnItem as ColumnItemType } from "@/type";
- import { DATA_TYPE_OPTIONS } from "@/constants";
- import { useSortable } from "@dnd-kit/sortable";
- import { CSS } from "@dnd-kit/utilities";
- import LangInput from "@/components/LangInput";
- import { DataType } from "@/enum";
- export default function ColumnItem({
- column,
- onChange,
- onDelete,
- }: {
- column: ColumnItemType;
- onChange: (key: string, value: any) => void;
- onDelete: (id: string) => void;
- }) {
- const { setNodeRef, attributes, listeners, transform, transition } =
- useSortable({
- id: column.id,
- transition: {
- duration: 500,
- easing: "cubic-bezier(0.25, 1, 0.5, 1)",
- },
- });
- const [code, setCode] = useState(column.schemaName);
- const [open, setOpen] = React.useState(false);
- const styles = {
- transform: CSS.Transform.toString(transform),
- transition,
- };
- const validCodeErrMsg = useMemo(() => {
- setOpen(true);
- if (!code) return "编码不能为空";
- if (code.length >= 50) {
- return "编码长度不能超过50";
- }
- const regex = /^[a-z][a-z0-9_]*$/;
- if (!regex.test(code)) return "编码只能包含字母和数字, 必须小写字母开头!";
- setOpen(false);
- return false;
- }, [code]);
- const handleSetCode = () => {
- if (code && !validCodeErrMsg) {
- onChange("schemaName", code);
- }
- if (!code) {
- setCode(column.schemaName);
- }
- };
- return (
- <div
- key={column.id}
- className="column-item flex gap-4px items-center jutify-space-between hover:bg-gray-100 mb-4px"
- style={styles}
- ref={setNodeRef}
- {...attributes}
- data-cypress="draggable-item"
- >
- <HolderOutlined
- className="cursor-move"
- data-cypress="draggable-handle"
- {...listeners}
- />
- <Tooltip title="字段编码">
- <Popover
- title={<span className="text-red">{validCodeErrMsg}</span>}
- open={open}
- onOpenChange={(o) => setOpen(o && !!validCodeErrMsg)}
- trigger={["focus"]}
- >
- <Input
- placeholder="编码"
- defaultValue={code}
- className="flex-1"
- disabled={column.isPreDefined}
- onChange={(e) => setCode(e.target.value)}
- onBlur={handleSetCode}
- status={validCodeErrMsg ? "error" : ""}
- />
- </Popover>
- </Tooltip>
- <Tooltip title="字段类型">
- <Select
- placeholder="类型"
- className="w-80px"
- options={DATA_TYPE_OPTIONS}
- value={column.type}
- disabled={column.isPreDefined}
- onChange={(value) => onChange("type", value)}
- dropdownStyle={{ width: 120 }}
- />
- </Tooltip>
- <Tooltip title="非空">
- <div
- className="
- rounded-4px
- cus-btn
- w-32px
- h-32px
- bg-#eee
- flex-none
- text-center
- leading-32px
- hover:bg-#ddd"
- style={{
- ...(column.isRequired
- ? { background: "#1677ff", color: "#fff" }
- : {}),
- cursor: column.isPreDefined ? "not-allowed" : "pointer",
- }}
- onClick={() =>
- !column.isPreDefined && onChange("isRequired", !column.isRequired)
- }
- >
- !
- </div>
- </Tooltip>
- <Tooltip title="唯一">
- <div
- className="
- rounded-4px
- cus-btn
- w-32px
- h-32px
- bg-#eee
- flex-none
- text-center
- leading-32px
- cursor-pointer
- hover:bg-#ddd"
- style={{
- ...(column.isUnique
- ? { background: "#1677ff", color: "#fff" }
- : {}),
- cursor: column.isPreDefined ? "not-allowed" : "pointer",
- }}
- onClick={() =>
- !column.isPreDefined && onChange("isUnique", !column.isUnique)
- }
- >
- 1
- </div>
- </Tooltip>
- <Popover
- trigger="click"
- placement="right"
- content={
- <div
- className="w-360px max-h-400px overflow-hidden"
- onClick={(e) => e.stopPropagation()}
- >
- <Form layout="vertical">
- <Row gutter={8}>
- <Col span={12}>
- <Form.Item label="字段名称">
- <LangInput
- disabled={column.isPreDefined}
- value={column.langNameList}
- onChange={(val) => {
- onChange("langNameList", val);
- }}
- />
- </Form.Item>
- </Col>
- <Col span={12}>
- <Form.Item label="默认值">
- <Input
- className="w-full"
- placeholder="默认值"
- disabled={column.isPreDefined}
- value={column.defaultValue}
- onChange={(e) => onChange("defaultValue", e.target.value)}
- />
- </Form.Item>
- </Col>
- </Row>
- {column.type === DataType.Nvarchar && (
- <Row gutter={8}>
- <Col span={12}>
- <Form.Item label="长度">
- <InputNumber
- placeholder="请输入"
- min={0}
- className="w-full"
- disabled={column.isPreDefined}
- value={column.maxLength}
- onChange={(num) => onChange("maxLength", num)}
- />
- </Form.Item>
- </Col>
- </Row>
- )}
- {column.type === DataType.Decimal && (
- <Row gutter={8}>
- <Col span={12}>
- <Form.Item label="总长度">
- <InputNumber
- placeholder="请输入"
- min={0}
- step={1}
- className="w-full"
- disabled={column.isPreDefined}
- value={column.precision}
- onChange={(num) => onChange("precision", num)}
- />
- </Form.Item>
- </Col>
- <Col span={12}>
- <Form.Item label="小数位数">
- <InputNumber
- placeholder="请输入"
- min={0}
- step={1}
- className="w-full"
- disabled={column.isPreDefined}
- value={column.scale}
- onChange={(num) => onChange("scale", num)}
- />
- </Form.Item>
- </Col>
- </Row>
- )}
- <Row>
- <Col span={24}>
- <Form.Item label="描述">
- <Input.TextArea
- placeholder="请输入"
- disabled={column.isPreDefined}
- value={column.memo}
- onChange={(e) => onChange("memo", e.target.value)}
- />
- </Form.Item>
- </Col>
- </Row>
- </Form>
- {!column.isPreDefined && (
- <Button
- type="default"
- danger
- className="w-full"
- onClick={() => onDelete(column.id)}
- >
- 删除
- </Button>
- )}
- </div>
- }
- >
- <div className="rounded-4px cus-btn w-32px h-32px bg-#eee flex-none text-center leading-32px cursor-pointer hover:bg-#ddd">
- <i className="iconfont icon-gengduo" />
- </div>
- </Popover>
- </div>
- );
- }
|