Kaynağa Gözat

feat(menu): 新增网关组管理和继续添加功能

- 新增网关组管理页面和相关路由
- 实现网关组的新增、编辑和删除功能
- 添加继续添加功能,提高数据录入效率
- 优化表单验证和重置逻辑
- 更新多语言文案
fusu 1 ay önce
ebeveyn
işleme
c9efdbce32

+ 3 - 2
internal/repository/gatewaygroupip.go

@@ -1,7 +1,8 @@
 package repository
 
 import (
-    "context"
+	"context"
+
 	"github.com/go-nunu/nunu-layout-advanced/internal/model"
 )
 
@@ -79,4 +80,4 @@ func (r *gateWayGroupIpRepository) GetGateWayGroupAllIpByGatewayGroupId(ctx cont
 		return nil, err
 	}
 	return res, nil
-}
+}

+ 8 - 6
internal/service/gatewaygroupip.go

@@ -1,7 +1,8 @@
 package service
 
 import (
-    "context"
+	"context"
+
 	"github.com/go-nunu/nunu-layout-advanced/internal/model"
 	"github.com/go-nunu/nunu-layout-advanced/internal/repository"
 )
@@ -13,12 +14,13 @@ type GateWayGroupIpService interface {
 	EditGateWayGroupIp(ctx context.Context, req *model.GateWayGroupIp) error
 	DeleteGateWayGroupIp(ctx context.Context, req *model.GateWayGroupIp) error
 }
+
 func NewGateWayGroupIpService(
-    service *Service,
-    gateWayGroupIpRepository repository.GateWayGroupIpRepository,
+	service *Service,
+	gateWayGroupIpRepository repository.GateWayGroupIpRepository,
 ) GateWayGroupIpService {
 	return &gateWayGroupIpService{
-		Service:        service,
+		Service:                  service,
 		gateWayGroupIpRepository: gateWayGroupIpRepository,
 	}
 }
@@ -33,7 +35,7 @@ func (s *gateWayGroupIpService) GetGateWayGroupIp(ctx context.Context, id int64)
 }
 
 func (s *gateWayGroupIpService) GetGateWayGroupIpByGatewayGroupId(ctx context.Context, gatewayGroupId int) (*[]model.GateWayGroupIp, error) {
-	res, err :=  s.gateWayGroupIpRepository.GetGateWayGroupIpByGatewayGroupId(ctx, gatewayGroupId)
+	res, err := s.gateWayGroupIpRepository.GetGateWayGroupIpByGatewayGroupId(ctx, gatewayGroupId)
 	if err != nil {
 		return nil, err
 	}
@@ -59,4 +61,4 @@ func (s *gateWayGroupIpService) DeleteGateWayGroupIp(ctx context.Context, req *m
 		return err
 	}
 	return nil
-}
+}

+ 2 - 2
web/src/locales/lang/global/zh-CN.js

