bi-sdk-react 0.0.59 → 0.0.60

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bi-sdk-react",
3
- "version": "0.0.59",
3
+ "version": "0.0.60",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "dist/umd/js/bi-sdk.umd.min.js",
@@ -2,7 +2,7 @@ import React from "react";
2
2
  import { createFromIconfontCN } from "@ant-design/icons";
3
3
 
4
4
  const IconFontCN = createFromIconfontCN({
5
- scriptUrl: "https://at.alicdn.com/t/c/font_5072483_30lly4gkmhf.js",
5
+ scriptUrl: "https://at.alicdn.com/t/c/font_5072483_qyp3hlby2nr.js",
6
6
  });
7
7
 
8
8
  export type IconFontProps = {
@@ -24,6 +24,7 @@ import {
24
24
  SwitchProps,
25
25
  TableProps,
26
26
  TextProps,
27
+ AnchorProps,
27
28
  } from "./item-props";
28
29
  import {
29
30
  ButtonRender,
@@ -47,6 +48,7 @@ import {
47
48
  SwitchRender,
48
49
  TableRender,
49
50
  TextRender,
51
+ AnchorRender,
50
52
  } from "./items";
51
53
 
52
54
  export const TextPlugin: PluginType = {
@@ -140,7 +142,8 @@ export const TablePlugin: PluginType = {
140
142
  source: "custom",
141
143
  datasourceId: null,
142
144
  scriptId: null,
143
- custom: "[{\"name\":\"苹果\",\"count\":12},{\"name\":\"华为\",\"count\":803},{\"name\":\"OPPO\",\"count\":654},{\"name\":\"vivo\",\"count\":719}]",
145
+ custom:
146
+ '[{"name":"苹果","count":12},{"name":"华为","count":803},{"name":"OPPO","count":654},{"name":"vivo","count":719}]',
144
147
  },
145
148
  props: {
146
149
  size: "default",
@@ -232,6 +235,31 @@ return {
232
235
  ],
233
236
  };
234
237
 
238
+ export const AnchorPlugin: PluginType = {
239
+ group: "基础组件",
240
+ key: "b-anchor",
241
+ label: "锚点",
242
+ icon: "icon-anchor",
243
+ component: AnchorRender,
244
+ formComponent: AnchorProps,
245
+ defaultOptions: {
246
+ props: {
247
+ items: [
248
+ { href: "#item1", title: "<i class='icon-dict'></i>项目1" },
249
+ { href: "#item2", title: "<i class='icon-dict'></i>项目2" },
250
+ { href: "#item3", title: "<i class='icon-dict'></i>项目3" },
251
+ ],
252
+ linePosition: 10,
253
+ lineColor: "rgba(5, 5, 5, 0.06)",
254
+ lineWidth: 2,
255
+ gap: 30,
256
+ itemClassNames: [],
257
+ itemTitleClassNames: [],
258
+ indicatorClassNames: [],
259
+ },
260
+ },
261
+ };
262
+
235
263
  export const InputPlugin: PluginType = {
236
264
  group: "表单组件",
237
265
  key: "b-input",
@@ -462,7 +490,7 @@ export const ModalPlugin: PluginType = {
462
490
  events: [
463
491
  { name: "打开", handler: "open" },
464
492
  { name: "关闭", handler: "close" },
465
- ]
493
+ ],
466
494
  };
467
495
 
468
496
  export const DrawerPlugin: PluginType = {
@@ -492,7 +520,7 @@ export const DrawerPlugin: PluginType = {
492
520
  events: [
493
521
  { name: "打开", handler: "open" },
494
522
  { name: "关闭", handler: "close" },
495
- ]
523
+ ],
496
524
  };
497
525
 
498
526
  export const plugins: PluginType[] = [
@@ -504,6 +532,7 @@ export const plugins: PluginType[] = [
504
532
  ListPlugin,
505
533
  HtmlPlugin,
506
534
  EchartsPlugin,
535
+ AnchorPlugin,
507
536
  InputPlugin,
508
537
  InputNumberPlugin,
509
538
  SelectPlugin,
@@ -0,0 +1,223 @@
1
+ import { DeleteOutlined, EditOutlined } from "@ant-design/icons";
2
+ import {
3
+ AutoComplete,
4
+ Button,
5
+ ColorPicker,
6
+ Divider,
7
+ Form,
8
+ Input,
9
+ InputNumber,
10
+ Modal,
11
+ Select,
12
+ Space,
13
+ Table,
14
+ } from "antd";
15
+ import React, { useContext, useMemo, useState } from "react";
16
+ import { AnchorItem, AnchorRenderProps } from "../items/AnchorRender";
17
+ import type { PropEditorProps } from "./types";
18
+ import { PageContext } from "../../../context/PageContext";
19
+
20
+ export const AnchorProps: React.FC<PropEditorProps<AnchorRenderProps>> = ({
21
+ model,
22
+ onChange,
23
+ }) => {
24
+ const { schema } = useContext(PageContext);
25
+
26
+ const trigger = (key: keyof AnchorRenderProps, value: any) =>
27
+ onChange && onChange({ ...model, [key]: value });
28
+ const setColumn = (index: number, col: Partial<AnchorItem>) => {
29
+ const items = [...(model.items || [])];
30
+ items[index] = { ...items[index], ...col };
31
+ trigger("items", items);
32
+ };
33
+ const removeColumn = (index: number) => {
34
+ const items = [...(model.items || [])];
35
+ items.splice(index, 1);
36
+ trigger("items", items);
37
+ };
38
+ const addColumn = () => {
39
+ trigger("items", [
40
+ ...(model.items || []),
41
+ { title: "", href: "", key: "" },
42
+ ]);
43
+ };
44
+ const [editVisible, setEditVisible] = useState(false);
45
+ const [editingIndex, setEditingIndex] = useState<number | null>(null);
46
+ const editingForm =
47
+ editingIndex != null && model.items?.[editingIndex]
48
+ ? model.items[editingIndex]
49
+ : { title: "", href: "", key: "" };
50
+ const columns = [
51
+ {
52
+ title: "标题",
53
+ dataIndex: "title",
54
+ render: (v: string) => (
55
+ <div dangerouslySetInnerHTML={{ __html: v }}></div>
56
+ ),
57
+ },
58
+ {
59
+ title: "操作",
60
+ width: 80,
61
+ align: "center" as const,
62
+ render: (_: any, r: AnchorItem, i: number) => (
63
+ <Space>
64
+ <a
65
+ onClick={() => {
66
+ setEditingIndex(i);
67
+ setEditVisible(true);
68
+ }}
69
+ >
70
+ <EditOutlined />
71
+ </a>
72
+ <a onClick={() => removeColumn(i)}>
73
+ <DeleteOutlined />
74
+ </a>
75
+ </Space>
76
+ ),
77
+ },
78
+ ];
79
+
80
+ const items = useMemo(() => {
81
+ const list: any[] = [];
82
+ const compute = (arr?: any[]) => {
83
+ if (!Array.isArray(arr)) return;
84
+ arr.forEach((item) => {
85
+ list.push(item);
86
+ if (Array.isArray(item.children)) {
87
+ compute(item.children);
88
+ } else if (typeof item.children === "object" && item.children) {
89
+ Object.keys(item.children).forEach((k) => compute(item.children[k]));
90
+ }
91
+ });
92
+ };
93
+ compute(schema?.items || []);
94
+ return list;
95
+ }, [schema]);
96
+
97
+ return (
98
+ <div>
99
+ <Form labelCol={{ span: 6 }} wrapperCol={{ span: 18 }}>
100
+ <Form.Item label="线位置(left)">
101
+ <InputNumber
102
+ size="small"
103
+ style={{ width: "100px" }}
104
+ value={model.linePosition}
105
+ suffix="px"
106
+ onChange={(v) => trigger("linePosition", v)}
107
+ />
108
+ </Form.Item>
109
+ <Form.Item label="线颜色">
110
+ <ColorPicker
111
+ size="small"
112
+ value={model.lineColor}
113
+ onChange={(v) => trigger("lineColor", v.toHexString())}
114
+ allowClear={true}
115
+ />
116
+ </Form.Item>
117
+ <Form.Item label="线宽度">
118
+ <InputNumber
119
+ size="small"
120
+ style={{ width: "100px" }}
121
+ value={model.lineWidth}
122
+ suffix="px"
123
+ onChange={(v) => trigger("lineWidth", v)}
124
+ />
125
+ </Form.Item>
126
+ <Form.Item label="间距">
127
+ <InputNumber
128
+ size="small"
129
+ style={{ width: "100px" }}
130
+ value={model.gap}
131
+ suffix="px"
132
+ onChange={(v) => trigger("gap", v)}
133
+ />
134
+ </Form.Item>
135
+
136
+ <Divider style={{ marginTop: 10 }}>样式设置</Divider>
137
+ <Form.Item
138
+ label="链接项类名"
139
+ layout="vertical"
140
+ labelCol={{ span: 24 }}
141
+ wrapperCol={{ span: 24 }}
142
+ >
143
+ <Select
144
+ mode="tags"
145
+ size="small"
146
+ value={model.itemClassNames || []}
147
+ onChange={(e) => trigger("itemClassNames", e)}
148
+ />
149
+ </Form.Item>
150
+ <Form.Item
151
+ label="标题文字类名"
152
+ layout="vertical"
153
+ labelCol={{ span: 24 }}
154
+ wrapperCol={{ span: 24 }}
155
+ >
156
+ <Select
157
+ mode="tags"
158
+ size="small"
159
+ value={model.itemTitleClassNames || []}
160
+ onChange={(e) => trigger("itemTitleClassNames", e)}
161
+ />
162
+ </Form.Item>
163
+ <Form.Item
164
+ label="指示器类名"
165
+ layout="vertical"
166
+ labelCol={{ span: 24 }}
167
+ wrapperCol={{ span: 24 }}
168
+ >
169
+ <Select
170
+ mode="tags"
171
+ size="small"
172
+ value={model.indicatorClassNames || []}
173
+ onChange={(e) => trigger("indicatorClassNames", e)}
174
+ />
175
+ </Form.Item>
176
+ </Form>
177
+ <Divider>锚点项设置</Divider>
178
+ <Table
179
+ size="small"
180
+ dataSource={model.items}
181
+ rowKey={(_, i) => String(i)}
182
+ columns={columns as any}
183
+ pagination={false}
184
+ bordered
185
+ />
186
+ <Button size="small" onClick={addColumn} block>
187
+ 添加列
188
+ </Button>
189
+ <Modal
190
+ title="编辑列"
191
+ open={editVisible}
192
+ footer={null}
193
+ width={400}
194
+ onCancel={() => setEditVisible(false)}
195
+ >
196
+ <Form layout="vertical" size="small">
197
+ <Form.Item
198
+ label="锚点内容"
199
+ tooltip="支持HTML标签"
200
+ style={{ marginBottom: 10 }}
201
+ >
202
+ <Input.TextArea
203
+ value={editingForm.title}
204
+ onChange={(e) =>
205
+ setColumn(editingIndex!, { title: e.target.value })
206
+ }
207
+ />
208
+ </Form.Item>
209
+ <Form.Item label="锚点链接" style={{ marginBottom: 10 }}>
210
+ <AutoComplete
211
+ value={editingForm.href}
212
+ onChange={(e) => setColumn(editingIndex!, { href: e })}
213
+ options={items.map((i) => ({
214
+ value: i.id,
215
+ label: i.name,
216
+ }))}
217
+ />
218
+ </Form.Item>
219
+ </Form>
220
+ </Modal>
221
+ </div>
222
+ );
223
+ };
@@ -19,4 +19,4 @@ export { ColProps } from './ColProps'
19
19
  export { ModalProps } from './ModalProps'
20
20
  export { SpaceProps } from './SpaceProps'
21
21
  export { DrawerProps } from './DrawerProps'
22
-
22
+ export { AnchorProps } from './AnchorProps'
@@ -0,0 +1,114 @@
1
+ import { Anchor, Space } from "antd";
2
+ import React, { useContext, useMemo } from "react";
3
+ import { IconFont } from "../../../icon/IconFont";
4
+ import styled from "styled-components";
5
+ import { PageContext } from "../../../context/PageContext";
6
+ import { HtmlBaseProps } from "../../../typing";
7
+
8
+ export type AnchorItem = {
9
+ key?: string;
10
+ href: string;
11
+ title: string;
12
+ };
13
+
14
+ export type AnchorRenderProps = {
15
+ id?: string;
16
+ item: any;
17
+ items?: AnchorItem[];
18
+ style?: React.CSSProperties;
19
+ linePosition?: number;
20
+ lineColor?: string;
21
+ lineWidth?: number;
22
+ gap?: number;
23
+ itemClassNames?: string[];
24
+ itemTitleClassNames?: string[];
25
+ indicatorClassNames?: string[];
26
+ } & HtmlBaseProps;
27
+
28
+ /**
29
+ * AnchorRender 组件
30
+ * 用途:渲染自定义 HTML 模板,支持数据源变量插值
31
+ * 参数:
32
+ * - id:组件唯一标识
33
+ * - template:HTML 模板字符串,支持 {{ expr }} 插值
34
+ * - item:当前元素数据(含 datasource)
35
+ * - style:样式
36
+ * - className:类名
37
+ * - ref:转发到 div 的引用(HTMLDivElement)
38
+ */
39
+ export const AnchorRender: React.FC<AnchorRenderProps> = ({
40
+ id,
41
+ item,
42
+ items = [],
43
+ style,
44
+ linePosition = 0,
45
+ lineColor = "rgba(5, 5, 5, 0.06)",
46
+ lineWidth = 2,
47
+ gap = 30,
48
+ itemClassNames = [],
49
+ itemTitleClassNames = [],
50
+ indicatorClassNames = [],
51
+ className,
52
+ }) => {
53
+ const { designable } = useContext(PageContext);
54
+ const anchorItems = useMemo(
55
+ () =>
56
+ items.map((item, index) => ({
57
+ ...item,
58
+ key: item.key || index,
59
+ title: <div dangerouslySetInnerHTML={{ __html: item.title }}></div>,
60
+ href: `#page-item-${item.href}`,
61
+ })),
62
+ [items],
63
+ );
64
+
65
+ const StyledAnchor = styled(Anchor)`
66
+ .ant-anchor:before {
67
+ inset-inline-start: ${linePosition || 0}px !important;
68
+ border-inline-start-color: ${lineColor ||
69
+ "rgba(5, 5, 5, 0.06)"} !important;
70
+ border-inline-start-width: ${lineWidth || 2}px !important;
71
+ }
72
+ .ant-anchor .ant-anchor-ink.ant-anchor-ink-visible {
73
+ left: ${linePosition || 0}px !important;
74
+ width: ${lineWidth || 2}px !important;
75
+ }
76
+ div.ant-anchor-link + div.ant-anchor-link {
77
+ margin-top: ${gap || 30}px;
78
+ }
79
+ `;
80
+
81
+ return (
82
+ <div id={id} className={className}>
83
+ <StyledAnchor
84
+ style={style}
85
+ items={anchorItems}
86
+ getContainer={() =>
87
+ designable
88
+ ? (document.querySelector(
89
+ ".center > .body.beautified_scrollbar.always",
90
+ ) as HTMLElement)
91
+ : window
92
+ }
93
+ classNames={{
94
+ item: (itemClassNames || []).join(" "),
95
+ itemTitle: (itemTitleClassNames || []).join(" "),
96
+ indicator: (indicatorClassNames || []).join(" "),
97
+ }}
98
+ styles={{
99
+ item: {
100
+ paddingTop: 0,
101
+ paddingBottom: 0,
102
+ },
103
+ itemTitle: {
104
+ // backgroundColor: "#ffffff",
105
+ },
106
+ indicator: {
107
+ left: `${linePosition || 0}px !important`,
108
+ width: `${lineWidth || 2}px !important`,
109
+ },
110
+ }}
111
+ />
112
+ </div>
113
+ );
114
+ };
@@ -19,3 +19,4 @@ export { DatePickerRender } from './DatePickerRender'
19
19
  export { SwitchRender } from './SwitchRender'
20
20
  export { ModalRender } from './ModalRender'
21
21
  export { DrawerRender } from './DrawerRender'
22
+ export { AnchorRender } from './AnchorRender'