Skip to content

Conversation

@zhaoxiaofeng876
Copy link
Contributor

@zhaoxiaofeng876 zhaoxiaofeng876 commented Dec 3, 2025

PR

效果图:

1920px
image

1366px
image

手机端
image

PR Checklist

Please check if your PR fulfills the following requirements:

  • The commit message follows our Commit Message Guidelines
  • Tests for the changes have been added (for bug fixes / features)
  • Docs have been added / updated (for bug fixes / features)

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Documentation content changes
  • Other... Please describe:

What is the current behavior?

Issue Number: N/A

What is the new behavior?

Does this PR introduce a breaking change?

  • Yes
  • No

Other information

Summary by CodeRabbit

  • New Features
    • Added an "Advance" menu entry, route, and comprehensive English/Chinese translations for the new form.
    • Introduced a two-panel Advanced Form with Basic Project Info and editable Process Grid (add/edit/save/delete), plus small render helper components.
    • Form supports validation, reset, submit with success feedback, and exposes validate/reset hooks for parent usage.
    • Added initial data API/mock to populate options and sample process entries.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Dec 3, 2025

Walkthrough

Adds an "Advance" form feature: new locale entries, menu item, route, API client and mock endpoint, plus TinyVue components (advance parent, basic-info form, editable process-grid and renderers) implementing data fetch, validation, grid editing, reset and submit flows.

Changes

Cohort / File(s) Summary
NestJs — Locales
template/nestJs/locales.json
Added menu.form.advance and a full set of advanceForm.form.* translation keys for enUS and zhCN.
NestJs — Menu
template/nestJs/src/menu/init/menuData.ts, template/nestJs/src/menu/menu.service.ts
Appended an "Advance" menu item to menuData and initialized its parentId mapping in handleMenuParentId.
NestJs — Mock API
template/nestJs/src/mock/data/forms.ts
Added status and department to mock data and a GET /api/advance/getdata mock endpoint returning the init data.
TinyVue — Locales
template/tinyvue/src/locales.json
Added menu.form.advance and advanceForm.form.* keys for enUS and zhCN (basicInfo, process, validation, actions).
TinyVue — Routing
template/tinyvue/src/router/routes/modules/form.ts
Added new route entry for the Advance form (path/name/id/component/locale metadata and auth roles).
TinyVue — Advance Parent Component
template/tinyvue/src/views/form/advance/index.vue
New parent component composing BasicInfo and ProcessGrid, fetches advance data via getAdvanceData, shows loading overlay, handles reset and submit with child validation.
TinyVue — BasicInfo Form
template/tinyvue/src/views/form/advance/basic-info/index.vue
New TinyForm-based SFC with reactive basicInfo, validation (validForm()), resetForm(), and options populated from API data; exposes validForm and resetForm.
TinyVue — ProcessGrid Component
template/tinyvue/src/views/form/advance/process-grid/index.vue
New editable grid SFC with add/edit/save/delete, single-active-row enforcement, status/department rendering, and exposed resetGrid() API.
TinyVue — ProcessGrid Renderers
template/tinyvue/src/views/form/advance/process-grid/select-render.vue, template/tinyvue/src/views/form/advance/process-grid/status-render.vue
Small renderer components: select-render.vue (value → label) and status-render.vue (TinyTag with mapped type).
TinyVue — API & Mocks
template/tinyvue/src/api/form.ts, template/tinyvue/src/views/form/step/mock.ts
Added getAdvanceData() API client and GET /api/advance/getdata mock; added status and department to mock data shapes.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant UI as TinyVue Advance UI
  participant Parent as Advance Parent Component
  participant Basic as BasicInfo Component
  participant Grid as ProcessGrid Component
  participant API as getAdvanceData()
  participant Mock as Mock Server (/api/advance/getdata)

  UI->>Parent: mount
  Parent->>API: call getAdvanceData()
  API->>Mock: HTTP GET /api/advance/getdata
  Mock-->>API: return init data (positions, hr, teacher, status, department)
  API-->>Parent: resolved data
  Parent->>Basic: populate options (positions/hr/teacher)
  Parent->>Grid: populate options (status/department)
  User->>Basic: fill fields
  User->>Grid: add/edit process rows
  Parent->>Basic: Basic.validForm()
  Parent->>Grid: Grid.saveRow() / validations
  Parent->>Parent: on success show success modal
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Review focus:
    • template/tinyvue/src/views/form/advance/basic-info/index.vue — validation rules, defineExpose usage, option population.
    • template/tinyvue/src/views/form/advance/process-grid/index.vue — add/edit/save/delete flows and single-active-row logic.
    • Consistency between mock responses and getAdvanceData() (field shapes: status, department, option label/value).
    • template/nestJs/src/menu/menu.service.ts — correctness of parentId assignment for menu tree integrity.

Poem

🐰 I hopped through code to craft a new Advance,
Forms and rows in order, each field given a chance.
English and Chinese labels hum in tune,
Menus, mocks, and routes aligned beneath the moon.
Carrots and commits — a tidy little dance.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add Advanced Form' clearly and specifically summarizes the main change—the addition of a new Advanced Form feature across multiple template files (NestJS and TinyVue).
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (3)
template/nestJs/src/menu/menu.service.ts (1)

114-142: Consider refactoring hardcoded array indices.

The handleMenuParentId method uses hardcoded array indices to establish parent-child menu relationships. While the new line 137 follows the established pattern, this approach is brittle and makes the code difficult to maintain when menu items are added, removed, or reordered.

Consider refactoring to use a more maintainable approach, such as:

  • Using menu names or unique identifiers instead of array indices
  • Building a lookup map by menu name/id
  • Or defining parent relationships directly in the menu data structure

Example approach:

