feat(trash): 商品删除→垃圾桶(软删可恢复)+ 左侧垃圾桶入口
后端(无需迁移,复用 Product.status active/archived):
- destroy 改软删(status→archived);正常列表/详情只看 active
- 新增 /products/trash(列已删)、/products/{id}/restore(恢复)、/{id}/purge(彻底删)
- tests.py:软删/列表隐藏/回收站/恢复/彻底删/拒绝彻底删 active —— 5 测试全过
前端:
- api:productsTrash / restoreProduct / purgeProduct
- 左侧导航加「垃圾桶」(新增 trash 图标);route-config 接 /trash 路由
- 新页 routes/trash.tsx + trash-page.css(仅 token):已删商品列表 + 恢复 + 彻底删(二次确认)
- 删除确认文案「不可撤销」→「移至垃圾桶可恢复」;toast「商品已删除」→「已移至垃圾桶」
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
b8fc1a0749
commit
3469799da5
@@ -40,6 +40,7 @@ import {
|
||||
import type { AuthMode, NavigateOptions, Notice, Page, ResolvedRoute } from "./routes/route-config";
|
||||
import { pathForPage, resolveRoute, routeLabels } from "./routes/route-config";
|
||||
import { AdminApp } from "./routes/admin/admin-app";
|
||||
import { TrashPage } from "./routes/trash";
|
||||
import { money } from "./routes/stage-config";
|
||||
|
||||
const crumbLabels: Partial<Record<Page, string>> = {
|
||||
@@ -651,7 +652,7 @@ export function App() {
|
||||
openProduct={(productId, tab) => navigate("productDetail", { productId, hash: tab === "videos" ? "videos" : undefined })}
|
||||
onCreate={(payload) => action(() => api.createProduct(payload), "")}
|
||||
onUploadImage={(productId, formData) => action(() => api.uploadProductImage(productId, formData), "")}
|
||||
onDelete={(productId) => action(() => api.deleteProduct(productId), "商品已删除")}
|
||||
onDelete={(productId) => action(() => api.deleteProduct(productId), "已移至垃圾桶")}
|
||||
/>
|
||||
);
|
||||
case "productCreateUpload":
|
||||
@@ -666,12 +667,12 @@ export function App() {
|
||||
openProduct={(productId, tab) => navigate("productDetail", { productId, hash: tab === "videos" ? "videos" : undefined })}
|
||||
onCreate={(payload) => action(() => api.createProduct(payload), "")}
|
||||
onUploadImage={(productId, formData) => action(() => api.uploadProductImage(productId, formData), "")}
|
||||
onDelete={(productId) => action(() => api.deleteProduct(productId), "商品已删除")}
|
||||
onDelete={(productId) => action(() => api.deleteProduct(productId), "已移至垃圾桶")}
|
||||
autoOpenCreate
|
||||
/>
|
||||
);
|
||||
case "productDetail":
|
||||
if (!activeProduct) return <ProductsPage products={products} loading={!dataLoaded} navigate={navigate} openProduct={(productId, tab) => navigate("productDetail", { productId, hash: tab === "videos" ? "videos" : undefined })} onCreate={(payload) => action(() => api.createProduct(payload), "")} onDelete={(productId) => action(() => api.deleteProduct(productId), "商品已删除")} />;
|
||||
if (!activeProduct) return <ProductsPage products={products} loading={!dataLoaded} navigate={navigate} openProduct={(productId, tab) => navigate("productDetail", { productId, hash: tab === "videos" ? "videos" : undefined })} onCreate={(payload) => action(() => api.createProduct(payload), "")} onDelete={(productId) => action(() => api.deleteProduct(productId), "已移至垃圾桶")} />;
|
||||
return (
|
||||
<ProductDetailPage
|
||||
product={activeProduct}
|
||||
@@ -744,6 +745,14 @@ export function App() {
|
||||
);
|
||||
case "library":
|
||||
return <LibraryPage onUpload={(formData) => action(() => api.uploadAsset(formData), "资产已上传")} onDelete={(id) => action(() => api.deleteAsset(id), "资产已删除")} />;
|
||||
case "trash":
|
||||
return (
|
||||
<TrashPage
|
||||
navigate={navigate}
|
||||
onRestore={(id) => action(() => api.restoreProduct(id), "已恢复到商品库")}
|
||||
onPurge={(id) => action(() => api.purgeProduct(id), "已彻底删除")}
|
||||
/>
|
||||
);
|
||||
case "account":
|
||||
return (
|
||||
<AccountPage
|
||||
|
||||
Reference in New Issue
Block a user