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,192 +0,0 @@
1
- import { useState, useEffect } from 'react';
2
- import { Card, Form, Select, Button, Space, message, Alert, Row, Col, Transfer } from 'antd';
3
- import { useTranslation } from 'react-i18next';
4
- import { useNavigate } from 'react-router-dom';
5
- import { Access } from '@/components/Access';
6
- import { getCoilPage } from '@/api/aps/coil';
7
- import { getOrderPage } from '@/api/aps/order';
8
- import { submitSingleCoilTask, submitGlobalTask } from '@/api/aps/task';
9
- import type { CoilVO } from '@/types/aps/coil';
10
- import type { OrderVO } from '@/types/aps/order';
11
-
12
- const OptimizationPage: React.FC = () => {
13
- const { t } = useTranslation('aps/task');
14
- const { t: tc } = useTranslation('common');
15
- const [form] = Form.useForm();
16
- const navigate = useNavigate();
17
- const [loading, setLoading] = useState(false);
18
-
19
- const [coils, setCoils] = useState<CoilVO[]>([]);
20
- const [orders, setOrders] = useState<OrderVO[]>([]);
21
- const [targetCoilIds, setTargetCoilIds] = useState<string[]>([]);
22
- const [targetOrderIds, setTargetOrderIds] = useState<string[]>([]);
23
-
24
- const loadData = async () => {
25
- const [coilRes, orderRes] = await Promise.all([
26
- getCoilPage({ pageNo: 1, pageSize: 1000, status: 0 }),
27
- getOrderPage({ pageNo: 1, pageSize: 1000, status: 0 }),
28
- ]);
29
- setCoils(coilRes.data.list);
30
- setOrders(orderRes.data.list);
31
- };
32
-
33
- useEffect(() => {
34
- // eslint-disable-next-line react-hooks/set-state-in-effect
35
- loadData();
36
- }, []);
37
-
38
- const handleSubmitSingle = async () => {
39
- if (targetCoilIds.length !== 1) {
40
- message.warning('请选择一个母卷');
41
- return;
42
- }
43
- if (targetOrderIds.length === 0) {
44
- message.warning('请至少选择一个订单');
45
- return;
46
- }
47
-
48
- setLoading(true);
49
- try {
50
- const strategy = form.getFieldValue('strategy') || 'AUTO';
51
- await submitSingleCoilTask({
52
- coilIds: targetCoilIds,
53
- orderIds: targetOrderIds,
54
- strategy,
55
- });
56
- message.success(tc('success'));
57
- navigate('/aps/task');
58
- } catch {
59
- message.error(tc('error'));
60
- } finally {
61
- setLoading(false);
62
- }
63
- };
64
-
65
- const handleSubmitGlobal = async () => {
66
- if (targetCoilIds.length < 2) {
67
- message.warning('请至少选择两个母卷');
68
- return;
69
- }
70
- if (targetOrderIds.length < 2) {
71
- message.warning('请至少选择两个订单');
72
- return;
73
- }
74
-
75
- setLoading(true);
76
- try {
77
- const strategy = form.getFieldValue('strategy') || 'AUTO';
78
- await submitGlobalTask({
79
- coilIds: targetCoilIds,
80
- orderIds: targetOrderIds,
81
- strategy,
82
- });
83
- message.success(tc('success'));
84
- navigate('/aps/task');
85
- } catch {
86
- message.error(tc('error'));
87
- } finally {
88
- setLoading(false);
89
- }
90
- };
91
-
92
- const coilTransferData = coils.map((c) => ({
93
- key: c.coilId,
94
- title: `${c.coilId} - ${c.alloy}/${c.temper} - ${c.width}×${c.thickness}mm - ${c.weight}吨`,
95
- description: c.coilId,
96
- }));
97
-
98
- const orderTransferData = orders.map((o) => ({
99
- key: o.orderId,
100
- title: `${o.orderId} - ${o.customerName} - ${o.width}mm - ${o.demand}吨`,
101
- description: o.orderId,
102
- }));
103
-
104
- return (
105
- <Form form={form} layout="vertical">
106
- <Card title={t('submitTask')} style={{ marginBottom: 16 }}>
107
- <Alert
108
- message="单卷方案:选择一个母卷和多个订单,生成该母卷的所有可行裁剪方案"
109
- description="全局优化:选择多个母卷和多个订单,系统自动进行匹配分组和全局优化"
110
- type="info"
111
- showIcon
112
- style={{ marginBottom: 16 }}
113
- />
114
-
115
- <Form.Item name="strategy" label={t('strategy')} initialValue="AUTO">
116
- <Select
117
- options={[
118
- { value: 'AUTO', label: t('strategies.AUTO') },
119
- { value: 'LENGTH_FIRST', label: t('strategies.LENGTH_FIRST') },
120
- { value: 'WIDTH_FIRST', label: t('strategies.WIDTH_FIRST') },
121
- ]}
122
- style={{ width: 200 }}
123
- />
124
- </Form.Item>
125
- </Card>
126
-
127
- <Row gutter={16}>
128
- <Col span={12}>
129
- <Card title={t('selectCoils')} size="small">
130
- <Transfer
131
- dataSource={coilTransferData}
132
- titles={['可选母卷', '已选母卷']}
133
- targetKeys={targetCoilIds}
134
- onChange={(keys) => setTargetCoilIds(keys as string[])}
135
- render={(item) => item.title as string}
136
- listStyle={{ width: '100%', height: 300 }}
137
- showSearch
138
- filterOption={(inputValue, item) =>
139
- (item.title as string).includes(inputValue) ||
140
- (item.description as string).includes(inputValue)
141
- }
142
- />
143
- </Card>
144
- </Col>
145
- <Col span={12}>
146
- <Card title={t('selectOrders')} size="small">
147
- <Transfer
148
- dataSource={orderTransferData}
149
- titles={['可选订单', '已选订单']}
150
- targetKeys={targetOrderIds}
151
- onChange={(keys) => setTargetOrderIds(keys as string[])}
152
- render={(item) => item.title as string}
153
- listStyle={{ width: '100%', height: 300 }}
154
- showSearch
155
- filterOption={(inputValue, item) =>
156
- (item.title as string).includes(inputValue) ||
157
- (item.description as string).includes(inputValue)
158
- }
159
- />
160
- </Card>
161
- </Col>
162
- </Row>
163
-
164
- <Card style={{ marginTop: 16 }}>
165
- <Space>
166
- <Access code="aps:task:create">
167
- <Button
168
- type="primary"
169
- onClick={handleSubmitSingle}
170
- loading={loading}
171
- disabled={targetCoilIds.length !== 1 || targetOrderIds.length === 0}
172
- >
173
- {t('singleCoil')}
174
- </Button>
175
- </Access>
176
- <Access code="aps:task:create">
177
- <Button
178
- type="primary"
179
- onClick={handleSubmitGlobal}
180
- loading={loading}
181
- disabled={targetCoilIds.length < 2 || targetOrderIds.length < 2}
182
- >
183
- {t('globalOptimization')}
184
- </Button>
185
- </Access>
186
- </Space>
187
- </Card>
188
- </Form>
189
- );
190
- };
191
-
192
- export default OptimizationPage;
@@ -1,251 +0,0 @@
1
- import { useEffect, useRef, useState } from 'react';
2
- import {
3
- Drawer,
4
- Form,
5
- Input,
6
- InputNumber,
7
- DatePicker,
8
- Select,
9
- Button,
10
- Space,
11
- Row,
12
- Col,
13
- Card,
14
- App,
15
- } from 'antd';
16
- import { useTranslation } from 'react-i18next';
17
- import { getOrder, createOrder, updateOrder } from '@/api/aps/order';
18
- import type { OrderSaveParams, OrderVO } from '@/types/aps/order';
19
- import dayjs from 'dayjs';
20
-
21
- interface OrderDrawerProps {
22
- open: boolean;
23
- id: number | null;
24
- onSuccess: () => void;
25
- onClose: () => void;
26
- }
27
-
28
- const OrderDrawer: React.FC<OrderDrawerProps> = ({ open, id, onSuccess, onClose }) => {
29
- const { t } = useTranslation('aps/order');
30
- const { t: tc } = useTranslation('common');
31
- const { message } = App.useApp();
32
- const [form] = Form.useForm();
33
- const [confirmLoading, setConfirmLoading] = useState(false);
34
- const isEdit = id != null;
35
- // 保留服务端原始字段,避免编辑时丢掉未在表单里出现的字段
36
- const originData = useRef<Partial<OrderVO>>({});
37
-
38
- useEffect(() => {
39
- if (!open) return;
40
- form.resetFields();
41
- originData.current = {};
42
- if (id != null) {
43
- getOrder(id).then(({ data }) => {
44
- originData.current = { ...data };
45
- form.setFieldsValue({
46
- ...data,
47
- deliveryDate: dayjs(data.deliveryDate),
48
- });
49
- });
50
- } else {
51
- form.setFieldsValue({ priority: 3 });
52
- }
53
- }, [open, id, form]);
54
-
55
- const handleOk = async () => {
56
- let values: OrderSaveParams;
57
- try {
58
- values = await form.validateFields();
59
- } catch {
60
- return;
61
- }
62
- setConfirmLoading(true);
63
- try {
64
- const params: OrderSaveParams = {
65
- ...originData.current,
66
- ...values,
67
- id: id ?? undefined,
68
- deliveryDate: dayjs(values.deliveryDate).format('YYYY-MM-DD'),
69
- } as OrderSaveParams;
70
- if (isEdit) {
71
- await updateOrder(params);
72
- message.success(tc('success'));
73
- } else {
74
- await createOrder(params);
75
- message.success(tc('success'));
76
- }
77
- onSuccess();
78
- } catch (err) {
79
- message.error((err as Error).message || tc('fail'));
80
- } finally {
81
- setConfirmLoading(false);
82
- }
83
- };
84
-
85
- return (
86
- <Drawer
87
- title={isEdit ? tc('edit') : tc('create')}
88
- open={open}
89
- onClose={onClose}
90
- destroyOnHidden={true}
91
- size={600}
92
- closable={{ placement: 'end' }}
93
- mask={{ closable: false }}
94
- styles={{ body: { background: '#f5f5f5' } }}
95
- footer={
96
- <Space style={{ float: 'right' }}>
97
- <Button onClick={onClose}>{tc('cancel')}</Button>
98
- <Button type="primary" loading={confirmLoading} onClick={handleOk}>
99
- {tc('confirm')}
100
- </Button>
101
- </Space>
102
- }
103
- >
104
- <Card style={{ border: 'none' }}>
105
- <Form form={form} layout="horizontal" labelCol={{ span: 8 }} wrapperCol={{ span: 16 }}>
106
- <Row gutter={16}>
107
- <Col span={12}>
108
- <Form.Item
109
- name="orderId"
110
- label={t('orderId')}
111
- rules={[{ required: true, message: tc('required') }]}
112
- >
113
- <Input />
114
- </Form.Item>
115
- </Col>
116
- <Col span={12}>
117
- <Form.Item
118
- name="customerName"
119
- label={t('customerName')}
120
- rules={[{ required: true, message: tc('required') }]}
121
- >
122
- <Input />
123
- </Form.Item>
124
- </Col>
125
- </Row>
126
- <Row gutter={16}>
127
- <Col span={12}>
128
- <Form.Item
129
- name="alloy"
130
- label={t('alloy')}
131
- rules={[{ required: true, message: tc('required') }]}
132
- >
133
- <Select
134
- options={[
135
- { value: '3003', label: '3003' },
136
- { value: '5052', label: '5052' },
137
- ]}
138
- />
139
- </Form.Item>
140
- </Col>
141
- <Col span={12}>
142
- <Form.Item
143
- name="temper"
144
- label={t('temper')}
145
- rules={[{ required: true, message: tc('required') }]}
146
- >
147
- <Select
148
- options={[
149
- { value: 'H24', label: 'H24' },
150
- { value: 'H18', label: 'H18' },
151
- { value: 'O', label: 'O' },
152
- ]}
153
- />
154
- </Form.Item>
155
- </Col>
156
- </Row>
157
- <Row gutter={16}>
158
- <Col span={12}>
159
- <Form.Item
160
- name="thickness"
161
- label={t('thickness')}
162
- rules={[{ required: true, message: tc('required') }]}
163
- >
164
- <InputNumber min={0} max={10} step={0.1} style={{ width: '100%' }} />
165
- </Form.Item>
166
- </Col>
167
- <Col span={12}>
168
- <Form.Item
169
- name="width"
170
- label={t('width')}
171
- rules={[{ required: true, message: tc('required') }]}
172
- >
173
- <InputNumber min={0} max={2500} style={{ width: '100%' }} />
174
- </Form.Item>
175
- </Col>
176
- </Row>
177
- <Row gutter={16}>
178
- <Col span={12}>
179
- <Form.Item
180
- name="innerDiameter"
181
- label={t('innerDiameter')}
182
- rules={[{ required: true, message: tc('required') }]}
183
- >
184
- <InputNumber min={0} style={{ width: '100%' }} />
185
- </Form.Item>
186
- </Col>
187
- <Col span={12}>
188
- <Form.Item
189
- name="minOuterDiameter"
190
- label={t('minOuterDiameter')}
191
- rules={[{ required: true, message: tc('required') }]}
192
- >
193
- <InputNumber min={0} style={{ width: '100%' }} />
194
- </Form.Item>
195
- </Col>
196
- </Row>
197
- <Row gutter={16}>
198
- <Col span={12}>
199
- <Form.Item
200
- name="maxOuterDiameter"
201
- label={t('maxOuterDiameter')}
202
- rules={[{ required: true, message: tc('required') }]}
203
- >
204
- <InputNumber min={0} style={{ width: '100%' }} />
205
- </Form.Item>
206
- </Col>
207
- <Col span={12}>
208
- <Form.Item
209
- name="demand"
210
- label={t('demand')}
211
- rules={[{ required: true, message: tc('required') }]}
212
- >
213
- <InputNumber min={0} max={50} step={0.1} style={{ width: '100%' }} />
214
- </Form.Item>
215
- </Col>
216
- </Row>
217
- <Row gutter={16}>
218
- <Col span={12}>
219
- <Form.Item
220
- name="deliveryDate"
221
- label={t('deliveryDate')}
222
- rules={[{ required: true, message: tc('required') }]}
223
- >
224
- <DatePicker style={{ width: '100%' }} />
225
- </Form.Item>
226
- </Col>
227
- <Col span={12}>
228
- <Form.Item
229
- name="priority"
230
- label={t('priority')}
231
- rules={[{ required: true, message: tc('required') }]}
232
- >
233
- <Select
234
- options={[
235
- { value: 1, label: '1 - 低' },
236
- { value: 2, label: '2 - 中低' },
237
- { value: 3, label: '3 - 中' },
238
- { value: 4, label: '4 - 中高' },
239
- { value: 5, label: '5 - 高' },
240
- ]}
241
- />
242
- </Form.Item>
243
- </Col>
244
- </Row>
245
- </Form>
246
- </Card>
247
- </Drawer>
248
- );
249
- };
250
-
251
- export default OrderDrawer;