async handleMenuParentId(menuId: number[]) {
  const menu = await this.menu.find();
  const menuMap = new Map(menu.map(m => [m.name, m]));
  
  // Define relationships by name instead of index
  const relationships = {
    'Home': 'Board',
    'Work': 'Board',
    'Base': 'Form',
    'Step': 'Form',
    'Advance': 'Form',
    // ... other relationships
  };
  
  for (const [childName, parentName] of Object.entries(relationships)) {
    const child = menuMap.get(childName);
    const parent = menuMap.get(parentName);
    if (child && parent) {
      child.parentId = parent.id;
    }
  }
  
  for (const item of menu) {
    await this.menu.update(item.id, { parentId: item.parentId });
  }
}
template/tinyvue/src/views/form/advance/process-grid/index.vue (1)

125-157: Consider fetching options from API instead of hardcoding.

The dropdown options (departmentOptions, statusOptions, runningStatusOptions) are currently hardcoded. For production use, these should typically be fetched from the backend to ensure consistency and maintainability.

Consider fetching options in onMounted:

import { onMounted } from 'vue';

const departmentOptions = ref([]);
const statusOptions = ref([]);
const runningStatusOptions = ref([]);

onMounted(async () => {
  try {
    // Fetch options from API
    const { data } = await getProcessGridOptions();
    departmentOptions.value = data.departments;
    statusOptions.value = data.statuses;
    runningStatusOptions.value = data.runningStatuses;
  } catch (error) {
    console.error('Failed to load options:', error);
  }
});
template/tinyvue/src/views/form/advance/basic-info/index.vue (1)

141-158: Reconsider requiring all fields.

All nine form fields use commonRule, making them all required. Consider whether fields like remark should truly be mandatory, as remarks are typically optional.

Consider making optional fields less strict:

 const rules = ref({
   projectName: [...commonRule],
   position: [...commonRule],
   hr: [...commonRule],
   teacher: [...commonRule],
   startTime: [...commonRule],
   endTime: [...commonRule],
   phone: [...commonRule],
   address: [...commonRule],
-  remark: [...commonRule],
+  remark: [], // Optional field
 });
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bf2c8a0 and d40107a.

