Skip to content

chore: sync release-3.24.0 to dev #3507

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jun 14, 2025
Merged

chore: sync release-3.24.0 to dev #3507

merged 6 commits into from
Jun 14, 2025

Conversation

zzcr
Copy link
Member

@zzcr zzcr commented Jun 14, 2025

PR

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

    • Introduced a comprehensive product management interface with editable product grid, add/remove/save actions, and local storage support.
    • Added a mobile remote control experience via QR code scanning, with secure session linking and AI chat integration.
    • Implemented a voice recording and speech recognition interface for chat input.
    • Added a customizable chat message card component.
    • Enabled external customization of chat prompt and suggestion items in the robot chat interface.
    • Added new routes and menu items for intelligent features and remote control.
    • Provided new documentation guides for integrating intelligent components (AI/voice) in both English and Chinese.
    • Introduced utility for reactive storage management and session handling.
    • Added TypeScript interfaces for strong typing of user, product, and form data.
  • Bug Fixes

    • Various component rendering, style, event handling, and API issues addressed (see changelog for details).
  • Chores

    • Updated dependencies and package versions.
    • Added a new contributor acknowledgment.
  • Documentation

    • Updated and expanded documentation, including detailed integration guides and changelog updates.
  • Style

    • Improved and unified component styles, including layouts and visual enhancements.

zzcr added 6 commits June 11, 2025 17:57
)

* feat: 官网新增mcp综合示例

* fix: 修复 tiny-robot-chat 组件中的提示项和建议项的传递逻辑,优化 Demo 组件的 QR 码展示样式

