You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
dianshang-qianduan/docs/superpowers/plans/2026-08-07-new-product-surv...

233 lines
11 KiB
Markdown

# New Product Survey Step Four Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Deliver the student-only fourth step that collects three AI application-value analyses and blocks final task submission until all are filled.
**Architecture:** Keep the existing `StudentTrainingAnswer.step4Answer` JSON persistence and add a stateless student-only validation endpoint. The Vue page retains a local draft and calls the validation endpoint only on final submission; the demo client enforces the same non-empty rule locally.
**Tech Stack:** Vue 3 Composition API, Element Plus, Vite, Spring Boot, Java 8, JUnit 5, Mockito.
## Global Constraints
- Only change the student `new-product-survey` page and its supporting student validation API; do not change teacher, admin, table schema, prior steps, or material download behavior.
- Persist `{ coreValue, tangibleValue, extendedValue }` in the existing `step4Answer` field.
- A value is valid only when `trim()` leaves non-empty text; validation does not score analysis quality.
- Saving a draft remains allowed with empty fields; final `SUBMIT` is guarded by validation.
- Keep legacy fourth-step JSON restoration compatible.
- Do not start the backend automatically; the user starts it manually.
---
### Task 1: Add server-side fourth-step validation
**Files:**
- Create: `E:/workspace/dianshang/link_commerce/.worktrees/new-product-survey-step3/src/main/java/com/sztzjy/linkCommerce/entity/dto/NewProductSurveyStepFourValidationRequest.java`
- Create: `E:/workspace/dianshang/link_commerce/.worktrees/new-product-survey-step3/src/main/java/com/sztzjy/linkCommerce/entity/dto/NewProductSurveyStepFourValidationResult.java`
- Create: `E:/workspace/dianshang/link_commerce/.worktrees/new-product-survey-step3/src/main/java/com/sztzjy/linkCommerce/service/NewProductSurveyStepFourService.java`
- Create: `E:/workspace/dianshang/link_commerce/.worktrees/new-product-survey-step3/src/main/java/com/sztzjy/linkCommerce/service/impl/NewProductSurveyStepFourServiceImpl.java`
- Modify: `E:/workspace/dianshang/link_commerce/.worktrees/new-product-survey-step3/src/main/java/com/sztzjy/linkCommerce/controller/stu/StudentTrainingAnswerController.java`
- Test: `E:/workspace/dianshang/link_commerce/.worktrees/new-product-survey-step3/src/test/java/com/sztzjy/linkCommerce/service/impl/NewProductSurveyStepFourServiceImplTest.java`
- Test: `E:/workspace/dianshang/link_commerce/.worktrees/new-product-survey-step3/src/test/java/com/sztzjy/linkCommerce/controller/stu/StudentTrainingAnswerControllerTest.java`
**Interfaces:**
- Consumes: authenticated `JwtUser` and `NewProductSurveyStepFourValidationRequest { String coreValue, String tangibleValue, String extendedValue }`.
- Produces: `NewProductSurveyStepFourValidationResult { boolean valid, String message }` from `POST /api/student-training-answers/new-product-survey/step-4/validate`.
- [ ] **Step 1: Write the failing service tests**
```java
@Test
void acceptsStudentWithAllThreeNonBlankValues() {
NewProductSurveyStepFourValidationRequest request = request("核心分析", "有形分析", "延伸分析");
assertTrue(service.validate(request, student()).isValid());
}
@ParameterizedTest
@NullAndEmptySource
@ValueSource(strings = {" ", "\t"})
void rejectsBlankCoreValue(String value) {
assertThrows(ServiceException.class, () -> service.validate(request(value, "有形", "延伸"), student()));
}
@Test
void rejectsNonStudent() {
assertThrows(ServiceException.class, () -> service.validate(request("核心", "有形", "延伸"), teacher()));
}
```
- [ ] **Step 2: Run the service test to verify it fails**
Run: `mvn -B '-Dtest=NewProductSurveyStepFourServiceImplTest' test`
Expected: FAIL because fourth-step request and service types do not exist.
- [ ] **Step 3: Implement DTOs and service**
```java
public interface NewProductSurveyStepFourService {
NewProductSurveyStepFourValidationResult validate(NewProductSurveyStepFourValidationRequest request, JwtUser user);
}
private void requireNonBlank(String value, String message) {
if (StringUtils.isBlank(value)) {
throw new ServiceException(HttpStatus.BAD_REQUEST, message);
}
}
```
Require the existing student role and user id, then require `coreValue`, `tangibleValue`, and `extendedValue` after trimming. Return `valid=true` and `校验通过` on success.
- [ ] **Step 4: Run the service test to verify it passes**
Run: `mvn -B '-Dtest=NewProductSurveyStepFourServiceImplTest' test`
Expected: PASS with nonblank, blank, and authorization behavior covered.
- [ ] **Step 5: Write the failing controller test**
```java
@Test
void validateStepFourUsesAuthenticatedStudentAndReturnsValidationResult() {
NewProductSurveyStepFourValidationResult result = new NewProductSurveyStepFourValidationResult(true, "校验通过");
when(newProductSurveyStepFourService.validate(any(), any())).thenReturn(result);
ResultEntity<NewProductSurveyStepFourValidationResult> response = controller
.validateNewProductSurveyStepFour(request("核心", "有形", "延伸"), authenticatedRequest());
assertEquals(HttpStatus.OK, response.getCode());
assertSame(result, response.getData());
}
```
- [ ] **Step 6: Run the controller test to verify it fails**
Run: `mvn -B '-Dtest=StudentTrainingAnswerControllerTest' test`
Expected: FAIL because `validateNewProductSurveyStepFour` does not exist.
- [ ] **Step 7: Add the controller endpoint**
```java
@PostMapping("/new-product-survey/step-4/validate")
public ResultEntity<NewProductSurveyStepFourValidationResult> validateNewProductSurveyStepFour(
@RequestBody NewProductSurveyStepFourValidationRequest answer, HttpServletRequest request) {
try {
return new ResultEntity<>(HttpStatus.OK, "校验通过",
newProductSurveyStepFourService.validate(answer, TokenProvider.getJWTUser(request)));
} catch (ServiceException e) {
return new ResultEntity<>(e.getCode(), e.getMessage());
}
}
```
- [ ] **Step 8: Run focused server tests**
Run: `mvn -B '-Dtest=NewProductSurveyStepFourServiceImplTest,StudentTrainingAnswerControllerTest' test`
Expected: PASS with fourth-step service behavior and endpoint delegation covered.
- [ ] **Step 9: Commit server validation**
```bash
git add src/main/java/com/sztzjy/linkCommerce/entity/dto/NewProductSurveyStepFourValidationRequest.java src/main/java/com/sztzjy/linkCommerce/entity/dto/NewProductSurveyStepFourValidationResult.java src/main/java/com/sztzjy/linkCommerce/service/NewProductSurveyStepFourService.java src/main/java/com/sztzjy/linkCommerce/service/impl/NewProductSurveyStepFourServiceImpl.java src/main/java/com/sztzjy/linkCommerce/controller/stu/StudentTrainingAnswerController.java src/test/java/com/sztzjy/linkCommerce/service/impl/NewProductSurveyStepFourServiceImplTest.java src/test/java/com/sztzjy/linkCommerce/controller/stu/StudentTrainingAnswerControllerTest.java
git commit -m "feat: validate new product survey step four"
```
### Task 2: Update the fourth-step student UI and submission flow
**Files:**
- Modify: `E:/workspace/dianshang/e-commerce-internet/.worktrees/new-product-survey-step3/src/api/studentTrainingAnswer.js`
- Modify: `E:/workspace/dianshang/e-commerce-internet/.worktrees/new-product-survey-step3/src/views/foundation/new-product-survey.vue`
- Modify: `E:/workspace/dianshang/e-commerce-internet/.worktrees/new-product-survey-step3/tests/new-product-survey-step-one.static.test.cjs`
**Interfaces:**
- Consumes: `checkNewProductSurveyStepFour(payload)` returning `{ code: 200, data: { valid: true, message: "校验通过" } }`.
- Produces: guarded `submitTask()` that saves `step4Answer` only after successful validation.
- [ ] **Step 1: Add failing static source assertions**
```js
assert.match(page, /AI技术是否实现产品功能突破是否形成差异化卖点/, "step four must show the core-layer prototype question");
assert.match(page, /AI技术是否影响产品形态如产品外形包装、电商主图设计、参数配置、价格带定位。/, "step four must show the tangible-layer prototype question");
assert.match(page, /AI技术如何通过服务升级、内容更新提升用户粘性推动付费服务/, "step four must show the extended-layer prototype question");
assert.match(page, /checkNewProductSurveyStepFour\(step4Form\.value\)/, "step four must validate before submission");
assert.match(api, /new-product-survey\/step-4\/validate/, "the API must expose the step-four validation route");
```
- [ ] **Step 2: Run the static test to verify it fails**
Run: `& 'E:\Program Files\nodejs\node.exe' tests\new-product-survey-step-one.static.test.cjs`
Expected: FAIL because the fourth-step question copy and validation call are absent.
- [ ] **Step 3: Implement client validation and prototype-aligned form**
```js
function validateNewProductSurveyStepFourDemo(form) {
const value = form || {};
for (const [field, label] of [["coreValue", "核心层"], ["tangibleValue", "有形层"], ["extendedValue", "延伸层"]]) {
if (!String(value[field] || "").trim()) throw new Error(`请填写${label}AI应用价值分析`);
}
return { valid: true, message: "校验通过" };
}
async function submitTask() {
checking.value = true;
try {
await checkNewProductSurveyStepFour(step4Form.value);
await saveAnswer("SUBMITTED");
} catch (error) {
proxy?.$modal?.msgWarning(error?.message || "请完成三层次AI应用价值分析");
} finally {
checking.value = false;
}
}
```
Replace the existing generic field labels with the three prototype questions, keep their bindings as `coreValue`, `tangibleValue`, and `extendedValue`, and preserve draft saving and restoration.
- [ ] **Step 4: Run the static test to verify it passes**
Run: `& 'E:\Program Files\nodejs\node.exe' tests\new-product-survey-step-one.static.test.cjs`
Expected: PASS with prior step contracts still intact.
- [ ] **Step 5: Commit student UI and client validation**
```bash
git add src/api/studentTrainingAnswer.js src/views/foundation/new-product-survey.vue tests/new-product-survey-step-one.static.test.cjs
git commit -m "feat: add new product survey step four"
```
### Task 3: Run full verification
**Files:**
- Modify: none.
**Interfaces:**
- Consumes: both committed fourth-step implementations.
- Produces: verification evidence before integration; no application process is started.
- [ ] **Step 1: Run complete backend tests**
Run: `mvn -B test`
Expected: Maven reports `BUILD SUCCESS` and zero failures.
- [ ] **Step 2: Run the frontend source contract**
Run: `& 'E:\Program Files\nodejs\node.exe' tests\new-product-survey-step-one.static.test.cjs`
Expected: `new product survey step-one contract passed`.
- [ ] **Step 3: Run the production frontend build**
Run: `& 'E:\Program Files\nodejs\node.exe' 'E:\workspace\dianshang\e-commerce-internet\node_modules\vite\bin\vite.js' build`
Expected: Vite exits with code 0. Existing `::v-deep`, unresolved `Navbar.vue` top1 asset, and large-chunk warnings may remain.
- [ ] **Step 4: Inspect repository state**
Run: `git status --short; git log --oneline --max-count=5`
Expected: only the intended fourth-step commits are present; do not start the backend.