@@ -93,8 +93,8 @@ export default {
   'menu.link.iframe': 'AntDesign',
   'menu.link.antdv': 'AntDesignVue',
   'menu.link.external': '跳转百度',
-  'menu.menu': '菜单',
-  'menu.menu.menu1': '菜单1',
+  'menu.menu': '网关组',
+  'menu.menu.menu1': '网关组管理',
   'menu.menu.menu2': '菜单2',
   'menu.menu.menu3': '菜单1-1',
   'menu.menu3.menu1': '菜单1-1-1',

+ 71 - 33
web/src/pages/menu/components/crud-table-modal.vue

@@ -1,43 +1,60 @@
 <script setup>
 import { cloneDeep } from 'lodash'
 import { addApi, updateApi } from '~@/api/list/gateway-list'
+import { nextTick } from 'vue'
 
 const emit = defineEmits(['cancel', 'ok'])
 const message = useMessage()
 const isUpdate = ref(false)
 const visible = ref(false)
 const loading = ref(false)
+const continueToAdd = ref(false)
+
 const title = computed(() => {
   return isUpdate.value ? '编辑' : '新增'
 })
 const formRef = ref()
-const formData = ref({
+const originalRecord = ref(null)
+
+const defaultFormData = {
   id: 0,
   name: '',
   hostId: 0,
-  ruleId : 0,
+  ruleId: 0,
   comment: '',
-  operator: 0,
+  operator: 1,
   banUdp: 0,
   banOverseas: 0,
-})
+}
+const formData = ref(cloneDeep(defaultFormData))
+
 const { t } = useI18n()
 const labelCol = { style: { width: '100px' } }
 const wrapperCol = { span: 24 }
+
 function open(record) {
   visible.value = true
   isUpdate.value = !!record?.id
-  formData.value = cloneDeep(record) ?? {
-    id: 0,
-    name: '',
-    hostId: 0,
-    ruleId : 0,
-    comment: '',
-    operator: 1,
-    banUdp: 0,
-    banOverseas: 0,
-  }
+  originalRecord.value = record ? cloneDeep(record) : null
+  formData.value = record ? cloneDeep(record) : cloneDeep(defaultFormData)
+  continueToAdd.value = false
+  nextTick(() => {
+    formRef.value?.clearValidate()
+  })
+}
+
+function handleReset() {
+  if (isUpdate.value)
+    formData.value = cloneDeep(originalRecord.value)
+
+  else
+    formData.value = cloneDeep(defaultFormData)
+
+  nextTick(() => {
+    formRef.value?.clearValidate()
+  })
 }
+
 async function handleOk() {
   try {
     await formRef.value?.validate()
@@ -46,7 +63,12 @@ async function handleOk() {
     await api(formData.value)
     message.success(isUpdate.value ? '修改成功' : '新增成功')
     emit('ok')
-    visible.value = false
+    if (!isUpdate.value && continueToAdd.value) {
+      handleReset()
+    }
+    else {
+      visible.value = false
+    }
   }
   catch (errorInfo) {
     console.log('Form Validate Failed:', errorInfo)
@@ -55,42 +77,44 @@ async function handleOk() {
     loading.value = false
   }
 }
+
 function handleCancel() {
-  formRef.value?.resetFields()
+  visible.value = false
   emit('cancel')
 }
+
 defineExpose({
   open,
 })
 </script>
 
 <template>
-  <a-modal v-model:open="visible" :title="title" :confirm-loading="loading" @ok="handleOk" @cancel="handleCancel">
+  <a-modal v-model:open="visible" :title="title" :confirm-loading="loading" @cancel="handleCancel">
     <a-form ref="formRef" :model="formData" class="w-full" :label-col="labelCol" :wrapper-col="wrapperCol">
-      <a-form-item  :label="t('gateway.group.name')" name="name" :rules="[{ required: true, message: '请输入网关组名称' }]">
+      <a-form-item :label="t('gateway.group.name')" name="name" :rules="[{ required: true, message: '请输入网关组名称' }]">
         <a-input v-model:value="formData.name" :maxlength="50" placeholder="请输入网关组名称" />
       </a-form-item>
-      <a-form-item  :label="t('gateway.group.hostId')" name="hostId" :rules="[{ required: true, message: '请输入订单ID' }]">
+      <a-form-item :label="t('gateway.group.hostId')" name="hostId" :rules="[{ required: true, message: '请输入订单ID' }]">
         <a-input v-model:value="formData.hostId" :maxlength="50" placeholder="请输入订单ID" />
       </a-form-item>
-      <a-form-item  :label="t('gateway.group.ruleId')" name="ruleId" :rules="[{ required: true, message: '请输入规则ID' }]">
+      <a-form-item :label="t('gateway.group.ruleId')" name="ruleId" :rules="[{ required: true, message: '请输入规则ID' }]">
         <a-input v-model:value="formData.ruleId" :maxlength="50" placeholder="请输入规则ID" />
       </a-form-item>
       <a-form-item :label="t('gateway.group.comment')" name="comment">
         <a-textarea v-model:value="formData.comment" show-count :maxlength="200" placeholder="请输入备注" />
       </a-form-item>
-      <a-form-item :label="t('gateway.group.banUdp')"  name="banUdp">
-      <a-radio-group  v-model:value="formData.banUdp">
-        <a-radio :value="1">
-          是
-        </a-radio>
-        <a-radio :value="0">
-          否
-        </a-radio>
-      </a-radio-group>
+      <a-form-item :label="t('gateway.group.banUdp')" name="banUdp">
+        <a-radio-group v-model:value="formData.banUdp">
+          <a-radio :value="1">
+            
+          </a-radio>
+          <a-radio :value="0">
+            
+          </a-radio>
+        </a-radio-group>
       </a-form-item>
-      <a-form-item :label="t('gateway.group.operator')"  name="operator">
-        <a-radio-group  v-model:value="formData.operator">
+      <a-form-item :label="t('gateway.group.operator')" name="operator">
+        <a-radio-group v-model:value="formData.operator">
           <a-radio :value="1">
             {{ t('gateway.group.telecommunications') }}
           </a-radio>
@@ -99,8 +123,8 @@ defineExpose({
           </a-radio>
         </a-radio-group>
       </a-form-item>
-      <a-form-item :label="t('gateway.group.banOverseas')"  name="banOverseas">
-        <a-radio-group  v-model:value="formData.banOverseas">
+      <a-form-item :label="t('gateway.group.banOverseas')" name="banOverseas">
+        <a-radio-group v-model:value="formData.banOverseas">
           <a-radio :value="1">
           </a-radio>
@@ -110,5 +134,19 @@ defineExpose({
         </a-radio-group>
       </a-form-item>
     </a-form>
+    <template #footer>
+      <a-checkbox v-if="!isUpdate" v-model:checked="continueToAdd" style="float: left; line-height: 32px;">
+        继续添加
+      </a-checkbox>
+      <a-button key="back" @click="handleCancel">
+        取消
+      </a-button>
+      <a-button key="reset" @click="handleReset">
+        重置
+      </a-button>
+      <a-button key="submit" type="primary" :loading="loading" @click="handleOk">
+        确定
+      </a-button>
+    </template>
   </a-modal>
 </template>

+ 7 - 2
web/src/pages/menu/menu1.vue

@@ -78,9 +78,9 @@ async function handleDelete(record) {
     return message.error('id 不能为空')
   try {
     const res = await deleteApi(record.id)
-    if (res.code === 200)
+    if (res.code === 0)
       await query()
-    message.success('删除成功')
+      message.success('删除成功')
 
   }
   catch (e) {
@@ -160,6 +160,11 @@ function handleEdit(record) {
                   删除
                 </a-button>
               </a-popconfirm>
+              <router-link :to="{ name: 'menu-ip-list', params: { id: scope?.record?.id } }">
+                <a-button type="link">
+                  查看IP列表
+                </a-button>
+              </router-link>
             </div>
           </template>
 

+ 2 - 2
web/src/router/dynamic-routes.js

@@ -120,7 +120,7 @@ export default [
     redirect: '/menu/menu1',
     name: 'Menu',
     meta: {
-      title: '菜单',
+      title: '网关组',
       icon: 'BarsOutlined',
     },
     component: basicRouteMap.RouteView,
@@ -130,7 +130,7 @@ export default [
         name: 'MenuMenu11',
         component: () => import('~/pages/menu/menu1.vue'),
         meta: {
-          title: '菜单1',
+          title: '网关组管理',
         },
       },
       {