* fix: 修复引入路径问题
…documentation (#3498)

* chore: 更新changelog,并添加TinyVue智能化组件接入文档

* chore: 添加菜单优化文档

* chore: 更新mcp.md文档中的sessionId说明,简化调试提示

* chore: 更新mcp-en.md文档中的标题和内容,统一语言为英文
* feat: 添加遥控器页面,更新next依赖

* chore: 修改代理为https url
Copy link

coderabbitai bot commented Jun 14, 2025

Walkthrough

This update introduces a comprehensive product management demo and remote control/voice chat features, including new Vue components, TypeScript interfaces, and product data. It adds documentation for integrating intelligent components, updates dependencies, modifies menu and routing configurations, and enhances storage and state management utilities for reactivity and persistent data handling.

Changes

File(s) Change Summary
examples/sites/demos/pc/menus.js Added a new menu item for "智能化"/"mcp".
examples/sites/demos/pc/webdoc/changelog.md Added changelog for v3.24.0/v2.24.0; removed old entry.
examples/sites/demos/pc/webdoc/mcp-en.md
examples/sites/demos/pc/webdoc/mcp.md
Added new documentation guides for TinyVue intelligent component integration (EN & ZH).
examples/sites/package.json Updated package version, dependencies, and added crypto-js.
examples/sites/src/App.vue Integrated $session.sessionId into client initialization and synchronized session IDs.
examples/sites/src/components/MessageCard.vue Added new Vue component for displaying chat messages with role-based styling.
examples/sites/src/components/demo.vue Changed import path for component configuration utilities.
examples/sites/src/components/tiny-robot-chat.vue Added props for prompt/suggestion items, updated bindings, and adjusted imports.
examples/sites/src/composable/DifyModelProvider.ts Removed an extraneous blank line.
examples/sites/src/composable/storage.ts Added new utility for reactive storage management and auto-persistence.
examples/sites/src/composable/utils.ts Made globalConversation reactive, added showTinyRobot, and re-exported storage utilities.
examples/sites/src/router.js Added routes for new "Comprehensive" and "Remoter" pages.
examples/sites/src/views/components-doc/common.vue Updated import paths for components and composables.
examples/sites/src/views/comprehensive/Demo.vue Added new product management demo component.
examples/sites/src/views/comprehensive/index.vue Added new comprehensive UI with QR code, chat, and right panel.
examples/sites/src/views/comprehensive/products.json Added product data JSON file.
examples/sites/src/views/comprehensive/types/index.ts Added TypeScript interfaces for User, Product, and forms.
examples/sites/src/views/layout/layout.vue Changed import paths for settings/version components.
examples/sites/src/views/remoter/index.vue Added new remote control page with session decryption and controller toggle.
examples/sites/src/views/remoter/sound.vue Added new voice recording and speech recognition component.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant ComprehensivePage
    participant QRCodeModal
    participant RemoterPage
    participant ChatController
    participant SoundController

    User->>ComprehensivePage: Load page
    ComprehensivePage->>QRCodeModal: Show QR code (encrypted session)
    User->>QRCodeModal: Scan QR code
    QRCodeModal->>RemoterPage: Open with encrypted session id
    RemoterPage->>RemoterPage: Decrypt session id, set global session
    User->>RemoterPage: Choose Chat or Voice
    RemoterPage->>ChatController: Show chat interface
    RemoterPage->>SoundController: Show voice interface
Loading

Suggested labels

chore

Poem

(\(\
( -.-)
o_(")(")

New demos bloom and voices sing,
Products, chat, and QR bring
Storage now remembers well,
Docs and types begin to swell.
Robot rabbits hop with glee—
Remote control for you and me!

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

examples/sites/demos/pc/menus.js

Oops! Something went wrong! :(

ESLint: 8.57.1

ESLint couldn't find the plugin "eslint-plugin-vue".

(The package "eslint-plugin-vue" was not found when loaded as a Node module from the directory "".)

It's likely that the plugin isn't installed correctly. Try reinstalling by running the following:

npm install eslint-plugin-vue@latest --save-dev

The plugin "eslint-plugin-vue" was referenced from the config file in ".eslintrc.js » @antfu/eslint-config » @antfu/eslint-config-vue".

If you still can't figure out the problem, please stop by https://eslint.org/chat/help to chat with the team.

examples/sites/src/App.vue

Oops! Something went wrong! :(

ESLint: 8.57.1

ESLint couldn't find the plugin "eslint-plugin-vue".

(The package "eslint-plugin-vue" was not found when loaded as a Node module from the directory "".)

It's likely that the plugin isn't installed correctly. Try reinstalling by running the following:

npm install eslint-plugin-vue@latest --save-dev

The plugin "eslint-plugin-vue" was referenced from the config file in ".eslintrc.js » @antfu/eslint-config » @antfu/eslint-config-vue".

If you still can't figure out the problem, please stop by https://eslint.org/chat/help to chat with the team.

examples/sites/src/components/MessageCard.vue

Oops! Something went wrong! :(

ESLint: 8.57.1

ESLint couldn't find the plugin "eslint-plugin-vue".

(The package "eslint-plugin-vue" was not found when loaded as a Node module from the directory "".)

It's likely that the plugin isn't installed correctly. Try reinstalling by running the following:

npm install eslint-plugin-vue@latest --save-dev

The plugin "eslint-plugin-vue" was referenced from the config file in ".eslintrc.js » @antfu/eslint-config » @antfu/eslint-config-vue".

If you still can't figure out the problem, please stop by https://eslint.org/chat/help to chat with the team.

  • 12 others
✨ Finishing Touches
  • 📝 Generate Docstrings

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions github-actions bot added the chore label Jun 14, 2025
@zzcr zzcr merged commit 0b1d2a8 into dev Jun 14, 2025
12 checks passed
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: 8

♻️ Duplicate comments (1)
examples/sites/demos/pc/webdoc/mcp.md (1)

41-46: Same duplication note as the English guide

The Chinese guide repeats sessionId in clientInfo while also returning it from the composable. Consider removing one occurrence for clarity.

🧹 Nitpick comments (19)
examples/sites/src/views/comprehensive/products.json (1)

1-99: Normalise data before it becomes production content

The JSON is fine for a demo, but a few small clean-ups will save headaches later:

  1. Mixed date formats ("2024-03-20" vs ISO strings). Pick one (ISO is safest).
  2. price & stock are integers; real apps often need decimals & bigints – at least leave a comment.
  3. The same external image URL is reused for several products – consider local, CDN, or placeholder links to avoid hot-link breakage.
  4. Field naming is English except the Chinese description text – that’s fine, but ensure i18n is deliberate.
examples/sites/src/views/comprehensive/types/index.ts (1)

29-37: Avoid duplicating Product shape – derive ProductForm

ProductForm is almost a copy of Product minus immutable fields. Keep a single source of truth:

-export interface ProductForm {
-  name: string
-  price: number
-  description: string
-  image: string
-  category: string
-  stock: number
-  status: 'on' | 'off'
-}
+export type ProductForm = Omit<Product, 'id' | 'createdAt' | 'updatedAt'>

This reduces maintenance cost when fields change.

examples/sites/src/composable/storage.ts (1)

60-69: useAutoStore is write-through only – add read-through sync

Changing $session.key directly (outside the ref) won’t refresh the component state.
A simple solution is to also watch storage events:

onMounted(() => {
  window.addEventListener('storage', (e) => {
    if (e.key === key) refVar.value = parse(e.newValue)
  })
})

(Not shown in diff wrapper to keep context small.)

examples/sites/src/views/components-doc/common.vue (2)

102-109: Deep relative paths hurt maintainability – prefer alias imports

Going from ./components/... to ../../components/... makes refactors brittle.
Register an alias (@/components) in Vite/Rollup and import via:

-import DemoBox from '../../components/demo.vue'
+import DemoBox from '@/components/demo.vue'

Repeat for the other moved imports.


111-111: Component naming is non-standard

robotChat is imported in camelCase and used in the template as <robotChat>.
HTML is case-insensitive, so Vue will see it as <robotchat> which is unconventional.
Use PascalCase to avoid surprises:

-import robotChat from '../../components/tiny-robot-chat.vue'
+import RobotChat from '@/components/tiny-robot-chat.vue'

and <RobotChat v-if="..."/> in the template.

examples/sites/src/App.vue (1)

43-44: Keep $session reactive across tabs

The watcher writes back to $session.sessionId but never clears it when the value becomes falsy (e.g., logout).
Consider resetting on null to avoid stale sessions.

examples/sites/src/router.js (2)

24-27: Add route meta for SEO and title handling

Unlike the overview route, comprehensive lacks meta: { title: 'xxx | TinyVue' }.
Without it router.afterEach will leave document.title unchanged.

-  component: Comprehensive,
+  component: Comprehensive,
   name: 'comprehensive',
+  meta: { title: 'Comprehensive Demo | TinyVue' }

28-32: Second new route suffers the same missing-meta issue

Replicate the meta addition for remoter.

examples/sites/src/composable/utils.ts (2)

10-13: Consider persisting showTinyRobot via the new storage helpers

showTinyRobot is a plain ref. Users would expect the toggle state to survive page reloads (similar to chat history).
Wiring it to $local or $session would achieve that with minimal code:

-import { ref, reactive, type Ref } from 'vue'
+import { ref, reactive, type Ref, watch } from 'vue'
+import { $local } from './storage'
 ...
-export const showTinyRobot = ref(true)
+export const showTinyRobot = ref($local.get('showTinyRobot') ?? true)
+
+watch(showTinyRobot, (val) => $local.set('showTinyRobot', val))

14-17: Missing typings for globalConversation

The reactive object is created ad-hoc, so property access elsewhere is untyped.
Declaring an interface keeps the advantage of TS inference:

interface ConversationState {
  id: string
  sessionId: string
}

export const globalConversation = reactive<ConversationState>({
  id: '',
  sessionId: ''
})
examples/sites/demos/pc/webdoc/mcp-en.md (1)

41-46: Minor typo – “NextClient Proxy Client” section code sample contains sessionId twice

sessionId is already returned from useNextClient; keep only the prop or the destructured value to avoid confusing readers.

examples/sites/src/components/MessageCard.vue (2)

18-24: Props should be marked as readonly in TS for Vue SFCs

-interface Props {
+interface Props {
   role: 'user' | 'assistant'
   message: string
   timestamp: number
 }

(readonly omitted above for brevity.)
Although Vue will proxy them as readonly at runtime, adding the modifier signals the intent in the type system.


30-37: Hard-coded locale limits reusability

toLocaleTimeString('zh-CN', …) forces Chinese formatting; apps with i18n might expect the browser locale.

-return date.toLocaleTimeString('zh-CN', {
+return date.toLocaleTimeString(undefined, {

Pass the locale from a global i18n util if required.

examples/sites/src/views/comprehensive/Demo.vue (1)

122-135: Confirm destructive action

removeSelecteds() executes immediately once rows are selected. Consider wrapping it with TinyModal.confirm so the user can cancel accidental deletions.

-  if (selectedRows.length > 0) {
-    gridRef?.value?.removeSelecteds()
-  }
+  if (selectedRows.length > 0) {
+    TinyModal.confirm({
+      message: `确定删除选中的 ${selectedRows.length} 项?`,
+      status: 'warning',
+      onOk: () => gridRef?.value?.removeSelecteds()
+    })
+  }
examples/sites/demos/pc/webdoc/changelog.md (1)

29-30: Fix typo “drowdown”

drowdowndropdown for easier grep-ability and consistency.

🧰 Tools
🪛 LanguageTool

[style] ~30-~30: Unless you want to emphasize “not”, use “cannot” which is more common.
Context: .../tiny-vue/pull/3445> - fix(select): fix can not set grid rowId in select by @gimmyhehe ...

(CAN_NOT_PREMIUM)

examples/sites/src/views/remoter/sound.vue (2)

83-85: Add proper TS types for recognition

recognition is any, losing autocomplete and safety. Import type SpeechRecognition and annotate:

-import { … } from 'vue'
+import { … } from 'vue'
+type SpeechRecognition = typeof window.SpeechRecognition-let recognition: any = null
+let recognition: SpeechRecognition | null = null

98-116: Timestamp logic overwrites earlier values

Mapping messageTimestamps on every change re-creates the whole array and assigns identical timestamps to all newly arrived messages in one batch.
Push one timestamp per new message instead to preserve per-message accuracy.

examples/sites/src/views/remoter/index.vue (1)

24-27: Ensure exclusive controller display

Clicking both buttons in succession sets both showSound and showChat to true. Reset other flags before enabling the chosen one.

-const showMoter = (type) => {
-  state.isShow = false
-  state[type] = true
-}
+const showMoter = (type: 'showSound' | 'showChat') => {
+  state.isShow = false
+  state.showSound = false
+  state.showChat = false
+  state[type] = true
+}
examples/sites/src/views/comprehensive/index.vue (1)

53-60: Unused import TinyRobotChat

TinyRobotChat is imported but the template uses the kebab-case custom element. Remove the import or use the Pascal-case component to avoid an unused-variable lint error.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fc5a11e and ac2c054.

📒 Files selected for processing (21)
  • examples/sites/demos/pc/menus.js (1 hunks)
  • examples/sites/demos/pc/webdoc/changelog.md (1 hunks)
  • examples/sites/demos/pc/webdoc/mcp-en.md (1 hunks)
  • examples/sites/demos/pc/webdoc/mcp.md (1 hunks)
  • examples/sites/package.json (3 hunks)
  • examples/sites/src/App.vue (2 hunks)
  • examples/sites/src/components/MessageCard.vue (1 hunks)
  • examples/sites/src/components/demo.vue (1 hunks)
  • examples/sites/src/components/tiny-robot-chat.vue (4 hunks)
  • examples/sites/src/composable/DifyModelProvider.ts (0 hunks)
  • examples/sites/src/composable/storage.ts (1 hunks)
  • examples/sites/src/composable/utils.ts (1 hunks)
  • examples/sites/src/router.js (2 hunks)
  • examples/sites/src/views/components-doc/common.vue (1 hunks)
  • examples/sites/src/views/comprehensive/Demo.vue (1 hunks)
  • examples/sites/src/views/comprehensive/index.vue (1 hunks)
  • examples/sites/src/views/comprehensive/products.json (1 hunks)
  • examples/sites/src/views/comprehensive/types/index.ts (1 hunks)
  • examples/sites/src/views/layout/layout.vue (1 hunks)
  • examples/sites/src/views/remoter/index.vue (1 hunks)
  • examples/sites/src/views/remoter/sound.vue (1 hunks)
💤 Files with no reviewable changes (1)
  • examples/sites/src/composable/DifyModelProvider.ts
🧰 Additional context used
🪛 LanguageTool
examples/sites/demos/pc/webdoc/changelog.md

[style] ~30-~30: Unless you want to emphasize “not”, use “cannot” which is more common.
Context: .../tiny-vue/pull/3445> - fix(select): fix can not set grid rowId in select by @gimmyhehe ...

(CAN_NOT_PREMIUM)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
🔇 Additional comments (9)
examples/sites/src/views/layout/layout.vue (1)

66-68: Path-alias update looks good – verify Vite/TS config is in sync

The component paths were flattened, which is easier to read and removes fragile deep-relative imports.
Just double-check that:

  1. vite.config.ts / tsconfig.json have the @/components alias.
  2. No residual imports of the old deep path linger elsewhere.

If both are true, nothing further to do.

examples/sites/src/components/demo.vue (1)

78-78: Import path change acknowledged

The move to a clear absolute path matches the other refactors – no issues spotted.

examples/sites/package.json (3)

4-4: Patch version bump looks fine, but ensure lock-file is regenerated

The json only updates "version": "3.24.4". Regenerate pnpm-lock.yaml/package-lock.json to keep CI in sync.


60-60:

❓ Verification inconclusive

crypto-js adds ~600 KB to the bundle – verify necessity and audit score

The new dependency is sizeable and occasionally flagged by security scanners. If only AES is needed consider crypto-es (tree-shakable) or the Web Crypto API.


🏁 Script executed:

#!/bin/bash
# Check for known advisories on crypto-js
npm audit --json | jq '.advisories[] | select(.module_name=="crypto-js") | {id, severity, title}'

Length of output: 957


🏁 Script executed:

#!/bin/bash
# 1. Generate a lockfile so that npm audit can run
npm install --package-lock-only

# 2. Check for any advisories related to crypto-js
npm audit --json | jq '.advisories[] | select(.module_name=="crypto-js") | {id, severity, title}'

# 3. Locate all imports/requires of crypto-js to see which submodules are used
rg "import .*crypto-js" -n
rg "require(['\"]crypto-js['\"])" -n

Length of output: 1882


🏁 Script executed:

#!/bin/bash
# Inspect which CryptoJS methods are used in the two Vue components
rg -n -A2 "CryptoJS\." examples/sites/src/views/remoter/index.vue examples/sites/src/views/comprehensive/index.vue

Length of output: 800


Review crypto-js dependency for size and security

File: examples/sites/package.json (line 60)

"crypto-js": "^4.2.0",

Your code only uses AES.encrypt, AES.decrypt and Utf8 decoding in:

  • examples/sites/src/views/comprehensive/index.vue
  • examples/sites/src/views/remoter/index.vue

crypto-js adds ~600 KB to the bundle. Consider:

  • Switching to the Web Crypto API (window.crypto.subtle) for native AES (zero bundle overhead)
  • Using a tree-shakable AES-only library (e.g. crypto-es or aes-js)

Also manually audit crypto-js (e.g. npm install --package-lock-only && npm audit) to confirm there are no known advisories.


30-35: 🛠️ Refactor suggestion

Switching to caret on pre-release packages may introduce breaking changes

"@opentiny/next-vue": "^0.0.1" and "@opentiny/tiny-vue-mcp": "^0.0.1" now float to any 0.x release, where SemVer treats every minor bump as breaking.
Pin exact versions or use a tilde (~) to avoid unexpected breakages during fresh installs.

-    "@opentiny/next-vue": "^0.0.1",
-    "@opentiny/tiny-vue-mcp": "^0.0.1",
+    "@opentiny/next-vue": "0.0.1",
+    "@opentiny/tiny-vue-mcp": "0.0.1",

Likely an incorrect or invalid review comment.

examples/sites/src/App.vue (1)

20-21: utils.ts re-exports are fine – ensure tree-shaking

The new { globalConversation, $session } import is side-effect-free.
No action required.

examples/sites/src/router.js (1)

10-12: Lazy imports LGTM

Dynamic imports keep initial bundle small.

examples/sites/src/components/tiny-robot-chat.vue (1)

5-5: Brand wording updated – ensure consistency across UI

The description now says “OpenTiny AI智能助手”. Search other files/components for the older “Opentiny” spelling to keep branding uniform.

examples/sites/src/views/remoter/sound.vue (1)

200-229: Desktop can’t start recording

handleStart is bound only to touchstart; on desktop there’s no way to trigger it. Add a mousedown/up fallback or a regular click handler so the feature works cross-platform.

Comment on lines +17 to +20
status: 'on' | 'off' // on: 上架, off: 下架
createdAt?: string
updatedAt?: string
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Make timestamp fields Date (or a branded type) instead of string

Keeping them as raw strings loses type safety and forces callers to remember to new Date() each time.

-  createdAt?: string
-  updatedAt?: string
+  createdAt?: Date
+  updatedAt?: Date

If the data really arrives as ISO text, convert once at the boundary (e.g., in the fetch layer).

📝 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
status: 'on' | 'off' // on: 上架, off: 下架
createdAt?: string
updatedAt?: string
}
status: 'on' | 'off' // on: 上架, off: 下架
createdAt?: Date
updatedAt?: Date
}
🤖 Prompt for AI Agents
In examples/sites/src/views/comprehensive/types/index.ts around lines 17 to 20,
the timestamp fields createdAt and updatedAt are typed as strings, which reduces
type safety and requires callers to manually convert them to Date objects.
Change the types of createdAt and updatedAt from string to Date (or a branded
Date type) to ensure proper type safety. If the data is received as ISO strings,
perform the conversion to Date once at the data boundary, such as in the fetch
or data parsing layer, so that the rest of the code works with Date objects
directly.

Comment on lines +3 to +20
function parse(str) {
if (str === null) return undefined
const type = str[0]
const strVal = str.slice(1)
// 对象时,有可能是Date, 否则反解析后统一是对象
if (type === 'o' || type === 'b') {
let val = JSON.parse(strVal)
return typeof val === 'string' ? new Date(val) : val
}
if (type === 'n') return +Number(strVal)
if (type === 's') return strVal
}

// 带前缀的保存值
function save(store, k, v) {
const type = typeof v
store.setItem(k, type[0] + (type === 'object' ? JSON.stringify(v) : v))
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Date vs. string ambiguity – persist an explicit Date flag

save() stores every object with prefix 'o', so Date becomes "o" + "\"2025-05-30T...Z\"".
parse() then assumes any parsed string came from a Date, creating false positives if an object property itself was a string.

Add a dedicated discriminator:

-function save(store, k, v) {
-  const type = typeof v
-  store.setItem(k, type[0] + (type === 'object' ? JSON.stringify(v) : v))
-}
+function save(store, k, v) {
+  if (v instanceof Date) return store.setItem(k, 'd' + v.toISOString())
+  const type = typeof v
+  store.setItem(k, type[0] + (type === 'object' ? JSON.stringify(v) : v))
+}
-  if (type === 'o' || type === 'b') {
+  if (type === 'd') return new Date(strVal)
+  if (type === 'o' || type === 'b') {

This removes the over-eager date cast.

📝 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
function parse(str) {
if (str === null) return undefined
const type = str[0]
const strVal = str.slice(1)
// 对象时,有可能是Date, 否则反解析后统一是对象
if (type === 'o' || type === 'b') {
let val = JSON.parse(strVal)
return typeof val === 'string' ? new Date(val) : val
}
if (type === 'n') return +Number(strVal)
if (type === 's') return strVal
}
// 带前缀的保存值
function save(store, k, v) {
const type = typeof v
store.setItem(k, type[0] + (type === 'object' ? JSON.stringify(v) : v))
}
function parse(str) {
if (str === null) return undefined
const type = str[0]
const strVal = str.slice(1)
if (type === 'd') return new Date(strVal)
if (type === 'o' || type === 'b') {
let val = JSON.parse(strVal)
return typeof val === 'string' ? new Date(val) : val
}
if (type === 'n') return +Number(strVal)
if (type === 's') return strVal
}
// 带前缀的保存值
function save(store, k, v) {
if (v instanceof Date) return store.setItem(k, 'd' + v.toISOString())
const type = typeof v
store.setItem(k, type[0] + (type === 'object' ? JSON.stringify(v) : v))
}
🤖 Prompt for AI Agents
In examples/sites/src/composable/storage.ts around lines 3 to 20, the save
function currently prefixes all objects with 'o', causing Date objects to be
stored indistinguishably from other objects and parse to incorrectly convert any
string to a Date. To fix this, modify save() to use a distinct prefix for Date
objects (e.g., 'd') and update parse() to check for this prefix and only convert
to Date when the prefix matches. This explicit discriminator prevents false date
conversions and preserves correct types.

Comment on lines +45 to +49
{
'title': '智能化',
'titleEn': 'mcp',
'key': 'mcp'
},
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Verify the existence of a matching “mcp” route before merging

A new menu entry is wired to key: 'mcp', but no corresponding route is added in router.js.
If the route/page is missing the click will 404. Please double-check that either:

  1. router.js defines a docs route like /mcp (or it is resolved via another dynamic rule), or
  2. this menu item should point at an existing key.

Run:


🏁 Script executed:

#!/bin/bash
# Search router for an explicit mcp route
rg -n $'/mcp'

Length of output: 119


🏁 Script executed:

#!/bin/bash
# Locate router file(s)
ROUTER_FILES=$(fd router.js -t f)
echo "Found router files:"
echo "$ROUTER_FILES"

# Search for 'mcp' in each router file
for file in $ROUTER_FILES; do
  echo "Searching in $file"
  rg -n "mcp" "$file" || echo "No matches in $file"
done

Length of output: 435


Add the missing mcp route in router.js or point the menu to an existing key

examples/sites/src/router.js currently has no entry for /mcp, so the new menu item in examples/sites/demos/pc/menus.js will 404 when clicked. Please choose one of the following fixes:

  • Add a route in examples/sites/src/router.js for mcp, e.g.:

     // at top of file
    + import McpDocs from '@/views/components-doc/common.vue'
     
     export const routes = [
       // … existing routes
    +  {
    +    path: '/mcp',
    +    name: 'mcp',
    +    component: McpDocs
    +  },
     ]
  • Or update the menu entry at examples/sites/demos/pc/menus.js to use an existing route key.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In examples/sites/demos/pc/menus.js around lines 45 to 49, the menu item with
key 'mcp' does not have a corresponding route defined in
examples/sites/src/router.js, which will cause a 404 error on click. To fix
this, either add a new route entry for 'mcp' in examples/sites/src/router.js
that points to the appropriate component or page, or update the menu item's key
in menus.js to match an existing route key already defined in router.js.

Comment on lines +36 to 37
proxyOptions: { url: 'https://agent.icjs.ink/sse', token: '', sessionId: $session.sessionId }
})
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Hard-coded SSE URL prevents staging / on-prem deployment

proxyOptions.url is fixed to https://agent.icjs.ink/sse. Externalising into an env var keeps dev/stage/prod flexible:

-      proxyOptions: { url: 'https://agent.icjs.ink/sse', token: '', sessionId: $session.sessionId }
+      proxyOptions: { url: import.meta.env.VITE_SSE_URL, token: '', sessionId: $session.sessionId }

Add VITE_SSE_URL to .env.*.

📝 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
proxyOptions: { url: 'https://agent.icjs.ink/sse', token: '', sessionId: $session.sessionId }
})
proxyOptions: { url: import.meta.env.VITE_SSE_URL, token: '', sessionId: $session.sessionId }
})
🤖 Prompt for AI Agents
In examples/sites/src/App.vue around lines 36 to 37, the SSE URL is hard-coded
as 'https://agent.icjs.ink/sse', which limits flexibility for different
environments. Replace this hard-coded URL with a reference to an environment
variable, such as import.meta.env.VITE_SSE_URL, and add VITE_SSE_URL to the
appropriate .env files for dev, staging, and production to allow configuration
per environment.

Comment on lines +72 to 74
const customPromptItems = props.promptItems || defaultPromptItems
const customSuggestionPillItems = props.suggestionPillItems || defaultSuggestionPillItems
</script>
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

customPromptItems / customSuggestionPillItems won’t update if parent prop changes

They are evaluated once at setup. Wrap them in computed to keep them in-sync:

-const customPromptItems = props.promptItems || defaultPromptItems
-const customSuggestionPillItems = props.suggestionPillItems || defaultSuggestionPillItems
+import { computed } from 'vue'
+
+const customPromptItems = computed(
+  () => props.promptItems ?? defaultPromptItems
+)
+const customSuggestionPillItems = computed(
+  () => props.suggestionPillItems ?? defaultSuggestionPillItems
+)
📝 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 customPromptItems = props.promptItems || defaultPromptItems
const customSuggestionPillItems = props.suggestionPillItems || defaultSuggestionPillItems
</script>
<script setup lang="ts">
import { computed } from 'vue'
import { defaultPromptItems, defaultSuggestionPillItems } from '@/path/to/defaults'
const props = defineProps<{
promptItems?: PromptItemType[]
suggestionPillItems?: SuggestionPillItemType[]
}>()
const customPromptItems = computed(
() => props.promptItems ?? defaultPromptItems
)
const customSuggestionPillItems = computed(
() => props.suggestionPillItems ?? defaultSuggestionPillItems
)
</script>
🤖 Prompt for AI Agents
In examples/sites/src/components/tiny-robot-chat.vue around lines 72 to 74, the
variables customPromptItems and customSuggestionPillItems are assigned once
during setup and do not react to changes in their corresponding props. To fix
this, wrap these assignments in Vue's computed properties so they automatically
update when the parent props promptItems or suggestionPillItems change.

Comment on lines +48 to 52
const props = defineProps<{
promptItems: any[]
suggestionPillItems: any[]
}>()

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Props declared as required but treated as optional

defineProps<{ promptItems: any[] suggestionPillItems: any[] }>() makes both props required in runtime validation, yet defaults are supplied when they are absent.

-const props = defineProps<{
-  promptItems: any[]
-  suggestionPillItems: any[]
-}>()
+const props = defineProps<{
+  promptItems?: any[]
+  suggestionPillItems?: any[]
+}>()
📝 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 props = defineProps<{
promptItems: any[]
suggestionPillItems: any[]
}>()
const props = defineProps<{
promptItems?: any[]
suggestionPillItems?: any[]
}>()
🤖 Prompt for AI Agents
In examples/sites/src/components/tiny-robot-chat.vue around lines 48 to 52, the
props promptItems and suggestionPillItems are declared as required by using
defineProps with a type that does not mark them optional, but default values are
provided elsewhere, implying they are optional. To fix this, update the
defineProps type to mark these props as optional by adding a question mark
(e.g., promptItems?: any[]) so that the runtime validation aligns with the
presence of default values.

Comment on lines +113 to +119
gridRef?.value?.insert({
'image': 'https://img1.baidu.com/it/u=1559062020,1043707656&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500',
price: 10000,
stock: 100,
category: 'phones',
status: 'on'
})
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Insert default name or prompt user before saving

The insert call adds a row without a name field. This will render as an empty cell and can break required-field validation later.
Add a sensible default (e.g. "新商品") or open an edit dialog right after insertion.

🤖 Prompt for AI Agents
In examples/sites/src/views/comprehensive/Demo.vue around lines 113 to 119, the
inserted row lacks a 'name' field, causing empty cells and potential validation
issues. Fix this by adding a default 'name' value like "新商品" to the inserted
object or trigger an edit dialog immediately after insertion to prompt the user
to enter a name.

Comment on lines +17 to +23
if (encryptedId) {
// 解密 id
const bytes = CryptoJS.AES.decrypt(encryptedId, secretKey)
const originalText = bytes.toString(CryptoJS.enc.Utf8)
// 存储解密后的 id 到 window.sessionId
globalConversation.sessionId = originalText
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Guard against invalid or tampered id

AES.decrypt can return empty text when the token is invalid but the code still sets sessionId to ''. Add a check and notify the user instead of silently accepting.

🤖 Prompt for AI Agents
In examples/sites/src/views/remoter/index.vue around lines 17 to 23, the code
decrypts an encryptedId and assigns the result to sessionId without verifying if
the decrypted text is valid. To fix this, add a check after decryption to ensure
the decrypted text is not empty or invalid; if it is, notify the user about the
invalid or tampered id instead of setting sessionId to an empty string.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant