From dfa471bf228e4c717bd6240a50a3bb5187a64af4 Mon Sep 17 00:00:00 2001 From: liu <2302563948@qq.com> Date: Wed, 5 Aug 2026 14:10:20 +0800 Subject: [PATCH] =?UTF-8?q?=E5=95=86=E5=93=81=E8=A1=A8=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/Product/ProductController.php | 2 +- app/Models/ProductModel.php | 28 ++++++++++++++++--- ...2026_07_23_030609_create_product_table.php | 2 +- package.json | 3 +- .../XinFormField/FieldRender/index.tsx | 5 ++++ .../XinFormField/FieldRender/typings.ts | 3 ++ web/locales/en_US/components/xin-form.ts | 5 ++++ web/locales/zh_CN/components/xin-form.ts | 5 ++++ web/pages/product/goods.tsx | 15 +++++----- 9 files changed, 54 insertions(+), 14 deletions(-) diff --git a/app/Http/Controllers/Product/ProductController.php b/app/Http/Controllers/Product/ProductController.php index 512b05e..aa5d375 100644 --- a/app/Http/Controllers/Product/ProductController.php +++ b/app/Http/Controllers/Product/ProductController.php @@ -22,7 +22,7 @@ use Modules\AnnoRoute\Attribute\RequestAttribute; use Modules\Common\Http\Controllers\BaseController; /** - * 商品档案管理(A1 商品列表 / A2 价格矩阵与批量调价 / 多等级价格体系) + * 商品档案管理 */ #[RequestAttribute('/product/goods', 'product.goods')] class ProductController extends BaseController diff --git a/app/Models/ProductModel.php b/app/Models/ProductModel.php index d821c46..68fb721 100644 --- a/app/Models/ProductModel.php +++ b/app/Models/ProductModel.php @@ -2,11 +2,13 @@ namespace App\Models; +use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\SoftDeletes; +use Modules\SystemTool\Models\SysFileModel; /** * 商品档案模型(品名/规格包规/供应商/等级/多等级价格体系) @@ -16,9 +18,9 @@ class ProductModel extends Model use SoftDeletes, HasFactory; /** 状态:下架 */ - public const STATUS_OFF = 0; + public const int STATUS_OFF = 0; /** 状态:上架 */ - public const STATUS_ON = 1; + public const int STATUS_ON = 1; protected $table = 'product'; protected $primaryKey = 'id'; @@ -28,10 +30,12 @@ class ProductModel extends Model 'supplier_id', 'name', 'spec', - 'grade', 'unit', - 'image', + 'images', + 'content', 'sort', + 'shelf_life', + 'stock', 'status', 'remark', ]; @@ -39,10 +43,26 @@ class ProductModel extends Model protected $casts = [ 'category_id' => 'integer', 'supplier_id' => 'integer', + 'shelf_life' => 'integer', + 'stock' => 'integer', 'sort' => 'integer', 'status' => 'integer', ]; + public function images(): Attribute + { + return Attribute::make( + get: function($value){ + if (empty($value)) { + return collect(); + } + $ids = explode(',', $value); + return SysFileModel::whereIn('id', $ids)->get(); + }, + set: fn ($value) => is_array($value) ? implode(',', $value) : $value, + ); + } + /** * 所属分类 */ diff --git a/database/migrations/2026_07_23_030609_create_product_table.php b/database/migrations/2026_07_23_030609_create_product_table.php index 2ebecf1..b346b8c 100644 --- a/database/migrations/2026_07_23_030609_create_product_table.php +++ b/database/migrations/2026_07_23_030609_create_product_table.php @@ -36,7 +36,7 @@ return new class extends Migration $table->string('name', 100)->comment('品名'); $table->string('spec', 100)->default('')->comment('规格/包规'); $table->string('unit', 20)->default('斤')->comment('计价单位(斤/件/箱等)'); - $table->string('image', 255)->default('')->comment('商品图片'); + $table->string('images', 255)->default('')->comment('商品图片'); $table->text('content')->default('')->comment('商品图文详情'); $table->integer('sort')->default(0)->comment('排序'); $table->integer('shelf_life')->default(0)->comment('保质期'); diff --git a/package.json b/package.json index ad0ad81..5e5916c 100644 --- a/package.json +++ b/package.json @@ -14,13 +14,14 @@ "@ant-design/x": "^2.7.0", "@ant-design/x-markdown": "^2.7.0", "@ant-design/x-sdk": "^2.7.0", + "@wangeditor/editor": "^5.1.23", + "@wangeditor/editor-for-react": "^1.0.6", "antd": "^6.0.0", "antd-img-crop": "^4.27.0", "axios": "^1.15.2", "dayjs": "^1.11.18", "echarts-for-react": "^3.0.2", "i18next": "^25.4.2", - "ifanrx-react-ueditor": "^2.3.2", "lodash": "^4.17.21", "react": "^19.1.0", "react-dom": "^19.1.0", diff --git a/web/components/XinFormField/FieldRender/index.tsx b/web/components/XinFormField/FieldRender/index.tsx index f465914..8f055b2 100644 --- a/web/components/XinFormField/FieldRender/index.tsx +++ b/web/components/XinFormField/FieldRender/index.tsx @@ -32,9 +32,11 @@ import type { RangePickerProps } from "antd/es/date-picker"; import type { CheckboxGroupProps } from 'antd/es/checkbox'; import IconSelector from '@/components/XinFormField/IconSelector'; import ImageUploader from '@/components/XinFormField/ImageUploader'; +import RichTextEditor from '@/components/XinFormField/RichTextEditor'; import UserSelector from '@/components/XinFormField/UserSelector'; import type { IconSelectProps } from '@/components/XinFormField/IconSelector/typings'; import type { ImageUploaderProps } from '@/components/XinFormField/ImageUploader/typings'; +import type { RichTextEditorProps } from '@/components/XinFormField/RichTextEditor/typings'; import type { UserSelectorProps } from '@/components/XinFormField/UserSelector/typings'; import type {ReactNode} from "react"; @@ -121,6 +123,9 @@ export default function FieldRender(props: FieldsRenderProps) { case 'image': dom = ; break; + case 'richText': + dom = ; + break; case 'icon': dom = ; break; diff --git a/web/components/XinFormField/FieldRender/typings.ts b/web/components/XinFormField/FieldRender/typings.ts index 3c58e30..d2f2b0d 100644 --- a/web/components/XinFormField/FieldRender/typings.ts +++ b/web/components/XinFormField/FieldRender/typings.ts @@ -22,6 +22,7 @@ import type { CheckboxGroupProps } from 'antd/es/checkbox'; import {type Key, type ReactNode} from 'react'; import type { IconSelectProps } from '@/components/XinFormField/IconSelector/typings'; import type { ImageUploaderProps } from '@/components/XinFormField/ImageUploader/typings'; +import type { RichTextEditorProps } from '@/components/XinFormField/RichTextEditor/typings'; import type { UserSelectorProps } from '@/components/XinFormField/UserSelector/typings'; /** @@ -52,6 +53,7 @@ export type FieldValue = | 'quarter' // 季度选择 | 'year' // 年选择 | 'image' // 图片上传 + | 'richText' // 富文本编辑器 | 'color' // 颜色选择 | 'icon' // 图标选择 | 'user' // 用户选择 @@ -84,6 +86,7 @@ export interface FieldPropsMap { quarter: DatePickerProps; year: DatePickerProps; image: ImageUploaderProps; + richText: RichTextEditorProps; color: ColorPickerProps; icon: IconSelectProps; user: UserSelectorProps; diff --git a/web/locales/en_US/components/xin-form.ts b/web/locales/en_US/components/xin-form.ts index 2e4cebb..49eb5a4 100644 --- a/web/locales/en_US/components/xin-form.ts +++ b/web/locales/en_US/components/xin-form.ts @@ -30,4 +30,9 @@ export default { "xin.form.imageUploader.error.dimensionExceeded": "Image dimensions cannot exceed {{maxWidth}}x{{maxHeight}}px!", "xin.form.imageUploader.error.loadFailed": "Failed to load image!", "xin.form.imageUploader.error.readFailed": "Failed to read image!", + + // RichTextEditor Component + "xin.form.richText.error.notImage": "Only image files can be uploaded!", + "xin.form.richText.error.sizeExceeded": "Image size cannot exceed {{maxSize}}MB!", + "xin.form.richText.error.uploadFailed": "Image upload failed!", } \ No newline at end of file diff --git a/web/locales/zh_CN/components/xin-form.ts b/web/locales/zh_CN/components/xin-form.ts index 4422f43..93f5919 100644 --- a/web/locales/zh_CN/components/xin-form.ts +++ b/web/locales/zh_CN/components/xin-form.ts @@ -30,4 +30,9 @@ export default { "xin.form.imageUploader.error.dimensionExceeded": "图片尺寸不能超过 {{maxWidth}}x{{maxHeight}}px!", "xin.form.imageUploader.error.loadFailed": "图片加载失败!", "xin.form.imageUploader.error.readFailed": "图片读取失败!", + + // RichTextEditor 组件 + "xin.form.richText.error.notImage": "只能上传图片文件!", + "xin.form.richText.error.sizeExceeded": "图片大小不能超过 {{maxSize}}MB!", + "xin.form.richText.error.uploadFailed": "图片上传失败!", }; diff --git a/web/pages/product/goods.tsx b/web/pages/product/goods.tsx index 3af01d9..30fccb7 100644 --- a/web/pages/product/goods.tsx +++ b/web/pages/product/goods.tsx @@ -165,6 +165,10 @@ const ProductGoodsPage: React.FC = () => { title: '商品名称', dataIndex: 'name', valueType: 'text', + colProps: { span: 24 }, + fieldProps: { + styles: { input: { height: 52, fontSize: 22 } } + }, required: true, rules: [{ required: true, message: '请输入商品名称' }], }, @@ -174,12 +178,6 @@ const ProductGoodsPage: React.FC = () => { valueType: 'text', hideInSearch: true, }, - { - title: '等级', - dataIndex: 'grade', - valueType: 'text', - hideInSearch: true, - }, { title: '单位', dataIndex: 'unit', @@ -347,7 +345,10 @@ const ProductGoodsPage: React.FC = () => { rowProps: { gutter: 20 }, layout: 'vertical', }, - modalProps: { width: 800 }, + modalProps: { + width: 800, + styles: {container: {height: '80vh', overflowY: "auto" }} + }, }; return (