adspecs 0.1.18 → 0.1.19

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 (29) 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/paths.json +17 -0
  6. 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
  7. package/.adspecs/workflows/adspecs/workflow.yml +5 -4
  8. package/.claude-plugin/marketplace.json +1 -1
  9. package/.claude-plugin/plugin.json +1 -1
  10. package/.qoder-plugin/plugin.json +1 -1
  11. package/package.json +1 -1
  12. package/references/antd-front-demo/.env +4 -4
  13. package/references/antd-front-demo/.env.develop +12 -0
  14. package/references/antd-front-demo/.env.production +5 -0
  15. package/references/antd-front-demo/package-lock.json +2 -2
  16. package/references/antd-front-demo/package.json +1 -1
  17. package/skills/adspecs-front-prototype/SKILL.md +405 -0
  18. package/skills/adspecs-git-commit/SKILL.md +23 -8
  19. package/skills/adspecs-git-initialize/SKILL.md +54 -0
  20. package/src/lib/prompts.js +23 -21
  21. package/references/antd-front-demo/src/pages/aps/coil/components/CoilDrawer.tsx +0 -141
  22. package/references/antd-front-demo/src/pages/aps/coil/index.tsx +0 -209
  23. package/references/antd-front-demo/src/pages/aps/optimization/index.tsx +0 -192
  24. package/references/antd-front-demo/src/pages/aps/order/components/OrderDrawer.tsx +0 -251
  25. package/references/antd-front-demo/src/pages/aps/order/index.tsx +0 -273
  26. package/references/antd-front-demo/src/pages/aps/param/index.tsx +0 -153
  27. package/references/antd-front-demo/src/pages/aps/plan/components/CuttingPlanVisualization.tsx +0 -821
  28. package/references/antd-front-demo/src/pages/aps/plan/index.tsx +0 -254
  29. package/references/antd-front-demo/src/pages/aps/task/index.tsx +0 -190
