feat: 更新产品相关表单,调整分红率和估值输入组件,优化用户体验

This commit is contained in:
2026-01-09 14:25:47 +07:00
parent 1be06c6f23
commit 978df12a6f
5 changed files with 38 additions and 104 deletions

View File

@@ -1,8 +1,6 @@
# SoybeanAdmin - AI 开发助手指南 ### 开发工作流
## 项目概述 - 如果我向你提一个新需求或一个 bug 修复请求,你有不懂的地方,先主动提问,直到你完全理解需求为止。
SoybeanAdmin 是一个基于 Vue3 + Vite7 + TypeScript 的清新优雅的中后台管理模板。这是一个 **pnpm monorepo** 架构的项目,包含多个子包。
### 核心技术栈 ### 核心技术栈
@@ -20,58 +18,10 @@ SoybeanAdmin 是一个基于 Vue3 + Vite7 + TypeScript 的清新优雅的中后
- **包管理器**: pnpm 10.5.0+ - **包管理器**: pnpm 10.5.0+
- **Node 版本**: 20.19.0+ - **Node 版本**: 20.19.0+
## 项目结构
### 主要目录说明
```
soybean-admin/
├── packages/ # Monorepo 子包目录
│ ├── alova/ # Alova 网络请求封装
│ ├── axios/ # Axios 网络请求封装
│ ├── color/ # 颜色工具包
│ ├── hooks/ # 通用 Hooks 集合
│ ├── materials/ # 组件物料库
│ ├── scripts/ # 脚本工具
│ ├── uno-preset/ # UnoCSS 预设
│ └── utils/ # 通用工具函数
├── src/ # 主应用源码
│ ├── assets/ # 静态资源
│ ├── components/ # 公共组件
│ ├── constants/ # 常量定义
│ ├── enum/ # 枚举定义
│ ├── hooks/ # 业务 Hooks
│ ├── layouts/ # 布局组件
│ ├── locales/ # 国际化配置
│ ├── plugins/ # 插件配置
│ ├── router/ # 路由配置
│ ├── service/ # API 服务层
│ ├── store/ # Pinia 状态管理
│ ├── styles/ # 全局样式
│ ├── theme/ # 主题配置
│ ├── typings/ # TypeScript 类型定义
│ ├── utils/ # 工具函数
│ └── views/ # 页面视图
├── build/ # 构建配置
└── public/ # 公共静态资源
```
### Monorepo 子包说明
- `@sa/axios`: Axios 封装,包含请求拦截、响应处理、错误处理等
- `@sa/alova`: Alova 封装,提供另一种网络请求方案
- `@sa/hooks`: 通用 React Hooks 风格的组合式函数
- `@sa/utils`: 通用工具函数库
- `@sa/color`: 颜色处理工具
- `@sa/materials`: UI 组件物料
- `@sa/scripts`: 命令行工具脚本
- `@sa/uno-preset`: UnoCSS 自定义预设
## 开发规范 ## 开发规范
### 代码风格 ### 代码风格
- 遵循 [SoybeanJS 规范](https://docs.soybeanjs.cn/zh/standard)
- 使用 ESLint (@soybeanjs/eslint-config) 进行代码检查 - 使用 ESLint (@soybeanjs/eslint-config) 进行代码检查
- 严格的 TypeScript 类型检查 - 严格的 TypeScript 类型检查
- 使用 Composition API 和 `<script setup>` 语法 - 使用 Composition API 和 `<script setup>` 语法
@@ -143,30 +93,6 @@ soybean-admin/
- 使用 `.d.ts` 文件进行类型声明 - 使用 `.d.ts` 文件进行类型声明
- API 类型定义在 `src/typings/api/` - API 类型定义在 `src/typings/api/`
## 常用命令
```bash
# 开发
pnpm dev # 测试环境开发
pnpm dev:prod # 生产环境模式开发
# 构建
pnpm build # 生产环境构建
pnpm build:test # 测试环境构建
# 代码质量
pnpm lint # ESLint 检查并修复
pnpm typecheck # TypeScript 类型检查
# 工具命令
pnpm gen-route # 生成路由
pnpm cleanup # 清理项目
pnpm commit # Git 提交 (英文)
pnpm commit:zh # Git 提交 (中文)
pnpm release # 发布版本
pnpm update-pkg # 更新依赖包
```
## 开发建议 ## 开发建议
### 创建新页面 ### 创建新页面
@@ -221,16 +147,6 @@ pnpm update-pkg # 更新依赖包
6. **移动端适配**: 注意响应式设计,支持移动端访问 6. **移动端适配**: 注意响应式设计,支持移动端访问
7. **Monorepo**: 修改 packages 下的包时注意影响范围 7. **Monorepo**: 修改 packages 下的包时注意影响范围
## 开发工作流
1. **启动项目**: `pnpm dev`
2. **创建分支**: 遵循 Git Flow 规范
3. **开发功能**: 遵循项目规范编码
4. **代码检查**: `pnpm lint``pnpm typecheck`
5. **提交代码**: `pnpm commit``pnpm commit:zh`
6. **测试验证**: 确保功能正常
7. **代码审查**: 提交 PR 前自查
## 外部资源 ## 外部资源
- [项目文档](https://github.com/soybeanjs/soybean-admin) - [项目文档](https://github.com/soybeanjs/soybean-admin)
@@ -256,5 +172,3 @@ pnpm update-pkg # 更新依赖包
10. 遵循响应式设计原则 10. 遵循响应式设计原则
--- ---
**最后更新**: 2025-12-24

View File

@@ -133,14 +133,17 @@ function handleCreateDraftAndSubmit() {
<NFormItem path="unitPrice" label="单价($)"> <NFormItem path="unitPrice" label="单价($)">
<NInputNumber :min="0" :value="Number(form.unitPrice)" @update:value="val => (form.unitPrice = String(val))" /> <NInputNumber :min="0" :value="Number(form.unitPrice)" @update:value="val => (form.unitPrice = String(val))" />
</NFormItem> </NFormItem>
<NFormItem path="dividendRate" label="分红率(0.01 = 1%)"> <NFormItem path="dividendRate" label="分红率(%)">
<NInputNumber <NInputNumber
:max="1" :max="100"
:min="0" :min="0"
:step="0.01" :step="0.1"
:value="Number(form.dividendRate)" :precision="2"
@update:value="val => (form.dividendRate = String(val))" :value="Number(form.dividendRate) * 100"
/> @update:value="val => (form.dividendRate = String((val || 0) / 100))"
>
<template #suffix>%</template>
</NInputNumber>
</NFormItem> </NFormItem>
<NFormItem path="launchDate" label="预热时间"> <NFormItem path="launchDate" label="预热时间">
<NDatePicker <NDatePicker

View File

@@ -111,16 +111,18 @@ function handleCreateDraftAndSubmit() {
<NInputNumber <NInputNumber
:min="1" :min="1"
:step="100" :step="100"
:precision="2"
:value="Number(form.estimatedValue)" :value="Number(form.estimatedValue)"
@update:value="val => (form.estimatedValue = String(val))" @update:value="val => (form.estimatedValue = String(val || 0))"
/> />
</NFormItem> </NFormItem>
<NFormItem path="totalSupplyLimit" label="总发行量"> <NFormItem path="totalSupplyLimit" label="总发行量">
<NInputNumber <NInputNumber
:min="1" :min="1"
:step="100" :step="100"
:precision="0"
:value="Number(form.totalSupplyLimit)" :value="Number(form.totalSupplyLimit)"
@update:value="val => (form.totalSupplyLimit = String(val))" @update:value="val => (form.totalSupplyLimit = String(val || 0))"
/> />
</NFormItem> </NFormItem>
<NFormItem path="description" label="产品描述"> <NFormItem path="description" label="产品描述">

View File

@@ -114,14 +114,17 @@ function handleSubmit() {
<NFormItem path="unitPrice" label="单价($)"> <NFormItem path="unitPrice" label="单价($)">
<NInputNumber :min="0" :value="Number(form.unitPrice)" @update:value="val => (form.unitPrice = String(val))" /> <NInputNumber :min="0" :value="Number(form.unitPrice)" @update:value="val => (form.unitPrice = String(val))" />
</NFormItem> </NFormItem>
<NFormItem path="dividendRate" label="分红率(0.01 = 1%)"> <NFormItem path="dividendRate" label="分红率(%)">
<NInputNumber <NInputNumber
:max="1" :max="100"
:min="0" :min="0"
:step="0.01" :step="0.1"
:value="Number(form.dividendRate)" :precision="2"
@update:value="val => (form.dividendRate = String(val))" :value="Number(form.dividendRate) * 100"
/> @update:value="val => (form.dividendRate = String((val || 0) / 100))"
>
<template #suffix>%</template>
</NInputNumber>
</NFormItem> </NFormItem>
<NFormItem path="launchDate" label="预热时间"> <NFormItem path="launchDate" label="预热时间">
<NDatePicker <NDatePicker

View File

@@ -102,10 +102,22 @@ function handleSubmit() {
/> />
</NFormItem> </NFormItem>
<NFormItem path="estimatedValue" label="产品估值"> <NFormItem path="estimatedValue" label="产品估值">
<NInput v-model:value="form.estimatedValue" /> <NInputNumber
:min="1"
:step="100"
:precision="2"
:value="Number(form.estimatedValue)"
@update:value="val => (form.estimatedValue = String(val || 0))"
/>
</NFormItem> </NFormItem>
<NFormItem path="totalSupplyLimit" label="总发行量"> <NFormItem path="totalSupplyLimit" label="总发行量">
<NInput v-model:value="form.totalSupplyLimit" /> <NInputNumber
:min="1"
:step="100"
:precision="0"
:value="Number(form.totalSupplyLimit)"
@update:value="val => (form.totalSupplyLimit = String(val || 0))"
/>
</NFormItem> </NFormItem>
<NFormItem path="description" label="产品描述"> <NFormItem path="description" label="产品描述">
<NInput v-model:value="form.description" type="textarea" /> <NInput v-model:value="form.description" type="textarea" />