From 941041ab29a9057cc90b1cdbb2a83a8ae3544546 Mon Sep 17 00:00:00 2001 From: "2090205686@qq.com" Date: Tue, 3 Jun 2025 17:35:22 +0800 Subject: [PATCH] =?UTF-8?q?=E5=95=86=E5=93=81=E4=B8=AD=E5=BF=83=E6=A8=A1?= =?UTF-8?q?=E5=9D=97=E5=BC=80=E5=8F=91=EF=BC=8C=E8=A1=A8=E6=A0=BC=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.development | 2 +- .gitignore | 1 + src/api/goods/info.js | 54 ++++ src/assets/styles/custom.scss | 68 +++- src/assets/styles/index.scss | 2 +- src/assets/styles/ruoyi.scss | 2 +- src/components/tableComponent.vue | 318 ++++++++++-------- src/router/index.js | 56 +++- src/views/customer/customerCategory.vue | 86 +++-- src/views/customer/customerManage.vue | 101 ++++-- src/views/goods/addGoods.vue | 145 +++++++++ src/views/goods/goodsCategory.vue | 394 ++++++++++++++++++++++ src/views/goods/goodsManage.vue | 412 ++++++++++++++++++++++++ 13 files changed, 1422 insertions(+), 219 deletions(-) create mode 100644 src/api/goods/info.js create mode 100644 src/views/goods/addGoods.vue create mode 100644 src/views/goods/goodsCategory.vue create mode 100644 src/views/goods/goodsManage.vue 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 @@
- +
- 第{{ internalPage }}页,共{{ - Math.ceil(internalTotal / internalPageSize) - }}页,共{{ internalTotal }}条 + 第{{ currentPage }}页,共{{ + Math.ceil(total / computedPageSize) + }}页,共{{ total }}条
- {{ internalPageSize }}条/页 + {{ computedPageSize }}条/页
@@ -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" > - + @@ -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" > - + @@ -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 @@ + + +