@@ -1,254 +0,0 @@
1
- import { useRef, useState } from 'react';
2
- import { Space, Tag, Popconfirm, message, Modal, Table, Descriptions } from 'antd';
3
- import { ProTable } from '@ant-design/pro-components';
4
- import type { ActionType, ProColumns } from '@ant-design/pro-components';
5
- import { useTranslation } from 'react-i18next';
6
- import { Access } from '@/components/Access';
7
- import { getPlanPage, deletePlan, confirmPlan, getPlanDetail, exportWorkInstruction } from '@/api/aps/plan';
8
- import type { CuttingPlanVO, PlanDetailVO, SmallCoilVO } from '@/types/aps/plan';
9
- import CuttingPlanVisualization from './components/CuttingPlanVisualization';
10
-
11
- const PlanPage: React.FC = () => {
12
- const { t } = useTranslation('aps/plan');
13
- const { t: tc } = useTranslation('common');
14
- const actionRef = useRef<ActionType>(null);
15
- const [detailOpen, setDetailOpen] = useState(false);
16
- const [detailData, setDetailData] = useState<PlanDetailVO | null>(null);
17
- const [detailLoading, setDetailLoading] = useState(false);
18
-
19
- const handleDelete = (planId: string) => async () => {
20
- await deletePlan(planId);
21
- message.success(tc('success'));
22
- actionRef.current?.reload();
23
- };
24
-
25
- const handleConfirm = (planId: string) => async () => {
26
- await confirmPlan(planId);
27
- message.success(tc('success'));
28
- actionRef.current?.reload();
29
- };
30
-
31
- const handleDetail = async (planId: string) => {
32
- setDetailOpen(true);
33
- setDetailLoading(true);
34
- try {
35
- const res = await getPlanDetail(planId);
36
- setDetailData(res.data);
37
- } finally {
38
- setDetailLoading(false);
39
- }
40
- };
41
-
42
- const handleExport = async (planId: string) => {
43
- await exportWorkInstruction(planId, 'excel');
44
- message.success(tc('success'));
45
- };
46
-
47
- const smallCoilColumns = [
48
- {
49
- title: t('smallCoilId'),
50
- dataIndex: 'smallCoilId',
51
- key: 'smallCoilId',
52
- width: 120,
53
- },
54
- {
55
- title: t('width'),
56
- dataIndex: 'width',
57
- key: 'width',
58
- width: 100,
59
- },
60
- {
61
- title: t('length'),
62
- dataIndex: 'length',
63
- key: 'length',
64
- width: 100,
65
- },
66
- {
67
- title: t('weight'),
68
- dataIndex: 'weight',
69
- key: 'weight',
70
- width: 100,
71
- },
72
- {
73
- title: t('outerDiameter'),
74
- dataIndex: 'outerDiameter',
75
- key: 'outerDiameter',
76
- width: 120,
77
- },
78
- {
79
- title: t('orderId'),
80
- dataIndex: 'orderId',
81
- key: 'orderId',
82
- width: 120,
83
- render: (orderId: string | undefined) => orderId || <Tag>{t('unassigned')}</Tag>,
84
- },
85
- {
86
- title: t('region'),
87
- dataIndex: 'region',
88
- key: 'region',
89
- width: 80,
90
- },
91
- ];
92
-
93
- const columns: ProColumns<CuttingPlanVO>[] = [
94
- {
95
- title: t('planId'),
96
- dataIndex: 'planId',
97
- ellipsis: true,
98
- width: 180,
99
- },
100
- {
101
- title: t('coilId'),
102
- dataIndex: 'coilId',
103
- width: 100,
104
- },
105
- {
106
- title: t('coilAlloy'),
107
- dataIndex: 'coilAlloy',
108
- search: false,
109
- width: 80,
110
- },
111
- {
112
- title: t('coilTemper'),
113
- dataIndex: 'coilTemper',
114
- search: false,
115
- width: 80,
116
- },
117
- {
118
- title: t('coilWidth'),
119
- dataIndex: 'coilWidth',
120
- search: false,
121
- width: 100,
122
- },
123
- {
124
- title: t('coilWeight'),
125
- dataIndex: 'coilWeight',
126
- search: false,
127
- width: 100,
128
- },
129
- {
130
- title: t('totalCuts'),
131
- dataIndex: 'totalCuts',
132
- search: false,
133
- width: 100,
134
- },
135
- {
136
- title: t('theoreticalUtilization'),
137
- dataIndex: 'theoreticalUtilization',
138
- search: false,
139
- width: 140,
140
- render: (_, record) => `${record.theoreticalUtilization.toFixed(2)}%`,
141
- },
142
- {
143
- title: t('score'),
144
- dataIndex: 'score',
145
- search: false,
146
- width: 100,
147
- render: (_, record) => record.score.toFixed(4),
148
- },
149
- {
150
- title: t('createTime'),
151
- dataIndex: 'createTime',
152
- search: false,
153
- width: 180,
154
- },
155
- {
156
- title: tc('operation'),
157
- key: 'action',
158
- fixed: 'right',
159
- search: false,
160
- width: 250,
161
- render: (_, record) => (
162
- <Space>
163
- <Access code="aps:plan:query">
164
- <a onClick={() => handleDetail(record.planId)}>{t('actions.detail')}</a>
165
- </Access>
166
- <Access code="aps:plan:confirm">
167
- <Popconfirm title={t('confirmConfirm')} onConfirm={handleConfirm(record.planId)}>
168
- <a>{t('actions.confirm')}</a>
169
- </Popconfirm>
170
- </Access>
171
- <Access code="aps:plan:export">
172
- <a onClick={() => handleExport(record.planId)}>{t('actions.export')}</a>
173
- </Access>
174
- <Access code="aps:plan:delete">
175
- <Popconfirm title={t('deleteConfirm')} onConfirm={handleDelete(record.planId)}>
176
- <a style={{ color: '#ff4d4f' }}>{t('actions.delete')}</a>
177
- </Popconfirm>
178
- </Access>
179
- </Space>
180
- ),
181
- },
182
- ];
183
-
184
- return (
185
- <>
186
- <ProTable<CuttingPlanVO>
187
- columns={columns}
188
- actionRef={actionRef}
189
- rowKey="planId"
190
- headerTitle={t('title')}
191
- request={async (params) => {
192
- const { current, pageSize, ...rest } = params;
193
- const { data } = await getPlanPage({
194
- pageNo: current!,
195
- pageSize: pageSize!,
196
- ...rest,
197
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
198
- } as any);
199
- return { data: data.list, total: data.total, success: true };
200
- }}
201
- pagination={{ defaultPageSize: 10, showSizeChanger: true }}
202
- scroll={{ x: 1400 }}
203
- />
204
-
205
- <Modal
206
- title={t('actions.detail')}
207
- open={detailOpen}
208
- onCancel={() => setDetailOpen(false)}
209
- footer={null}
210
- width={1200}
211
- >
212
- {detailData && (
213
- <>
214
- <Descriptions bordered column={2} size="small" style={{ marginBottom: 16 }}>
215
- <Descriptions.Item label={t('planId')}>{detailData.planId}</Descriptions.Item>
216
- <Descriptions.Item label={t('coilId')}>{detailData.coilId}</Descriptions.Item>
217
- <Descriptions.Item label={t('coilAlloy')}>{detailData.coilAlloy}</Descriptions.Item>
218
- <Descriptions.Item label={t('coilTemper')}>{detailData.coilTemper}</Descriptions.Item>
219
- <Descriptions.Item label={t('coilWidth')}>{detailData.coilWidth} mm</Descriptions.Item>
220
- <Descriptions.Item label={t('coilWeight')}>{detailData.coilWeight} 吨</Descriptions.Item>
221
- <Descriptions.Item label={t('totalCuts')}>{detailData.totalCuts}</Descriptions.Item>
222
- <Descriptions.Item label={t('theoreticalUtilization')}>
223
- {detailData.theoreticalUtilization.toFixed(2)}%
224
- </Descriptions.Item>
225
- <Descriptions.Item label={t('score')}>{detailData.score.toFixed(4)}</Descriptions.Item>
226
- <Descriptions.Item label={t('createTime')}>{detailData.createTime}</Descriptions.Item>
227
- <Descriptions.Item label={t('verticalCuts')} span={2}>
228
- {detailData.verticalCuts}
229
- </Descriptions.Item>
230
- <Descriptions.Item label={t('horizontalCuts')} span={2}>
231
- {detailData.horizontalCuts}
232
- </Descriptions.Item>
233
- </Descriptions>
234
-
235
- <CuttingPlanVisualization plan={detailData} />
236
-
237
- <h4 style={{ marginTop: 16 }}>{t('smallCoils')}</h4>
238
- <Table<SmallCoilVO>
239
- columns={smallCoilColumns}
240
- dataSource={detailData.smallCoils}
241
- rowKey="smallCoilId"
242
- size="small"
243
- pagination={false}
244
- scroll={{ x: 800 }}
245
- loading={detailLoading}
246
- />
247
- </>
248
- )}
249
- </Modal>
250
- </>
251
- );
252
- };
253
-
254
- export default PlanPage;
@@ -1,190 +0,0 @@
1
- import { useRef } from 'react';
2
- import { Space, Tag, Popconfirm, Progress, message } from 'antd';
3
- import { useNavigate } from 'react-router-dom';
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 { getTaskPage, cancelTask, resumeTask, deleteTask } from '@/api/aps/task';
9
- import type { OptimizationTaskVO } from '@/types/aps/task';
10
- import { TASK_STATUS, TASK_TYPE, TASK_PHASE } from '@/types/aps/task';
11
-
12
- const TaskPage: React.FC = () => {
13
- const { t } = useTranslation('aps/task');
14
- const { t: tc } = useTranslation('common');
15
- const actionRef = useRef<ActionType>(null);
16
- const navigate = useNavigate();
17
-
18
- const handleCancel = (taskId: string) => async () => {
19
- await cancelTask(taskId);
20
- message.success(tc('success'));
21
- actionRef.current?.reload();
22
- };
23
-
24
- const handleResume = (taskId: string) => async () => {
25
- await resumeTask(taskId);
26
- message.success(tc('success'));
27
- actionRef.current?.reload();
28
- };
29
-
30
- const handleDelete = (taskId: string) => async () => {
31
- await deleteTask(taskId);
32
- message.success(tc('success'));
33
- actionRef.current?.reload();
34
- };
35
-
36
- const columns: ProColumns<OptimizationTaskVO>[] = [
37
- {
38
- title: t('taskId'),
39
- dataIndex: 'taskId',
40
- ellipsis: true,
41
- width: 180,
42
- },
43
- {
44
- title: t('taskType'),
45
- dataIndex: 'taskType',
46
- valueType: 'select',
47
- valueEnum: {
48
- SINGLE_COIL: { text: TASK_TYPE.SINGLE_COIL.label },
49
- GLOBAL_OPTIMIZATION: { text: TASK_TYPE.GLOBAL_OPTIMIZATION.label },
50
- },
51
- width: 120,
52
- render: (_, record) => {
53
- const item = TASK_TYPE[record.taskType as keyof typeof TASK_TYPE];
54
- return item ? <Tag color={item.color}>{item.label}</Tag> : '-';
55
- },
56
- },
57
- {
58
- title: t('status'),
59
- dataIndex: 'status',
60
- valueType: 'select',
61
- valueEnum: {
62
- PENDING: { text: TASK_STATUS.PENDING.label, status: 'Default' },
63
- RUNNING: { text: TASK_STATUS.RUNNING.label, status: 'Processing' },
64
- PAUSED: { text: TASK_STATUS.PAUSED.label, status: 'Warning' },
65
- COMPLETED: { text: TASK_STATUS.COMPLETED.label, status: 'Success' },
66
- FAILED: { text: TASK_STATUS.FAILED.label, status: 'Error' },
67
- CANCELLED: { text: TASK_STATUS.CANCELLED.label, status: 'Default' },
68
- },
69
- width: 100,
70
- render: (_, record) => {
71
- const item = TASK_STATUS[record.status as keyof typeof TASK_STATUS];
72
- return item ? <Tag color={item.color}>{item.label}</Tag> : '-';
73
- },
74
- },
75
- {
76
- title: t('progress'),
77
- dataIndex: 'progress',
78
- search: false,
79
- width: 150,
80
- render: (_, record) => (
81
- <Progress
82
- percent={record.progress}
83
- size="small"
84
- status={
85
- record.status === 'RUNNING' ? 'active' :
86
- record.status === 'COMPLETED' ? 'success' :
87
- record.status === 'FAILED' ? 'exception' : 'normal'
88
- }
89
- />
90
- ),
91
- },
92
- {
93
- title: t('currentPhase'),
94
- dataIndex: 'currentPhase',
95
- search: false,
96
- width: 120,
97
- render: (_, record) => {
98
- if (!record.currentPhase) return '-';
99
- const item = TASK_PHASE[record.currentPhase as keyof typeof TASK_PHASE];
100
- return item ? <Tag color={item.color}>{item.label}</Tag> : '-';
101
- },
102
- },
103
- {
104
- title: t('progressDesc'),
105
- dataIndex: 'progressDesc',
106
- search: false,
107
- ellipsis: true,
108
- width: 180,
109
- },
110
- {
111
- title: t('errorMessage'),
112
- dataIndex: 'errorMessage',
113
- search: false,
114
- ellipsis: true,
115
- width: 200,
116
- render: (_, record) => record.errorMessage || '-',
117
- },
118
- {
119
- title: t('createdBy'),
120
- dataIndex: 'createdBy',
121
- search: false,
122
- width: 100,
123
- },
124
- {
125
- title: t('createTime'),
126
- dataIndex: 'createTime',
127
- search: false,
128
- width: 180,
129
- },
130
- {
131
- title: tc('operation'),
132
- key: 'action',
133
- fixed: 'right',
134
- search: false,
135
- width: 200,
136
- render: (_, record) => (
137
- <Space>
138
- {(record.status === 'RUNNING' || record.status === 'PENDING') && (
139
- <Access code="aps:task:cancel">
140
- <Popconfirm title={t('cancelConfirm')} onConfirm={handleCancel(record.taskId)}>
141
- <a>{t('actions.cancel')}</a>
142
- </Popconfirm>
143
- </Access>
144
- )}
145
- {(record.status === 'FAILED' || record.status === 'CANCELLED' || record.status === 'PAUSED') && (
146
- <Access code="aps:task:resume">
147
- <Popconfirm title={t('resumeConfirm')} onConfirm={handleResume(record.taskId)}>
148
- <a>{t('actions.resume')}</a>
149
- </Popconfirm>
150
- </Access>
151
- )}
152
- {record.status === 'COMPLETED' && record.resultRef && (
153
- <Access code="aps:plan:query">
154
- <a onClick={() => navigate(`/aps/plan?planId=${record.resultRef}`)}>{t('actions.viewResult')}</a>
155
- </Access>
156
- )}
157
- <Access code="aps:task:delete">
158
- <Popconfirm title={t('deleteConfirm')} onConfirm={handleDelete(record.taskId)}>
159
- <a style={{ color: '#ff4d4f' }}>{t('actions.delete')}</a>
160
- </Popconfirm>
161
- </Access>
162
- </Space>
163
- ),
164
- },
165
- ];
166
-
167
- return (
168
- <ProTable<OptimizationTaskVO>
169
- columns={columns}
170
- actionRef={actionRef}
171
- rowKey="taskId"
172
- headerTitle={t('title')}
173
- request={async (params) => {
174
- const { current, pageSize, ...rest } = params;
175
- const { data } = await getTaskPage({
176
- pageNo: current!,
177
- pageSize: pageSize!,
178
- ...rest,
179
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
180
- } as any);
181
- return { data: data.list, total: data.total, success: true };
182
- }}
183
- pagination={{ defaultPageSize: 10, showSizeChanger: true }}
184
- scroll={{ x: 1600 }}
185
- polling={5000} // Auto-refresh every 5 seconds for running tasks
186
- />
187
- );
188
- };
189
-
190
- export default TaskPage;