📒 Files selected for processing (8)
  • template/nestJs/locales.json (1 hunks)
  • template/nestJs/src/menu/init/menuData.ts (1 hunks)
  • template/nestJs/src/menu/menu.service.ts (1 hunks)
  • template/tinyvue/src/locales.json (1 hunks)
  • template/tinyvue/src/router/routes/modules/form.ts (1 hunks)
  • template/tinyvue/src/views/form/advance/basic-info/index.vue (1 hunks)
  • template/tinyvue/src/views/form/advance/index.vue (1 hunks)
  • template/tinyvue/src/views/form/advance/process-grid/index.vue (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
template/tinyvue/src/router/routes/modules/form.ts (1)
template/tinyvue/src/store/modules/user/types.ts (1)
  • RoleType (1-1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: e2e-test
🔇 Additional comments (6)
template/tinyvue/src/router/routes/modules/form.ts (1)

40-51: LGTM! Route configuration follows established patterns.

The new Advance route is correctly configured with:

  • Consistent path and component structure
  • Appropriate lazy loading
  • Correct metadata (locale key, authentication, role restriction)
  • Alignment with existing Base and Step form routes
template/nestJs/src/menu/init/menuData.ts (1)

292-301: Menu item configuration looks correct.

The new "Advance" menu item follows the established pattern for form child menu items:

  • Correct order value (3, following Base:1 and Step:2)
  • parentId: null is expected (will be set by handleMenuParentId)
  • Component and path values align with the Vue router configuration
  • Locale key matches the translations added in locale files

Note: The icon is set to an empty string, which is consistent with other form child items (Base, Step).

template/tinyvue/src/views/form/advance/process-grid/index.vue (1)

125-136: Review the initial sample data.

The grid is initialized with a hardcoded sample row containing what appears to be test data (name: '黄芊义', etc.). Consider whether this should:

  1. Start empty for production
  2. Load real data from an API
  3. Remain as a placeholder for demonstration purposes

If this is production code, the initial data should likely be removed or loaded from the backend.

template/tinyvue/src/locales.json (2)

870-895: Locale key organization looks good.

The new locale keys follow a clear hierarchical structure:

  • menu.form.advance for navigation
  • advanceForm.form.basicInfo.* for basic info form fields
  • advanceForm.form.process.* for process grid labels and actions
  • advanceForm.form.validError.* for validation messages
  • advanceForm.form.delete.title and advanceForm.form.nodata for UI feedback

This organization makes the keys easy to maintain and understand.


870-895: Verify corresponding enUS translations exist for all advanceForm locale keys.

The Chinese translations for the advance form are added in the zhCN section (lines 870-895), but ensure all corresponding keys exist in the enUS section. Both language sections should include all new locale keys for consistency.

template/nestJs/locales.json (1)

930-930: Verify that the corresponding enUS translation exists.

The Chinese translation for menu.form.advance is added at line 930, but a corresponding entry in the enUS section of this file should also be included to maintain consistency.

Comment on lines +164 to +177
const validForm = () => {
let baseValidate = false;
formRef.value.validate((valid) => {
if (!valid) {
Modal.message({
message: t('baseForm.form.submit.error'),
status: 'error',
});
}
baseValidate = valid;
});

return baseValidate;
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

validForm has confusing synchronous/asynchronous behavior.

The validForm method returns a boolean immediately, but form validation via formRef.value.validate() is callback-based. The return value may not reflect the actual validation result if validation is asynchronous.

Consider refactoring to use an async/Promise-based approach:

const validForm = () => {
  return new Promise<boolean>((resolve) => {
    formRef.value.validate((valid) => {
      if (!valid) {
        Modal.message({
          message: t('baseForm.form.submit.error'),
          status: 'error',
        });
      }
      resolve(valid);
    });
  });
};

Then update the parent component's handleSubmit to use await:

const handleSubmit = async () => {
  const baseValid = await basicInfoRef.value.validForm();
  // ...
};
🤖 Prompt for AI Agents
In template/tinyvue/src/views/form/advance/basic-info/index.vue around lines 164
to 177, validForm currently returns a boolean synchronously while
formRef.value.validate() is callback-based and may be asynchronous; change
validForm to return a Promise<boolean> that wraps
formRef.value.validate((valid)=>{...; resolve(valid);}), keep the Modal.message
call when valid is false, and update all callers (e.g., parent handleSubmit) to
await basicInfoRef.value.validForm() (make handleSubmit async) so the true
validation result is used.

Comment on lines 184 to 201
const fetchData = async () => {
loadingState.value = Loading.service({
text: 'loading...',
target: document.getElementById('project-form'),
background: 'rgba(0, 0, 0, 0.7)',
});
try {
const { data } = await getBaseData();
projectData.positionOptions = data.position;
projectData.hrOptions = data.HR;
projectData.teacherOptions = data.mentor.map((item) => ({
label: item,
value: item,
}));
} finally {
loadingState.value.close();
}
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add error handling for API failures.

The fetchData method doesn't handle API errors. If getBaseData() fails, the loading indicator will close, but users won't know why the dropdowns are empty and have no way to retry.

Apply this diff to add error handling:

 const fetchData = async () => {
   loadingState.value = Loading.service({
     text: 'loading...',
     target: document.getElementById('project-form'),
     background: 'rgba(0, 0, 0, 0.7)',
   });
   try {
     const { data } = await getBaseData();
     projectData.positionOptions = data.position;
     projectData.hrOptions = data.HR;
     projectData.teacherOptions = data.mentor.map((item) => ({
       label: item,
       value: item,
     }));
+  } catch (error) {
+    console.error('Failed to load form data:', error);
+    Modal.message({
+      message: t('baseForm.form.get.error'),
+      status: 'error',
+    });
   } finally {
     loadingState.value.close();
   }
 };
🤖 Prompt for AI Agents
In template/tinyvue/src/views/form/advance/basic-info/index.vue around lines 184
to 201, fetchData currently awaits getBaseData() inside try/finally but does not
handle API errors; wrap the await in a try/catch/finally, on catch call the UI
notification (e.g., Message.error or this.$message.error) with a clear
user-facing message and the error, optionally set projectData.* options to empty
arrays or previous values, and expose a retry path (e.g., enable a retry button
or return a boolean) so callers can retry; ensure loadingState.value.close()
remains in finally so the spinner always hides.

Comment on lines +48 to +56
const handleSubmit = () => {
const baseValid = basicInfoRef.value.validForm();
if (baseValid) {
Modal.message({
message: t('baseForm.form.submit.success'),
status: 'success',
});
}
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add validation for ProcessGrid and implement actual form submission.

The handleSubmit method has several concerns:

  1. Missing ProcessGrid validation: Only basicInfoRef is validated, but processGrid is not checked. If the grid has required data or validation rules, they should be enforced here.

  2. No actual form submission: The method shows a success message without submitting data to any API endpoint. This appears to be a placeholder implementation.

  3. Missing null safety: No check if basicInfoRef.value exists before calling validForm().

Apply this diff to address these concerns:

 const handleSubmit = () => {
+  if (!basicInfoRef.value || !processGrid.value) {
+    Modal.message({
+      message: t('baseForm.form.submit.error'),
+      status: 'error',
+    });
+    return;
+  }
+
   const baseValid = basicInfoRef.value.validForm();
-  if (baseValid) {
+  const gridValid = processGrid.value.getTableData().length > 0; // Or add validation method to ProcessGrid
+  
+  if (baseValid && gridValid) {
+    // TODO: Implement actual form submission
+    // const formData = {
+    //   basicInfo: basicInfoRef.value.getFormData(),
+    //   processData: processGrid.value.getTableData()
+    // };
+    // await submitAdvanceForm(formData);
+    
     Modal.message({
       message: t('baseForm.form.submit.success'),
       status: 'success',
     });
   }
 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const handleSubmit = () => {
const baseValid = basicInfoRef.value.validForm();
if (baseValid) {
Modal.message({
message: t('baseForm.form.submit.success'),
status: 'success',
});
}
};
const handleSubmit = () => {
if (!basicInfoRef.value || !processGrid.value) {
Modal.message({
message: t('baseForm.form.submit.error'),
status: 'error',
});
return;
}
const baseValid = basicInfoRef.value.validForm();
const gridValid = processGrid.value.getTableData().length > 0; // Or add validation method to ProcessGrid
if (baseValid && gridValid) {
// TODO: Implement actual form submission
// const formData = {
// basicInfo: basicInfoRef.value.getFormData(),
// processData: processGrid.value.getTableData()
// };
// await submitAdvanceForm(formData);
Modal.message({
message: t('baseForm.form.submit.success'),
status: 'success',
});
}
};

Comment on lines +173 to +175
const saveRow = (row) => {
gridRef.value.clearActived();
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Add row validation before saving.

The saveRow method clears the active state without validating the row data. This allows users to save incomplete or invalid rows.

Apply this diff to add validation:

 const saveRow = (row) => {
+  // Validate required fields
+  if (!row.name || !row.number || !row.department) {
+    Modal.message({
+      message: t('advanceForm.form.validError.null'),
+      status: 'error',
+    });
+    return;
+  }
+  
+  // TODO: Add API call to persist the row data
+  // try {
+  //   await saveProcessRow(row);
+  // } catch (error) {
+  //   Modal.message({
+  //     message: t('advanceForm.form.save.error'),
+  //     status: 'error',
+  //   });
+  //   return;
+  // }
+  
   gridRef.value.clearActived();
+  Modal.message({
+    message: t('advanceForm.form.process.save') + ' ' + t('baseForm.form.submit.success'),
+    status: 'success',
+  });
 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const saveRow = (row) => {
gridRef.value.clearActived();
};
const saveRow = (row) => {
// Validate required fields
if (!row.name || !row.number || !row.department) {
Modal.message({
message: t('advanceForm.form.validError.null'),
status: 'error',
});
return;
}
// TODO: Add API call to persist the row data
// try {
// await saveProcessRow(row);
// } catch (error) {
// Modal.message({
// message: t('advanceForm.form.save.error'),
// status: 'error',
// });
// return;
// }
gridRef.value.clearActived();
Modal.message({
message: t('advanceForm.form.process.save') + ' ' + t('baseForm.form.submit.success'),
status: 'success',
});
};
🤖 Prompt for AI Agents
In template/tinyvue/src/views/form/advance/process-grid/index.vue around lines
173-175, the saveRow function currently clears the active row without validating
its data; update saveRow to run validation on the provided row (synchronously or
await an existing grid/form validation method), and only call
gridRef.value.clearActived() when validation passes; if validation fails,
prevent clearing, surface validation errors to the user (e.g., mark
fields/errors or show a message), and handle async validators with try/catch so
saveRow waits for validation to finish before proceeding.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
template/tinyvue/src/views/form/advance/process-grid/index.vue (1)

200-202: Add row validation before clearing active state in saveRow

saveRow immediately clears the active row without checking that required fields (name/number/department, etc.) are filled, so users can “save” incomplete rows. It would be safer to validate the row first (either manually checking required fields or using any grid-level validation API you have) and only call gridRef.value.clearActived() when validation passes, surfacing an error message otherwise.

🧹 Nitpick comments (4)
template/tinyvue/src/views/form/advance/process-grid/status-render.vue (1)

1-25: Status renderer is clear; consider a safe fallback for unknown values

The mapping of running/finished/delayed to tag types is straightforward and matches the mock data. If there’s any chance of other status values appearing, you may want to default type (e.g., empty string or a neutral type) when tagType[props.value] is undefined so TinyTag never receives an unexpected value.

template/tinyvue/src/views/form/advance/process-grid/select-render.vue (1)

1-17: Guard against missing options and fix the tranformValue typo

Current logic assumes props.options is always defined; if this prop is ever omitted or null, props.options.find(...) will throw. Consider defaulting to an empty array in the computed (e.g., using a local const options = props.options || []) before searching. Also, renaming tranformValuetransformValue will make the intent clearer and avoid carrying a typo into future usages.

template/tinyvue/src/views/form/advance/process-grid/index.vue (2)

154-162: Correct the options prop definition to use a constructor type and factory default

options.type is currently an object literal with status/department fields, and default is a bare object. This doesn’t follow Vue’s expected prop option shape and can lead to confusing runtime checks and shared mutable defaults. Consider something like:

-  defineProps({
-    options: {
-      type: {
-        status: [],
-        department: [],
-      },
-      default: {},
-    },
-  });
+  defineProps({
+    options: {
+      type: Object,
+      default: () => ({
+        status: [],
+        department: [],
+      }),
+    },
+  });

This keeps the runtime contract clear and avoids shared state across component instances.


168-183: Consider formatting createTime values instead of relying on raw Date output

createTime is initialized with new Date() and rendered via defaultRender, which will display the default stringification of the Date object. If you want a stable, user-friendly format, it would be better to format this field (e.g., when setting the value or in defaultRender), especially since useDateFormat is already imported.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d40107a and c58f946.

📒 Files selected for processing (8)
  • template/nestJs/src/mock/data/forms.ts (2 hunks)
  • template/tinyvue/src/api/form.ts (1 hunks)
  • template/tinyvue/src/views/form/advance/basic-info/index.vue (1 hunks)
  • template/tinyvue/src/views/form/advance/index.vue (1 hunks)
  • template/tinyvue/src/views/form/advance/process-grid/index.vue (1 hunks)
  • template/tinyvue/src/views/form/advance/process-grid/select-render.vue (1 hunks)
  • template/tinyvue/src/views/form/advance/process-grid/status-render.vue (1 hunks)
  • template/tinyvue/src/views/form/step/mock.ts (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • template/tinyvue/src/views/form/advance/index.vue
  • template/tinyvue/src/views/form/advance/basic-info/index.vue
🔇 Additional comments (6)
template/nestJs/src/mock/data/forms.ts (2)

39-53: Status and department mock options look consistent with frontend usage

The added status strings and department option objects are well-suited for select/tag renderers and match the expected simple value/label shape.


84-91: /api/advance/getdata mock endpoint correctly reuses initBase

The new advance init endpoint reusing initBase keeps the data contract aligned with base/step mocks and the new getAdvanceData API.

template/tinyvue/src/api/form.ts (1)

30-33: Advance form API wiring matches existing pattern

submitStepForm keeps the original payload semantics, and getAdvanceData is consistent with getBaseData/getStepData and the new /api/advance/getdata mock. No issues from an API-shape standpoint.

Also applies to: 41-45

template/tinyvue/src/views/form/step/mock.ts (3)

1-4: Expanded initBase mock supports new process fields

The shared initBase now includes status and department, which lines up with the new advance form grid’s select/tag fields. Keeping this in a single base structure will simplify maintaining option lists across base/step/advance flows.

Also applies to: 39-53


66-73: /api/step/getdata now backed by initBase for consistency

Switching the step init endpoint to return initBase keeps the step form options in sync with the base/advance mocks. This should make it easier to reuse option sets across forms.


84-91: New /api/advance/getdata mock aligns with frontend getAdvanceData

The added init-advance mock endpoint reuses initBase and matches the /api/advance/getdata URL consumed by getAdvanceData, so the TinyVue advance form can run entirely against the local mock data.

@kagol
Copy link
Member

kagol commented Dec 6, 2025

/cmd docker --check

@github-actions
Copy link

github-actions bot commented Dec 6, 2025

🐳 Docker Check Status

CI triggered by command /cmd docker --check.

Status:Building... Preparing environment and running Docker health checks.

@github-actions
Copy link

github-actions bot commented Dec 6, 2025

✅ Docker Check Status

CI triggered by command /cmd docker --check.

Status: SUCCESS! Service is built, running, and responded to health check on http://localhost:3000/healthCheck.

@kagol
Copy link
Member

kagol commented Dec 8, 2025

@zhaoxiaofeng876 主要有以下优化点:

  1. 手机端表格建议增大一点列宽(出横向滚动条),美观一点
  2. 表格的创建时间,建议显示成YYYY-MM-DD hh:mm:ss格式
  3. 表格操作列中的保存和删除文字与前面的图标没有完全居中对齐
  4. 表格操作列建议增加编辑功能,点击之后可以整行编辑(跟新建类似效果)
image

}"
>
<template #default="data">
<selectRender
Copy link
Member

@kagol kagol Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<selectRender
<select-render

import { useDateFormat } from '@vueuse/core';
import { ref } from 'vue';
import statusRender from './status-render.vue';
import selectRender from './select-render.vue';
Copy link
Member

@kagol kagol Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

一般组件名称用烤串命名法或者大驼峰(建议烤串,因为TinyVue组件是烤串,统一风格)

</tiny-grid>
</div>
</template>
<script setup>
Copy link
Member

@kagol kagol Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

建议加上 lang="ts",获得更好的 TypeScript 类型提示

Suggested change
<script setup>
<script setup lang="ts">

);
});
</script>
<style lang=""></style>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

如果只是模板数据格式转换,可以直接使用计算属性,不需要封装组件

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (5)
template/tinyvue/src/views/form/advance/index.vue (2)

61-64: Reset handlers now safely guard child refs

Switching to optional chaining (basicInfoRef.value?.resetForm(), processGrid.value?.resetGrid()) addresses the earlier concern about calling methods on potentially undefined refs.


66-74: Submit flow still only validates BasicInfo and stays client‑only

handleSubmit only checks basicInfoRef.value.validForm() and then shows a success message; it doesn’t validate/process the grid data or actually submit a combined payload. If the grid is intended to be required for submission, consider exposing a validation/data method from ProcessGrid (e.g., via defineExpose) and using it here, and later wiring this to a real API call.

template/tinyvue/src/views/form/advance/process-grid/index.vue (3)

8-17: Using only the #empty slot resolves the previous render-empty concern

Dropping the unused :render-empty binding and relying solely on the #empty slot avoids passing an undefined renderer into TinyGrid and keeps the empty-state implementation straightforward.

Also applies to: 142-145


200-233: Consider adding basic row validation and feedback in saveRow

saveRow currently just clears the active state:

const saveRow = (row) => {
  gridRef.value.clearActived();
};

To prevent saving obviously incomplete rows, you could perform a simple check on required fields (e.g., name/number/department) and show a localized error message when validation fails, only clearing the active state when validation passes.


35-55: Align component naming and script language with existing project conventions

Minor polish items:

  • The imported selectRender from ./select-render.vue is used as <selectRender>. For consistency with other TinyVue components and prior review feedback, you may prefer kebab-case in the template, e.g. <select-render ...>.
  • Adding lang="ts" to the script block (if the rest of the project uses TypeScript) will improve type hints and catch more issues at build time:
-<script setup>
+<script setup lang="ts">

These are stylistic but help keep the codebase consistent.

Also applies to: 68-75, 148-166

🧹 Nitpick comments (3)
template/tinyvue/src/views/form/step/mock.ts (1)

134-141: Consider decoupling step and advance mock payloads

Reusing initStep for /api/advance/getdata works now, but it couples the step and advance forms’ payload shapes. If the two forms diverge later (extra fields, validations), consider introducing a dedicated initAdvance mock to avoid cross-impact.

template/tinyvue/src/views/form/advance/index.vue (1)

76-99: Harden fetchData with error feedback and a defensive close

Right now, failures from getAdvanceData are silently swallowed and loadingState.value.close() is called unguarded. Consider:

  • Wrapping the call with a catch that shows an error message (for example, using an existing i18n key like baseForm.form.get.error).
  • Changing the finally block to loadingState.value?.close() to avoid potential issues if the loading instance is ever missing.

This will make the initial load path more resilient without changing the happy path behavior.

template/tinyvue/src/views/form/advance/process-grid/index.vue (1)

168-176: Normalize the options prop definition to standard Vue patterns

The current defineProps config uses an object as type and a plain object as default, which is unconventional for Vue props and can lead to shared default instances:

defineProps({
  options: {
    type: {
      status: [],
      department: [],
    },
    default: {},
  },
});

Consider switching to the usual object-prop pattern with a factory default:

-  defineProps({
-    options: {
-      type: {
-        status: [],
-        department: [],
-      },
-      default: {},
-    },
-  });
+  defineProps({
+    options: {
+      type: Object,
+      default: () => ({
+        status: [],
+        department: [],
+      }),
+    },
+  });

This keeps the shape you expect while avoiding shared mutable defaults.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c58f946 and adfb293.

📒 Files selected for processing (5)
  • template/nestJs/locales.json (2 hunks)
  • template/tinyvue/src/locales.json (2 hunks)
  • template/tinyvue/src/views/form/advance/index.vue (1 hunks)
  • template/tinyvue/src/views/form/advance/process-grid/index.vue (1 hunks)
  • template/tinyvue/src/views/form/step/mock.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • template/tinyvue/src/locales.json
🔇 Additional comments (5)
template/tinyvue/src/views/form/step/mock.ts (1)

89-103: Status and department options match advanced form usage

Adding status as string values and department as { value, label } objects aligns with how fetchData in the advance form maps and consumes these options; the mock shape looks consistent and ready for frontend use.

template/nestJs/locales.json (2)

281-307: Advanced form enUS translations are coherent and aligned with usage

The new menu.form.advance and advanceForm.form.* keys in enUS look consistent and match the component usages (basic info title, grid columns, actions, validation, empty text).


957-983: Advanced form zhCN translations mirror enUS semantics

The zhCN entries for menu.form.advance and advanceForm.form.* accurately mirror the English meanings (section titles, grid fields, actions, validation, delete prompt, empty state), ensuring i18n coverage for the new form.

template/tinyvue/src/views/form/advance/index.vue (1)

1-31: Advanced form layout and i18n wiring look solid

The page structure (breadcrumb, two content cards, footer actions) and use of advanceForm.* / stepForm.* locale keys integrate cleanly with the new BasicInfo and ProcessGrid components.

Also applies to: 101-138

template/tinyvue/src/views/form/advance/process-grid/index.vue (1)

105-141: Guard $refs.gridRef in the Edit link condition to maintain consistency with the Save link

The Save link safely guards $refs.gridRef:

v-if="$refs.gridRef && $refs.gridRef.hasActiveRow(data.row)"

However, the Edit link directly calls hasActiveRow without checking if $refs.gridRef exists:

v-if="!$refs.gridRef.hasActiveRow(data.row)"

This creates an asymmetry in null-safety. Using v-else would both eliminate the second condition evaluation and ensure the guard is maintained:

-          <a
-            v-if="!$refs.gridRef.hasActiveRow(data.row)"
-            class="mr-2"
-            @click="editRow(data.row)"
-          >
+          <a
+            v-else
+            class="mr-2"
+            @click="editRow(data.row)"
+          >
             <IconEdit class="operation-icon"></IconEdit
             >{{ $t('advanceForm.form.process.edit') }}
           </a>

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (4)
template/tinyvue/src/views/form/advance/index.vue (1)

64-77: Align handleSubmit with async validation and consider grid validation

Right now handleSubmit:

  • Calls basicInfoRef.value.validForm() synchronously.
  • Ignores any validation/state from processGrid.
  • Always just shows a success toast without actually submitting data.

Once validForm is changed to return a Promise<boolean>, this should be made async and null‑safe, and ideally wired to grid validation as well, e.g.:

-  const handleSubmit = () => {
-    const baseValid = basicInfoRef.value.validForm();
-    if (baseValid) {
-      Modal.message({
-        message: t('baseForm.form.submit.success'),
-        status: 'success',
-      });
-    }
-  };
+  const handleSubmit = async () => {
+    if (!basicInfoRef.value || !processGrid.value) {
+      Modal.message({
+        message: t('baseForm.form.submit.error'),
+        status: 'error',
+      });
+      return;
+    }
+
+    const baseValid = await basicInfoRef.value.validForm();
+    // TODO: expose a validation method from ProcessGrid (e.g. validGrid())
+    // and include it here before treating the form as successfully submitted.
+
+    if (baseValid) {
+      Modal.message({
+        message: t('baseForm.form.submit.success'),
+        status: 'success',
+      });
+    }
+  };

This also revisits an earlier comment about incorporating ProcessGrid into the overall validation flow.

template/tinyvue/src/views/form/advance/process-grid/index.vue (2)

215-217: Add basic row validation and feedback before clearing edit state

saveRow currently just clears the active row:

const saveRow = (row) => {
  gridRef.value.clearActived();
};

Per the earlier review, this lets users “save” incomplete rows with no validation or feedback. Even a simple client‑side check on required fields would improve UX:

-  const saveRow = (row) => {
-    gridRef.value.clearActived();
-  };
+  const saveRow = (row) => {
+    if (!row.name || !row.number || !row.department) {
+      Modal.message({
+        message: t('advanceForm.form.validError.null'),
+        status: 'error',
+      });
+      return;
+    }
+
+    // TODO: hook up an API call here when backend is ready.
+
+    gridRef.value.clearActived();
+    Modal.message({
+      message:
+        t('advanceForm.form.process.save') +
+        ' ' +
+        t('baseForm.form.submit.success'),
+      status: 'success',
+    });
+  };

This keeps the grid in edit mode when data is invalid and gives clear success/error messaging when saving.


68-75: Fix SelectRender tag casing for the status column

In the status column slot you’re using <selectRender>:

<template #default="data">
  <selectRender
    :data="data"
    :options="options.status"
    field="status"
  ></selectRender>
</template>

Since the component is imported as SelectRender, Vue will resolve it as SelectRender (PascalCase) or select-render (kebab‑case); <selectRender> is lower‑cased by the HTML parser to selectrender and likely won’t match the registered component, so this slot will not render as intended.

Align this with the department column and earlier naming advice by switching to kebab‑case:

-        <template #default="data">
-          <selectRender
-            :data="data"
-            :options="options.status"
-            field="status"
-          ></selectRender>
-        </template>
+        <template #default="data">
+          <select-render
+            :data="data"
+            :options="options.status"
+            field="status"
+          ></select-render>
+        </template>

or use <SelectRender> consistently.

template/tinyvue/src/views/form/advance/basic-info/index.vue (1)

143-156: validForm’s synchronous return is unreliable with callback‑based validation

validForm returns baseValidate immediately after calling formRef.value.validate((valid) => ...). With TinyForm’s callback‑based (and often async) validation, there’s a real risk that baseValidate is still false when returned, so handleSubmit in the parent will almost never see true even when the form is valid. This matches an earlier bot comment on a similar pattern.

To make this robust, have validForm return a Promise<boolean> and await it from the parent:

-  const validForm = () => {
-    let baseValidate = false;
-    formRef.value.validate((valid) => {
-      if (!valid) {
-        Modal.message({
-          message: t('baseForm.form.submit.error'),
-          status: 'error',
-        });
-      }
-      baseValidate = valid;
-    });
-
-    return baseValidate;
-  };
+  const validForm = () => {
+    if (!formRef.value) return Promise.resolve(false);
+
+    return new Promise<boolean>((resolve) => {
+      formRef.value.validate((valid: boolean) => {
+        if (!valid) {
+          Modal.message({
+            message: t('baseForm.form.submit.error'),
+            status: 'error',
+          });
+        }
+        resolve(valid);
+      });
+    });
+  };

Then in the parent handleSubmit make it async and use const baseValid = await basicInfoRef.value?.validForm();.

This ensures the submit flow uses the actual validation result instead of a stale default.

🧹 Nitpick comments (3)
template/tinyvue/src/views/form/advance/basic-info/index.vue (1)

102-107: Prop definition for projectData should use a proper type and factory default

type: { positionOptions: [], hrOptions: [], teacherOptions: [] } is not a valid Vue prop type (it expects a constructor or PropType), and default: {} for an object prop will reuse the same object across component instances.

Consider tightening this to something like:

-  defineProps({
-    projectData: {
-      type: { positionOptions: [], hrOptions: [], teacherOptions: [] },
-      default: {},
-    },
-  });
+  import type { PropType } from 'vue';
+
+  const props = defineProps({
+    projectData: {
+      type: Object as PropType<{
+        positionOptions: any[];
+        hrOptions: any[];
+        teacherOptions: any[];
+      }>,
+      default: () => ({
+        positionOptions: [],
+        hrOptions: [],
+        teacherOptions: [],
+      }),
+    },
+  });

This avoids shared mutable defaults and gives you better type checking.

template/tinyvue/src/views/form/advance/index.vue (1)

79-102: Handle getAdvanceData failures and guard loadingState cleanup

fetchData always closes the loading overlay in finally, but if getAdvanceData() throws, users just see empty selects with no explanation and no retry hint. Also, if Loading.service ever fails or returns nothing, loadingState.value.close() could throw.

Consider:

  const fetchData = async () => {
-    loadingState.value = Loading.service({
+    loadingState.value = Loading.service({
       text: 'loading...',
       target: document.getElementById('content-container'),
       background: 'rgba(0, 0, 0, 0.7)',
     });
     try {
       const { data } = await getAdvanceData();
       projectData.positionOptions = data.position;
       projectData.hrOptions = data.HR;
       projectData.teacherOptions = data.mentor.map((item) => ({
         label: item,
         value: item,
       }));
       processOptions.status = data.status.map((item) => ({
         label: item,
         value: item,
       }));
       processOptions.department = data.department;
-    } finally {
-      loadingState.value.close();
+    } catch (error) {
+      console.error('Failed to load advance form data:', error);
+      Modal.message({
+        message: t('baseForm.form.get.error'),
+        status: 'error',
+      });
+    } finally {
+      loadingState.value && loadingState.value.close();
     }
   };

This keeps the UX responsive when the API fails and avoids a potential null dereference on loadingState.value.

template/tinyvue/src/views/form/advance/process-grid/index.vue (1)

110-121: Use the Composition API ref instead of $refs and guard hasActiveRow calls

The operation column mixes $refs.gridRef with Composition API refs:

<a
  v-if="$refs.gridRef && $refs.gridRef.hasActiveRow(data.row)"
  ...
>
...
<a
  v-if="!$refs.gridRef.hasActiveRow(data.row)"
  ...
>

The second condition can throw when $refs.gridRef is undefined (e.g., during initial render), and $refs is generally discouraged in new Composition API code when you already have gridRef.

Since template unwrapping exposes gridRef directly, you can simplify and make this safe:

-          <a
-            v-if="$refs.gridRef && $refs.gridRef.hasActiveRow(data.row)"
-            class="mr-2"
-            @click="saveRow(data.row)"
-          >
+          <a
+            v-if="gridRef && gridRef.hasActiveRow(data.row)"
+            class="mr-2"
+            @click="saveRow(data.row)"
+          >
             <IconSave class="operation-icon"></IconSave
             >{{ $t('advanceForm.form.process.save') }}
           </a>
-          <a
-            v-if="!$refs.gridRef.hasActiveRow(data.row)"
-            class="mr-2"
-            @click="editRow(data.row)"
-          >
+          <a
+            v-else
+            class="mr-2"
+            @click="editRow(data.row)"
+          >

This avoids direct $refs usage, removes the null‑dereference risk, and guarantees only one of “save” / “edit” is shown.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between adfb293 and 17918ba.

📒 Files selected for processing (4)
  • template/tinyvue/src/views/form/advance/basic-info/index.vue (1 hunks)
  • template/tinyvue/src/views/form/advance/index.vue (1 hunks)
  • template/tinyvue/src/views/form/advance/process-grid/index.vue (1 hunks)
  • template/tinyvue/src/views/form/advance/process-grid/status-render.vue (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • template/tinyvue/src/views/form/advance/process-grid/status-render.vue

@zhaoxiaofeng876
Copy link
Contributor Author

@zhaoxiaofeng876 主要有以下优化点:

  1. 手机端表格建议增大一点列宽(出横向滚动条),美观一点
  2. 表格的创建时间,建议显示成YYYY-MM-DD hh:mm:ss格式
  3. 表格操作列中的保存和删除文字与前面的图标没有完全居中对齐
  4. 表格操作列建议增加编辑功能,点击之后可以整行编辑(跟新建类似效果)
image

已修改:
2025-12-09_144946
2025-12-09_145311

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

♻️ Duplicate comments (1)
template/tinyvue/src/views/form/advance/process-grid/index.vue (1)

216-218: Validation missing before saving row.

The saveRow method clears the active state without validating row data, allowing incomplete or invalid rows to be saved. This issue was previously flagged and should be addressed.

🧹 Nitpick comments (1)
template/tinyvue/src/views/form/advance/process-grid/index.vue (1)

159-160: Remove unused imports.

TinyPager and TinyTag are imported but never used in this component.

Apply this diff:

     TinyPopconfirm,
     Modal,
     TinyDatePicker,
-    TinyPager,
-    TinyTag,
   } from '@opentiny/vue';
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 17918ba and 29acbf2.

📒 Files selected for processing (1)
  • template/tinyvue/src/views/form/advance/process-grid/index.vue (1 hunks)

@@ -0,0 +1,241 @@
<template lang="">
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Remove or set the empty lang attribute.

The lang="" attribute on the template tag serves no purpose. Either remove it entirely or set it to a meaningful value.

Apply this diff:

-<template lang="">
+<template>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<template lang="">
<template>
🤖 Prompt for AI Agents
In template/tinyvue/src/views/form/advance/process-grid/index.vue around line 1,
the <template> tag contains an empty lang attribute (lang="") which is
unnecessary; remove the lang attribute entirely or set it to a valid value (for
example lang="pug" or lang="html") depending on whether a template preprocessor
is used. Update the tag accordingly so it is either <template> or <template
lang="..."> ensuring consistency with any configured preprocessors in the
project.

}"
>
<template #default="data">
<selectRender
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix inconsistent component name casing.

Line 70 uses selectRender (camelCase) while line 49 uses SelectRender (PascalCase) for the same component. Since the import at line 167 is SelectRender, line 70 is incorrect and may cause rendering issues.

Apply this diff:

-          <selectRender
+          <SelectRender
             :data="data"
             :options="options.status"
             field="status"
-          ></selectRender>
+          ></SelectRender>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<selectRender
<SelectRender
:data="data"
:options="options.status"
field="status"
></SelectRender>
🤖 Prompt for AI Agents
template/tinyvue/src/views/form/advance/process-grid/index.vue around line 70:
the component is incorrectly cased as `selectRender` (camelCase) while the
component is imported/used elsewhere as `SelectRender` (PascalCase) and the
import at line 167 is `SelectRender`; change the tag at line 70 from
`selectRender` to `SelectRender` so casing matches the import and the other
usage to avoid rendering issues.

Comment on lines +113 to +127
v-if="$refs.gridRef && $refs.gridRef.hasActiveRow(data.row)"
class="mr-2"
@click="saveRow(data.row)"
>
<IconSave class="operation-icon"></IconSave
>{{ $t('advanceForm.form.process.save') }}
</a>
<a
v-if="!$refs.gridRef.hasActiveRow(data.row)"
class="mr-2"
@click="editRow(data.row)"
>
<IconEdit class="operation-icon"></IconEdit
>{{ $t('advanceForm.form.process.edit') }}
</a>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Avoid using $refs in template conditionals.

Lines 113 and 121 access $refs.gridRef directly in the template, which is fragile because refs may not be available during initial render and won't trigger proper reactivity.

Refactor to use a method or computed property:

+// In script setup, add a helper method:
+const isRowActive = (row) => {
+  return gridRef.value?.hasActiveRow?.(row) ?? false;
+};

Then update the template:

         <template #default="data">
           <a
-            v-if="$refs.gridRef && $refs.gridRef.hasActiveRow(data.row)"
+            v-if="isRowActive(data.row)"
             class="mr-2"
             @click="saveRow(data.row)"
           >
             <IconSave class="operation-icon"></IconSave
             >{{ $t('advanceForm.form.process.save') }}
           </a>
           <a
-            v-if="!$refs.gridRef.hasActiveRow(data.row)"
+            v-if="!isRowActive(data.row)"
             class="mr-2"
             @click="editRow(data.row)"
           >
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
v-if="$refs.gridRef && $refs.gridRef.hasActiveRow(data.row)"
class="mr-2"
@click="saveRow(data.row)"
>
<IconSave class="operation-icon"></IconSave
>{{ $t('advanceForm.form.process.save') }}
</a>
<a
v-if="!$refs.gridRef.hasActiveRow(data.row)"
class="mr-2"
@click="editRow(data.row)"
>
<IconEdit class="operation-icon"></IconEdit
>{{ $t('advanceForm.form.process.edit') }}
</a>
v-if="isRowActive(data.row)"
class="mr-2"
@click="saveRow(data.row)"
>
<IconSave class="operation-icon"></IconSave
>{{ $t('advanceForm.form.process.save') }}
</a>
<a
v-if="!isRowActive(data.row)"
class="mr-2"
@click="editRow(data.row)"
>
<IconEdit class="operation-icon"></IconEdit
>{{ $t('advanceForm.form.process.edit') }}
</a>

Comment on lines +169 to +177
defineProps({
options: {
type: {
status: [],
department: [],
},
default: {},
},
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix invalid TypeScript prop definition.

The current type definition syntax is invalid. For TypeScript, use a proper interface or type definition.

Apply this diff:

+  interface Options {
+    status: Array<{ label: string; value: string }>;
+    department: Array<{ label: string; value: string }>;
+  }
+
   defineProps({
     options: {
-      type: {
-        status: [],
-        department: [],
-      },
-      default: {},
+      type: Object as () => Options,
+      default: () => ({ status: [], department: [] }),
     },
   });

Alternatively, use TypeScript's defineProps with type parameters:

interface Props {
  options?: {
    status: Array<{ label: string; value: string }>;
    department: Array<{ label: string; value: string }>;
  };
}

const props = withDefaults(defineProps<Props>(), {
  options: () => ({ status: [], department: [] }),
});
🤖 Prompt for AI Agents
In template/tinyvue/src/views/form/advance/process-grid/index.vue around lines
169-177, the prop uses an invalid TypeScript `type` object syntax; replace it by
declaring a Props interface (specifying options with status and department
arrays of {label:string;value:string}) and use defineProps with that type plus
withDefaults to provide the default options factory returning empty arrays;
update references to use the returned props variable if needed.

},
});

const gridRef = ref('gridRef');
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Critical: Fix incorrect ref initialization.

gridRef is initialized with the string 'gridRef' instead of null. This will cause runtime errors when methods like gridRef.value.getActiveRow() are called.

Apply this diff:

-  const gridRef = ref('gridRef');
+  const gridRef = ref<InstanceType<typeof TinyGrid>>();

Or if you prefer simpler typing:

-  const gridRef = ref('gridRef');
+  const gridRef = ref(null);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const gridRef = ref('gridRef');
const gridRef = ref(null);
🤖 Prompt for AI Agents
In template/tinyvue/src/views/form/advance/process-grid/index.vue around line
179, gridRef is incorrectly initialized to the string 'gridRef' which will break
runtime calls like gridRef.value.getActiveRow(); change the initialization to a
null-based ref (e.g., ref(null) or typed ref of null such as
ref<InstanceType<typeof SomeGridComponent> | null>(null)) so gridRef.value is
null until the component mounts and method calls check for existence before
invoking.

@kagol kagol merged commit a4dab4d into opentiny:dev Dec 9, 2025
1 of 3 checks passed
@kagol kagol added the enhancement New feature or request label Jan 10, 2026
@kagol kagol changed the title Add Advanced Form feat: Add Advanced Form Jan 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants