From fca272f8fad38ea9467462e4215811721616ee11 Mon Sep 17 00:00:00 2001 From: 2256907009 <2256907009@qq.com> Date: Thu, 23 Oct 2025 14:10:18 +0800 Subject: [PATCH 01/10] fix:xiug --- src/views/acs/nodes/VmDetail.vue | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/views/acs/nodes/VmDetail.vue b/src/views/acs/nodes/VmDetail.vue index cdd7998..12d47a1 100644 --- a/src/views/acs/nodes/VmDetail.vue +++ b/src/views/acs/nodes/VmDetail.vue @@ -15,6 +15,7 @@
返回 刷新数据 + 清除缓存
@@ -99,7 +100,7 @@
链接端口号
-
{{ vmInfo.link_port || '10006' }}
+
{{ vmInfo.node_port || (portsList.length > 0 ? portsList[0].node_port : '10006') }}
虚拟机用户名
@@ -825,7 +826,7 @@ const setCachedData = (instanceId, data) => { console.log(`缓存虚拟机数据: ${instanceId}`, cacheData); }; -const isCacheValid = (cachedData, maxAge = 5 * 60 * 1000) => { // 默认5分钟有效期 +const isCacheValid = (cachedData, maxAge = 10 * 60 * 1000) => { // 默认10分钟有效期 if (!cachedData || !cachedData.timestamp) return false; return (Date.now() - cachedData.timestamp) < maxAge; }; @@ -1379,12 +1380,17 @@ const fetchVmInfo = async (instanceId = null, useCache = true) => { const serverRes = await selectServer({server_id:res.data.data.server_id}) const planRes = await selectServerPlan({plan_id:res.data.data.plan_id,server_type:"hyperV"}) const imageRes= await Mirrorinfo({image_id:res.data.data.image_id,server_type:"hyperV"}) + + // 如果端口列表已加载,获取第一个端口号 + const firstPort = portsList.value.length > 0 ? portsList.value[0].node_port : null; + const data = { ...res.data.data, server_name:serverRes.data.data.name, server_ip:serverRes.data.data.server_ip, plan_name:planRes.data.data.name, - image_name:imageRes.data.data.name + image_name:imageRes.data.data.name, + node_port: res.data.data.node_port || firstPort // 优先使用API返回的,否则用端口列表的第一个 } if (res && res.data && res.data.code === 200) { vmInfo.value = data || {}; @@ -1554,6 +1560,13 @@ const refreshData = () => { loadAllData(instanceId, false); }; +// 清除所有缓存 +const clearAllCache = () => { + console.log('清除所有虚拟机缓存'); + dataCache.value.clear(); + ElMessage.success('已清除所有缓存'); +}; + // 启动虚拟机 const handleStart = async () => { try { From 11cb40c86af0a651724ef7a1c2dcc2f042914627 Mon Sep 17 00:00:00 2001 From: 2256907009 <2256907009@qq.com> Date: Fri, 24 Oct 2025 17:34:52 +0800 Subject: [PATCH 02/10] =?UTF-8?q?fix:=E4=BF=AE=E6=94=B9=E5=AE=9E=E4=BE=8B?= =?UTF-8?q?=E8=A7=84=E6=A0=BC=E5=8F=82=E6=95=B0=E5=92=8C=E9=95=9C=E5=83=8F?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/acs/images/VmImages.vue | 9 +++-- src/views/acs/nodes/server.vue | 57 ++++++++++++++++++++++++++++++- 2 files changed, 63 insertions(+), 3 deletions(-) diff --git a/src/views/acs/images/VmImages.vue b/src/views/acs/images/VmImages.vue index 9742c1b..13939d7 100644 --- a/src/views/acs/images/VmImages.vue +++ b/src/views/acs/images/VmImages.vue @@ -195,6 +195,9 @@ + + + { // 编辑镜像 const handleEdit = async (row) => { + console.log("编辑镜像信息:",row) try { let res = await getServerPlan({ server_id: row.server_id }) planlist.value = res.data.data.map(item => { @@ -580,7 +585,7 @@ const handleEdit = async (row) => { }) // 获取分类列表 await fetchCategoryList(row.server_id) - + console.log("编辑镜像信息:",row) editOr.value = true dialogVisible.value = true showNewCategoryInput.value = false // 编辑时默认不显示新分类输入框 diff --git a/src/views/acs/nodes/server.vue b/src/views/acs/nodes/server.vue index dbf527d..c8042c8 100644 --- a/src/views/acs/nodes/server.vue +++ b/src/views/acs/nodes/server.vue @@ -837,6 +837,54 @@
+
+
GPU配置
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
价格与验证
@@ -2205,7 +2253,13 @@ const spec_form = reactive({ min_iops: "", max_iops: "", description: "", - must_real_name: 0 + must_real_name: 0, + gpu_percentage: "", + min_partition_vram: "", + max_partition_vram: "", + optimal_partition_vram: "", + low_mmio_space: "", + high_mmio_space: "" }); function show_spec(data = null) { @@ -2227,6 +2281,7 @@ function show_spec(data = null) { spec_form.snapshot_num = '3'; spec_form.min_iops = '1000'; spec_form.max_iops = '5000'; + spec_form.low_mmio_space = '128'; } } else { // 复制传入的数据 From 067e0539ba8d34692e1ff69c3d8ac1373349d924 Mon Sep 17 00:00:00 2001 From: 2256907009 <2256907009@qq.com> Date: Thu, 13 Nov 2025 15:05:54 +0800 Subject: [PATCH 03/10] =?UTF-8?q?feat:=E6=B7=BB=E5=8A=A0admin=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.vue | 1 + src/api/admin/Permission.js | 69 + src/api/admin/activity.js | 17 + src/api/admin/cdn.js | 9 + src/api/admin/discount.js | 172 ++ src/api/admin/file.js | 42 + src/api/admin/group.js | 25 + src/api/admin/order.js | 35 + src/api/admin/product.js | 142 ++ src/api/admin/router.js | 19 + src/api/admin/setting.js | 86 + src/api/admin/user.js | 165 ++ src/api/domain.js | 11 +- src/api/ticket.js | 55 +- src/components/admin/AvatarSelector.vue | 431 ++++ src/components/layout/AdminLayout.vue | 32 +- .../marketing/DiscountDetailDialog.vue | 295 +++ src/config/menus.js | 153 +- src/router/index.js | 255 +- src/utils/acs/audit.js | 8 +- src/utils/acs/file.js | 18 +- src/utils/acs/guacamole.js | 10 +- src/utils/acs/message.js | 22 +- src/utils/acs/mirror.js | 26 +- src/utils/acs/order.js | 8 +- src/utils/acs/pay.js | 6 +- src/utils/acs/server.js | 140 +- src/utils/acs/setting.js | 14 +- src/utils/acs/user-set.js | 12 +- src/utils/acs/user.js | 134 +- src/utils/acs/virtual.js | 44 +- src/utils/request.js | 9 +- src/utils/tool.js | 52 +- src/views/Login.vue | 1 + src/views/activity/SigninActivity.vue | 436 ++++ src/views/marketing/DiscountCode.vue | 533 ++++ src/views/marketing/DiscountGoods.vue | 719 ++++++ src/views/marketing/DiscountUsers.vue | 883 +++++++ src/views/marketing/UserVoucher.vue | 892 +++++++ src/views/marketing/Voucher.vue | 512 ++++ src/views/marketing/VoucherHistory.vue | 581 +++++ src/views/marketing/VoucherHolders.vue | 781 ++++++ src/views/order/OrderList.vue | 584 +++++ src/views/product/ProductGroup.vue | 275 ++ src/views/product/ProductList.vue | 497 ++++ src/views/product/ProductParameter.vue | 637 +++++ src/views/system/DomainWhitelist.vue | 33 +- src/views/system/PermissionAdmin.vue | 778 ++++++ src/views/system/PermissionRoute.vue | 281 +++ src/views/system/Setting.vue | 535 ++++ src/views/system/SettingGroup.vue | 344 +++ src/views/system/SystemFile.vue | 771 ++++++ src/views/user/AdminGroup.vue | 358 +++ src/views/user/UserBalance.vue | 1475 +++++++++++ src/views/user/UserDetail.vue | 2237 +++++++++++++++++ src/views/user/UserGroup.vue | 632 +++++ src/views/user/UserList.vue | 1030 ++++++++ 默认模块.openapi.json | 687 +++++ 58 files changed, 18736 insertions(+), 273 deletions(-) create mode 100644 src/api/admin/Permission.js create mode 100644 src/api/admin/activity.js create mode 100644 src/api/admin/cdn.js create mode 100644 src/api/admin/discount.js create mode 100644 src/api/admin/file.js create mode 100644 src/api/admin/group.js create mode 100644 src/api/admin/order.js create mode 100644 src/api/admin/product.js create mode 100644 src/api/admin/router.js create mode 100644 src/api/admin/setting.js create mode 100644 src/api/admin/user.js create mode 100644 src/components/admin/AvatarSelector.vue create mode 100644 src/components/marketing/DiscountDetailDialog.vue create mode 100644 src/views/activity/SigninActivity.vue create mode 100644 src/views/marketing/DiscountCode.vue create mode 100644 src/views/marketing/DiscountGoods.vue create mode 100644 src/views/marketing/DiscountUsers.vue create mode 100644 src/views/marketing/UserVoucher.vue create mode 100644 src/views/marketing/Voucher.vue create mode 100644 src/views/marketing/VoucherHistory.vue create mode 100644 src/views/marketing/VoucherHolders.vue create mode 100644 src/views/order/OrderList.vue create mode 100644 src/views/product/ProductGroup.vue create mode 100644 src/views/product/ProductList.vue create mode 100644 src/views/product/ProductParameter.vue create mode 100644 src/views/system/PermissionAdmin.vue create mode 100644 src/views/system/PermissionRoute.vue create mode 100644 src/views/system/Setting.vue create mode 100644 src/views/system/SettingGroup.vue create mode 100644 src/views/system/SystemFile.vue create mode 100644 src/views/user/AdminGroup.vue create mode 100644 src/views/user/UserBalance.vue create mode 100644 src/views/user/UserDetail.vue create mode 100644 src/views/user/UserGroup.vue create mode 100644 src/views/user/UserList.vue create mode 100644 默认模块.openapi.json diff --git a/src/App.vue b/src/App.vue index 705bc6c..305658f 100644 --- a/src/App.vue +++ b/src/App.vue @@ -16,6 +16,7 @@ import {getUserInfo} from "@/api/login.js"; const userStore = useUserStore() onMounted(async () => { let resp = await getUserInfo() + console.log("用户信息:",resp) userStore.setUserInfo(resp.data) console.log(userStore.userInfo) }) diff --git a/src/api/admin/Permission.js b/src/api/admin/Permission.js new file mode 100644 index 0000000..18f978b --- /dev/null +++ b/src/api/admin/Permission.js @@ -0,0 +1,69 @@ +import {http2} from "@/utils/request.js"; +/* -------------------------------------------------------------- */ +/**管理员权限管理 */ +/**-------------------------------------------------------- */ +/**路由权限管理 */ + +/**获取权限列表 */ +export const getPermissionList = (params) => { + return http2.get('/api/v1/admin/server/permission/path/list', {params: params}) +} +/**新增权限信息 */ +export const addPermissionInfo = (data) => { + return http2.post('/api/v1/admin/server/permission/path/add', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} +/**修改权限信息 */ +export const updatePermissionInfo = (data) => { + return http2.post('/api/v1/admin/server/permission/path/update', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} +/**删除权限信息 */ +export const deletePermissionInfo = (data) => { + return http2.delete('/api/v1/admin/server/permission/path/delete', { + data: data, + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} + +/**-------------------------------------------------------- */ +/**管理员权限分配 */ + +/**获取指定管理员的权限列表 */ +export const getPermissionListByAdmin = (params) => { + return http2.get('/api/v1/admin/server/permission/admin/list', {params: params}) +} +/**新增管理员权限 */ +export const addPermissionAdmin = (data) => { + return http2.post('/api/v1/admin/server/permission/admin/add', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} +/**修改管理员权限 */ +export const updatePermissionAdmin = (data) => { + return http2.post('/api/v1/admin/server/permission/admin/update', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} +/**删除管理员权限 */ +export const deletePermissionAdmin = (data) => { + return http2.delete('/api/v1/admin/server/permission/admin/delete', { + data: data, + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} + diff --git a/src/api/admin/activity.js b/src/api/admin/activity.js new file mode 100644 index 0000000..f21cb68 --- /dev/null +++ b/src/api/admin/activity.js @@ -0,0 +1,17 @@ +import {http2} from "@/utils/request.js"; +/**新增签到奖励 */ +export const addSignReward = (data) => { + return http2.post('/api/v1/admin/activity/signin/add_reward', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} +/**新增签到奖励类型 */ +export const addSignRewardType = (data) => { + return http2.post('/api/v1/admin/activity/signin/add_reward_type', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} diff --git a/src/api/admin/cdn.js b/src/api/admin/cdn.js new file mode 100644 index 0000000..94c947b --- /dev/null +++ b/src/api/admin/cdn.js @@ -0,0 +1,9 @@ +import {http2} from "@/utils/request.js"; +/**新增goedge服务器 */ +export const addGoedgeServer = (data) => { + return http2.post('/api/v1/admin/api/goedge/add_server', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} diff --git a/src/api/admin/discount.js b/src/api/admin/discount.js new file mode 100644 index 0000000..ca37497 --- /dev/null +++ b/src/api/admin/discount.js @@ -0,0 +1,172 @@ +import {http2} from "@/utils/request.js"; + +/**---------------------------------- */ +/**优惠码/代金券管理 (统一接口) */ + +/**获取优惠码/代金券列表 */ +export const getDiscountCodeList = (params) => { + return http2.get('/api/v1/admin/code/discount/list', {params: params}) +} + +/**获取优惠码/代金券详情 */ +export const getDiscountCodeDetail = (params) => { + return http2.get('/api/v1/admin/code/discount/detail', {params: params}) +} + +/**创建优惠码/代金券 */ +export const createDiscountCode = (data) => { + return http2.post('/api/v1/admin/code/discount/create', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} + +/**更新优惠码/代金券 */ +export const updateDiscountCode = (data) => { + return http2.post('/api/v1/admin/code/discount/update', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} + +/**删除优惠码/代金券 */ +export const deleteDiscountCode = (data) => { + return http2.delete('/api/v1/admin/code/discount/delete?code_id=' + data.code_id) +} + +/**---------------------------------- */ +/**商品关联管理 */ + +/**获取优惠码/代金券商品列表 */ +export const getDiscountGoodsList = (params) => { + return http2.get('/api/v1/admin/code/discount/goods/list', {params: params}) +} + +/**新增优惠码/代金券商品关联 */ +export const addDiscountGoods = (data) => { + return http2.post('/api/v1/admin/code/discount/goods/add', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} + +/**修改优惠码/代金券商品关联 */ +export const updateDiscountGoods = (data) => { + return http2.post('/api/v1/admin/code/discount/goods/update', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} + +/**删除优惠码/代金券商品关联 */ +export const deleteDiscountGoods = (data) => { + return http2.delete('/api/v1/admin/code/discount/goods/delete', { + data: data, + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} + +/**---------------------------------- */ +/**用户关联管理 */ + +/**获取优惠码/代金券用户关联列表 */ +export const getDiscountUsersList = (params) => { + return http2.get('/api/v1/admin/code/discount/users/list', {params: params}) +} + +/**新增优惠码/代金券用户关联 */ +export const addDiscountUsers = (data) => { + return http2.post('/api/v1/admin/code/discount/users/add', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} + +/**修改优惠码/代金券用户关联 */ +export const updateDiscountUsers = (data) => { + return http2.post('/api/v1/admin/code/discount/users/update', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} + +/**删除优惠码/代金券用户关联 */ +export const deleteDiscountUsers = (data) => { + return http2.delete('/api/v1/admin/code/discount/users/delete', { + data: data, + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} + +/**---------------------------------- */ +/**用户代金券管理 */ + +/**获取用户优惠码/代金券列表 */ +export const getUserVoucherList = (params) => { + return http2.get('/api/v1/admin/code/discount/user/list', {params: params}) +} + +/**为用户添加代金券 */ +export const addUserVoucher = (data) => { + return http2.post('/api/v1/admin/code/discount/user/add_coupon', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} + +/**修改用户代金券 */ +export const updateUserVoucher = (data) => { + return http2.post('/api/v1/admin/code/discount/user/update_coupon', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} + +/**删除用户代金券 */ +export const deleteUserVoucher = (data) => { + return http2.delete('/api/v1/admin/code/discount/user/delete_coupon', { + data: data, + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} + +/**获取用户优惠码/代金券使用记录 */ +export const getUserVoucherHistory = (params) => { + return http2.get('/api/v1/admin/code/discount/user/history', {params: params}) +} + +/**为用户分配代金券 */ +export const allocateVoucher = (data) => { + return http2.post('/api/v1/admin/code/discount/coupon/allocate', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} + +/**查询代金券的拥有者列表 */ +export const getVoucherHolderList = (params) => { + return http2.get('/api/v1/admin/code/discount/coupon/holder_list', {params: params}) +} + +/**---------------------------------- */ +/**兼容旧接口别名 */ +export const getVoucherList = getDiscountCodeList +export const getVoucherDetail = getDiscountCodeDetail +export const createVoucher = createDiscountCode +export const updateVoucher = updateDiscountCode +export const deleteVoucher = deleteDiscountCode diff --git a/src/api/admin/file.js b/src/api/admin/file.js new file mode 100644 index 0000000..64c261a --- /dev/null +++ b/src/api/admin/file.js @@ -0,0 +1,42 @@ +import {http2} from "@/utils/request.js"; +/**获取文件列表 */ +export const getFileList = (params) => { + return http2.get('/api/v1/admin/file/list',{params}) +} + +/**获取文件详情 */ +export const getFileDetail = (data) => { + return http2.get('/api/v1/admin/file/detail?file_id='+data.file_id) +} + +/**删除文件 */ +export const deleteFile = (data) => { + return http2.delete('/api/v1/admin/file/delete', { + params: data + }) +} +/**修改文件信息 */ +export const updateFile = (data) => { + return http2.post('/api/v1/admin/file/update', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} +/**公共接口 获取文件信息 */ +export const getFile = (data) => { + return http2.get('/api/v1/tools/file/info?file_id='+data.file_id) +} + +/**文件上传 */ +export const uploadFile = (data) => { + return http2.post('/api/v1/tools/file/upload', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} +/**文件下载 */ +export const downloadFile = (data) => { + return http2.get('/api/v1/tool/file/down?file_id='+data.file_id) +} diff --git a/src/api/admin/group.js b/src/api/admin/group.js new file mode 100644 index 0000000..2b4b8ba --- /dev/null +++ b/src/api/admin/group.js @@ -0,0 +1,25 @@ +import {http2} from "@/utils/request.js"; +/**获取管理员组列表 */ +export const getAdminGroupList = (params) => { + return http2.get('/api/v1/admin/admin_group/list', {params: params}) +} +/**获取管理员组成员列表 */ +export const getAdminGroupMemberList = (params) => { + return http2.get('/api/v1/admin/admin_group/member_list', {params:params}) +} +/**获取管理员组详情 */ +export const getAdminGroupDetail = (params) => { + return http2.get('/api/v1/admin/admin_group/detail', {params: params}) +} +/**新增管理员组 */ +export const addAdminGroup = (data) => { + return http2.post('/api/v1/admin/admin_group/create', data) +} +/**更新管理员组信息 */ +export const updateAdminGroupInfo = (data) => { + return http2.post('/api/v1/admin/admin_group/update', data) +} +/**删除管理员组 */ +export const deleteAdminGroup = (data) => { + return http2.delete('/api/v1/admin/admin_group/delete?group_id=' + data.group_id) +} diff --git a/src/api/admin/order.js b/src/api/admin/order.js new file mode 100644 index 0000000..d58fa36 --- /dev/null +++ b/src/api/admin/order.js @@ -0,0 +1,35 @@ +import {http2} from "@/utils/request.js"; +/**获取订单列表 */ +export const getOrderList = (params) => { + return http2.get('/api/v1/admin/order/list', {params: params}) +} +/**获取订单详情 */ +export const getOrderDetail = (params) => { + return http2.get('/api/v1/admin/order/detail', {params: params}) +} +/**删除订单 (未提供删除接口,暂时保留) */ +/**删除订单 */ +export const deleteOrder = (data) => { + return http2.delete('/api/v1/admin/trades/delete_trade', { + data: data, + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} +/**创建订单 */ +export const createOrder = (data) => { + return http2.post('/api/v1/admin/order/create', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} +/**修改订单 */ +export const updateOrder = (data) => { + return http2.post('/api/v1/admin/order/update', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} diff --git a/src/api/admin/product.js b/src/api/admin/product.js new file mode 100644 index 0000000..cc1d340 --- /dev/null +++ b/src/api/admin/product.js @@ -0,0 +1,142 @@ +import {http2} from "@/utils/request.js"; +/**---------------------------------- */ +/**商品组管理 */ + +/**获取商品分组列表 */ +export const getProductGroupList = (params) => { + return http2.get('/api/v1/admin/good/group/list', {params: params}) +} +/**创建商品分组 */ +export const createProductGroup = (data) => { + return http2.post('/api/v1/admin/good/group/create', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} +/**更新商品分组 */ +export const updateProductGroup = (data) => { + return http2.post('/api/v1/admin/good/group/update', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} +/**隐藏商品组 */ +export const hideProductGroup = (data) => { + return http2.post('/api/v1/admin/good/group/disable', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} +/**启动商品组 */ +export const startProductGroup = (data) => { + return http2.post('/api/v1/admin/good/group/enable', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} +/**删除商品分组 */ +export const deleteProductGroup = (data) => { + return http2.delete('/api/v1/admin/good/group/delete',{ + data: data, + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} + + + +/**---------------------------------- */ +/**商品管理 */ + +/**获取商品列表 */ +export const getProductList = (params) => { + return http2.get('/api/v1/admin/good/goods/list', {params: params}) +} +/**创建商品 */ +export const createProduct = (data) => { + return http2.post('/api/v1/admin/good/goods/create', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} +/**更新商品 */ +export const updateProduct = (data) => { + return http2.post('/api/v1/admin/good/goods/update', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} +/**删除商品 */ +export const deleteProduct = (data) => { + return http2.delete('/api/v1/admin/good/goods/delete',{ + data:data, + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} + + + +/**---------------------------------- */ +/**商品参数管理 */ + +/**获取商品参数列表 */ +export const getProductParameterList = (params) => { + return http2.get('/api/v1/admin/good/spec/list', {params: params}) +} +/**创建商品参数 */ +export const createProductParameter = (data) => { + return http2.post('/api/v1/admin/good/spec/create', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} +/**获取商品参数详情 */ +export const getProductParameterDetail = (params) => { + return http2.get('/api/v1/admin/good/spec/detail', {params: params}) +} +/**更新商品参数 */ +export const updateProductParameter = (data) => { + return http2.post('/api/v1/admin/good/spec/update', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} +/**删除商品参数 */ +export const deleteProductParameter = (data) => { + return http2.delete('/api/v1/admin/good/spec/delete', { + params: data + }) +} +/**增加商品参数值 */ +export const addProductParameterValue = (data) => { + return http2.post('/api/v1/admin/good/spec/add_value', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} +/**删除商品参数值 */ +export const deleteProductParameterValue = (data) => { + return http2.delete('/api/v1/admin/good/spec/delete_value', { + params: data + }) +} +/**更新商品参数值 */ +export const updateProductParameterValue = (data) => { + return http2.post('/api/v1/admin/good/spec/update_value', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} \ No newline at end of file diff --git a/src/api/admin/router.js b/src/api/admin/router.js new file mode 100644 index 0000000..70ff216 --- /dev/null +++ b/src/api/admin/router.js @@ -0,0 +1,19 @@ +import {http2} from "@/utils/request.js"; + +/**路由管理 */ +/**新增前端路由 */ +export const addRouter = (data) => { + return http2.post('/api/v1/admin/web_routs/add', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} +/**更新前端路由 */ +export const updateRouter = (data) => { + return http2.post('/api/v1/admin/web_routs/update', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} diff --git a/src/api/admin/setting.js b/src/api/admin/setting.js new file mode 100644 index 0000000..2a40c93 --- /dev/null +++ b/src/api/admin/setting.js @@ -0,0 +1,86 @@ +import { http2 } from "@/utils/request.js" + +// ========== 配置组管理 ========== + +/** 获取配置分组列表 */ +export const getSettingGroupList = (params) => { + return http2.get('/api/v1/admin/server/setting/group/list', { params }) +} + +/** 获取配置分组信息 */ +export const getSettingGroupInfo = (params) => { + return http2.get('/api/v1/admin/server/setting/group/info', { params }) +} + +/** 创建配置分组 */ +export const createSettingGroup = (data) => { + return http2.post('/api/v1/admin/server/setting/group/create', data, { + headers: { + 'Content-Type': 'multipart/form-data' + } + }) +} + +/** 修改配置分组 */ +export const updateSettingGroup = (data) => { + return http2.post('/api/v1/admin/server/setting/group/update', data, { + headers: { + 'Content-Type': 'multipart/form-data' + } + }) +} + +/** 删除配置分组 */ +export const deleteSettingGroup = (params) => { + return http2.delete('/api/v1/admin/server/setting/group/delete', { params }) +} + +// ========== 配置管理 ========== + +/** 获取配置列表 */ +export const getSettingList = (params) => { + return http2.get('/api/v1/admin/server/setting/list', { params }) +} + +/** 获取配置信息 */ +export const getSettingInfo = (params) => { + return http2.get('/api/v1/admin/server/setting/info', { params }) +} + +/** 创建配置 */ +export const createSetting = (data) => { + return http2.post('/api/v1/admin/server/setting/create', data, { + headers: { + 'Content-Type': 'multipart/form-data' + } + }) +} + +/** 修改配置 */ +export const updateSetting = (data) => { + return http2.post('/api/v1/admin/server/setting/update', data, { + headers: { + 'Content-Type': 'multipart/form-data' + } + }) +} + +/** 修改配置是否开放访问 */ +export const setSettingOpen = (data) => { + return http2.post('/api/v1/admin/server/setting/set_open', data, { + headers: { + 'Content-Type': 'multipart/form-data' + } + }) +} + +/** 删除配置 */ +export const deleteSetting = (data) => { + return http2.delete('/api/v1/admin/server/setting/delete', { + data, + headers: { + 'Content-Type': 'multipart/form-data' + } + }) +} + diff --git a/src/api/admin/user.js b/src/api/admin/user.js new file mode 100644 index 0000000..570c897 --- /dev/null +++ b/src/api/admin/user.js @@ -0,0 +1,165 @@ +import {http2} from "@/utils/request.js"; + +/**用户余额管理 */ +/**修改用户余额 */ +export const editUserBalance = (data) => { + return http2.post('/api/v1/admin/user/balance/update', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} +/**添加用户消费记录 */ +export const addUserConsumption = (data) => { + return http2.post('/api/v1/admin/user/balance/add_history', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} + +/**查询用户余额 */ +export const getUserBalance = (data) => { + return http2.get('/api/v1/admin/user/balance/select?user_id='+data.user_id) +} + +/**获取用户余额记录 */ +export const getUserBalanceRecord = (data) => { + return http2.get('/api/v1/admin/user/balance/history?user_id='+data.user_id + '&balance_type=' + data.balance_type + '&page=' + data.page + '&count=' + data.count) +} + +/**获取用户余额 */ +export const getUserBalanceCount = (data) => { + return http2.get('/api/v1/admin/user/balance/get?user_id='+data.user_id) +} +/**获取用户信息 */ +export const getUserInfo = (data) => { + return http2.get('/api/v1/admin/user/user/detail?user_id='+data.user_id) +} + +/**获取用户列表 */ +export const getUserList = (data) => { + return http2.get('/api/v1/admin/user/user/list?page=' + data.page + '&count=' + data.count + '&key=' + data.key) +} + +/**更新用户信息 */ +export const updateUserInfo = (data) => { + return http2.post('/api/v1/admin/user/user/update', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} + +/**删除用户 */ +export const deleteUser = (data) => { + return http2.delete('/api/v1/admin/user/user/delete?group_id='+data.group_id) +} +/**修改用户头像 */ +export const updateUserAvatar = (data) => { + return http2.post('/api/v1/admin/user/user/update_cover', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} +/**修改用户密码 */ +export const updateUserPassword = (data) => { + return http2.post('/api/v1/admin/user/user/update_password', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} + +/**修改用户组 */ +export const updateUserGroup = (data) => { + return http2.post('/api/v1/admin/user/user/update_group', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} +/**修改用户管理员权限*/ +export const updateUserAdmin = (data) => { + return http2.post('/api/v1/admin/user/user/user2admin', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} +/**修改用户实名信息*/ +export const updateUserRealName = (data) => { + return http2.post('/api/v1/admin/user/user/update_real_name', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} +/**获取用户登录记录*/ +export const getUserLoginRecord = (data) => { + return http2.get('/api/v1/admin/user/user/login_history?user_id='+data.user_id + '&page=' + data.page + '&count=' + data.count) +} + +/**获取用户操作记录 */ +export const getUserOperationRecord = (data) => { + return http2.get('/api/v1/admin/user/user/manage_history?user_id='+data.user_id + '&page=' + data.page + '&count=' + data.count) +} +/**模拟用户登录 */ +export const mockUserLogin = (data) => { + return http2.get('/api/v1/admin/user/user/simulation_login?user_id='+data.user_id) +} +/**新建任务 */ +export const createTask = (data) => { + return http2.post('/api/v1/admin/user/user/create', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} + +/**用户组管理 */ +/**获取用户组列表 */ +export const getUserGroupList = (data) => { + return http2.get('/api/v1/admin/user_group/list?page=' + data.page + '&count=' + data.count) +} +/**获取用户组成员列表 */ +export const getUserGroupMemberList = (data) => { + return http2.get('/api/v1/admin/user_group/member_list?group_id=' + data.group_id + '&page=' + data.page + '&count=' + data.count) +} +/**获取用户组详情信息 */ +export const getUserGroupDetail = (data) => { + return http2.get('/api/v1/admin/user_group/detail?group_id=' + data.group_id) +} +/**新建用户组 */ +export const createUserGroup = (data) => { + return http2.post('/api/v1/admin/user_group/create', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} +/**更新用户组信息 */ +export const updateUserGroupInfo = (data) => { + return http2.post('/api/v1/admin/user_group/update', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} +/**删除用户组 */ +export const deleteUserGroup = (data) => { + return http2.delete(`/api/v1/admin/user_group/delete?group_id=`+data.group_id,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} +/**添加用户组成员 */ +export const addUserGroupMember = (data) => { + return http2.post('/api/v1/admin/user_group/add_member', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} \ No newline at end of file diff --git a/src/api/domain.js b/src/api/domain.js index e6cddcd..b0fc1a9 100644 --- a/src/api/domain.js +++ b/src/api/domain.js @@ -11,15 +11,20 @@ export function addDomain(data) { } // 删除域名白名单 -export function deleteDomain(id) { - return request.post("/api/v1/admin/server/domain_withe/delete",{domain_id: id}) +export function deleteDomain(data) { + return request.post("/api/v1/admin/server/domain_withe/delete",data,{ + + headers:{ + 'Content-Type':'multipart/form-data' + } + }) } // 批量删除域名白名单 export async function batchDeleteDomain(ids) { let promises = [] for (let id of ids) { - promises.push(deleteDomain(id)) + promises.push(deleteDomain({domain_id:id})) } return await Promise.all(promises) } \ No newline at end of file diff --git a/src/api/ticket.js b/src/api/ticket.js index dfc61f5..47f9dbd 100644 --- a/src/api/ticket.js +++ b/src/api/ticket.js @@ -29,12 +29,12 @@ export function getCompletedTicketList(count, page) { return getTickerList(count,page,3) } -// 获取详情 +// 获取工单详情 export function getTicketDetail(work_id) { return request.get('/api/v1/admin/work_order/detail', { work_id }) } -// 回复 +// 回复工单 export function replyTicket(work_id, content, files) { return request.post('/api/v1/admin/work_order/reply', { work_id, content, files }) } @@ -67,4 +67,53 @@ export async function parseFilesToImages(files) { const fileIds = files.split(',') return await Promise.all(fileIds.map(async (id) => await getFileImage(id.trim()))) -} \ No newline at end of file +} + +/**获取工单数量 */ +export function getTicketCount() { + return request.get('/api/v1/admin/work_order/count') +} +/**修改工单信息 */ +export function updateTicketInfo(data) { + return request.post('/api/v1/admin/work_order/update', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} +/**添加工单类型 */ +export function addTicketType(data) { + return request.post('/api/v1/admin/work_order/add_type', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} +/**修改工单类型 */ +export function updateTicketType(data) { + return request.post('/api/v1/admin/work_order/update_type', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} +/**删除工单类型 */ +export function deleteTicketType(data) { + return request.delete('/api/v1/admin/work_order/delete_type', data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} +/**获取工单类型列表 */ +export function getTicketTypeList(data) { + return request.get('/api/v1/admin/work_order/type_list', data) +} +/**修改工单回复信息 */ +export function updateTicketReplayInfo(data){ + return request.post('/api/v1/admin/work_order/update_reply',data,{ + headers:{ + 'Content-Type':'multipart/form-data' + } + }) +} diff --git a/src/components/admin/AvatarSelector.vue b/src/components/admin/AvatarSelector.vue new file mode 100644 index 0000000..4652c90 --- /dev/null +++ b/src/components/admin/AvatarSelector.vue @@ -0,0 +1,431 @@ + + + + + \ No newline at end of file diff --git a/src/components/layout/AdminLayout.vue b/src/components/layout/AdminLayout.vue index f983e31..b71f932 100644 --- a/src/components/layout/AdminLayout.vue +++ b/src/components/layout/AdminLayout.vue @@ -5,7 +5,7 @@

零零七云计算后台控制面板

- + { color: #1890ff; } +.sidebar-scrollbar { + height: calc(100vh - 60px); +} + .sidebar-menu { border-right: none; - height: calc(100vh - 60px); + min-height: 100%; } /* 主容器样式 */ @@ -279,4 +283,28 @@ const handleLogout = () => { :deep(.el-dropdown-menu__item i) { margin-right: 8px; } + +/* 侧边栏滚动条样式优化 */ +:deep(.sidebar-scrollbar .el-scrollbar__wrap) { + overflow-x: hidden; +} + +:deep(.sidebar-scrollbar .el-scrollbar__view) { + height: 100%; +} + +/* Element Plus 菜单项样式优化 */ +:deep(.el-menu) { + border-right: none; +} + +:deep(.el-sub-menu__title) { + height: 48px; + line-height: 48px; +} + +:deep(.el-menu-item) { + height: 48px; + line-height: 48px; +} \ No newline at end of file diff --git a/src/components/marketing/DiscountDetailDialog.vue b/src/components/marketing/DiscountDetailDialog.vue new file mode 100644 index 0000000..38a2439 --- /dev/null +++ b/src/components/marketing/DiscountDetailDialog.vue @@ -0,0 +1,295 @@ + + + + + + diff --git a/src/config/menus.js b/src/config/menus.js index 4f55ce3..9cfc27e 100644 --- a/src/config/menus.js +++ b/src/config/menus.js @@ -8,7 +8,115 @@ export const menus = [ path : '/ticket', title: '工单处理', icon: 'DataBoard' - + }, + { + path:'/user', + title: '用户管理', + icon: 'User', + children: [ + { + path: '/user/list', + title: '用户列表' + }, + { + path: '/user/balance', + title: '用户余额管理' + }, + { + path: '/user/group', + title: '用户组管理' + }, + { + path: '/user/admin-group', + title: '管理员组管理' + } + ] + }, + { + path: '/product', + title: '商品管理', + icon: 'Goods', + children: [ + { + path: '/product/list', + title: '商品列表' + }, + { + path: '/product/group', + title: '商品分组' + }, + { + path: '/product/parameter', + title: '商品参数' + } + ] + }, + { + path: '/order', + title: '订单管理', + icon: 'Document', + children: [ + { + path: '/order/list', + title: '订单列表' + } + ] + }, + { + path: '/marketing', + title: '优惠营销', + icon: 'Present', + children: [ + { + path: '/marketing/discount', + title: '优惠码管理' + }, + { + path: '/marketing/voucher', + title: '代金券管理' + }, + { + path: '/marketing/user-distribution', + title: '用户分发管理' + }, + + { + id: 'discount-goods', + title: '商品关联管理', + path: '/marketing/discount-goods', + badge: 'NEW' + }, + { + id: 'discount-users', + title: '用户关联管理', + path: '/marketing/discount-users', + badge: 'NEW' + }, + + { + id: 'user-info', + title: '用户信息管理', + path: '/marketing/user-info', + badge: 'NEW' + }, + { + id: 'user-history', + title: '用户使用记录管理', + path: '/marketing/user-history', + badge: 'NEW' + } + ] + }, + { + path: '/activity', + title: '活动管理', + icon: 'TrophyBase', + children: [ + { + path: '/activity/signin', + title: '签到活动' + } + ] }, { path: '/acs', @@ -34,24 +142,24 @@ export const menus = [ ] }, { - path: '/acs/nodes', title: '节点管理' + path: '/acs/nodes', + title: '节点管理' }, { path: '/acs/guacamole', - title: '远程桌面网关管理', - icon: 'Monitor' - },{ + title: '远程桌面网关管理' + }, + { path: '/audit', title: '站点审计', - icon: 'Monitor', children: [ { path: '/audit/all', title: '所有站点' }, { path: '/audit/violation', title: '违规站点' } ] - },{ + }, + { path:'/setting', title:'全局设置管理', - icon:'Setting', children:[ {path:'/setting/global',title:'全局设置'} ] @@ -63,9 +171,32 @@ export const menus = [ title: '系统管理', icon: 'Setting', children: [ - // { path: '/system/users', title: '用户管理' }, - // { path: '/system/operation-log', title: '操作日志' }, - { path: '/system/domain-whitelist', title: '域名白名单' } + { + path: '/system/permission', + title: '权限管理', + children: [ + { path: '/system/permission/route', title: '路由权限' }, + { path: '/system/permission/admin', title: '管理员权限' } + ] + }, + + { + path: '/system/file', + title: '文件管理' + }, + + { + path: '/system/domain-whitelist', + title: '域名白名单' + }, + { + path: '/system/setting-group', + title: '配置组管理' + }, + { + path: '/system/setting-list', + title: '配置管理' + } ] } ] \ No newline at end of file diff --git a/src/router/index.js b/src/router/index.js index 47f9c8c..0c93b33 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -140,6 +140,206 @@ const routes = [ } ] }, + // 用户管理路由 + { + path: 'user', + name: 'User', + meta: { + title: '用户管理', + icon: 'User' + }, + redirect: '/user/list', + children: [ + { + path: 'list', + name: 'UserList', + component: () => import('../views/user/UserList.vue'), + meta: { + title: '用户列表' + } + }, + { + path: 'detail', + name: 'UserDetail', + component: () => import('../views/user/UserDetail.vue'), + meta: { + title: '用户详情' + } + }, + { + path: 'balance', + name: 'UserBalance', + component: () => import('../views/user/UserBalance.vue'), + meta: { + title: '用户余额管理' + } + }, + { + path: 'group', + name: 'UserGroup', + component: () => import('../views/user/UserGroup.vue'), + meta: { + title: '用户组管理' + } + }, + { + path: 'admin-group', + name: 'AdminGroup', + component: () => import('../views/user/AdminGroup.vue'), + meta: { + title: '管理员组管理' + } + } + ] + }, + // 商品管理路由 + { + path: 'product', + name: 'Product', + meta: { + title: '商品管理', + icon: 'Goods' + }, + redirect: '/product/list', + children: [ + { + path: 'list', + name: 'ProductList', + component: () => import('../views/product/ProductList.vue'), + meta: { + title: '商品列表' + } + }, + { + path: 'group', + name: 'ProductGroup', + component: () => import('../views/product/ProductGroup.vue'), + meta: { + title: '商品分组' + } + }, + { + path: 'parameter', + name: 'ProductParameter', + component: () => import('../views/product/ProductParameter.vue'), + meta: { + title: '商品参数' + } + } + ] + }, + // 订单管理路由 + { + path: 'order', + name: 'Order', + meta: { + title: '订单管理', + icon: 'Document' + }, + redirect: '/order/list', + children: [ + { + path: 'list', + name: 'OrderList', + component: () => import('../views/order/OrderList.vue'), + meta: { + title: '订单列表' + } + } + ] + }, + // 优惠营销路由 + { + path: 'marketing', + name: 'Marketing', + meta: { + title: '优惠营销', + icon: 'Present' + }, + redirect: '/marketing/discount', + children: [ + { + path: 'discount', + name: 'DiscountCode', + component: () => import('../views/marketing/DiscountCode.vue'), + meta: { + title: '优惠码管理' + } + }, + { + path: 'voucher', + name: 'Voucher', + component: () => import('../views/marketing/Voucher.vue'), + meta: { + title: '代金券管理' + } + }, + { + path: 'user-distribution', + name: 'UserDistribution', + component: () => import('../views/marketing/UserVoucher.vue'), + meta: { + title: '用户分发管理' + } + }, + { + path: 'discount-goods', + name: 'DiscountGoods', + component: () => import('../views/marketing/DiscountGoods.vue'), + meta: { + title: '商品关联管理', + badge: 'NEW' + } + }, + { + path: 'discount-users', + name: 'DiscountUsers', + component: () => import('../views/marketing/DiscountUsers.vue'), + meta: { + title: '用户关联管理', + badge: 'NEW' + } + }, + { + path: 'user-info', + name: 'UserInfo', + component: () => import('../views/marketing/VoucherHolders.vue'), + meta: { + title: '用户信息管理', + badge: 'NEW' + } + }, + { + path: 'user-history', + name: 'UserHistory', + component: () => import('../views/marketing/VoucherHistory.vue'), + meta: { + title: '用户使用记录管理', + badge: 'NEW' + } + } + ] + }, + // 活动管理路由 + { + path: 'activity', + name: 'Activity', + meta: { + title: '活动管理', + icon: 'TrophyBase' + }, + redirect: '/activity/signin', + children: [ + { + path: 'signin', + name: 'SigninActivity', + component: () => import('../views/activity/SigninActivity.vue'), + meta: { + title: '签到活动' + } + } + ] + }, { path: 'system', name: 'System', @@ -147,28 +347,51 @@ const routes = [ title: '系统管理', icon: 'Setting' }, - redirect: '/system/domain-whitelist', + redirect: '/system/permission/route', children: [ - // 注释掉的用户管理和操作日志路由,与菜单配置保持一致 - // { - // path: 'users', - // name: 'Users', - // component: () => import('../views/system/Users.vue'), - // meta: { - // title: '用户管理' - // } - // }, - // { - // path: 'operation-log', - // name: 'OperationLog', - // component: OperationLog, - // meta: { title: '操作日志' } - // }, + { + path: 'permission/route', + name: 'PermissionRoute', + component: () => import('../views/system/PermissionRoute.vue'), + meta: { + title: '路由权限' + } + }, + { + path: 'permission/admin', + name: 'PermissionAdmin', + component: () => import('../views/system/PermissionAdmin.vue'), + meta: { + title: '管理员权限' + } + }, + + { + path: 'file', + name: 'SystemFile', + component: () => import('../views/system/SystemFile.vue'), + meta: { + title: '文件管理' + } + }, + { path: 'domain-whitelist', name: 'DomainWhitelist', component: () => import('../views/system/DomainWhitelist.vue'), meta: { title: '域名白名单' } + }, + { + path: 'setting-group', + name: 'SettingGroup', + component: () => import('../views/system/SettingGroup.vue'), + meta: { title: '配置组管理' } + }, + { + path: 'setting-list', + name: 'SettingList', + component: () => import('../views/system/Setting.vue'), + meta: { title: '配置管理' } } ] }, diff --git a/src/utils/acs/audit.js b/src/utils/acs/audit.js index 7c83abb..7147baa 100644 --- a/src/utils/acs/audit.js +++ b/src/utils/acs/audit.js @@ -3,15 +3,15 @@ import {http2} from "@/utils/request.js"; /**获取所有站点 */ export const getSiteList = (data) => { - return http2.get(`/v1/admin/audit/list?page=${data.page}&server_id=${data.server_id}&user_id=${data.user_id}&count=${data.count}&key=${data.key}`) + return http2.get(`/acs/v1/admin/audit/list?page=${data.page}&server_id=${data.server_id}&user_id=${data.user_id}&count=${data.count}&key=${data.key}`) } /**手动触发站点审计 */ export const auditSite = () => { - return http2.get(`/v1/admin/audit/start`) + return http2.get(`/acs/v1/admin/audit/start`) } /**删除违规网页审计 传入参数: web_key 站点名*/ export const delAudit = (data) => { - return http2.post(`/v1/admin/audit/delete`,data,{ + return http2.post(`/acs/v1/admin/audit/delete`,data,{ headers: { 'Content-Type': 'multipart/form-data' } @@ -19,5 +19,5 @@ export const delAudit = (data) => { } /**获取违规网页审计列表 */ export const getAuditList = (data) => { - return http2.get(`/v1/admin/audit/violation_list?page=${data.page}&count=${data.count}&key=${data.key}`) + return http2.get(`/acs/v1/admin/audit/violation_list?page=${data.page}&count=${data.count}&key=${data.key}`) } diff --git a/src/utils/acs/file.js b/src/utils/acs/file.js index 81f69f3..ef3deb2 100644 --- a/src/utils/acs/file.js +++ b/src/utils/acs/file.js @@ -1,10 +1,10 @@ import {http2} from "@/utils/request.js"; export const getFileList = (data) => { - return http2.get(`/v1/file/list?container_id=${data.container_id}&path=${data.path}`) + return http2.get(`/acs/v1/file/list?container_id=${data.container_id}&path=${data.path}`) } /** 读取文件内容 */ export const readFile = (data) => { - return http2.post(`/v1/file/read`,data, { + return http2.post(`/acs/v1/file/read`,data, { headers: { "Content-Type": "multipart/form-data" } @@ -12,7 +12,7 @@ export const readFile = (data) => { } /*删除文件或文件夹 */ export const deleteFile = (data) => { - return http2.post(`/v1/file/delete`,data, { + return http2.post(`/acs/v1/file/delete`,data, { headers: { "Content-Type": "multipart/form-data" } @@ -20,7 +20,7 @@ export const deleteFile = (data) => { } /*写入文件 */ export const writeFile = (data) => { - return http2.post(`/v1/file/write`,data, { + return http2.post(`/acs/v1/file/write`,data, { headers: { "Content-Type": "multipart/form-data" } @@ -28,7 +28,7 @@ export const writeFile = (data) => { } /*创建文件夹 */ export const createFolder = (data) => { - return http2.post(`/v1/file/mkdir`,data, { + return http2.post(`/acs/v1/file/mkdir`,data, { headers: { "Content-Type": "multipart/form-data" } @@ -36,7 +36,7 @@ export const createFolder = (data) => { } /**上传文件 */ export const uploadFile = (data) => { - return http2.post(`/v1/file/upload_file`,data, { + return http2.post(`/acs/v1/file/upload_file`,data, { headers: { "Content-Type": "multipart/form-data" } @@ -44,7 +44,7 @@ export const uploadFile = (data) => { } /**下载文件链接 */ export const downloadFile = (data) => { - return http2.post(`/v1/file/get_down_link`,data, { + return http2.post(`/acs/v1/file/get_down_link`,data, { headers: { "Content-Type": "multipart/form-data" } @@ -52,7 +52,7 @@ export const downloadFile = (data) => { } /**压缩文件 */ export const compressFile = (data) => { - return http2.post(`/v1/file/zip_file`,data, { + return http2.post(`/acs/v1/file/zip_file`,data, { headers: { "Content-Type": "multipart/form-data" } @@ -60,7 +60,7 @@ export const compressFile = (data) => { } /**解压文件 */ export const decompressFile = (data) => { - return http2.post(`/v1/file/unzip_file`,data, { + return http2.post(`/acs/v1/file/unzip_file`,data, { headers: { "Content-Type": "multipart/form-data" } diff --git a/src/utils/acs/guacamole.js b/src/utils/acs/guacamole.js index 13b6184..f0c2059 100644 --- a/src/utils/acs/guacamole.js +++ b/src/utils/acs/guacamole.js @@ -2,15 +2,15 @@ import {http2} from "@/utils/request.js"; /**获取 guacamole 列表 */ export const getGuacamoleList = data => { - return http2.get(`/v1/admin/server/get_guacamole_list`); + return http2.get(`/acs/v1/admin/server/get_guacamole_list`); }; /**获取服务器 guacamole 信息 */ export const getGuacamoleInfo = data => { - return http2.get(`/v1/admin/server/get_server_guacamole?server_id=${data}`); + return http2.get(`/acs/v1/admin/server/get_server_guacamole?server_id=${data}`); }; /**新增 guacamole 参数 url:string,username:string,password:string*/ export const addGuacamoleInfo = data => { - return http2.post(`/v1/admin/server/add_guacamole`, data,{ + return http2.post(`/acs/v1/admin/server/add_guacamole`, data,{ headers:{ 'Content-Type': 'multipart/form-data' } @@ -18,7 +18,7 @@ export const addGuacamoleInfo = data => { }; /**修改guacamole 参数 id:string,url:string,username:string,password:string*/ export const updateGuacamoleInfo = data => { - return http2.post(`/v1/admin/server/edit_guacamole`, data,{ + return http2.post(`/acs/v1/admin/server/edit_guacamole`, data,{ headers:{ 'Content-Type': 'multipart/form-data' } @@ -26,7 +26,7 @@ export const updateGuacamoleInfo = data => { }; /**删除guacamole 参数 id:string */ export const deleteGuacamoleInfo = data => { - return http2.post(`/v1/admin/server/delete_guacamole`, data,{ + return http2.post(`/acs/v1/admin/server/delete_guacamole`, data,{ headers:{ 'Content-Type': 'multipart/form-data' } diff --git a/src/utils/acs/message.js b/src/utils/acs/message.js index c6f4402..2aeae90 100644 --- a/src/utils/acs/message.js +++ b/src/utils/acs/message.js @@ -1,15 +1,15 @@ import {http2} from "@/utils/request.js"; /**获取消息列表 */ export const getMessageList = (data) => { - return http2.get(`/v1/messages/get_message_list?page=${data.page}&count=${data.count}&message_type=${data.message_type}`) + return http2.get(`/acs/v1/messages/get_message_list?page=${data.page}&count=${data.count}&message_type=${data.message_type}`) } /**获取单条消息 */ export const getMessage = (data) => { - return http2.get(`/v1/messages/get_message?message_id=${data}`) + return http2.get(`/acs/v1/messages/get_message?message_id=${data}`) } /**添加消息 */ export const addMessage = (data) => { - return http2.post(`/v1/messages/add_message`, data,{ + return http2.post(`/acs/v1/messages/add_message`, data,{ headers: { 'Content-Type': 'multipart/form-data' } @@ -17,7 +17,7 @@ headers: { } /**删除消息 */ export const deleteMessage = (data) => { - return http2.post(`/v1/messages/delete_message`, data,{ + return http2.post(`/acs/v1/messages/delete_message`, data,{ headers: { 'Content-Type': 'multipart/form-data' } @@ -25,7 +25,7 @@ headers: { } /**修改消息 */ export const editMessage = (data) => { - return http2.post(`/v1/messages/update_message`, data,{ + return http2.post(`/acs/v1/messages/update_message`, data,{ headers: { 'Content-Type': 'multipart/form-data' } @@ -33,11 +33,11 @@ headers: { } /**获取附件列表 */ export const getFileList = (data) => { - return http2.get(`/v1/attachment/get_attachment_list?page=${data.page}&count=${data.count}&key=${data.key}&user_type=${data.user_type}`) + return http2.get(`/acs/v1/attachment/get_attachment_list?page=${data.page}&count=${data.count}&key=${data.key}&user_type=${data.user_type}`) } /**上传附件 */ export const uploadFile = (data) => { - return http2.post(`/v1/attachment/add_attachment`, data,{ + return http2.post(`/acs/v1/attachment/add_attachment`, data,{ headers: { 'Content-Type': 'multipart/form-data' } @@ -45,20 +45,20 @@ headers: { } /**删除附件 */ export const deleteFile = (data) => { - return http2.get(`/v1/attachment/delete_attachment?aid=${data}`) + return http2.get(`/acs/v1/attachment/delete_attachment?aid=${data}`) } /**用户获取消息列表 */ export const getUserMessageList = (data) => { - return http2.get(`/v1/messages/get_message_list?page=${data.page}&count=${data.count}&message_type=${data.message_type}`) + return http2.get(`/acs/v1/messages/get_message_list?page=${data.page}&count=${data.count}&message_type=${data.message_type}`) } /**用户获取单条消息 */ export const getUserMessage = (data) => { - return http2.get(`/v1/messages/get_message?message_id=${data}`) + return http2.get(`/acs/v1/messages/get_message?message_id=${data}`) } /**获取消息详情 */ export const getMessageDetail = (data) => { - return http2.get(`/v1/messages/get_message?message_id=${data.message_id}`) + return http2.get(`/acs/v1/messages/get_message?message_id=${data.message_id}`) } /**修改图片大小 */ export const compressAndConvertFileToBase64=async(file)=> { diff --git a/src/utils/acs/mirror.js b/src/utils/acs/mirror.js index cbe3a63..9fc23d1 100644 --- a/src/utils/acs/mirror.js +++ b/src/utils/acs/mirror.js @@ -2,19 +2,19 @@ import {http2} from "@/utils/request.js"; /**获取镜像列表 */ export const getMirrorList = data => { if(typeof data == "string"){ - return http2.get("/v1/image/list?server_id=" + data + "&count=9999999") + return http2.get("/acs/v1/image/list?server_id=" + data + "&count=9999999") } - return http2.get(`/v1/image/list?server_id=${data.server_id}&page=${data.page}&count=${data.count}&key=${data.key}&class_id=${data.class_id}`); + return http2.get(`/acs/v1/image/list?server_id=${data.server_id}&page=${data.page}&count=${data.count}&key=${data.key}&class_id=${data.class_id}`); }; /*用户获取镜像列表 */ export const getUserMirrorList = data => { return http2.get( - `/v1/image/list?server_id=${data.server_id}&count=${data.count}&page=${data.page}&key=${data.key}` + `/acs/v1/image/list?server_id=${data.server_id}&count=${data.count}&page=${data.page}&key=${data.key}` ); }; /**上传镜像 */ export const uploadMirror = data => { - return http2.post("/v1/image/pull", data, { + return http2.post("/acs/v1/image/pull", data, { headers: { "Content-Type": "multipart/form-data" } @@ -22,7 +22,7 @@ export const uploadMirror = data => { }; /**编辑镜像 */ export const editMirror = data => { - return http2.post("/v1/image/update", data, { + return http2.post("/acs/v1/image/update", data, { headers: { "Content-Type": "multipart/form-data" } @@ -30,7 +30,7 @@ export const editMirror = data => { }; /**删除镜像 */ export const delMirror = data => { - return http2.post("/v1/image/delete", data, { + return http2.post("/acs/v1/image/delete", data, { headers: { "Content-Type": "multipart/form-data" } @@ -38,11 +38,11 @@ export const delMirror = data => { }; /**镜像同步 */ export const syncMirror = data => { - return http2.get(`/v1/image/sync?server_id=${data}`); + return http2.get(`/acs/v1/image/sync?server_id=${data}`); }; /**重新拉取镜像 */ export const pullMirror = data => { - return http2.post(`/v1/image/repull`, data, { + return http2.post(`/acs/v1/image/repull`, data, { headers: { "Content-Type": "multipart/form-data" } @@ -53,12 +53,12 @@ export const pullMirror = data => { export const Mirrorinfo = data => { const serverType = data.server_type || "dockerContainer"; // 设置默认值 return http2.get( - `/v1/image/info?image_id=${data.image_id}&server_type=${serverType}` + `/acs/v1/image/info?image_id=${data.image_id}&server_type=${serverType}` ); }; export const addVirtualMirror = data => { - return http2.post("/v1/image/create", data, { + return http2.post("/acs/v1/image/create", data, { headers: { "Content-Type": "multipart/form-data" } @@ -67,11 +67,11 @@ export const addVirtualMirror = data => { export const getImageTypeList = (server_id) => { - return http2.get(`/v1/image/class_list?server_id=${server_id}`); + return http2.get(`/acs/v1/image/class_list?server_id=${server_id}`); }; export const createImageType = (server_id,class_name,class_ico) => { - return http2.post("/v1/image/class_create", { + return http2.post("/acs/v1/image/class_create", { server_id, class_name, class_ico @@ -83,7 +83,7 @@ export const createImageType = (server_id,class_name,class_ico) => { }; export const updateImageType = (class_id,class_name,class_ico) => { - return http2.post("/v1/image/class_update", { + return http2.post("/acs/v1/image/class_update", { class_id, class_name, class_ico diff --git a/src/utils/acs/order.js b/src/utils/acs/order.js index 1e37294..19352fe 100644 --- a/src/utils/acs/order.js +++ b/src/utils/acs/order.js @@ -1,11 +1,11 @@ import {http2} from "@/utils/request.js"; /**获取订单列表 */ export const getOrderList = (data) => { - return http2.get(`/v1/admin/trades/get_trades?page=${data.page}&count=${data.count}&key=${data.key}`) + return http2.get(`/acs/v1/admin/trades/get_trades?page=${data.page}&count=${data.count}&key=${data.key}`) } /**编辑订单 */ export const editOrder = (data) => { - return http2.post('/v1/admin/trades/update_trades',data,{ + return http2.post('/acs/v1/admin/trades/update_trades',data,{ headers: { 'Content-Type': 'multipart/form-data' } @@ -13,7 +13,7 @@ headers: { } /**删除订单 */ export const deleteOrder = (data) => { - return http2.post('/v1/admin/trades/delete_trade',data,{ + return http2.post('/acs/v1/admin/trades/delete_trade',data,{ headers: { 'Content-Type': 'multipart/form-data' } @@ -21,5 +21,5 @@ headers: { } /**用户获取订单列表 */ export const getUserOrderList = (data) => { - return http2.get(`/v1/user/procedure/get_trade_list?page=${data.page}&count=${data.count}&key=${data.key}`) + return http2.get(`/acs/v1/user/procedure/get_trade_list?page=${data.page}&count=${data.count}&key=${data.key}`) } \ No newline at end of file diff --git a/src/utils/acs/pay.js b/src/utils/acs/pay.js index 8246250..e31a9c4 100644 --- a/src/utils/acs/pay.js +++ b/src/utils/acs/pay.js @@ -7,7 +7,7 @@ export const get_pay_code = data => { }; // /**email验证码 */ // export const ask_update_user_email = data => { -// return http2.post("/v1/user/info/ask_update_user_email", data, { +// return http2.post("/acs/v1/user/info/ask_update_user_email", data, { // headers: { // "Content-Type": "multipart/form-data" // } @@ -15,7 +15,7 @@ export const get_pay_code = data => { // }; /**获取容器订单金额 */ export const procedure_get_price = data => { - return http2.post("/v1/user/procedure/get_price", data, { + return http2.post("/acs/v1/user/procedure/get_price", data, { headers: { "Content-Type": "multipart/form-data" } @@ -24,7 +24,7 @@ export const procedure_get_price = data => { /**获取虚拟机订单金额 */ export const procedure_vir_price = data => { - return http2.post("/v1/user/procedure/get_vm_price", data, { + return http2.post("/acs/v1/user/procedure/get_vm_price", data, { headers: { "Content-Type": "multipart/form-data" } diff --git a/src/utils/acs/server.js b/src/utils/acs/server.js index 30e767b..7830a83 100644 --- a/src/utils/acs/server.js +++ b/src/utils/acs/server.js @@ -3,13 +3,13 @@ import {http2} from "@/utils/request.js"; /** 获取所有服务器 */ export const getServer = (page, count, key, type = "dockerContainer") => { return http2.get( - `/v1/admin/server/get_server_list?page=${page}&count=${count}&key=${key}&server_type=${type}` + `/acs/v1/admin/server/get_server_list?page=${page}&count=${count}&key=${key}&server_type=${type}` ); }; /**新增服务器 */ export const addServer = data => { - return http2.post("/v1/admin/server/add_server", data, { + return http2.post("/acs/v1/admin/server/add_server", data, { headers: { "Content-Type": "multipart/form-data" } @@ -17,7 +17,7 @@ export const addServer = data => { }; /**编辑服务器 */ export const editServer = data => { - return http2.post("/v1/admin/server/update_server", data, { + return http2.post("/acs/v1/admin/server/update_server", data, { headers: { "Content-Type": "multipart/form-data" } @@ -25,7 +25,7 @@ export const editServer = data => { }; /**删除服务器 */ export const deleteServer = data => { - return http2.post("/v1/admin/server/delete_server", data, { + return http2.post("/acs/v1/admin/server/delete_server", data, { headers: { "Content-Type": "multipart/form-data" } @@ -33,7 +33,7 @@ export const deleteServer = data => { }; /**查询指定服务器 */ export const selectServer = data => { - return http2.post("/v1/admin/server/select_server", data, { + return http2.post("/acs/v1/admin/server/select_server", data, { headers: { "Content-Type": "multipart/form-data" } @@ -42,12 +42,12 @@ export const selectServer = data => { /**获取服务器套餐列表*/ export const getServerPlan = data => { return http2.get( - `/v1/admin/container_plan/get_server_plan_list?server_id=${data.server_id}&count=${data.count}` + `/acs/v1/admin/container_plan/get_server_plan_list?server_id=${data.server_id}&count=${data.count}` ); }; /**获取指定套餐 */ export const selectServerPlan = data => { - return http2.post("/v1/admin/container_plan/get_server_plan_detail", data, { + return http2.post("/acs/v1/admin/container_plan/get_server_plan_detail", data, { headers: { "Content-Type": "multipart/form-data" } @@ -55,7 +55,7 @@ export const selectServerPlan = data => { }; /**新增容器 */ export const addContainer = data => { - return http2.post("/v1/admin/container/add_container", data, { + return http2.post("/acs/v1/admin/container/add_container", data, { headers: { "Content-Type": "multipart/form-data" } @@ -63,7 +63,7 @@ export const addContainer = data => { }; /**删除容器网络 */ export const deleteContainerNetwork = data => { - return http2.post("/v1/user/container/delete_connect", data, { + return http2.post("/acs/v1/user/container/delete_connect", data, { headers: { "Content-Type": "multipart/form-data" } @@ -72,7 +72,7 @@ export const deleteContainerNetwork = data => { /**修改套餐信息 */ export const editServerPlan = data => { - return http2.post("/v1/admin/container_plan/update_server_plan", data, { + return http2.post("/acs/v1/admin/container_plan/update_server_plan", data, { headers: { "Content-Type": "multipart/form-data" } @@ -80,7 +80,7 @@ export const editServerPlan = data => { }; /**新增套餐 */ export const addServerPlan = data => { - return http2.post("/v1/admin/container_plan/add_server_plan", data, { + return http2.post("/acs/v1/admin/container_plan/add_server_plan", data, { headers: { "Content-Type": "multipart/form-data" } @@ -88,7 +88,7 @@ export const addServerPlan = data => { }; /**删除套餐 */ export const deleteServerPlan = data => { - return http2.post("/v1/admin/container_plan/delete_server_plan", data, { + return http2.post("/acs/v1/admin/container_plan/delete_server_plan", data, { headers: { "Content-Type": "multipart/form-data" } @@ -97,19 +97,19 @@ export const deleteServerPlan = data => { /**获取容器列表 */ export const getContainer = data => { return http2.get( - `/v1/admin/container/get_container_list?server_id=${data.server_id}&user_id=${data.user_id}&page=${data.page}&count=${data.count}&key=${data.key}` + `/acs/v1/admin/container/get_container_list?server_id=${data.server_id}&user_id=${data.user_id}&page=${data.page}&count=${data.count}&key=${data.key}` ); }; /**获取虚拟机列表 */ export const getInstanceList = data => { return http2.get( - `/v1/admin/instance/list?server_id=${data.server_id}&user_id=${data.user_id}&page=${data.page}&count=${data.count}&key=${data.key}` + `/acs/v1/admin/instance/list?server_id=${data.server_id}&user_id=${data.user_id}&page=${data.page}&count=${data.count}&key=${data.key}` ); }; /**获取单个指定容器 */ export const getOneContainer = data => { - return http2.post("/v1/admin/container/get_container_detail", data, { + return http2.post("/acs/v1/admin/container/get_container_detail", data, { headers: { "Content-Type": "multipart/form-data" } @@ -117,11 +117,11 @@ export const getOneContainer = data => { }; /**查询指定虚拟机信息(管理员查询) */ export const getVmAdminContainer = id => { - return http2.get(`/v1/admin/instance/detail/${id}`); + return http2.get(`/acs/v1/admin/instance/detail/${id}`); }; // 暂停容器 export const pauseContainer = data => { - return http2.post("/v1/admin/container/pause_container", data, { + return http2.post("/acs/v1/admin/container/pause_container", data, { headers: { "Content-Type": "multipart/form-data" } @@ -129,7 +129,7 @@ export const pauseContainer = data => { }; // 暂停虚拟机 export const pauseInstance = (data, id) => { - return http2.post(`/v1/admin/instance/pause/${id}`, data, { + return http2.post(`/acs/v1/admin/instance/pause/${id}`, data, { headers: { "Content-Type": "multipart/form-data" } @@ -137,7 +137,7 @@ export const pauseInstance = (data, id) => { }; /**恢复虚拟机 */ export const unpauseInstance = (id, data = "") => { - return http2.post(`/v1/admin/instance/resume/${id}`, data, { + return http2.post(`/acs/v1/admin/instance/resume/${id}`, data, { headers: { "Content-Type": "multipart/form-data" } @@ -146,7 +146,7 @@ export const unpauseInstance = (id, data = "") => { // 解除暂停 export const unpauseContainer = data => { - return http2.post("/v1/admin/container/unpause_container", data, { + return http2.post("/acs/v1/admin/container/unpause_container", data, { headers: { "Content-Type": "multipart/form-data" } @@ -154,7 +154,7 @@ export const unpauseContainer = data => { }; /**获取容器状态 */ export const getContainerStatus = data => { - return http2.post("/v1/admin/container/get_container_status", data, { + return http2.post("/acs/v1/admin/container/get_container_status", data, { headers: { "Content-Type": "multipart/form-data" } @@ -162,15 +162,15 @@ export const getContainerStatus = data => { }; /**获取虚拟机状态 */ export const getInstanceStatus = id => { - return http2.get(`/v1/admin/instance/get_state/${id}`); + return http2.get(`/acs/v1/admin/instance/get_state/${id}`); }; /**查询服务器状态 */ export const getServerStatus = id => { - return http2.get(`/v1/admin/server/send_server_status?server_id=${id}`); + return http2.get(`/acs/v1/admin/server/send_server_status?server_id=${id}`); }; /**开通容器 */ export const openContainer = data => { - return http2.post("/v1/admin/container/open_container", data, { + return http2.post("/acs/v1/admin/container/open_container", data, { headers: { "Content-Type": "multipart/form-data" } @@ -178,7 +178,7 @@ export const openContainer = data => { }; /**开通虚拟机 */ export const openInstance = (id, data = "") => { - return http2.post(`/v1/admin/instance/approve/${id}`, data, { + return http2.post(`/acs/v1/admin/instance/approve/${id}`, data, { headers: { "Content-Type": "multipart/form-data" } @@ -186,7 +186,7 @@ export const openInstance = (id, data = "") => { }; /**启动容器 */ export const startContainer = data => { - return http2.post("/v1/admin/container/start_container", data, { + return http2.post("/acs/v1/admin/container/start_container", data, { headers: { "Content-Type": "multipart/form-data" } @@ -194,11 +194,11 @@ export const startContainer = data => { }; /**启动虚拟机 */ export const startInstance = data => { - return http2.get(`/v1/admin/instance/start/${data}`); + return http2.get(`/acs/v1/admin/instance/start/${data}`); }; /**重装容器 */ export const reinstallC = data => { - return http2.post("/v1/admin/container/reinstall_container", data, { + return http2.post("/acs/v1/admin/container/reinstall_container", data, { headers: { "Content-Type": "multipart/form-data" } @@ -206,7 +206,7 @@ export const reinstallC = data => { }; /**重装虚拟机 */ export const reinstallI = (data, id) => { - return http2.post(`/v1/admin/instance/reinstall/${id}`, data, { + return http2.post(`/acs/v1/admin/instance/reinstall/${id}`, data, { headers: { "Content-Type": "multipart/form-data" } @@ -215,7 +215,7 @@ export const reinstallI = (data, id) => { /**获取容器日志 */ export const getContainerLog = data => { - return http2.post(`/v1/admin/container/get_container_log`, data, { + return http2.post(`/acs/v1/admin/container/get_container_log`, data, { headers: { "Content-Type": "multipart/form-data" } @@ -224,13 +224,13 @@ export const getContainerLog = data => { /**获取虚拟机操作日志 */ export const getInstanceLog = (id, data) => { return http2.get( - `/v1/admin/instance/log/${id}?page=${data.page}&count=${data.count}` + `/acs/v1/admin/instance/log/${id}?page=${data.page}&count=${data.count}` ); }; /**重启容器 */ export const restartContainer = data => { - return http2.post("/v1/admin/container/reboot_container", data, { + return http2.post("/acs/v1/admin/container/reboot_container", data, { headers: { "Content-Type": "multipart/form-data" } @@ -238,12 +238,12 @@ export const restartContainer = data => { }; /**重启虚拟机 */ export const restartInstance = data => { - return http2.get(`/v1/admin/instance/reboot/${data}`); + return http2.get(`/acs/v1/admin/instance/reboot/${data}`); }; /**停止容器 */ export const stopContainer = data => { - return http2.post("/v1/admin/container/stop_container", data, { + return http2.post("/acs/v1/admin/container/stop_container", data, { headers: { "Content-Type": "multipart/form-data" } @@ -251,12 +251,12 @@ export const stopContainer = data => { }; /**停止虚拟机 */ export const stopInstance = data => { - return http2.get(`/v1/admin/instance/stop/${data}`); + return http2.get(`/acs/v1/admin/instance/stop/${data}`); }; /**删除容器 */ export const deleteContainer = data => { - return http2.post("/v1/admin/container/delete_container", data, { + return http2.post("/acs/v1/admin/container/delete_container", data, { headers: { "Content-Type": "multipart/form-data" } @@ -264,7 +264,7 @@ export const deleteContainer = data => { }; /**删除虚拟机 */ export const deleteInstance = (id, data = "") => { - return http2.post(`/v1/admin/instance/delete/${id}`, data, { + return http2.post(`/acs/v1/admin/instance/delete/${id}`, data, { headers: { "Content-Type": "multipart/form-data" } @@ -272,7 +272,7 @@ export const deleteInstance = (id, data = "") => { }; /**清除容器流量 */ export const clearContainerTraffic = data => { - return http2.post("/v1/admin/container/clear_container_traffic", data, { + return http2.post("/acs/v1/admin/container/clear_container_traffic", data, { headers: { "Content-Type": "multipart/form-data" } @@ -280,7 +280,7 @@ export const clearContainerTraffic = data => { }; /**连接控制台 */ export const connectConsole = data => { - return http2.post("/v1/admin/container/get_container_console", data, { + return http2.post("/acs/v1/admin/container/get_container_console", data, { headers: { "Content-Type": "multipart/form-data" } @@ -288,7 +288,7 @@ export const connectConsole = data => { }; /**新增虚拟机 (管理员) */ export const addInstance = data => { - return http2.post("/v1/admin/instance/create_vm", data, { + return http2.post("/acs/v1/admin/instance/create_vm", data, { headers: { "Content-Type": "multipart/form-data" } @@ -296,21 +296,21 @@ export const addInstance = data => { }; /**获取虚拟机控制台 */ export const getInstanceConsole = data => { - return http2.get(`/v1/admin/instance/console/${data}`); + return http2.get(`/acs/v1/admin/instance/console/${data}`); }; /**查询容器所有卷信息 */ export const getVolumeList = data => { - return http2.get(`/v1/admin/volume/get_volume_list?instance_id=${data.instance_id}&page=${data.page}&count=${data.count}`); + return http2.get(`/acs/v1/admin/volume/get_volume_list?instance_id=${data.instance_id}&page=${data.page}&count=${data.count}`); }; /**查询虚拟机所有卷信息 */ export const getInstanceVolumeList = data => { return http2.get( - `/v1/admin/volume/get_volume_list?instance_id=${data.instance_id}&page=${data.page}&count=${data.count}` + `/acs/v1/admin/volume/get_volume_list?instance_id=${data.instance_id}&page=${data.page}&count=${data.count}` ); }; /**新增卷 */ export const addVolume = data => { - return http2.post("/v1/admin/volume/add_volume", data, { + return http2.post("/acs/v1/admin/volume/add_volume", data, { headers: { "Content-Type": "multipart/form-data" } @@ -318,7 +318,7 @@ export const addVolume = data => { }; /**修改卷大小 */ export const updateVolume = data => { - return http2.post("/v1/admin/volume/update_volume_size", data, { + return http2.post("/acs/v1/admin/volume/update_volume_size", data, { headers: { "Content-Type": "multipart/form-data" } @@ -326,7 +326,7 @@ export const updateVolume = data => { }; /**删除数据卷 */ export const deleteVolume = data => { - return http2.post("/v1/admin/volume/delete_volume", data, { + return http2.post("/acs/v1/admin/volume/delete_volume", data, { headers: { "Content-Type": "multipart/form-data" } @@ -336,7 +336,7 @@ export const deleteVolume = data => { /**获取容器网络信息 */ export const getNetworkList = data => { return http2.get( - `/v1/container/proxy/get_container_proxy?container_id=${data}` + `/acs/v1/container/proxy/get_container_proxy?container_id=${data}` ); }; /**获取虚拟机端口列表 */ @@ -347,12 +347,12 @@ export const getInstancePortList = data => { if (data.internal_port !== undefined) params.append("internal_port", data.internal_port.toString()); return http2.get( - `/v1/admin/instance_port/list?instance_id=${data.instance_id}&${params.toString()}` + `/acs/v1/admin/instance_port/list?instance_id=${data.instance_id}&${params.toString()}` ); }; /**添加容器网络 */ export const addNetwork = data => { - return http2.post("/v1/container/proxy/add_container_proxy", data, { + return http2.post("/acs/v1/container/proxy/add_container_proxy", data, { headers: { "Content-Type": "multipart/form-data" } @@ -360,7 +360,7 @@ export const addNetwork = data => { }; /**创建端口 */ export const addPort = data => { - return http2.post("/v1/admin/instance_port/create", data, { + return http2.post("/acs/v1/admin/instance_port/create", data, { headers: { "Content-Type": "multipart/form-data" } @@ -369,12 +369,12 @@ export const addPort = data => { /**获取浮动ip列表 */ export const getFloatingIpList = data => { return http2.get( - `/v1/admin/floating_ip/get_list?server_id=${data.server_id}&page=${data.page}&count=${data.count}` + `/acs/v1/admin/floating_ip/get_list?server_id=${data.server_id}&page=${data.page}&count=${data.count}` ); }; /**新增浮动ip */ export const addFloatingIp = data => { - return http2.post("/v1/admin/floating_ip/add", data, { + return http2.post("/acs/v1/admin/floating_ip/add", data, { headers: { "Content-Type": "multipart/form-data" } @@ -382,7 +382,7 @@ export const addFloatingIp = data => { }; /**批量添加浮动ip */ export const addFloatingIpBatch = data => { - return http2.post("/v1/admin/floating_ip/add_list", data, { + return http2.post("/acs/v1/admin/floating_ip/add_list", data, { headers: { "Content-Type": "multipart/form-data" } @@ -390,7 +390,7 @@ export const addFloatingIpBatch = data => { }; /**删除浮动ip */ export const delFloatingIp = data => { - return http2.post("/v1/admin/floating_ip/delete", data, { + return http2.post("/acs/v1/admin/floating_ip/delete", data, { headers: { "Content-Type": "multipart/form-data" } @@ -400,13 +400,13 @@ export const delFloatingIp = data => { /**获取单个用户操作日志 */ export const getUserLog = data => { return http2.get( - `/v1/user/procedure/get_user_log?user_id=${data.user_id}&page=${data.page}&count=${data.count}` + `/acs/v1/user/procedure/get_user_log?user_id=${data.user_id}&page=${data.page}&count=${data.count}` ); }; /**管理员修改头像 */ export const editAvatar = data => { - return http2.post("/v1/admin/users/upload_user_avatar", data, { + return http2.post("/acs/v1/admin/users/upload_user_avatar", data, { headers: { "Content-Type": "multipart/form-data" } @@ -415,28 +415,28 @@ export const editAvatar = data => { /**获取服务器硬盘信息 */ export const getDiskInfo = data => { - return http2.get(`/v1/admin/server/get_server_disk?server_id=${data}`); + return http2.get(`/acs/v1/admin/server/get_server_disk?server_id=${data}`); }; /**获取服务器实际划分硬盘信息 */ export const getRealDisk = data => { - return http2.get(`/v1/admin/server/get_server_disk_info?server_id=${data}`); + return http2.get(`/acs/v1/admin/server/get_server_disk_info?server_id=${data}`); }; /**获取服务器流量信息 */ export const getTraffic = data => { - return http2.get(`/v1/admin/server/get_server_bandwidth?server_id=${data}`); + return http2.get(`/acs/v1/admin/server/get_server_bandwidth?server_id=${data}`); }; /**获取服务器总流量信息 */ export const getTotalTraffic = data => { - return http2.get(`/v1/admin/server/get_server_total_bandwidth?server_id=${data}`); + return http2.get(`/acs/v1/admin/server/get_server_total_bandwidth?server_id=${data}`); }; /**获取版本更新 */ export const getVersion = () => { - return http2.get(`/v1/admin/version`); + return http2.get(`/acs/v1/admin/version`); }; // 管理员删除https网络 export const AdminDelHttps = data => { - return http2.post("/v1/container/proxy/del_https_connet", data, { + return http2.post("/acs/v1/container/proxy/del_https_connet", data, { headers: { "Content-Type": "multipart/form-data" } @@ -445,7 +445,7 @@ export const AdminDelHttps = data => { // 管理员添加https网络 export const AdminAddHttps = data => { - return http2.post("/v1/container/proxy/add_https_proxy", data, { + return http2.post("/acs/v1/container/proxy/add_https_proxy", data, { headers: { "Content-Type": "multipart/form-data" } @@ -453,11 +453,11 @@ export const AdminAddHttps = data => { }; /**获取指定端口信息 */ export const getPortInfo = data => { - return http2.get(`/v1/admin/instance_port/detail?port_id=${data}`); + return http2.get(`/acs/v1/admin/instance_port/detail?port_id=${data}`); }; /**新增卷 */ export const addVolumeMount = data => { - return http2.post("/v1/admin/volume/add_volume", data, { + return http2.post("/acs/v1/admin/volume/add_volume", data, { headers: { "Content-Type": "multipart/form-data" } @@ -466,17 +466,17 @@ export const addVolumeMount = data => { /**进入救援系统 */ export const rescueInstance = id => { - return http2.get(`/v1/admin/instance/rescue/enter/${id}`); + return http2.get(`/acs/v1/admin/instance/rescue/enter/${id}`); }; /**退出救援系统 */ export const exitRescueInstance = id => { - return http2.get(`/v1/admin/instance/rescue/exit/${id}`); + return http2.get(`/acs/v1/admin/instance/rescue/exit/${id}`); }; /**修改虚拟机密码 */ export const changeInstancePassword = (id, data) => { - return http2.post(`/v1/admin/instance/update_password/${id}`, data, { + return http2.post(`/acs/v1/admin/instance/update_password/${id}`, data, { headers: { "Content-Type": "multipart/form-data" } @@ -484,7 +484,7 @@ export const changeInstancePassword = (id, data) => { }; /**修改虚拟机密码(用户) */ export const changeInstancePasswordUser = (id, data) => { - return http2.post(`/v1/user/instance/update_password/${id}`, data, { + return http2.post(`/acs/v1/user/instance/update_password/${id}`, data, { headers: { "Content-Type": "multipart/form-data" } @@ -493,7 +493,7 @@ export const changeInstancePasswordUser = (id, data) => { /**删除端口 */ export const deletePort = data => { - return http2.post("/v1/admin/instance_port/delete", data, { + return http2.post("/acs/v1/admin/instance_port/delete", data, { headers: { "Content-Type": "multipart/form-data" } diff --git a/src/utils/acs/setting.js b/src/utils/acs/setting.js index 1df40b0..b8df5e9 100644 --- a/src/utils/acs/setting.js +++ b/src/utils/acs/setting.js @@ -1,11 +1,11 @@ import {http2} from "@/utils/request.js"; /**获取全局配置 */ export const getSetting = () => { - return http2.get('/v1/admin/settings/get_settings') + return http2.get('/acs/v1/admin/settings/get_settings') } /**变更设置 */ export const updateSetting = (data) => { - return http2.post('/v1/admin/settings/update_settings', data, { + return http2.post('/acs/v1/admin/settings/update_settings', data, { headers: { 'Content-Type': 'multipart/form-data' } @@ -13,7 +13,7 @@ export const updateSetting = (data) => { } /**新增设置 */ export const addSetting = (data) => { - return http2.post('/v1/admin/settings/add_settings', data, { + return http2.post('/acs/v1/admin/settings/add_settings', data, { headers: { 'Content-Type': 'multipart/form-data' } @@ -21,7 +21,7 @@ export const addSetting = (data) => { } /**删除设置 */ export const deleteSetting = (data) => { - return http2.post('/v1/admin/settings/delete_settings', data,{ + return http2.post('/acs/v1/admin/settings/delete_settings', data,{ headers: { 'Content-Type': 'multipart/form-data' } @@ -29,12 +29,12 @@ export const deleteSetting = (data) => { } /**获取单项配置 */ export const getOneSetting = (data) => { - return http2.get(`/v1/admin/settings/get_setting?name=${data}`) + return http2.get(`/acs/v1/admin/settings/get_setting?name=${data}`) } /**获取多个配置 */ export const getSettings = (data) => { - // return http2.get(`/v1/admin/settings/get_settings?names=${data}`); + // return http2.get(`/acs/v1/admin/settings/get_settings?names=${data}`); const namesParam = data.join(','); // 将处理后的namesParam放入URL中 - return http2.get(`/v1/admin/settings/get_setting?names=${encodeURIComponent(namesParam)}`); + return http2.get(`/acs/v1/admin/settings/get_setting?names=${encodeURIComponent(namesParam)}`); } \ No newline at end of file diff --git a/src/utils/acs/user-set.js b/src/utils/acs/user-set.js index 840cdd9..4dcf941 100644 --- a/src/utils/acs/user-set.js +++ b/src/utils/acs/user-set.js @@ -1,11 +1,11 @@ import {http2} from "@/utils/request.js"; /**获取用户列表 */ export const ask_update_user_email11 = data => { - return http2.get(`/v1/user/info/ask_update_user_email?email=${data.email}`); + return http2.get(`/acs/v1/user/info/ask_update_user_email?email=${data.email}`); }; /**email验证码 */ export const ask_update_user_email = data => { - return http2.post("/v1/user/info/ask_update_user_email", data, { + return http2.post("/acs/v1/user/info/ask_update_user_email", data, { headers: { "Content-Type": "multipart/form-data" } @@ -13,7 +13,7 @@ export const ask_update_user_email = data => { }; /**email修改 */ export const update_user_email = data => { - return http2.post("/v1/user/info/update_user_email", data, { + return http2.post("/acs/v1/user/info/update_user_email", data, { headers: { "Content-Type": "multipart/form-data" } @@ -21,7 +21,7 @@ export const update_user_email = data => { }; /**phone验证码 */ export const ask_update_user_phone = data => { - return http2.post("/v1/user/info/ask_update_user_phone", data, { + return http2.post("/acs/v1/user/info/ask_update_user_phone", data, { headers: { "Content-Type": "multipart/form-data" } @@ -29,7 +29,7 @@ export const ask_update_user_phone = data => { }; /**phone修改 */ export const update_user_phone = data => { - return http2.post("/v1/user/info/update_user_phone", data, { + return http2.post("/acs/v1/user/info/update_user_phone", data, { headers: { "Content-Type": "multipart/form-data" } @@ -37,7 +37,7 @@ export const update_user_phone = data => { }; /**密码修改 */ export const update_user_password = data => { - return http2.post("/v1/user/info/update_user_password", data, { + return http2.post("/acs/v1/user/info/update_user_password", data, { headers: { "Content-Type": "multipart/form-data" } diff --git a/src/utils/acs/user.js b/src/utils/acs/user.js index e3980e9..64e35a9 100644 --- a/src/utils/acs/user.js +++ b/src/utils/acs/user.js @@ -4,12 +4,12 @@ import {http2} from "@/utils/request.js"; // 获取图像验证码 export const Captch = data => { - return http2.get(`/v1/user/check/get_code_img`); + return http2.get(`/acs/v1/user/check/get_code_img`); }; /** 登录 */ export const getLogin = data => { - return http2.post("/v1/user/login", data, { + return http2.post("/acs/v1/user/login", data, { headers: { "Content-Type": "multipart/form-data" } @@ -24,12 +24,12 @@ export const getLogin = data => { /**获取用户列表 */ export const getUserList = data => { return http2.get( - `/v1/admin/users/get_user_list?page=${data.page}&count=${data.count}&key=${data.key}` + `/acs/v1/admin/users/get_user_list?page=${data.page}&count=${data.count}&key=${data.key}` ); }; /**添加用户 */ export const addUser = data => { - return http2.post("/v1/admin/users/add_user", data, { + return http2.post("/acs/v1/admin/users/add_user", data, { headers: { "Content-Type": "multipart/form-data" } @@ -37,7 +37,7 @@ export const addUser = data => { }; /**编辑用户信息 */ export const editUser = data => { - return http2.post("/v1/admin/users/update_user", data, { + return http2.post("/acs/v1/admin/users/update_user", data, { headers: { "Content-Type": "multipart/form-data" } @@ -45,7 +45,7 @@ export const editUser = data => { }; /**修改用户密码 */ export const editPassword = data => { - return http2.post("/v1/admin/users/update_user_password", data, { + return http2.post("/acs/v1/admin/users/update_user_password", data, { headers: { "Content-Type": "multipart/form-data" } @@ -53,7 +53,7 @@ export const editPassword = data => { }; /**删除用户 */ export const deleteUser = data => { - return http2.post("/v1/admin/users/del_user", data, { + return http2.post("/acs/v1/admin/users/del_user", data, { headers: { "Content-Type": "multipart/form-data" } @@ -61,7 +61,7 @@ export const deleteUser = data => { }; /**查询单个用户 */ export const userDetail = data => { - return http2.post("/v1/admin/users/select_user", data, { + return http2.post("/acs/v1/admin/users/select_user", data, { headers: { "Content-Type": "multipart/form-data" } @@ -69,7 +69,7 @@ export const userDetail = data => { }; /**修改用户余额 */ export const editBalance = data => { - return http2.post("/v1/admin/users/update_user_balance", data, { + return http2.post("/acs/v1/admin/users/update_user_balance", data, { headers: { "Content-Type": "multipart/form-data" } @@ -79,12 +79,12 @@ export const editBalance = data => { export const getUserServer = (data = {}) => { const serverType = data.server_type || "dockerContainer"; // 设置默认值 return http2.get( - `/v1/user/procedure/get_server_list?server_type=${serverType}` + `/acs/v1/user/procedure/get_server_list?server_type=${serverType}` ); }; /**用户获取虚拟机列表 */ export const getVirtualList = data => { - let url = `/v1/user/instance/list?page=${data.page}&count=${data.count}`; + let url = `/acs/v1/user/instance/list?page=${data.page}&count=${data.count}`; if (data.key) { url += `&key=${data.key}`; } @@ -95,35 +95,35 @@ export const getVirtualList = data => { }; /**用户获取服务器套餐 */ export const getUserPackage = data => { - return http2.get(`/v1/user/procedure/get_server_plan_list?server_id=${data}`); + return http2.get(`/acs/v1/user/procedure/get_server_plan_list?server_id=${data}`); }; /**获取用户容器列表 */ export const getUserContainer = data => { return http2.get( - `/v1/user/container/list?page=${data.page}&count=${data.count}` + `/acs/v1/user/container/list?page=${data.page}&count=${data.count}` ); }; /**用户按地区获取容器 */ export const getUserContainerD = data => { return http2.get( - `/v1/user/container/list?page=${data.page}&count=${data.count}&server_id=${data.server_id}` + `/acs/v1/user/container/list?page=${data.page}&count=${data.count}&server_id=${data.server_id}` ); }; /**获取用户操作日志 */ export const get_user_log = () => { - return http2.get(`/v1/user/procedure/get_user_log`); + return http2.get(`/acs/v1/user/procedure/get_user_log`); }; /**获取用户自身信息 */ export const getUserInfo = () => { - return http2.get(`/v1/user/procedure/get_user_info`); + return http2.get(`/acs/v1/user/procedure/get_user_info`); }; /**获取用户自身信息 */ export const getUserInfoV1 = () => { - return http2.get(`/v1/user/info/get_user_info`); + return http2.get(`/acs/v1/user/info/get_user_info`); }; /**用户实名 */ export const realName = data => { - return http2.post("/v1/external/real_name", data, { + return http2.post("/acs/v1/external/real_name", data, { headers: { "Content-Type": "multipart/form-data" } @@ -131,7 +131,7 @@ export const realName = data => { }; /**发送手机验证码 */ export const sendCode = data => { - return http2.post("/v1/external/send_message", data, { + return http2.post("/acs/v1/external/send_message", data, { headers: { "Content-Type": "multipart/form-data" } @@ -139,7 +139,7 @@ export const sendCode = data => { }; /**发送邮箱验证码 */ export const sendEmailCode = data => { - return http2.post("/v1/external/send_email", data, { + return http2.post("/acs/v1/external/send_email", data, { headers: { "Content-Type": "multipart/form-data" } @@ -147,7 +147,7 @@ export const sendEmailCode = data => { }; /**用户注册 */ export const register = data => { - return http2.post("/v1/user/register", data, { + return http2.post("/acs/v1/user/register", data, { headers: { "Content-Type": "multipart/form-data" } @@ -155,7 +155,7 @@ export const register = data => { }; /**手机号修改校证码 */ export const CodePhone = data => { - return http2.post("/v1/user/info/ask_update_user_phone", data, { + return http2.post("/acs/v1/user/info/ask_update_user_phone", data, { headers: { "Content-Type": "multipart/form-data" } @@ -163,7 +163,7 @@ export const CodePhone = data => { }; /**修改手机号码 */ export const SetPhone = data => { - return http2.post("/v1/user/info/update_user_phone", data, { + return http2.post("/acs/v1/user/info/update_user_phone", data, { headers: { "Content-Type": "multipart/form-data" } @@ -171,7 +171,7 @@ export const SetPhone = data => { }; /**邮箱修改校证码 */ export const CodeEmail = data => { - return http2.post("/v1/user/info/ask_update_user_email", data, { + return http2.post("/acs/v1/user/info/ask_update_user_email", data, { headers: { "Content-Type": "multipart/form-data" } @@ -179,7 +179,7 @@ export const CodeEmail = data => { }; /**修改邮箱 */ export const SetEmail = data => { - return http2.post("/v1/user/info/update_user_email", data, { + return http2.post("/acs/v1/user/info/update_user_email", data, { headers: { "Content-Type": "multipart/form-data" } @@ -187,7 +187,7 @@ export const SetEmail = data => { }; /**上传头像 */ export const uploadAvatar = data => { - return http2.post("/v1/user/info/upload_user_avatar", data, { + return http2.post("/acs/v1/user/info/upload_user_avatar", data, { headers: { "Content-Type": "multipart/form-data" } @@ -195,7 +195,7 @@ export const uploadAvatar = data => { }; /**手机号忘记密码 */ export const forgetphone = data => { - return http2.post("/v1/user/info/forget_user_password_phone", data, { + return http2.post("/acs/v1/user/info/forget_user_password_phone", data, { headers: { "Content-Type": "multipart/form-data" } @@ -204,7 +204,7 @@ export const forgetphone = data => { /**邮箱忘记密码 */ export const forgetemail = data => { - return http2.post("/v1/user/info/forget_user_password_email", data, { + return http2.post("/acs/v1/user/info/forget_user_password_email", data, { headers: { "Content-Type": "multipart/form-data" } @@ -212,7 +212,7 @@ export const forgetemail = data => { }; /**管理员全局搜索 */ export const Find = data => { - return http2.post("/v1/admin/search", data, { + return http2.post("/acs/v1/admin/search", data, { headers: { "Content-Type": "multipart/form-data" } @@ -220,7 +220,7 @@ export const Find = data => { }; // 管理员删除容器网络 export const delContainer = data => { - return http2.post("/v1/user/container/delete_connect", data, { + return http2.post("/acs/v1/user/container/delete_connect", data, { headers: { "Content-Type": "multipart/form-data" } @@ -228,7 +228,7 @@ export const delContainer = data => { }; // 删除端口 export const delPort = data => { - return http2.post("/v1/admin/instance_port/delete", data, { + return http2.post("/acs/v1/admin/instance_port/delete", data, { headers: { "Content-Type": "multipart/form-data" } @@ -236,7 +236,7 @@ export const delPort = data => { }; // 自定义容器价格 export const Containerpay = data => { - return http2.post("/v1/admin/container/update_container_price", data, { + return http2.post("/acs/v1/admin/container/update_container_price", data, { headers: { "Content-Type": "multipart/form-data" } @@ -244,7 +244,7 @@ export const Containerpay = data => { }; // 修改虚拟机续费价格 export const Containerpaytime = (data, id) => { - return http2.post(`/v1/admin/instance/update_price/${id}`, data, { + return http2.post(`/acs/v1/admin/instance/update_price/${id}`, data, { headers: { "Content-Type": "multipart/form-data" } @@ -252,7 +252,7 @@ export const Containerpaytime = (data, id) => { }; // 自定义容器到期时间 export const Containertime = data => { - return http2.post("/v1/admin/container/update_container_expire_time", data, { + return http2.post("/acs/v1/admin/container/update_container_expire_time", data, { headers: { "Content-Type": "multipart/form-data" } @@ -260,7 +260,7 @@ export const Containertime = data => { }; // 修改虚拟机续到期时间 export const Containertimetime = (data, id) => { - return http2.post(`/v1/admin/instance/update_expire_time/${id}`, data, { + return http2.post(`/acs/v1/admin/instance/update_expire_time/${id}`, data, { headers: { "Content-Type": "multipart/form-data" } @@ -268,7 +268,7 @@ export const Containertimetime = (data, id) => { }; // 修改虚拟机信息 export const editContainer = (data, id) => { - return http2.post(`/v1/admin/instance/update/${id}`, data, { + return http2.post(`/acs/v1/admin/instance/update/${id}`, data, { headers: { "Content-Type": "multipart/form-data" } @@ -280,7 +280,7 @@ export const editContainer = (data, id) => { /** 容器操作 */ export const startUserContainer = (type, id) => { return http2.post( - "/v1/user/container/" + type, + "/acs/v1/user/container/" + type, { container_id: id }, @@ -293,7 +293,7 @@ export const startUserContainer = (type, id) => { }; /**用户容器退款 */ export const backUserContainer = data => { - return http2.post("/v1/user/container/delete", data, { + return http2.post("/acs/v1/user/container/delete", data, { headers: { "Content-Type": "multipart/form-data" } @@ -301,7 +301,7 @@ export const backUserContainer = data => { }; /**重装容器 */ export const reinContainer = data => { - return http2.post("/v1/user/container/reinstall", data, { + return http2.post("/acs/v1/user/container/reinstall", data, { headers: { "Content-Type": "multipart/form-data" } @@ -309,7 +309,7 @@ export const reinContainer = data => { }; /**重装虚拟机 */ export const reinVmContainer = (id, data) => { - return http2.post(`/v1/user/instance/reinstall/${id}`, data, { + return http2.post(`/acs/v1/user/instance/reinstall/${id}`, data, { headers: { "Content-Type": "multipart/form-data" } @@ -318,7 +318,7 @@ export const reinVmContainer = (id, data) => { /** 容器操作 */ export const startAdminContainer = (type, id) => { return http2.post( - "/v1/admin/container/" + type, + "/acs/v1/admin/container/" + type, { container_id: id }, @@ -331,7 +331,7 @@ export const startAdminContainer = (type, id) => { }; /** 容器操作 */ export const procedureUpdateContainerRenew = data => { - return http2.post("/v1/user/procedure/update_container_renew", data, { + return http2.post("/acs/v1/user/procedure/update_container_renew", data, { headers: { "Content-Type": "multipart/form-data" } @@ -339,15 +339,15 @@ export const procedureUpdateContainerRenew = data => { }; /**获取容器完整信息 */ export const getContainerDetail = id => { - return http2.get(`/v1/user/container/detail?container_id=${id}`); + return http2.get(`/acs/v1/user/container/detail?container_id=${id}`); }; /**获取虚拟机完整信息 */ export const getVmContainerDetail = id => { - return http2.get(`/v1/user/instance/detail/${id}`); + return http2.get(`/acs/v1/user/instance/detail/${id}`); }; /**容器操作信息 */ export const containerLog = data => { - return http2.post("/v1/user/container/logs", data, { + return http2.post("/acs/v1/user/container/logs", data, { headers: { "Content-Type": "multipart/form-data" } @@ -356,12 +356,12 @@ export const containerLog = data => { /**虚拟机操作日志 */ export const vmLog = data => { return http2.get( - `/v1/user/instance/log/${data.id}?page=${data.page}&count=${data.count}` + `/acs/v1/user/instance/log/${data.id}?page=${data.page}&count=${data.count}` ); }; /**获取容器状态 */ export const getContainerStatus = data => { - return http2.post(`/v1/user/container/status`, data, { + return http2.post(`/acs/v1/user/container/status`, data, { headers: { "Content-Type": "multipart/form-data" } @@ -369,11 +369,11 @@ export const getContainerStatus = data => { }; /**获取虚拟机状态 */ export const getVmStatus = id => { - return http2.get(`/v1/user/instance/get_state/${id}`); + return http2.get(`/acs/v1/user/instance/get_state/${id}`); }; /**获取容器运行日志 */ export const getContainerLog = data => { - return http2.post(`/v1/user/container/run_logs`, data, { + return http2.post(`/acs/v1/user/container/run_logs`, data, { headers: { "Content-Type": "multipart/form-data" } @@ -381,7 +381,7 @@ export const getContainerLog = data => { }; /**获取容器购买网络订单 */ export const getContainerList = data => { - return http2.post(`/v1/user/procedure/add_network`, data, { + return http2.post(`/acs/v1/user/procedure/add_network`, data, { headers: { "Content-Type": "multipart/form-data" } @@ -389,7 +389,7 @@ export const getContainerList = data => { }; /**计算容器网络价格 */ export const getContainerPrice = data => { - return http2.post(`/v1/user/procedure/get_price_network`, data, { + return http2.post(`/acs/v1/user/procedure/get_price_network`, data, { headers: { "Content-Type": "multipart/form-data" } @@ -397,33 +397,33 @@ export const getContainerPrice = data => { }; /** 启动虚拟机 */ export const start_vm = id => { - return http2.get(`/v1/user/instance/start/${id}`); + return http2.get(`/acs/v1/user/instance/start/${id}`); }; /** 停止虚拟机(关机) */ export const stop_vm = id => { - return http2.get(`/v1/user/instance/stop/${id}`); + return http2.get(`/acs/v1/user/instance/stop/${id}`); }; /**重启虚拟机 */ export const restart_vm = id => { - return http2.get(`/v1/user/instance/reboot/${id}`); + return http2.get(`/acs/v1/user/instance/reboot/${id}`); }; /**获取虚拟机控制台 */ export const get_vm_console = id => { - return http2.get(`/v1/user/instance/console/${id}`); + return http2.get(`/acs/v1/user/instance/console/${id}`); }; /**进入救援系统 */ export const rescue_vm = id => { - return http2.get(`/v1/user/instance/rescue/enter/${id}`); + return http2.get(`/acs/v1/user/instance/rescue/enter/${id}`); }; /**退出救援系统 */ export const unrescue_vm = id => { - return http2.get(`/v1/user/instance/rescue/exit/${id}`); + return http2.get(`/acs/v1/user/instance/rescue/exit/${id}`); }; // ******************************* new /** 提交充值订单 */ export const user_update_container_recharge = data => { - return http2.post("/v1/user/procedure/update_container_recharge", data, { + return http2.post("/acs/v1/user/procedure/update_container_recharge", data, { headers: { "Content-Type": "multipart/form-data" } @@ -431,7 +431,7 @@ export const user_update_container_recharge = data => { }; /** 提交容器订单 */ export const user_update_plan_info = data => { - return http2.post("/v1/user/procedure/update_plan_info", data, { + return http2.post("/acs/v1/user/procedure/update_plan_info", data, { headers: { "Content-Type": "multipart/form-data" } @@ -439,7 +439,7 @@ export const user_update_plan_info = data => { }; /** 提交虚拟机订单 */ export const user_update_vm_info = data => { - return http2.post("/v1/user/procedure/create_vm_trade", data, { + return http2.post("/acs/v1/user/procedure/create_vm_trade", data, { headers: { "Content-Type": "multipart/form-data" } @@ -447,11 +447,11 @@ export const user_update_vm_info = data => { }; /**获取订单简略信息 */ export const getOrderDetail = id => { - return http2.get(`/v1/user/procedure/get_low_trade_info?trade_id=${id}`); + return http2.get(`/acs/v1/user/procedure/get_low_trade_info?trade_id=${id}`); }; /**支付请求 */ export const pay_request = data => { - return http2.post("/v1/external/pay", data, { + return http2.post("/acs/v1/external/pay", data, { headers: { "Content-Type": "multipart/form-data" } @@ -459,7 +459,7 @@ export const pay_request = data => { }; /**用户删除容器网络 */ export const deleteConNet = data => { - return http2.post("/v1/user/container/delete_connect", data, { + return http2.post("/acs/v1/user/container/delete_connect", data, { headers: { "Content-Type": "multipart/form-data" } @@ -468,7 +468,7 @@ export const deleteConNet = data => { // 添加https export const additionHttp = data => { - return http2.post("/v1/user/container/add_https_connet", data, { + return http2.post("/acs/v1/user/container/add_https_connet", data, { headers: { "Content-Type": "multipart/form-data" } @@ -477,7 +477,7 @@ export const additionHttp = data => { // 删除https export const DelHttp = data => { - return http2.post("/v1/user/container/del_https_connet", data, { + return http2.post("/acs/v1/user/container/del_https_connet", data, { headers: { "Content-Type": "multipart/form-data" } @@ -485,7 +485,7 @@ export const DelHttp = data => { }; /**获取新增虚拟机端口价格 */ export const getVmPortPrice = data => { - return http2.post("/v1/user/procedure/get_price_instance_port", data, { + return http2.post("/acs/v1/user/procedure/get_price_instance_port", data, { headers: { "Content-Type": "multipart/form-data" } @@ -493,7 +493,7 @@ export const getVmPortPrice = data => { }; /**提交新增虚拟机端口订单 */ export const addVmPort = data => { - return http2.post("/v1/user/procedure/add_instance_port", data, { + return http2.post("/acs/v1/user/procedure/add_instance_port", data, { headers: { "Content-Type": "multipart/form-data" } diff --git a/src/utils/acs/virtual.js b/src/utils/acs/virtual.js index b3e4522..7677122 100644 --- a/src/utils/acs/virtual.js +++ b/src/utils/acs/virtual.js @@ -3,7 +3,7 @@ import {http2} from "@/utils/request.js"; /**获取虚拟机列表 */ export const getVirtualList = data => { - let url = `/v1/admin/instance/list?page=${data.page}&count=${data.count}`; + let url = `/acs/v1/admin/instance/list?page=${data.page}&count=${data.count}`; if (data.key) { url += `&key=${data.key}`; } @@ -18,12 +18,12 @@ export const getVirtualList = data => { /**新增虚拟机 */ export const addVirtual = data => { - return http2.post("/v1/admin/instance/create_vm", data); + return http2.post("/acs/v1/admin/instance/create_vm", data); }; /**迁移数据卷 */ export const migrate_disk = data => { - return http2.post("/v1/admin/volume/migrate_volume", data, { + return http2.post("/acs/v1/admin/volume/migrate_volume", data, { headers: { "Content-Type": "multipart/form-data" } @@ -32,18 +32,18 @@ export const migrate_disk = data => { /**获取虚拟机访问控制列表 */ export const getVirtualAccessList = data => { - let url = `/v1/admin/instance/access_control/list?page=${data.page}&count=${data.count}&instance_id=${data.instance_id}`; + let url = `/acs/v1/admin/instance/access_control/list?page=${data.page}&count=${data.count}&instance_id=${data.instance_id}`; return http2.get(url); }; /**获取虚拟机访问控制列表(用户) */ export const getUserAccessList = data => { - let url = `/v1/user/instance/access_control/list?page=${data.page}&count=${data.count}&instance_id=${data.instance_id}`; + let url = `/acs/v1/user/instance/access_control/list?page=${data.page}&count=${data.count}&instance_id=${data.instance_id}`; return http2.get(url); }; /**创建访问控制 */ export const createAccessControl = data => { - return http2.post("/v1/admin/instance/access_control/create", data, { + return http2.post("/acs/v1/admin/instance/access_control/create", data, { headers: { "Content-Type": "multipart/form-data" } @@ -51,7 +51,7 @@ export const createAccessControl = data => { }; /**创建访问控制(用户) */ export const createUserAccessControl = data => { - return http2.post("/v1/user/instance/access_control/create", data, { + return http2.post("/acs/v1/user/instance/access_control/create", data, { headers: { "Content-Type": "multipart/form-data" } @@ -59,7 +59,7 @@ export const createUserAccessControl = data => { }; /**删除访问控制 */ export const deleteAccessControl = data => { - return http2.post("/v1/admin/instance/access_control/delete", data, { + return http2.post("/acs/v1/admin/instance/access_control/delete", data, { headers: { "Content-Type": "multipart/form-data" } @@ -67,7 +67,7 @@ export const deleteAccessControl = data => { }; /**删除访问控制(用户) */ export const deleteUserAccessControl = data => { - return http2.post("/v1/user/instance/access_control/delete", data, { + return http2.post("/acs/v1/user/instance/access_control/delete", data, { headers: { "Content-Type": "multipart/form-data" } @@ -76,17 +76,17 @@ export const deleteUserAccessControl = data => { /**获取虚拟机快照列表 */ export const getSnapshotList = data => { - let url = `/v1/admin/instance/snapshot/list/${data.instance_id}?page=${data.page}&count=${data.count}`; + let url = `/acs/v1/admin/instance/snapshot/list/${data.instance_id}?page=${data.page}&count=${data.count}`; return http2.get(url); }; /**获取虚拟机快照列表(用户) */ export const getUserSnapshotList = data => { - let url = `/v1/user/instance/snapshot/list/${data.instance_id}?page=${data.page}&count=${data.count}`; + let url = `/acs/v1/user/instance/snapshot/list/${data.instance_id}?page=${data.page}&count=${data.count}`; return http2.get(url); }; /**创建虚拟机快照 */ export const createSnapshot = (data, id) => { - return http2.post(`/v1/admin/instance/snapshot/create/${id}`, data, { + return http2.post(`/acs/v1/admin/instance/snapshot/create/${id}`, data, { headers: { "Content-Type": "multipart/form-data" } @@ -94,7 +94,7 @@ export const createSnapshot = (data, id) => { }; /**创建虚拟机快照(用户) */ export const createUserSnapshot = (data, id) => { - return http2.post(`/v1/user/instance/snapshot/create/${id}`, data, { + return http2.post(`/acs/v1/user/instance/snapshot/create/${id}`, data, { headers: { "Content-Type": "multipart/form-data" } @@ -103,7 +103,7 @@ export const createUserSnapshot = (data, id) => { /**删除虚拟机快照 */ export const deleteSnapshot = (data, id) => { - return http2.post(`/v1/admin/instance/snapshot/delete/${id}`, data, { + return http2.post(`/acs/v1/admin/instance/snapshot/delete/${id}`, data, { headers: { "Content-Type": "multipart/form-data" } @@ -112,7 +112,7 @@ export const deleteSnapshot = (data, id) => { /**恢复虚拟机快照 */ export const recoverSnapshot = (data, id) => { - return http2.post(`/v1/admin/instance/snapshot/restore/${id}`, data, { + return http2.post(`/acs/v1/admin/instance/snapshot/restore/${id}`, data, { headers: { "Content-Type": "multipart/form-data" } @@ -120,7 +120,7 @@ export const recoverSnapshot = (data, id) => { }; /**恢复虚拟机快照(用户) */ export const recoverUserSnapshot = (data, id) => { - return http2.post(`/v1/user/instance/snapshot/restore/${id}`, data, { + return http2.post(`/acs/v1/user/instance/snapshot/restore/${id}`, data, { headers: { "Content-Type": "multipart/form-data" } @@ -129,24 +129,24 @@ export const recoverUserSnapshot = (data, id) => { /**获取实时监控 */ export const getVirtualLog = data => { return http2.get( - `/v1/admin/instance/run_logs/${data.id}?start_time=${data.start_time}&end_time=${data.end_time}` + `/acs/v1/admin/instance/run_logs/${data.id}?start_time=${data.start_time}&end_time=${data.end_time}` ); }; /**获取实时监控(用户) */ export const getUserVirtualLog = data => { return http2.get( - `/v1/user/instance/run_logs/${data.id}?start_time=${data.start_time}&end_time=${data.end_time}` + `/acs/v1/user/instance/run_logs/${data.id}?start_time=${data.start_time}&end_time=${data.end_time}` ); }; /**获取新增虚拟机快照数量价格 */ export const getSnapshotPrice = data => { - return http2.get(`/v1/user/procedure/get_price_snapshot?num=${data}`); + return http2.get(`/acs/v1/user/procedure/get_price_snapshot?num=${data}`); }; /**提交虚拟机购买快照订单 */ export const submitSnapshotOrder = data => { - return http2.post("/v1/user/procedure/update_container_snapshot", data, { + return http2.post("/acs/v1/user/procedure/update_container_snapshot", data, { headers: { "Content-Type": "multipart/form-data" } @@ -154,7 +154,7 @@ export const submitSnapshotOrder = data => { }; // 获取购买虚拟机数据卷价格 export const getVolumePrice = data => { - return http2.post("/v1/user/procedure/get_price_volume", data, { + return http2.post("/acs/v1/user/procedure/get_price_volume", data, { headers: { "Content-Type": "multipart/form-data" } @@ -163,7 +163,7 @@ export const getVolumePrice = data => { // 提交虚拟机数据卷订单 export const submitVolumeOrder = data => { - return http2.post("/v1/user/procedure/update_container_volume", data, { + return http2.post("/acs/v1/user/procedure/update_container_volume", data, { headers: { "Content-Type": "multipart/form-data" } diff --git a/src/utils/request.js b/src/utils/request.js index 5634548..93c5e00 100644 --- a/src/utils/request.js +++ b/src/utils/request.js @@ -93,8 +93,8 @@ class Request { } // DELETE 请求 - delete(url, config = {}) { - return this.instance.delete(url, config) + delete(url,data={}, config = {}) { + return this.instance.delete(url,data, config) } // PATCH 请求 @@ -112,7 +112,8 @@ const request = new Request({ } }) -export const mainUrl = baseUrl + "/acs" +export const mainUrl = baseUrl + '/acs' +export const baseURL = baseUrl export const http2 = axios.create({ baseURL: baseUrl, @@ -132,7 +133,7 @@ http2.interceptors.request.use(config => { } config.headers.Authorization = `Bearer ${token}`; - config.url = '/acs' + config.url + config.url = config.url return config }) diff --git a/src/utils/tool.js b/src/utils/tool.js index 35afa7a..3d0a39f 100644 --- a/src/utils/tool.js +++ b/src/utils/tool.js @@ -1,4 +1,54 @@ export const FileName = (data) =>{ let name = data.split("/").pop() return name -} \ No newline at end of file +} +export const formatTime = (time) => { + return new Date(time).toLocaleString() +} + +export const formatDate = (dateStr) => { + if (!dateStr || dateStr === '0001-01-01T00:00:00Z' || dateStr === null) return '-' + const date = new Date(dateStr) + if (isNaN(date.getTime())) return '-' + const year = date.getFullYear() + const month = String(date.getMonth() + 1).padStart(2, '0') + const day = String(date.getDate()).padStart(2, '0') + const hours = String(date.getHours()).padStart(2, '0') + const minutes = String(date.getMinutes()).padStart(2, '0') + return `${year}-${month}-${day} ${hours}:${minutes}` +} +/** + * 时间格式转 Unix 时间戳(毫秒级) + * @param {string|Date} time - 输入时间(支持 '2025-10-28 00:00:00'、'2025/10/28'、Date 对象等) + * @returns {number|null} 转换后的毫秒级时间戳(失败返回 null) + */ +export function timeToTimestamp(time) { + let date; + + // 处理字符串格式(如 '2025-10-28 00:00:00' 或 '2025/10/28') + if (typeof time === 'string') { + // 替换 '-' 为 '/'(避免 Safari 等浏览器对 '-' 格式解析失败) + const formattedTime = time.replace(/-/g, '/'); + date = new Date(formattedTime); + } + + // 处理 Date 对象 + else if (time instanceof Date) { + date = time; + } + + // 无效输入 + else { + console.error('无效的时间格式,支持字符串(如 "2025-10-28 00:00:00")或 Date 对象'); + return null; + } + + // 验证时间是否有效 + const timestamp = date.getTime(); + if (isNaN(timestamp)) { + console.error(`无法解析时间:${time}`); + return null; + } + + return Math.floor(timestamp / 1000); // 返回毫秒级时间戳(如 1751107200000) + } \ No newline at end of file diff --git a/src/views/Login.vue b/src/views/Login.vue index 0be731d..88bf59b 100644 --- a/src/views/Login.vue +++ b/src/views/Login.vue @@ -108,6 +108,7 @@ const handleLogin = () => { if (valid) { loading.value = true let resp = await userLogin(loginForm.username, loginForm.password) + console.log("login:",resp) loading.value = false if(resp.code === 200){ diff --git a/src/views/activity/SigninActivity.vue b/src/views/activity/SigninActivity.vue new file mode 100644 index 0000000..8c596b6 --- /dev/null +++ b/src/views/activity/SigninActivity.vue @@ -0,0 +1,436 @@ + + + + + + diff --git a/src/views/marketing/DiscountCode.vue b/src/views/marketing/DiscountCode.vue new file mode 100644 index 0000000..f1db928 --- /dev/null +++ b/src/views/marketing/DiscountCode.vue @@ -0,0 +1,533 @@ + + + + + + + diff --git a/src/views/marketing/DiscountGoods.vue b/src/views/marketing/DiscountGoods.vue new file mode 100644 index 0000000..7a652a0 --- /dev/null +++ b/src/views/marketing/DiscountGoods.vue @@ -0,0 +1,719 @@ + + + + + + diff --git a/src/views/marketing/DiscountUsers.vue b/src/views/marketing/DiscountUsers.vue new file mode 100644 index 0000000..9c714ce --- /dev/null +++ b/src/views/marketing/DiscountUsers.vue @@ -0,0 +1,883 @@ + + + + + + diff --git a/src/views/marketing/UserVoucher.vue b/src/views/marketing/UserVoucher.vue new file mode 100644 index 0000000..7f98b2f --- /dev/null +++ b/src/views/marketing/UserVoucher.vue @@ -0,0 +1,892 @@ + + + + + + diff --git a/src/views/marketing/Voucher.vue b/src/views/marketing/Voucher.vue new file mode 100644 index 0000000..b5db990 --- /dev/null +++ b/src/views/marketing/Voucher.vue @@ -0,0 +1,512 @@ + + + + + + + + diff --git a/src/views/marketing/VoucherHistory.vue b/src/views/marketing/VoucherHistory.vue new file mode 100644 index 0000000..339e7e9 --- /dev/null +++ b/src/views/marketing/VoucherHistory.vue @@ -0,0 +1,581 @@ + + + + + + diff --git a/src/views/marketing/VoucherHolders.vue b/src/views/marketing/VoucherHolders.vue new file mode 100644 index 0000000..3574033 --- /dev/null +++ b/src/views/marketing/VoucherHolders.vue @@ -0,0 +1,781 @@ + + + + + + diff --git a/src/views/order/OrderList.vue b/src/views/order/OrderList.vue new file mode 100644 index 0000000..0aff140 --- /dev/null +++ b/src/views/order/OrderList.vue @@ -0,0 +1,584 @@ + + + + + + diff --git a/src/views/product/ProductGroup.vue b/src/views/product/ProductGroup.vue new file mode 100644 index 0000000..29db65f --- /dev/null +++ b/src/views/product/ProductGroup.vue @@ -0,0 +1,275 @@ + + + + + + diff --git a/src/views/product/ProductList.vue b/src/views/product/ProductList.vue new file mode 100644 index 0000000..dd04522 --- /dev/null +++ b/src/views/product/ProductList.vue @@ -0,0 +1,497 @@ + + + + + + diff --git a/src/views/product/ProductParameter.vue b/src/views/product/ProductParameter.vue new file mode 100644 index 0000000..e268e78 --- /dev/null +++ b/src/views/product/ProductParameter.vue @@ -0,0 +1,637 @@ + + + + + + diff --git a/src/views/system/DomainWhitelist.vue b/src/views/system/DomainWhitelist.vue index e1a84ef..67567e6 100644 --- a/src/views/system/DomainWhitelist.vue +++ b/src/views/system/DomainWhitelist.vue @@ -15,6 +15,11 @@ 新增域名 + + + 刷新 + + 批量删除 @@ -30,10 +35,10 @@ style="width: 100%" > - - + + @@ -223,9 +228,14 @@ const handleDelete = (row) => { type: 'warning' }).then(async () => { try { - await deleteDomain(row.Id) - ElMessage.success('删除成功') - getList() + const res = await deleteDomain({domain_id: row.id}) + console.log(res) + if (res.code === 200) { + ElMessage.success('删除成功') + getList() + } else { + ElMessage.error(res.data.message || '删除失败') + } } catch (error) { console.error('删除域名失败:', error) ElMessage.error('删除失败') @@ -239,10 +249,11 @@ const handleBatchDelete = () => { ElMessage.warning('请选择要删除的域名') return } - - const ids = selectedRows.value.map(item => item.Id) + + const ids = selectedRows.value.map(item => item.id) + const domains = selectedRows.value.map(item => item.domain).join('、') - + console.log('id数据:',ids) ElMessageBox.confirm(`确认删除以下域名吗?\n${domains}`, '警告', { confirmButtonText: '确定', cancelButtonText: '取消', @@ -257,9 +268,7 @@ const handleBatchDelete = () => { console.error('批量删除域名失败:', error) ElMessage.error('批量删除失败') } - await batchDeleteDomain(ids) - ElMessage.success('批量删除成功') - getList() + } catch (error) { console.error('批量删除域名失败:', error) ElMessage.error('批量删除失败') diff --git a/src/views/system/PermissionAdmin.vue b/src/views/system/PermissionAdmin.vue new file mode 100644 index 0000000..b1dac29 --- /dev/null +++ b/src/views/system/PermissionAdmin.vue @@ -0,0 +1,778 @@ + + + + + + diff --git a/src/views/system/PermissionRoute.vue b/src/views/system/PermissionRoute.vue new file mode 100644 index 0000000..df0a46e --- /dev/null +++ b/src/views/system/PermissionRoute.vue @@ -0,0 +1,281 @@ + + + + + + diff --git a/src/views/system/Setting.vue b/src/views/system/Setting.vue new file mode 100644 index 0000000..d4a206f --- /dev/null +++ b/src/views/system/Setting.vue @@ -0,0 +1,535 @@ + + + + + + diff --git a/src/views/system/SettingGroup.vue b/src/views/system/SettingGroup.vue new file mode 100644 index 0000000..806e7b0 --- /dev/null +++ b/src/views/system/SettingGroup.vue @@ -0,0 +1,344 @@ + + + + + + diff --git a/src/views/system/SystemFile.vue b/src/views/system/SystemFile.vue new file mode 100644 index 0000000..4fcb752 --- /dev/null +++ b/src/views/system/SystemFile.vue @@ -0,0 +1,771 @@ + + + + + + diff --git a/src/views/user/AdminGroup.vue b/src/views/user/AdminGroup.vue new file mode 100644 index 0000000..9faa99d --- /dev/null +++ b/src/views/user/AdminGroup.vue @@ -0,0 +1,358 @@ + + + + + + diff --git a/src/views/user/UserBalance.vue b/src/views/user/UserBalance.vue new file mode 100644 index 0000000..6a4064d --- /dev/null +++ b/src/views/user/UserBalance.vue @@ -0,0 +1,1475 @@ + + + + + + + + diff --git a/src/views/user/UserDetail.vue b/src/views/user/UserDetail.vue new file mode 100644 index 0000000..1dd715f --- /dev/null +++ b/src/views/user/UserDetail.vue @@ -0,0 +1,2237 @@ + + + + + diff --git a/src/views/user/UserGroup.vue b/src/views/user/UserGroup.vue new file mode 100644 index 0000000..86d5f61 --- /dev/null +++ b/src/views/user/UserGroup.vue @@ -0,0 +1,632 @@ + + + + + + diff --git a/src/views/user/UserList.vue b/src/views/user/UserList.vue new file mode 100644 index 0000000..f530769 --- /dev/null +++ b/src/views/user/UserList.vue @@ -0,0 +1,1030 @@ + + + + + + diff --git a/默认模块.openapi.json b/默认模块.openapi.json new file mode 100644 index 0000000..910a5bc --- /dev/null +++ b/默认模块.openapi.json @@ -0,0 +1,687 @@ +{ + "openapi": "3.0.1", + "info": { + "title": "默认模块", + "description": "", + "version": "1.0.0" + }, + "tags": [], + "paths": { + "/api/v1/admin/server/setting/group/list": { + "get": { + "summary": "获取配置分组列表", + "deprecated": false, + "description": "", + "tags": [], + "parameters": [ + { + "name": "page", + "in": "query", + "description": "获取页码 默认 1", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "count", + "in": "query", + "description": "获取条数 默认 10", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "key", + "in": "query", + "description": "关键词筛选", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "Authorization", + "in": "header", + "description": "", + "example": "Bearer {{token}}", + "schema": { + "type": "string", + "default": "Bearer {{token}}" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": {} + } + } + }, + "headers": {} + } + }, + "security": [] + } + }, + "/api/v1/admin/server/setting/group/info": { + "get": { + "summary": "获取配置分组信息", + "deprecated": false, + "description": "", + "tags": [], + "parameters": [ + { + "name": "setting_group_id", + "in": "query", + "description": "", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "Authorization", + "in": "header", + "description": "", + "example": "Bearer {{token}}", + "schema": { + "type": "string", + "default": "Bearer {{token}}" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": {} + } + } + }, + "headers": {} + } + }, + "security": [] + } + }, + "/api/v1/admin/server/setting/group/create": { + "post": { + "summary": "创建配置分组", + "deprecated": false, + "description": "", + "tags": [], + "parameters": [ + { + "name": "Authorization", + "in": "header", + "description": "", + "example": "Bearer {{token}}", + "schema": { + "type": "string", + "default": "Bearer {{token}}" + } + } + ], + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "properties": { + "name": { + "description": "名称", + "example": "", + "type": "string" + }, + "note": { + "description": "备注", + "example": "", + "type": "string" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": {} + }, + "example": { + "code": 200, + "message": "Success" + } + } + }, + "headers": {} + } + }, + "security": [] + } + }, + "/api/v1/admin/server/setting/group/update": { + "post": { + "summary": "修改配置分组", + "deprecated": false, + "description": "", + "tags": [], + "parameters": [ + { + "name": "Authorization", + "in": "header", + "description": "", + "example": "Bearer {{token}}", + "schema": { + "type": "string", + "default": "Bearer {{token}}" + } + } + ], + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "properties": { + "id": { + "description": "ID", + "example": "", + "type": "string" + }, + "name": { + "description": "名称", + "example": "", + "type": "string" + }, + "note": { + "description": "备注", + "example": "", + "type": "string" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": {} + } + } + }, + "headers": {} + } + }, + "security": [] + } + }, + "/api/v1/admin/server/setting/group/delete": { + "delete": { + "summary": "删除配置分组", + "deprecated": false, + "description": "", + "tags": [], + "parameters": [ + { + "name": "setting_group_id", + "in": "query", + "description": "", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "Authorization", + "in": "header", + "description": "", + "example": "Bearer {{token}}", + "schema": { + "type": "string", + "default": "Bearer {{token}}" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": {} + } + } + }, + "headers": {} + } + }, + "security": [] + } + }, + "/api/v1/admin/server/setting/list": { + "get": { + "summary": "获取配置列表", + "deprecated": false, + "description": "", + "tags": [], + "parameters": [ + { + "name": "page", + "in": "query", + "description": "获取页码 默认 1", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "count", + "in": "query", + "description": "获取条数 默认 10", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "group_id", + "in": "query", + "description": "组id(与组名称二选一)", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "group_name", + "in": "query", + "description": "组名称(与组id二选一)", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "key", + "in": "query", + "description": "关键词筛选", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "Authorization", + "in": "header", + "description": "", + "example": "Bearer {{token}}", + "schema": { + "type": "string", + "default": "Bearer {{token}}" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": {} + } + } + }, + "headers": {} + } + }, + "security": [] + } + }, + "/api/v1/admin/server/setting/info": { + "get": { + "summary": "获取配置信息", + "deprecated": false, + "description": "", + "tags": [], + "parameters": [ + { + "name": "id", + "in": "query", + "description": "配置id (与name二选一)", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "name", + "in": "query", + "description": "配置名称 (与id二选一)", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "Authorization", + "in": "header", + "description": "", + "example": "Bearer {{token}}", + "schema": { + "type": "string", + "default": "Bearer {{token}}" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": {} + } + } + }, + "headers": {} + } + }, + "security": [] + } + }, + "/api/v1/admin/server/setting/create": { + "post": { + "summary": "创建配置", + "deprecated": false, + "description": "", + "tags": [], + "parameters": [ + { + "name": "Authorization", + "in": "header", + "description": "", + "example": "Bearer {{token}}", + "schema": { + "type": "string", + "default": "Bearer {{token}}" + } + } + ], + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "properties": { + "name": { + "description": "名称", + "example": "", + "type": "string" + }, + "value": { + "example": "", + "type": "string" + }, + "note": { + "description": "备注", + "example": "", + "type": "string" + }, + "type": { + "description": "类型 string/int/float/bool/", + "example": "", + "type": "string" + }, + "setting_group_id": { + "description": "配置组id", + "example": 0, + "type": "integer" + }, + "open": { + "description": "是否开放访问", + "example": "", + "type": "boolean" + } + }, + "required": [ + "name", + "value", + "type" + ] + } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": {} + } + } + }, + "headers": {} + } + }, + "security": [] + } + }, + "/api/v1/admin/server/setting/update": { + "post": { + "summary": "修改配置", + "deprecated": false, + "description": "", + "tags": [], + "parameters": [ + { + "name": "Authorization", + "in": "header", + "description": "", + "example": "Bearer {{token}}", + "schema": { + "type": "string", + "default": "Bearer {{token}}" + } + } + ], + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "properties": { + "id": { + "example": 0, + "type": "integer" + }, + "name": { + "description": "名称", + "example": "", + "type": "string" + }, + "value": { + "example": "", + "type": "string" + }, + "note": { + "description": "备注", + "example": "", + "type": "string" + }, + "type": { + "description": "类型 string/int/float/bool/", + "example": "", + "type": "string" + }, + "setting_group_id": { + "description": "配置组id", + "example": "", + "type": "string" + } + }, + "required": [ + "id" + ] + } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": {} + } + } + }, + "headers": {} + } + }, + "security": [] + } + }, + "/api/v1/admin/server/setting/set_open": { + "post": { + "summary": "修改配置是否开放访问", + "deprecated": false, + "description": "", + "tags": [], + "parameters": [ + { + "name": "Authorization", + "in": "header", + "description": "", + "example": "Bearer {{token}}", + "schema": { + "type": "string", + "default": "Bearer {{token}}" + } + } + ], + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "properties": { + "id": { + "example": 0, + "type": "integer" + }, + "open": { + "description": "是否开放", + "example": "", + "type": "boolean" + } + }, + "required": [ + "id", + "open" + ] + } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": {} + } + } + }, + "headers": {} + } + }, + "security": [] + } + }, + "/api/v1/admin/server/setting/delete": { + "delete": { + "summary": "删除配置", + "deprecated": false, + "description": "", + "tags": [], + "parameters": [ + { + "name": "Authorization", + "in": "header", + "description": "", + "example": "Bearer {{token}}", + "schema": { + "type": "string", + "default": "Bearer {{token}}" + } + } + ], + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "properties": { + "id": { + "example": "", + "type": "string" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": {} + } + } + }, + "headers": {} + } + }, + "security": [] + } + } + }, + "components": { + "schemas": {}, + "securitySchemes": {} + }, + "servers": [], + "security": [] +} \ No newline at end of file From f7c3be1d30996c6a0110fdc305afb9898ecaebfb Mon Sep 17 00:00:00 2001 From: wlkjyy Date: Fri, 28 Nov 2025 14:15:29 +0800 Subject: [PATCH 04/10] refactor: extract image form to standalone page and implement tags view store - Created ImageForm.vue as standalone page for add/edit image functionality - Removed dialog-based image form from VmImages.vue - Implemented tagsViewStore for global tab state management - Added automatic tab closing on form cancel/back - Fixed data persistence issue when switching between image edits - Removed quick actions section from ImageForm - Updated router configuration for new image form route --- src/App.vue | 334 +++- src/assets/logo.png | Bin 23115 -> 28390 bytes src/components/layout/AdminLayout.vue | 196 ++- src/components/layout/Breadcrumb.vue | 48 +- src/components/layout/SidebarMenuItem.vue | 72 +- src/components/layout/TagsView.vue | 210 ++- src/router/index.js | 50 +- src/store/tagsViewStore.js | 91 + src/utils/regions.json | 88 + src/views/acs/guacamole/Guacamole.vue | 345 ++-- src/views/acs/images/ContainerImages.vue | 290 ++-- src/views/acs/images/ImageCategories.vue | 318 ++-- src/views/acs/images/ImageForm.vue | 825 +++++++++ src/views/acs/images/ImageRequests.vue | 309 ++-- src/views/acs/images/VmImages.vue | 919 ++-------- src/views/acs/messages/Announcements.vue | 269 +-- src/views/acs/messages/News.vue | 234 ++- src/views/acs/messages/Policies.vue | 287 ++-- src/views/acs/nodes/Nodes.vue | 966 +++-------- src/views/acs/nodes/ServerForm.vue | 847 +++++++++ src/views/acs/nodes/server.vue | 325 ++-- src/views/audit/AllSites.vue | 393 ++--- src/views/audit/ViolationSites.vue | 481 +++--- src/views/marketing/DiscountCode.vue | 316 +++- src/views/marketing/DiscountGoods.vue | 365 ++-- src/views/marketing/DiscountUsers.vue | 340 ++-- src/views/order/OrderList.vue | 366 ++-- src/views/product/ProductGroup.vue | 239 ++- src/views/product/ProductList.vue | 318 ++-- src/views/product/ProductParameter.vue | 336 ++-- src/views/setting/GlobalSetting.vue | 273 +-- src/views/system/DomainWhitelist.vue | 208 ++- src/views/system/OperationLog.vue | 313 ++-- src/views/system/PermissionAdmin.vue | 292 ++-- src/views/system/PermissionRoute.vue | 187 +- src/views/system/Setting.vue | 263 +-- src/views/system/SettingGroup.vue | 207 ++- src/views/system/SystemFile.vue | 268 +-- src/views/system/Users.vue | 363 ++-- src/views/ticket/TicketChat.vue | 74 +- src/views/user/AdminGroup.vue | 324 +++- src/views/user/UserBalance.vue | 45 +- src/views/user/UserDetail.vue | 1894 +++++---------------- src/views/user/UserGroup.vue | 440 +++-- src/views/user/UserList.vue | 329 +++- 45 files changed, 8776 insertions(+), 6881 deletions(-) create mode 100644 src/store/tagsViewStore.js create mode 100644 src/utils/regions.json create mode 100644 src/views/acs/images/ImageForm.vue create mode 100644 src/views/acs/nodes/ServerForm.vue diff --git a/src/App.vue b/src/App.vue index 305658f..ebb004e 100644 --- a/src/App.vue +++ b/src/App.vue @@ -88,40 +88,350 @@ html, body { background: #a8a8a8; } -/* Element Plus样式优化 */ +/* Element Plus全局配色优化 */ + +/* 按钮扁平化 */ .el-button { - font-weight: 400; - border-radius: 4px; + border-radius: 0 !important; + transition: all 0.2s ease; + font-weight: 500; } +/* 主按钮 - 深蓝灰色 */ +.el-button--primary { + background-color: #2c3e50 !important; + border-color: #2c3e50 !important; + color: #ffffff !important; +} + +.el-button--primary:hover { + background-color: #34495e !important; + border-color: #34495e !important; +} + +.el-button--primary:active { + background-color: #1a252f !important; + border-color: #1a252f !important; +} + +/* 成功按钮 - 绿色系 */ +.el-button--success { + background-color: #27ae60 !important; + border-color: #27ae60 !important; + color: #ffffff !important; +} + +.el-button--success:hover { + background-color: #2ecc71 !important; + border-color: #2ecc71 !important; +} + +.el-button--success:active { + background-color: #229954 !important; + border-color: #229954 !important; +} + +/* 危险按钮 - 红色系 */ +.el-button--danger { + background-color: #e74c3c !important; + border-color: #e74c3c !important; + color: #ffffff !important; +} + +.el-button--danger:hover { + background-color: #ec7063 !important; + border-color: #ec7063 !important; +} + +.el-button--danger:active { + background-color: #c0392b !important; + border-color: #c0392b !important; +} + +/* 默认按钮 */ +.el-button--default { + background-color: #ffffff !important; + border-color: #d5d9e0 !important; + color: #606266 !important; +} + +.el-button--default:hover { + background-color: #f5f7fa !important; + border-color: #c0c4cc !important; + color: #606266 !important; +} + +/* Link按钮 */ +.el-button.is-link { + color: #3498db !important; + border: none !important; + padding: 0; + background: transparent !important; +} + +.el-button.is-link:hover { + color: #2980b9 !important; + background: transparent !important; +} + +.el-button--primary.is-link { + color: #3498db !important; + background: transparent !important; +} + +.el-button--primary.is-link:hover { + color: #2980b9 !important; + background: transparent !important; +} + +/* 输入框扁平化 */ +.el-input__wrapper { + border-radius: 0 !important; + box-shadow: 0 0 0 1px #d5d9e0 inset !important; + background-color: #ffffff !important; + transition: all 0.2s ease; +} + +.el-input__wrapper:hover { + box-shadow: 0 0 0 1px #b8bcc5 inset !important; +} + +.el-input__wrapper.is-focus { + box-shadow: 0 0 0 1px #2c3e50 inset !important; +} + +/* 标签扁平化 */ +.el-tag { + border-radius: 0 !important; + border: none !important; + font-weight: 500; + padding: 2px 10px; +} + +/* 成功标签 */ +.el-tag--success { + background-color: #d5f4e6 !important; + color: #27ae60 !important; +} + +/* 危险标签 */ +.el-tag--danger { + background-color: #fadbd8 !important; + color: #e74c3c !important; +} + +/* 信息标签 */ +.el-tag--info { + background-color: #ebf5fb !important; + color: #3498db !important; +} + +/* 卡片扁平化 */ .el-card { - border-radius: 4px; + border-radius: 0 !important; + border: 1px solid #e1e8ed !important; + box-shadow: none !important; } +/* 表格扁平化 */ +.el-table { + border-radius: 0 !important; + border: none !important; + color: #2c3e50 !important; +} + +.el-table__header { + background: #f8f9fa !important; +} + +.el-table th { + background: #f8f9fa !important; + border-bottom: 2px solid #e1e8ed !important; + color: #2c3e50 !important; + font-weight: 600 !important; + font-size: 13px !important; +} + +.el-table td { + border-bottom: 1px solid #f0f2f5 !important; + color: #34495e !important; +} + +.el-table tr:hover > td { + background-color: #f8f9fa !important; +} + +/* 分页扁平化 */ +.el-pagination .el-pager li { + border-radius: 0 !important; + color: #606266 !important; + font-weight: 500; +} + +.el-pagination .el-pager li.is-active { + background-color: #2c3e50 !important; + color: #ffffff !important; +} + +.el-pagination .el-pager li:hover { + color: #2c3e50 !important; +} + +.el-pagination button { + border-radius: 0 !important; + color: #606266 !important; +} + +.el-pagination button:hover { + color: #2c3e50 !important; +} + +.el-pagination .el-select .el-input__wrapper { + box-shadow: 0 0 0 1px #d5d9e0 inset !important; +} + +.el-pagination .el-input__inner { + color: #606266 !important; +} + +/* 下拉菜单扁平化 */ +.el-dropdown-menu { + border-radius: 0 !important; + border: 1px solid #e1e8ed !important; + background-color: #ffffff !important; + box-shadow: 0 2px 8px rgba(44, 62, 80, 0.1) !important; + padding: 4px 0; +} + +.el-dropdown-menu__item { + color: #34495e !important; + transition: all 0.2s ease; + padding: 8px 16px; +} + +.el-dropdown-menu__item:hover { + background-color: #f8f9fa !important; + color: #2c3e50 !important; +} + +.el-dropdown-menu__item.is-divided { + border-top: 1px solid #e1e8ed !important; +} + +/* 选择框扁平化 */ +.el-select .el-input__wrapper { + border-radius: 0 !important; +} + +/* 文本域扁平化 */ +.el-textarea__inner { + border-radius: 0 !important; + box-shadow: 0 0 0 1px #d5d9e0 inset !important; + transition: all 0.2s ease; +} + +.el-textarea__inner:hover { + box-shadow: 0 0 0 1px #b8bcc5 inset !important; +} + +.el-textarea__inner:focus { + box-shadow: 0 0 0 1px #2c3e50 inset !important; +} + +/* 菜单扁平化 */ .el-menu { border-right: none; } -.el-table { - border-radius: 4px; +/* 表单标签 */ +.el-form-item__label { + color: #2c3e50 !important; + font-weight: 500; +} + +/* Dialog 扁平化样式 */ +.el-overlay { + background-color: rgba(0, 0, 0, 0.5); +} + +.el-overlay-dialog { + display: flex; + align-items: center; + justify-content: center; } .el-dialog { - border-radius: 8px; + border-radius: 0; + border: none; + box-shadow: 0 4px 16px rgba(44, 62, 80, 0.15); + background-color: #ffffff; + margin: 0; + padding: 0 !important; +} + +.el-dialog__wrapper { + border: none; } .el-dialog__header { margin: 0; - padding: 20px; - border-bottom: 1px solid #f0f0f0; - font-weight: 500; + padding: 20px 24px; + border-bottom: 1px solid #e1e8ed; + background-color: #fafbfc; + font-weight: 600; + font-size: 16px; + color: #2c3e50; +} + +.el-dialog__headerbtn { + top: 20px; + right: 24px; + width: 32px; + height: 32px; +} + +.el-dialog__close { + color: #7f8c8d; + font-size: 18px; + transition: all 0.2s ease; +} + +.el-dialog__close:hover { + color: #2c3e50; + background-color: #f8f9fa; } .el-dialog__body { - padding: 20px; + padding: 24px; + color: #34495e; + background-color: #ffffff; } .el-dialog__footer { - padding: 10px 20px 20px; + padding: 16px 24px; + border-top: 1px solid #e1e8ed; + background-color: #fafbfc; +} + +/* Dialog 内表单组件样式 */ +.el-dialog .el-input__wrapper { + border-radius: 0; +} + +.el-dialog .el-select .el-input__wrapper { + border-radius: 0; +} + +.el-dialog .el-textarea__inner { + border-radius: 0; +} + +.el-dialog .el-form-item__label { + color: #2c3e50; + font-weight: 500; +} + +.el-dialog .el-form-item { + margin-bottom: 20px; } \ No newline at end of file diff --git a/src/assets/logo.png b/src/assets/logo.png index 6bc8dad1ff7dcb55f8f19e86763e49d398da9c19..994fed6100df1b8e3d945b539a4ba12c43f8990c 100644 GIT binary patch literal 28390 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 F{tu51OWObd literal 23115 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�!PAk)4_p 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 diff --git a/src/components/layout/AdminLayout.vue b/src/components/layout/AdminLayout.vue index b71f932..b2d2ec9 100644 --- a/src/components/layout/AdminLayout.vue +++ b/src/components/layout/AdminLayout.vue @@ -3,15 +3,15 @@