adspecs 0.1.18 → 0.1.20

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.
Files changed (88) hide show
  1. package/.adspecs/extensions/git/commands/adspecs.git.initialize.md +4 -4
  2. package/.adspecs/extensions/git/extension.yml +1 -1
  3. package/.adspecs/extensions/git/git-config.yml +17 -2
  4. package/.adspecs/extensions.yml +32 -0
  5. package/.adspecs/feature.json +16 -16
  6. package/.adspecs/feature.yml +28 -28
  7. package/.adspecs/paths.json +17 -0
  8. package/.adspecs/templates/02-/344/272/247/345/223/201/351/234/200/346/261/202/350/257/264/346/230/216/344/271/246/346/250/241/346/235/277.md +4 -0
  9. package/.adspecs/workflows/adspecs/workflow.yml +5 -4
  10. package/.claude-plugin/marketplace.json +23 -23
  11. package/.claude-plugin/plugin.json +18 -18
  12. package/.qoder-plugin/plugin.json +31 -31
  13. package/CLAUDE.md +1 -5
  14. package/README.md +395 -395
  15. package/bin/adspecs.js +129 -129
  16. package/hooks/commit-queue.js +245 -245
  17. package/hooks/hooks.json +63 -63
  18. package/hooks/session-start.js +44 -44
  19. package/hooks/wiki-queue.js +127 -127
  20. package/package.json +61 -61
  21. package/references/ant6-front-standard/index.md +99 -99
  22. package/references/antd-front-demo/.env.develop +12 -0
  23. package/references/antd-front-demo/.env.production +5 -0
  24. package/references/antd-front-demo/package-lock.json +2 -2
  25. package/references/antd-front-demo/package.json +1 -1
  26. package/references/antd-front-demo/public/mockServiceWorker.js +361 -361
  27. package/references/ecp-end-standard/index.md +63 -63
  28. package/references/python-end-standard/01-Python/345/220/216/347/253/257/347/274/226/347/240/201/350/247/204/350/214/203.md +372 -372
  29. package/references/python-end-standard/02-/346/225/260/346/215/256/345/272/223/350/256/276/350/256/241/344/270/216/344/275/277/347/224/250/350/247/204/350/214/203.md +226 -226
  30. package/references/python-end-standard/03-Celery/345/274/202/346/255/245/344/273/273/345/212/241/350/247/204/350/214/203.md +237 -237
  31. package/references/python-end-standard/04-Redis/344/275/277/347/224/250/350/247/204/350/214/203.md +231 -231
  32. package/scripts/postinstall.js +107 -107
  33. package/scripts/sync-version.js +105 -105
  34. package/skills/.claude/.wiki-update-queue +26 -26
  35. package/skills/adspecs-constitution/SKILL.md +157 -0
  36. package/skills/adspecs-export-word/SKILL.md +498 -498
  37. package/skills/adspecs-export-word/references/md-to-docx.js +862 -862
  38. package/skills/adspecs-export-word/references/package-lock.json +220 -220
  39. package/skills/adspecs-export-word/references/package.json +10 -10
  40. package/skills/adspecs-front-prototype/SKILL.md +405 -0
  41. package/skills/adspecs-git-commit/SKILL.md +23 -8
  42. package/skills/adspecs-git-initialize/SKILL.md +54 -0
  43. package/skills/adspecs-plan/SKILL.md +59 -69
  44. package/skills/adspecs-prd/SKILL.md +13 -5
  45. package/skills/adspecs-prd-to-demo/SKILL.md +532 -0
  46. package/skills/adspecs-tasks/SKILL.md +175 -204
  47. package/skills/adspecs-update-status/SKILL.md +382 -382
  48. package/skills/adspecs-utest/SKILL.md +107 -116
  49. package/skills/grill-me/SKILL.md +7 -0
  50. package/skills/grill-me/agents/openai.yaml +5 -0
  51. package/skills/playwright-cli/SKILL.md +420 -0
  52. package/skills/playwright-cli/references/element-attributes.md +23 -0
  53. package/skills/playwright-cli/references/playwright-tests.md +39 -0
  54. package/skills/playwright-cli/references/request-mocking.md +87 -0
  55. package/skills/playwright-cli/references/running-code.md +241 -0
  56. package/skills/playwright-cli/references/session-management.md +225 -0
  57. package/skills/playwright-cli/references/storage-state.md +275 -0
  58. package/skills/playwright-cli/references/test-generation.md +433 -0
  59. package/skills/playwright-cli/references/tracing.md +139 -0
  60. package/skills/playwright-cli/references/video-recording.md +143 -0
  61. package/skills/playwright-trace/SKILL.md +171 -0
  62. package/skills/project-init/references/front-demo/.claude/settings.local.json +9 -0
  63. package/skills/wiki-update/SKILL.md +232 -232
  64. package/src/commands/doctor.js +197 -197
  65. package/src/commands/init.js +83 -83
  66. package/src/commands/plugin.js +165 -165
  67. package/src/commands/update.js +87 -87
  68. package/src/lib/area-scanner.js +129 -129
  69. package/src/lib/copier.js +104 -104
  70. package/src/lib/dir-utils.js +133 -133
  71. package/src/lib/json-merge.js +114 -114
  72. package/src/lib/paths-defaults.js +37 -37
  73. package/src/lib/prompts.js +347 -345
  74. package/src/lib/readme-gen.js +143 -143
  75. package/src/lib/report.js +327 -327
  76. package/src/lib/scaffolder.js +518 -518
  77. package/src/lib/short-name.js +36 -36
  78. package/src/utils.js +80 -80
  79. package/references/antd-front-demo/.env +0 -15
  80. package/references/antd-front-demo/src/pages/aps/coil/components/CoilDrawer.tsx +0 -141
  81. package/references/antd-front-demo/src/pages/aps/coil/index.tsx +0 -209
  82. package/references/antd-front-demo/src/pages/aps/optimization/index.tsx +0 -192
  83. package/references/antd-front-demo/src/pages/aps/order/components/OrderDrawer.tsx +0 -251
  84. package/references/antd-front-demo/src/pages/aps/order/index.tsx +0 -273
  85. package/references/antd-front-demo/src/pages/aps/param/index.tsx +0 -153
  86. package/references/antd-front-demo/src/pages/aps/plan/components/CuttingPlanVisualization.tsx +0 -821
  87. package/references/antd-front-demo/src/pages/aps/plan/index.tsx +0 -254
  88. package/references/antd-front-demo/src/pages/aps/task/index.tsx +0 -190
