diff --git a/.env.development b/.env.development
index a1c6593..6f56968 100644
--- a/.env.development
+++ b/.env.development
@@ -5,5 +5,5 @@ VITE_APP_TITLE = 运营云后台管理系统
VITE_APP_ENV = 'development'
# 开发环境
-VITE_APP_BASE_API = 'http://192.168.18.9:8080/'
+VITE_APP_BASE_API = 'http://192.168.18.99:8080/'
VITE_APP_PLATFORM = 'http://localhost:9000/platform'
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 9c34e07..4faf397 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,3 +24,4 @@ selenium-debug.log
package-lock.json
yarn.lock
+public/临时记录.txt
diff --git a/src/api/goods/info.js b/src/api/goods/info.js
new file mode 100644
index 0000000..46c79d7
--- /dev/null
+++ b/src/api/goods/info.js
@@ -0,0 +1,54 @@
+import request from '@/utils/request'
+
+// 获取商品管理列表
+export function getGoodManageInfo(query) {
+ return request({
+ url: '/goodInfoManage/getGoodManage',
+ method: 'get',
+ params: query
+ })
+}
+
+
+
+
+
+
+
+
+
+
+
+// 查询岗位详细
+export function getPost(postId) {
+ return request({
+ url: '/system/post/' + postId,
+ method: 'get'
+ })
+}
+
+// 新增岗位
+export function addPost(data) {
+ return request({
+ url: '/system/post',
+ method: 'post',
+ data: data
+ })
+}
+
+// 修改岗位
+export function updatePost(data) {
+ return request({
+ url: '/system/post',
+ method: 'put',
+ data: data
+ })
+}
+
+// 删除岗位
+export function delPost(postId) {
+ return request({
+ url: '/system/post/' + postId,
+ method: 'delete'
+ })
+}
diff --git a/src/assets/styles/custom.scss b/src/assets/styles/custom.scss
index 11e890a..14e520d 100644
--- a/src/assets/styles/custom.scss
+++ b/src/assets/styles/custom.scss
@@ -9,6 +9,29 @@
padding: 16px 8px 0 16px;
border-radius: 16px;
background: #fff;
+ .order-tab {
+ width: 100%;
+ .el-tabs__nav-wrap::after {
+ background: transparent !important;
+ }
+ .el-tabs__active-bar {
+ height: 3px !important;
+ border-radius: 4px;
+ }
+ .el-descriptions__label,
+ .el-descriptions__content {
+ font-size: 16px !important;
+ }
+ .cell-item {
+ display: inline-flex;
+ }
+ .el-descriptions__label {
+ color: #999;
+ }
+ .el-descriptions__content {
+ color: #333;
+ }
+ }
}
.search-bar {
display: flex;
@@ -21,7 +44,8 @@
.search-bar-right {
width: 100px;
- text-align: center;
+ text-align: right;
+ padding-right: 8px;
}
.demo-form-inline {
@@ -53,9 +77,8 @@
overflow: hidden;
background-color: #fff;
position: relative;
- .el-icon-custom {
- vertical-align: middle;
- cursor: pointer;
+ .el-table__empty-text {
+ width: 200px;
}
}
@@ -164,9 +187,42 @@
.color-red {
color: red;
}
+ }
+ .el-button {
+ font-size: 12px !important;
+ font-weight: 400;
}
}
+// 页面添加的自定义容器,上下撑满
.customer-control {
- position: absolute;
- height: 100%;
+ position: absolute;
+ height: 100%;
+ left: 0;
+ right: 0;
+}
+// 表格组件中的各插槽元素自定义样式
+.custom-tooltip-content {
+ display: flex;
+ justify-content: space-between;
+ gap: 10px;
+ padding: 3px 0;
+}
+.el-icon-custom {
+ vertical-align: middle;
+ cursor: pointer;
+ font-size: 16px;
+ color: #fff;
+}
+.table-cell-img-box {
+ width: 60px;
+ height: 60px;
+ overflow: hidden; /* 隐藏超出部分 */
+ display: flex; /* 使用 Flex 布局居中 */
+ justify-content: center;
+ align-items: center;
+ .table-cell-img {
+ min-width: 100%; /* 至少撑满宽度 */
+ min-height: 100%; /* 至少撑满高度 */
+ object-fit: cover; /* 保持比例并覆盖容器 */
+ }
}
diff --git a/src/assets/styles/index.scss b/src/assets/styles/index.scss
index 9446cf6..bddd6ac 100644
--- a/src/assets/styles/index.scss
+++ b/src/assets/styles/index.scss
@@ -84,7 +84,7 @@ div:focus {
}
.inlineBlock {
- display: block;
+ display: inline-block;
}
.clearfix {
diff --git a/src/assets/styles/ruoyi.scss b/src/assets/styles/ruoyi.scss
index b3240c3..0ba8955 100644
--- a/src/assets/styles/ruoyi.scss
+++ b/src/assets/styles/ruoyi.scss
@@ -61,7 +61,7 @@
}
.el-form .el-form-item__label {
- font-weight: 700;
+ font-weight: 400;
}
.el-dialog:not(.is-fullscreen) {
margin-top: 6vh !important;
diff --git a/src/components/tableComponent.vue b/src/components/tableComponent.vue
index b34b22f..7c065f4 100644
--- a/src/components/tableComponent.vue
+++ b/src/components/tableComponent.vue
@@ -2,9 +2,9 @@
@@ -87,6 +95,10 @@
import { ref, watch, computed, onMounted, onBeforeUnmount } from "vue";
const props = defineProps({
+ loading: {
+ type: Boolean,
+ default: false,
+ },
// 表格数据
tableData: {
type: Array,
@@ -97,6 +109,21 @@ const props = defineProps({
type: Array,
default: () => [],
},
+ // 当前页码(由外部传入)
+ currentPage: {
+ type: Number,
+ default: 1,
+ },
+ // 每页数量(由外部传入)
+ pageSize: {
+ type: Number,
+ default: 10,
+ },
+ // 总条数
+ total: {
+ type: Number,
+ default: 0,
+ },
// 是否显示分页
showPagination: {
type: Boolean,
@@ -149,56 +176,57 @@ const props = defineProps({
},
});
-const emit = defineEmits(["page-change", "selection-change"]);
+const emit = defineEmits([
+ "update:currentPage",
+ "update:pageSize",
+ "page-change",
+ "selection-change",
+]);
-// 内部管理的分页状态
-const internalPage = ref(1);
-const internalPageSize = ref(props.pageSizes?.[0] || 10);
-const internalTotal = ref(0);
-
-// 计算当前页显示的数据
-const pagedTableData = computed(() => {
- const start = (internalPage.value - 1) * internalPageSize.value;
- const end = start + internalPageSize.value;
- return props.tableData.slice(start, end);
+// 每页数量(双向绑定)
+const computedPageSize = computed({
+ get: () => props.pageSize,
+ set: (val) => emit('update:pageSize', val)
+});
+// 当前页码(双向绑定)
+const computedCurrentPage = computed({
+ get: () => props.currentPage,
+ set: (val) => emit('update:currentPage', val)
});
-// 计算总页数(可根据实际需求调整)
-watch(
- () => props.tableData,
- (newData) => {
- internalTotal.value = newData.length; // 示例:假设总数据量是当前显示的3倍
- },
- { immediate: true }
-);
+// 监听外部传入的pageSize变化
+// watch(
+// () => props.pageSize,
+// (newVal) => {
+// internalPageSize.value = newVal;
+// }
+// );
// 分页大小改变
const pageSizeChange = (val) => {
console.log(`每页 ${val} 条`);
internalPageSize.value = val;
- internalPage.value = 1; // 重置为第一页
- console.log(internalPage.value, internalPageSize.value);
- emitPageChange();
+ console.log(props.currentPage, internalPageSize.value);
+ emit("update:pageSize", val);
+ emit("page-change", {
+ page: props.currentPage,
+ pageSize: val,
+ });
};
// 当前页改变
const handleCurrentChange = (val) => {
console.log(`当前页改变 ${val} 页`);
- internalPage.value = val;
- emitPageChange();
-};
-
-// 触发分页变化事件
-const emitPageChange = () => {
emit("page-change", {
- page: internalPage.value,
+ page: val,
pageSize: internalPageSize.value,
});
};
// 多选框变化
const handleSelectionChange = (selection) => {
- emit("selection-change", selection);
+ const selectedIds = selection.map((row) => row.id);
+ emit("selection-change", selection, selectedIds);
};
const tableRef = ref(null);
@@ -241,117 +269,123 @@ onBeforeUnmount(() => {
flex-direction: column;
height: 100%; /* 关键:继承父容器高度 */
overflow: hidden; /* 防止内容溢出 */
-}
-/* 表格弹性布局 */
-:deep(.el-table) {
- flex: 1;
- display: flex;
- flex-direction: column;
- /* 表头固定 */
- .el-table__header-wrapper {
- flex-shrink: 0;
- }
-
- /* 表体可滚动 */
- .el-table__body-wrapper {
+ /* 表格弹性布局 */
+ :deep(.el-table) {
flex: 1;
- overflow: auto;
- }
-}
+ display: flex;
+ flex-direction: column;
-.demo-form-inline {
- text-align: left;
- padding-left: 20px;
-}
+ /* 表头固定 */
+ .el-table__header-wrapper {
+ flex-shrink: 0;
+ }
-.pagination-container {
- margin-top: 10px;
- padding: 0 20px;
- display: flex;
- justify-content: space-between;
- color: #999;
- font-weight: 400;
-}
-.custom-pagination-text {
- flex: 1;
- text-align: left;
- line-height: 32px;
- font-size: 14px;
-}
-
-.custom-pagination-size {
- text-align: right;
- line-height: 32px;
- margin-left: 20px;
- font-size: 14px;
-}
-
-/* 去除表格边框 */
-:deep(.el-table) {
- --el-table-border-color: transparent;
-}
-
-/* 自定义鼠标悬停颜色 */
-:deep(.el-table__body tr:hover > td) {
- background-color: rgba(37, 191, 130, 0.1) !important;
-}
-
-/* 自定义表头样式 */
-:deep(.custom-header) {
- background-color: #fff !important;
- color: #999;
- font-weight: 400;
-}
-
-:deep(.el-pagination) {
- /* 整体分页样式 */
- font-size: 14px;
- font-weight: normal;
-
- /* 页码按钮容器 */
- .el-pager {
- /* 所有页码项 */
- li {
- font-weight: 400; /* 普通页码字体不加粗 */
- color: #606266; /* 普通页码颜色 */
- background: transparent;
- font-size: 14px;
-
- /* 当前选中页码 */
- &.active,
- &.is-active {
- font-weight: 400 !important; /* 当前页不加粗 */
- color: #25bf82 !important; /* 自定义当前页颜色 - 橙色示例 */
- }
-
- /* 悬停状态 */
- &:hover {
- color: #409eff;
- }
+ /* 表体可滚动 */
+ .el-table__body-wrapper {
+ flex: 1;
+ overflow: auto;
}
}
- /* 上一页/下一页按钮 */
- .btn-prev,
- .btn-next {
+ .demo-form-inline {
+ text-align: left;
+ padding-left: 20px;
+ padding-top: 4px;
+ }
+
+ .pagination-container {
+ margin-top: 10px;
+ padding: 0 30px 0 20px;
+ display: flex;
+ justify-content: space-between;
+ color: #999;
font-weight: 400;
-
- &:disabled {
- color: #c0c4cc;
- }
+ }
+ .custom-pagination-text {
+ flex: 1;
+ text-align: left;
+ line-height: 32px;
+ font-size: 14px;
}
- /* 每页条数选择器 */
- .el-pagination__sizes {
- .el-input__inner {
+ .custom-pagination-size {
+ text-align: right;
+ line-height: 32px;
+ margin-left: 20px;
+ font-size: 14px;
+ }
+
+ /* 去除表格边框 */
+ :deep(.el-table) {
+ --el-table-border-color: transparent;
+ }
+
+ /* 自定义鼠标悬停颜色 */
+ :deep(.el-table__body tr:hover > td) {
+ background-color: rgba(37, 191, 130, 0.1) !important;
+ }
+
+ /* 自定义表头样式 */
+ :deep(.custom-header) {
+ background-color: #fff !important;
+ color: #999;
+ font-weight: 400;
+ }
+
+ :deep(.el-pagination) {
+ /* 整体分页样式 */
+ font-size: 14px;
+ font-weight: normal;
+
+ /* 页码按钮容器 */
+ .el-pager {
+ /* 所有页码项 */
+ li {
+ font-weight: 400; /* 普通页码字体不加粗 */
+ color: #606266; /* 普通页码颜色 */
+ background: transparent;
+ font-size: 14px;
+
+ /* 当前选中页码 */
+ &.active,
+ &.is-active {
+ font-weight: 400 !important; /* 当前页不加粗 */
+ color: #25bf82 !important; /* 自定义当前页颜色 - 橙色示例 */
+ }
+
+ /* 悬停状态 */
+ &:hover {
+ color: #409eff;
+ }
+ }
+ }
+
+ /* 上一页/下一页按钮 */
+ .btn-prev,
+ .btn-next {
font-weight: 400;
- }
- }
- /* 跳页输入框 */
- .el-pagination__jump {
- font-weight: 400;
+ &:disabled {
+ color: #c0c4cc;
+ }
+ }
+
+ /* 每页条数选择器 */
+ .el-pagination__sizes {
+ .el-input__inner {
+ font-weight: 400;
+ }
+ }
+
+ /* 跳页输入框 */
+ .el-pagination__jump {
+ font-weight: 400;
+ position: absolute;
+ right: 16px;
+ bottom: 12px;
+ color: #999;
+ }
}
}
diff --git a/src/router/index.js b/src/router/index.js
index 166acbd..a06b99f 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -71,11 +71,25 @@ export const constantRoutes = [
path: '/index',
component: () => import('@/views/index'),
name: 'Index',
- meta: { title: '首页', icon: 'dashboard', affix: true }
+ meta: { title: '首页', icon: 'chart', affix: true }
}
]
},
{
+ path: '/goods',
+ component: Layout,
+ hidden: true,
+ redirect: 'noredirect',
+ children: [
+ {
+ path: 'addGoods/:activeTab?',
+ component: () => import('@/views/goods/addGoods'),
+ name: 'addGoods',
+ meta: { title: '新增商品', icon: '' }
+ }
+ ]
+ },
+ {
path: '/user',
component: Layout,
hidden: true,
@@ -129,6 +143,46 @@ export const constantRoutes = [
}
],
},
+ {
+ path: '/goods',
+ name: "goods",
+ component: Layout,
+ hidden: false,
+ alwaysShow: true,
+ redirect: 'noredirect',
+ meta: {
+ icon: "example",
+ link: null,
+ noCache: false,
+ title: "商品中心",
+ },
+ children: [
+ {
+ path: 'goods/goodsManage',
+ component: () => import('@/views/goods/goodsManage'),
+ name: 'goodsManage',
+ hidden: false,
+ meta: {
+ title: "商品信息管理",
+ icon: "",
+ noCache: false,
+ link: null,
+ },
+ },
+ {
+ path: 'goods/goodsCategory',
+ component: () => import('@/views/goods/goodsCategory'),
+ name: 'goodsCategory',
+ hidden: false,
+ meta: {
+ title: "商品分类设置",
+ icon: "",
+ noCache: false,
+ link: null,
+ },
+ }
+ ],
+ },
{
path: '/plant',
name: "plant",
diff --git a/src/views/customer/customerCategory.vue b/src/views/customer/customerCategory.vue
index 15bad66..959f8f6 100644
--- a/src/views/customer/customerCategory.vue
+++ b/src/views/customer/customerCategory.vue
@@ -27,8 +27,7 @@
/>
-
-
+
@@ -87,6 +86,7 @@
:header-cell-class-name="getHeaderClass"
@page-change="handlePaginationChange"
@selection-change="handleSelectionChange"
+ :total="tableTotal" :current-page="formInline.current" :page-size="formInline.size"
>
@@ -98,26 +98,36 @@
>
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
- Action 1
- Action 2
- Action 3
-
-
-
+
@@ -137,13 +147,15 @@ const formInline = reactive({
userCategoryName: "",
accountNumber: "",
phoneNumber: "",
- sex: "99",
- userStatus: "99",
- userCategory: "99",
+ sex: "",
+ userStatus: "",
+ userCategory: "",
unitPrice: "",
ordersNums: "",
startDate: "",
endDate: "",
+ current: 1,
+ size: 10,
});
// 禁用开始日期的逻辑(不能晚于已选的结束日期)
@@ -174,20 +186,22 @@ const resetForm = () => {
// 表格数据
const tableData = ref([]);
+const tableLoading = ref(false);
+const tableTotal = ref(0);
+let nowClickRow = ref({});
// 列配置
-const columns = ref([]);
-const columns1 = ref([
+const columns = ref([
{ prop: "id", label: "ID" },
{ prop: "nickname", label: "昵称", width: "120" },
{ prop: "userName", label: "姓名" },
- { prop: "accountNumber", label: "账号" },
+ { prop: "accountNumber", label: "账号", width: "120" },
{ prop: "phoneNumber", label: "手机号", width: "120" },
{ prop: "sex", label: "性别" },
{ prop: "userStatus", label: "用户状态", slotName: "userStatus" },
{ prop: "userCategory", label: "用户分类" },
{ prop: "unitPrice", label: "客单价" },
{ prop: "ordersNums", label: "订单数目" },
- { prop: "action", label: "操作", slotName: "action", width: "180" },
+ { prop: "action", label: "操作", slotName: "action" },
]);
// 生成食物主题昵称
@@ -230,7 +244,7 @@ const generateFoodNickname = () => {
// 生成模拟数据
const generateMockData = () => {
return Mock.mock({
- "list|30": [
+ "list|10": [
{
"id|+1": 10000,
nickname: () => generateFoodNickname(), //昵称
@@ -252,6 +266,7 @@ const loadData = () => {
// 模拟API请求延迟
setTimeout(() => {
tableData.value = generateMockData();
+ tableTotal.value = tableData.value.length;
}, 500);
};
// 自定义表头类名,也可以在columns指定列中添加headerClassName: 'custom-header'
@@ -269,12 +284,20 @@ const handleSelectionChange = (selection) => {
console.log("选中项:", selection);
};
-let nowClickRow = ref({});
-// 编辑操作
-const handleEdit = (row, num) => {
+// 查看详情
+const seeDetails = (row) => {
nowClickRow.value = row;
- console.log("编辑的行:", row);
- console.log("第几个按钮:", num);
+ console.log("要查看详情的行:", row);
+};
+// 编辑操作
+const handleEdit = (row) => {
+ nowClickRow.value = row;
+ console.log("要编辑的行:", row);
+};
+// 删除操作
+const handleDelete = (row) => {
+ nowClickRow.value = row;
+ console.log("要删除的行:", row);
};
const titleRef = ref(null);
@@ -299,7 +322,6 @@ const calculateTableHeight = () => {
};
// 组件挂载时加载数据
onMounted(() => {
- columns.value = columns1.value;
loadData();
calculateTableHeight();
diff --git a/src/views/customer/customerManage.vue b/src/views/customer/customerManage.vue
index 027f864..4b0e3db 100644
--- a/src/views/customer/customerManage.vue
+++ b/src/views/customer/customerManage.vue
@@ -48,15 +48,21 @@
/>
-
-
+
-
-
+
@@ -65,8 +71,8 @@
-
@@ -148,6 +154,7 @@
:header-cell-class-name="getHeaderClass"
@page-change="handlePaginationChange"
@selection-change="handleSelectionChange"
+ :total="tableTotal" :current-page="formInline.current" :page-size="formInline.size"
>
@@ -159,26 +166,36 @@
>
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
- Action 1
- Action 2
- Action 3
-
-
-
+
@@ -189,7 +206,8 @@
import { ref, reactive, computed, onMounted, onBeforeUnmount } from "vue";
import tableComponent from "@/components/tableComponent.vue";
import Mock from "mockjs";
-import { id } from "element-plus/es/locales.mjs";
+
+const iconSize = "16px";
const formInline = reactive({
id: "",
@@ -197,13 +215,15 @@ const formInline = reactive({
userName: "",
accountNumber: "",
phoneNumber: "",
- sex: "99",
- userStatus: "99",
- userCategory: "99",
+ sex: "",
+ userStatus: "",
+ userCategory: "",
unitPrice: "",
ordersNums: "",
startDate: "",
endDate: "",
+ current: 1,
+ size: 10,
});
// 禁用开始日期的逻辑(不能晚于已选的结束日期)
@@ -234,9 +254,11 @@ const resetForm = () => {
// 表格数据
const tableData = ref([]);
+const tableLoading = ref(false);
+const tableTotal = ref(0);
+let nowClickRow = ref({});
// 列配置
-const columns = ref([]);
-const columns1 = ref([
+const columns = ref([
{ prop: "id", label: "ID" },
{ prop: "nickname", label: "昵称", width: "120" },
{ prop: "userName", label: "姓名" },
@@ -247,7 +269,7 @@ const columns1 = ref([
{ prop: "userCategory", label: "用户分类" },
{ prop: "unitPrice", label: "客单价" },
{ prop: "ordersNums", label: "订单数目" },
- { prop: "action", label: "操作", slotName: "action", width: "180" },
+ { prop: "action", label: "操作", slotName: "action" },
]);
// 生成食物主题昵称
@@ -290,7 +312,7 @@ const generateFoodNickname = () => {
// 生成模拟数据
const generateMockData = () => {
return Mock.mock({
- "list|30": [
+ "list|10": [
{
"id|+1": 10000,
nickname: () => generateFoodNickname(), //昵称
@@ -312,6 +334,7 @@ const loadData = () => {
// 模拟API请求延迟
setTimeout(() => {
tableData.value = generateMockData();
+ tableTotal.value = tableData.value.length;
}, 500);
};
// 自定义表头类名,也可以在columns指定列中添加headerClassName: 'custom-header'
@@ -329,13 +352,22 @@ const handleSelectionChange = (selection) => {
console.log("选中项:", selection);
};
-let nowClickRow = ref({});
-// 编辑操作
-const handleEdit = (row, num) => {
+// 查看详情
+const seeDetails = (row) => {
nowClickRow.value = row;
- console.log("编辑的行:", row);
- console.log("第几个按钮:", num);
+ console.log("要查看详情的行:", row);
};
+// 编辑操作
+const handleEdit = (row) => {
+ nowClickRow.value = row;
+ console.log("要编辑的行:", row);
+};
+// 删除操作
+const handleDelete = (row) => {
+ nowClickRow.value = row;
+ console.log("要编辑的行:", row);
+};
+
const titleRef = ref(null);
const searchBarRef = ref(null);
@@ -359,7 +391,6 @@ const calculateTableHeight = () => {
};
// 组件挂载时加载数据
onMounted(() => {
- columns.value = columns1.value;
loadData();
calculateTableHeight();
diff --git a/src/views/goods/addGoods.vue b/src/views/goods/addGoods.vue
new file mode 100644
index 0000000..3c0f3cd
--- /dev/null
+++ b/src/views/goods/addGoods.vue
@@ -0,0 +1,145 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/goods/goodsCategory.vue b/src/views/goods/goodsCategory.vue
new file mode 100644
index 0000000..b690015
--- /dev/null
+++ b/src/views/goods/goodsCategory.vue
@@ -0,0 +1,394 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+ 查询
+ 重置
+
+
+
+
+
+
+ 批量删除
+
+ 添加分类
+
+
+
+
+
+
+
![]()
+
+
+
+
+
+ 已启用
+ 未启用
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/goods/goodsManage.vue b/src/views/goods/goodsManage.vue
new file mode 100644
index 0000000..d3e3303
--- /dev/null
+++ b/src/views/goods/goodsManage.vue
@@ -0,0 +1,412 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 查询
+ 重置
+
+
+
+
+
+
+ 批量删除
+
+ 新增商品
+
+
+
+
+
+
+
![]()
+
+
+
+
+
+ 上架
+ 下架
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+