@@ -1,36 +1,36 @@
1
- 'use strict';
2
-
3
- /**
4
- * project_short_name 自动推导
5
- *
6
- * 规则(与 project-init SKILL.md 保持一致):
7
- * 1. 从 project_name 中提取所有英文字母和数字(去除中文、空格、连字符、下划线等)
8
- * 2. 转为小写
9
- * 3. 如果结果为空(项目名称全中文),则从 project_dir 推导(去除连字符和下划线)
10
- * 4. 如果仍为空,使用 'project' 作为默认值
11
- */
12
-
13
- /**
14
- * 推导 project_short_name
15
- * @param {string} projectName - 项目完整名称
16
- * @param {string} projectDir - 项目目录名(可选)
17
- * @returns {string} 仅包含英文字母和数字的小写短名称
18
- */
19
- function deriveShortName(projectName, projectDir) {
20
- // 1. 从 project_name 提取英文字母和数字
21
- if (projectName) {
22
- const fromName = projectName.replace(/[^a-zA-Z0-9]/g, '').toLowerCase();
23
- if (fromName) return fromName;
24
- }
25
-
26
- // 2. 从 project_dir 推导(去除连字符和下划线)
27
- if (projectDir) {
28
- const fromDir = projectDir.replace(/[-_\s]/g, '').toLowerCase();
29
- if (fromDir) return fromDir;
30
- }
31
-
32
- // 3. 默认值
33
- return 'project';
34
- }
35
-
36
- module.exports = { deriveShortName };
1
+ 'use strict';
2
+
3
+ /**
4
+ * project_short_name 自动推导
5
+ *
6
+ * 规则(与 project-init SKILL.md 保持一致):
7
+ * 1. 从 project_name 中提取所有英文字母和数字(去除中文、空格、连字符、下划线等)
8
+ * 2. 转为小写
9
+ * 3. 如果结果为空(项目名称全中文),则从 project_dir 推导(去除连字符和下划线)
10
+ * 4. 如果仍为空,使用 'project' 作为默认值
11
+ */
12
+
13
+ /**
14
+ * 推导 project_short_name
15
+ * @param {string} projectName - 项目完整名称
16
+ * @param {string} projectDir - 项目目录名(可选)
17
+ * @returns {string} 仅包含英文字母和数字的小写短名称
18
+ */
19
+ function deriveShortName(projectName, projectDir) {
20
+ // 1. 从 project_name 提取英文字母和数字
21
+ if (projectName) {
22
+ const fromName = projectName.replace(/[^a-zA-Z0-9]/g, '').toLowerCase();
23
+ if (fromName) return fromName;
24
+ }
25
+
26
+ // 2. 从 project_dir 推导(去除连字符和下划线)
27
+ if (projectDir) {
28
+ const fromDir = projectDir.replace(/[-_\s]/g, '').toLowerCase();
29
+ if (fromDir) return fromDir;
30
+ }
31
+
32
+ // 3. 默认值
33
+ return 'project';
34
+ }
35
+
36
+ module.exports = { deriveShortName };
package/src/utils.js CHANGED
@@ -1,80 +1,80 @@
1
- 'use strict';
2
-
3
- /**
4
- * adspecs CLI 通用工具
5
- *
6
- * 此模块作为 package.json 的 "main" 入口,
7
- * 供其他 Node.js 脚本 require('adspecs') 时使用。
8
- */
9
-
10
- const path = require('path');
11
- const fs = require('fs');
12
-
13
- /**
14
- * 获取插件根目录(即 adspecs/ 目录)
15
- * @returns {string}
16
- */
17
- function getPluginDir() {
18
- return path.resolve(__dirname, '..');
19
- }
20
-
21
- /**
22
- * 获取 package.json 内容
23
- * @returns {object}
24
- */
25
- function getPkg() {
26
- const pkgPath = path.join(getPluginDir(), 'package.json');
27
- return JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
28
- }
29
-
30
- /**
31
- * 获取版本号
32
- * @returns {string}
33
- */
34
- function getVersion() {
35
- return getPkg().version;
36
- }
37
-
38
- /**
39
- * 判断目标路径是否在 adspecs 插件目录内
40
- * @param {string} targetPath
41
- * @returns {boolean}
42
- */
43
- function isInsidePlugin(targetPath) {
44
- const pluginDir = getPluginDir();
45
- const resolved = path.resolve(targetPath);
46
- return resolved.startsWith(pluginDir);
47
- }
48
-
49
- /**
50
- * 安全读取 JSON 文件
51
- * @param {string} filePath
52
- * @param {object} [fallback]
53
- * @returns {object|null}
54
- */
55
- function safeReadJson(filePath, fallback = null) {
56
- try {
57
- return JSON.parse(fs.readFileSync(filePath, 'utf8'));
58
- } catch {
59
- return fallback;
60
- }
61
- }
62
-
63
- /**
64
- * 安全写入 JSON 文件(带 2 空格缩进 + 尾部换行)
65
- * @param {string} filePath
66
- * @param {object} data
67
- */
68
- function safeWriteJson(filePath, data) {
69
- fs.mkdirSync(path.dirname(filePath), { recursive: true });
70
- fs.writeFileSync(filePath, JSON.stringify(data, null, 2) + '\n', 'utf8');
71
- }
72
-
73
- module.exports = {
74
- getPluginDir,
75
- getPkg,
76
- getVersion,
77
- isInsidePlugin,
78
- safeReadJson,
79
- safeWriteJson,
80
- };
1
+ 'use strict';
2
+
3
+ /**
4
+ * adspecs CLI 通用工具
5
+ *
6
+ * 此模块作为 package.json 的 "main" 入口,
7
+ * 供其他 Node.js 脚本 require('adspecs') 时使用。
8
+ */
9
+
10
+ const path = require('path');
11
+ const fs = require('fs');
12
+
13
+ /**
14
+ * 获取插件根目录(即 adspecs/ 目录)
15
+ * @returns {string}
16
+ */
17
+ function getPluginDir() {
18
+ return path.resolve(__dirname, '..');
19
+ }
20
+
21
+ /**
22
+ * 获取 package.json 内容
23
+ * @returns {object}
24
+ */
25
+ function getPkg() {
26
+ const pkgPath = path.join(getPluginDir(), 'package.json');
27
+ return JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
28
+ }
29
+
30
+ /**
31
+ * 获取版本号
32
+ * @returns {string}
33
+ */
34
+ function getVersion() {
35
+ return getPkg().version;
36
+ }
37
+
38
+ /**
39
+ * 判断目标路径是否在 adspecs 插件目录内
40
+ * @param {string} targetPath
41
+ * @returns {boolean}
42
+ */
43
+ function isInsidePlugin(targetPath) {
44
+ const pluginDir = getPluginDir();
45
+ const resolved = path.resolve(targetPath);
46
+ return resolved.startsWith(pluginDir);
47
+ }
48
+
49
+ /**
50
+ * 安全读取 JSON 文件
51
+ * @param {string} filePath
52
+ * @param {object} [fallback]
53
+ * @returns {object|null}
54
+ */
55
+ function safeReadJson(filePath, fallback = null) {
56
+ try {
57
+ return JSON.parse(fs.readFileSync(filePath, 'utf8'));
58
+ } catch {
59
+ return fallback;
60
+ }
61
+ }
62
+
63
+ /**
64
+ * 安全写入 JSON 文件(带 2 空格缩进 + 尾部换行)
65
+ * @param {string} filePath
66
+ * @param {object} data
67
+ */
68
+ function safeWriteJson(filePath, data) {
69
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
70
+ fs.writeFileSync(filePath, JSON.stringify(data, null, 2) + '\n', 'utf8');
71
+ }
72
+
73
+ module.exports = {
74
+ getPluginDir,
75
+ getPkg,
76
+ getVersion,
77
+ isInsidePlugin,
78
+ safeReadJson,
79
+ safeWriteJson,
80
+ };
@@ -1,15 +0,0 @@
1
- # 应用标题
2
- VITE_APP_TITLE=Sie Front Demo
3
- VITE_APP_SIDEBAR_TITLE=Sie Demo
4
- VITE_APP_BRAND_TITLE=Sie Front Demo
5
-
6
- # 应用命名空间
7
- VITE_APP_NAMESPACE=sie-demo
8
-
9
- # 请求路径
10
- VITE_BASE_URL=
11
- # 接口地址
12
- VITE_API_BASE_URL=/admin-api
13
-
14
- # 是否开启模拟数据(Demo 项目默认开启)
15
- VITE_MOCK_ENABLED=true
@@ -1,141 +0,0 @@
1
- import { useEffect } from 'react';
2
- import { Drawer, Form, Input, InputNumber, DatePicker, Select, Button, Space, Card, message } from 'antd';
3
- import { useTranslation } from 'react-i18next';
4
- import { getCoil, createCoil, updateCoil } from '@/api/aps/coil';
5
- import type { CoilSaveParams } from '@/types/aps/coil';
6
- import dayjs from 'dayjs';
7
-
8
- interface CoilDrawerProps {
9
- open: boolean;
10
- id: number | null;
11
- onSuccess: () => void;
12
- onClose: () => void;
13
- }
14
-
15
- const CoilDrawer: React.FC<CoilDrawerProps> = ({ open, id, onSuccess, onClose }) => {
16
- const { t } = useTranslation('aps/coil');
17
- const { t: tc } = useTranslation('common');
18
- const [form] = Form.useForm();
19
- const isEdit = id !== null;
20
-
21
- useEffect(() => {
22
- if (open && id) {
23
- getCoil(id).then((res) => {
24
- form.setFieldsValue({
25
- ...res.data,
26
- inDate: dayjs(res.data.inDate),
27
- });
28
- });
29
- } else {
30
- form.resetFields();
31
- }
32
- }, [open, id, form]);
33
-
34
- const handleOk = async () => {
35
- try {
36
- const values = await form.validateFields();
37
- const params: CoilSaveParams = {
38
- ...values,
39
- id: id || undefined,
40
- inDate: values.inDate.format('YYYY-MM-DD'),
41
- };
42
- if (isEdit) {
43
- await updateCoil(params);
44
- } else {
45
- await createCoil(params);
46
- }
47
- message.success(tc('success'));
48
- onSuccess();
49
- } catch {
50
- // Validation failed
51
- }
52
- };
53
-
54
- return (
55
- <Drawer
56
- title={isEdit ? tc('edit') : tc('create')}
57
- open={open}
58
- onClose={onClose}
59
- size={256}
60
- closable={{ placement: 'end' }}
61
- destroyOnHidden={true}
62
- mask={{ closable: false }}
63
- styles={{ body: { background: '#f5f5f5' } }}
64
- footer={
65
- <Space style={{ float: 'right' }}>
66
- <Button onClick={onClose}>{tc('cancel')}</Button>
67
- <Button type="primary" onClick={handleOk}>
68
- {tc('confirm')}
69
- </Button>
70
- </Space>
71
- }
72
- >
73
- <Card style={{ border: 'none' }}>
74
- <Form form={form} layout="vertical">
75
- <Form.Item
76
- name="coilId"
77
- label={t('coilId')}
78
- rules={[{ required: true, message: tc('required') }]}
79
- >
80
- <Input />
81
- </Form.Item>
82
- <Form.Item
83
- name="alloy"
84
- label={t('alloy')}
85
- rules={[{ required: true, message: tc('required') }]}
86
- >
87
- <Select
88
- options={[
89
- { value: '3003', label: '3003' },
90
- { value: '5052', label: '5052' },
91
- ]}
92
- />
93
- </Form.Item>
94
- <Form.Item
95
- name="temper"
96
- label={t('temper')}
97
- rules={[{ required: true, message: tc('required') }]}
98
- >
99
- <Select
100
- options={[
101
- { value: 'H24', label: 'H24' },
102
- { value: 'H18', label: 'H18' },
103
- { value: 'O', label: 'O' },
104
- ]}
105
- />
106
- </Form.Item>
107
- <Form.Item
108
- name="width"
109
- label={t('width')}
110
- rules={[{ required: true, message: tc('required') }]}
111
- >
112
- <InputNumber min={0} max={2500} style={{ width: '100%' }} />
113
- </Form.Item>
114
- <Form.Item
115
- name="thickness"
116
- label={t('thickness')}
117
- rules={[{ required: true, message: tc('required') }]}
118
- >
119
- <InputNumber min={0} max={10} step={0.1} style={{ width: '100%' }} />
120
- </Form.Item>
121
- <Form.Item
122
- name="weight"
123
- label={t('weight')}
124
- rules={[{ required: true, message: tc('required') }]}
125
- >
126
- <InputNumber min={0} max={30} step={0.1} style={{ width: '100%' }} />
127
- </Form.Item>
128
- <Form.Item
129
- name="inDate"
130
- label={t('inDate')}
131
- rules={[{ required: true, message: tc('required') }]}
132
- >
133
- <DatePicker style={{ width: '100%' }} />
134
- </Form.Item>
135
- </Form>
136
- </Card>
137
- </Drawer>
138
- );
139
- };
140
-
141
- export default CoilDrawer;
@@ -1,209 +0,0 @@
1
- import { useRef, useState } from 'react';
2
- import { Button, Space, Tag, Popconfirm, Upload, message } from 'antd';
3
- import { PlusOutlined, UploadOutlined, DownloadOutlined } from '@ant-design/icons';
4
- import { ProTable } from '@ant-design/pro-components';
5
- import type { ActionType, ProColumns } from '@ant-design/pro-components';
6
- import { useTranslation } from 'react-i18next';
7
- import { Access } from '@/components/Access';
8
- import { getCoilPage, deleteCoil, importCoils, exportCoils, downloadCoilTemplate } from '@/api/aps/coil';
9
- import type { CoilVO } from '@/types/aps/coil';
10
- import { COIL_STATUS } from '@/types/aps/coil';
11
- import CoilDrawer from './components/CoilDrawer';
12
-
13
- const CoilPage: React.FC = () => {
14
- const { t } = useTranslation('aps/coil');
15
- const { t: tc } = useTranslation('common');
16
- const actionRef = useRef<ActionType>(null);
17
- const [drawerOpen, setDrawerOpen] = useState(false);
18
- const [editId, setEditId] = useState<number | null>(null);
19
-
20
- const handleDelete = (id: number) => async () => {
21
- await deleteCoil(id);
22
- message.success(tc('success'));
23
- actionRef.current?.reload();
24
- };
25
-
26
- const handleImport = async (file: File) => {
27
- const result = await importCoils(file);
28
- if (result.data.failCount === 0) {
29
- message.success(t('importSuccess', { count: result.data.successCount }));
30
- } else {
31
- message.warning(t('importFailed', { count: result.data.failCount }));
32
- }
33
- actionRef.current?.reload();
34
- return false;
35
- };
36
-
37
- const handleExport = async () => {
38
- await exportCoils({});
39
- message.success(tc('success'));
40
- };
41
-
42
- const handleDownloadTemplate = async () => {
43
- await downloadCoilTemplate();
44
- message.success(tc('success'));
45
- };
46
-
47
- const columns: ProColumns<CoilVO>[] = [
48
- {
49
- title: t('coilId'),
50
- dataIndex: 'coilId',
51
- ellipsis: true,
52
- width: 120,
53
- },
54
- {
55
- title: t('alloy'),
56
- dataIndex: 'alloy',
57
- valueType: 'select',
58
- valueEnum: {
59
- '3003': { text: '3003' },
60
- '5052': { text: '5052' },
61
- },
62
- width: 100,
63
- },
64
- {
65
- title: t('temper'),
66
- dataIndex: 'temper',
67
- search: false,
68
- width: 80,
69
- },
70
- {
71
- title: t('width'),
72
- dataIndex: 'width',
73
- search: false,
74
- width: 100,
75
- },
76
- {
77
- title: t('thickness'),
78
- dataIndex: 'thickness',
79
- search: false,
80
- width: 100,
81
- },
82
- {
83
- title: t('weight'),
84
- dataIndex: 'weight',
85
- search: false,
86
- width: 100,
87
- },
88
- {
89
- title: t('inDate'),
90
- dataIndex: 'inDate',
91
- search: false,
92
- width: 120,
93
- },
94
- {
95
- title: t('status'),
96
- dataIndex: 'status',
97
- valueType: 'select',
98
- valueEnum: {
99
- 0: { text: COIL_STATUS[0].label, status: 'Default' },
100
- 1: { text: COIL_STATUS[1].label, status: 'Processing' },
101
- 2: { text: COIL_STATUS[2].label, status: 'Success' },
102
- 3: { text: COIL_STATUS[3].label, status: 'Error' },
103
- },
104
- width: 100,
105
- render: (_, record) => {
106
- const item = COIL_STATUS[record.status as keyof typeof COIL_STATUS];
107
- return item ? <Tag color={item.color}>{item.label}</Tag> : '-';
108
- },
109
- },
110
- {
111
- title: t('createTime'),
112
- dataIndex: 'createTime',
113
- search: false,
114
- width: 180,
115
- },
116
- {
117
- title: tc('operation'),
118
- key: 'action',
119
- fixed: 'right',
120
- search: false,
121
- width: 150,
122
- render: (_, record) => (
123
- <Space>
124
- <Access code="aps:coil:update">
125
- <a
126
- onClick={() => {
127
- setEditId(record.id);
128
- setDrawerOpen(true);
129
- }}
130
- >
131
- {tc('edit')}
132
- </a>
133
- </Access>
134
- <Access code="aps:coil:delete">
135
- <Popconfirm title={t('deleteConfirm')} onConfirm={handleDelete(record.id)}>
136
- <a style={{ color: '#ff4d4f' }}>{tc('delete')}</a>
137
- </Popconfirm>
138
- </Access>
139
- </Space>
140
- ),
141
- },
142
- ];
143
-
144
- return (
145
- <>
146
- <ProTable<CoilVO>
147
- columns={columns}
148
- actionRef={actionRef}
149
- rowKey="id"
150
- headerTitle={t('title')}
151
- request={async (params) => {
152
- const { current, pageSize, ...rest } = params;
153
- const { data } = await getCoilPage({
154
- pageNo: current!,
155
- pageSize: pageSize!,
156
- ...rest,
157
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
158
- } as any);
159
- return { data: data.list, total: data.total, success: true };
160
- }}
161
- pagination={{ defaultPageSize: 10, showSizeChanger: true }}
162
- scroll={{ x: 1200 }}
163
- toolBarRender={() => [
164
- <Access code="aps:coil:create" key="add">
165
- <Button
166
- type="primary"
167
- icon={<PlusOutlined />}
168
- onClick={() => {
169
- setEditId(null);
170
- setDrawerOpen(true);
171
- }}
172
- >
173
- {tc('create')}
174
- </Button>
175
- </Access>,
176
- <Access code="aps:coil:import" key="import">
177
- <Upload
178
- accept=".xlsx,.xls"
179
- showUploadList={false}
180
- beforeUpload={handleImport}
181
- >
182
- <Button icon={<UploadOutlined />}>{t('import')}</Button>
183
- </Upload>
184
- </Access>,
185
- <Access code="aps:coil:export" key="export">
186
- <Button icon={<DownloadOutlined />} onClick={handleExport}>
187
- {t('export')}
188
- </Button>
189
- </Access>,
190
- <Button key="template" icon={<DownloadOutlined />} onClick={handleDownloadTemplate}>
191
- {t('downloadTemplate')}
192
- </Button>,
193
- ]}
194
- />
195
-
196
- <CoilDrawer
197
- open={drawerOpen}
198
- id={editId}
199
- onSuccess={() => {
200
- setDrawerOpen(false);
201
- actionRef.current?.reload();
202
- }}
203
- onClose={() => setDrawerOpen(false)}
204
- />
205
- </>
206
- );
207
- };
208
-
209
- export default CoilPage;