吴sir vor 4 Monaten
Ursprung
Commit
e3be33b359

+ 15 - 2
src/api/customer.js

@@ -10,7 +10,7 @@ export function getCustomerList(data) {
 
 export function addCustomer(data) {
     return service({
-        url: '/app/user/addCustomer',
+        url: 'admin/platform/addCustomer',
         method: 'post',
         data
     })
@@ -18,7 +18,7 @@ export function addCustomer(data) {
 
 export function updateCustomer(data) {
     return service({
-        url: "/app/user/updateCustomer",
+        url: "admin/platform/updateCustomer",
         method: "post",
         data,
     });
@@ -38,4 +38,17 @@ export function getCustomer(data) {
         method: "post",
         data,
     });
+}
+
+// 获取客户列表
+export  function  getMessUserList(data){
+    return service({
+        url: 'admin/platform/customerList',
+        method: 'post',
+        data
+    })
+}
+// 客户详情
+export  function  deleteMessUser(params){
+    return service.get('admin/platform/customerInfo', {params})
 }

+ 9 - 1
src/components/Layout/components/layout/blendLeft.vue

@@ -62,6 +62,11 @@ import { useRoute, useRouter } from "vue-router";
 import { useSystemStore } from "@/store/modules/systemStore";
 import LayoutHeader from "@/components/Layout/components/layoutHeader/index.vue";
 import subMenu from "@/components/Layout/components/subMenu/index.vue";
+import {RouterTagData} from '@/store/modules/routerTag.js'
+
+// 标签页仓库
+const settingStore = RouterTagData()
+
 const systemStore = useSystemStore();
 
 const route = useRoute();
@@ -98,8 +103,10 @@ const evMouseleaveMenu = (e) => {
 const evMouseLeavesSubMenu = () => {
   menuSecondData.value = menuSecondSelectedStatusData.value;
 };
+// 鼠标滑动上去更新菜单栏 目前先屏蔽
 const evMenuGetFn = (routeItem, type) => {
-  menuSecondData.value = routeItem;
+  // menuSecondData.value = routeItem;
+  // console.log(routeItem);
 };
 
 // 查找最下级
@@ -119,6 +126,7 @@ const changeRoutesItems = (e) => {
 
 // 跳转路由
 const evGoPage = async (routeItem) => {
+  // settingStore.tagsPushData(routeItem);
   await router.push({
     name: routeItem.name,
   });

+ 90 - 61
src/components/Layout/components/layoutHeader/index.vue

@@ -1,110 +1,139 @@
 <template>
   <div class="header">
-    <a-select :style="{width:'100px'}" v-model="langStore.lang"  :bordered="false" @change="toggleLang">
-      <a-option v-for="item in langList" :key="item.key" :value="item.key">{{item.label}}</a-option>
-    </a-select>
-
-    <div class="toggle-theme-box">
-      <icon-sun-fill v-if="designStore.getDarkTheme"  @click="toggleTheme(false)" :size="18"/>
-      <icon-moon-fill  v-else  @click="toggleTheme(true)"  :size="18"/>
+    <!--    标签-->
+    <div class="flex-left-tag">
+<!--      <a-space wrap>-->
+<!--        <a-tag-->
+<!--            v-for="(tag, index) in tags"-->
+<!--            :key="tag.name"-->
+<!--            :closable="index !== 0"-->
+<!--            @close="settingStore.handleRemove(tag)"-->
+<!--        >-->
+<!--          {{ tag.meta.title }}-->
+<!--        </a-tag>-->
+<!--      </a-space>-->
     </div>
+    <!--    个人信息和操作-->
+    <div class="flex-right-user">
+      <a-select :style="{width:'100px'}" v-model="langStore.lang" :bordered="false" @change="toggleLang">
+        <a-option v-for="item in langList" :key="item.key" :value="item.key">{{ item.label }}</a-option>
+      </a-select>
 
-    <a-dropdown trigger="click">
-      <a-avatar :size="38" class="avatar-body">
-        <img
-          class="avatar-image"
-          alt="avatar"
-          src="https://avatars.githubusercontent.com/u/39849555?v=4"
-        />
-      </a-avatar>
-      <template #content>
-        <a-doption>
-          <a-space @click="evHandleLogout">
-            <icon-export />
-            <span>{{ $t('global.logOut') }}</span>
-          </a-space>
-        </a-doption>
-      </template>
-    </a-dropdown>
-
+      <div class="toggle-theme-box">
+        <icon-sun-fill v-if="designStore.getDarkTheme" @click="toggleTheme(false)" :size="18"/>
+        <icon-moon-fill v-else @click="toggleTheme(true)" :size="18"/>
+      </div>
 
+      <a-dropdown trigger="click">
+        <a-avatar :size="38" class="avatar-body">
+          <img
+              class="avatar-image"
+              alt="avatar"
+              src="https://avatars.githubusercontent.com/u/39849555?v=4"
+          />
+        </a-avatar>
+        <template #content>
+          <a-doption>
+            <a-space @click="evHandleLogout">
+              <icon-export/>
+              <span>{{ $t('global.logOut') }}</span>
+            </a-space>
+          </a-doption>
+        </template>
+      </a-dropdown>
+    </div>
   </div>
 </template>
 
 <script setup>
-import { ref,inject } from 'vue'
-import { useRouter } from 'vue-router'
-import { useSystemStore } from '@/store/modules/systemStore'
-import { Notification } from '@arco-design/web-vue'
-import { useDesignStore } from '@/store/modules/designStore'
-import { useLangStore } from '@/store/modules/langStore'
-import { useI18n } from 'vue-i18n'
-import { langList } from '@/i18n'
-import { fn_logout } from '@/utils'
-
-import { updateRouteByMenu  } from "@/router/router.update.js"
-
- 
+import {ref, inject, onMounted, watch, reactive} from 'vue'
+import {useRouter} from 'vue-router'
+import {useSystemStore} from '@/store/modules/systemStore'
+import {Notification} from '@arco-design/web-vue'
+import {useDesignStore} from '@/store/modules/designStore'
+import {useLangStore} from '@/store/modules/langStore'
+import {useI18n} from 'vue-i18n'
+import {langList} from '@/i18n'
+import {fn_logout} from '@/utils'
+import {RouterTagData} from '@/store/modules/routerTag.js'
+import { setLocalStorage, getLocalStorage } from "@/utils";
+// 标签页仓库
+const settingStore = RouterTagData()
+import {updateRouteByMenu} from "@/router/router.update.js"
+
+
 const router = useRouter()
-const { locale } = useI18n()
+const {locale} = useI18n()
 const systemStore = useSystemStore()
 const designStore = useDesignStore()
 const langStore = useLangStore()
 
 
 // const reload  = inject('reloadRoutePage')
-  
-const toggleTheme  = (e) =>{
+
+const toggleTheme = (e) => {
   designStore.changeTheme(e)
 }
 
-const toggleLang = async (e) =>{
-  langStore.changeLang(e) 
+const toggleLang = async (e) => {
+  langStore.changeLang(e)
   locale.value = langStore.lang
   await updateRouteByMenu(router, systemStore)
   router.go(0)
 }
 
 const evHandleLogout = () => {
-  
-    Notification.success({
-      content: '退出成功!',
-      duration: 1000,
-    })
-    // 清除缓存数据
-    fn_logout()
-
-    router.push({
-      name: "login",
-    })
+
+  Notification.success({
+    content: '退出成功!',
+    duration: 1000,
+  })
+  // 清除缓存数据
+  fn_logout()
+
+  router.push({
+    name: "login",
+  })
 }
 
+
+
 </script>
 
 <style scoped lang="less">
-.header{
+.header {
   height: 100%;
   display: flex;
   align-items: center;
-  justify-content: flex-end;
+  justify-content: space-between;
   padding: 0 10px;
 }
-.avatar-body{
-  :deep(.arco-avatar-image){
+
+.flex-right-user {
+  width: auto;
+  display: flex;
+  align-items: center;
+}
+
+.avatar-body {
+  :deep(.arco-avatar-image) {
     display: flex;
     align-items: center;
     justify-content: center;
   }
-  .avatar-image{
+
+  .avatar-image {
     border-radius: 50%;
     width: 34px;
     height: 34px;
   }
 }
-.toggle-theme-box{
+
+.toggle-theme-box {
   margin-right: 0.8rem;
 }
-:deep(.arco-select-view-suffix){
+
+:deep(.arco-select-view-suffix) {
   padding: 0;
 }
 </style>

+ 113 - 0
src/components/upload/index.vue

@@ -0,0 +1,113 @@
+<template>
+  <a-upload
+      :show-file-list="true"
+      :custom-request="customRequest"
+      list-type="picture-card"
+      :file-list="fileList"
+      :limit="minx"
+      @before-remove="beforeRemove"
+  />
+</template>
+
+<script setup>
+import {defineProps, defineEmits, toRef, ref, watch, watchEffect} from 'vue';
+import {useSystemStore} from '@/store/modules/systemStore';
+import {Modal} from "@arco-design/web-vue";
+import {useI18n} from 'vue-i18n';
+
+const systemStore = useSystemStore();
+const {t} = useI18n();
+
+// 接收外部传入的 props:modelValue 和 minx
+const props = defineProps({
+  modelValue: {
+    type: [String, Array],
+    default: '',
+  },
+  minx: {
+    type: Number,
+    default: 1
+  }
+});
+
+// 使用 toRef 确保对 props 的访问是响应式的
+const minx = toRef(props, 'minx');
+const modelValue = toRef(props, 'modelValue');
+
+// 定义 emit,用于向外抛出事件
+const emit = defineEmits(['update:modelValue']);
+
+// 用于存储文件列表,初始化时显示传递给子组件的值
+const fileList = ref([]);
+
+// 初始化:根据外部传入的 modelValue 进行文件列表的设置
+watchEffect(() => {
+  if (modelValue.value) {
+    if (Array.isArray(modelValue.value)) {
+      // 如果传递的是数组,则直接使用
+      fileList.value = modelValue.value.map(item => ({url: item}));
+    } else if (typeof modelValue.value === 'string') {
+      // 如果传递的是字符串,则将字符串按逗号分割成数组
+      const urlList = modelValue.value.split(',').map(url => ({url: url.trim()}));
+      fileList.value = urlList;
+    }
+  } else {
+    fileList.value = [];
+  }
+});
+
+// 自定义请求:上传文件的处理逻辑
+const customRequest = async (option) => {
+  const {file} = option.fileItem;
+  const fileName = `thumbnail_${file.name}`;
+  const key = `test/${fileName}`;
+
+  try {
+    // 获取上传客户端(假设 systemStore 已经定义了上传接口)
+    const client = await systemStore.getSTSClient();
+    const resClient = await client.putObject({
+      key: key,
+      body: file
+    });
+
+    // 上传成功后,更新 fileList 和 modelValue
+    if (resClient.statusCode === 200) {
+      const uploadedFileUrl = resClient.url;
+      fileList.value.push({url: uploadedFileUrl});
+
+      // 更新父组件的 modelValue
+      if (minx.value === 1) {
+        emit('update:modelValue', uploadedFileUrl);
+      } else {
+        emit('update:modelValue', fileList.value.map(res => res.url).join(','));
+      }
+    }
+  } catch (error) {
+    console.error('上传失败', error);
+  }
+};
+
+// 删除文件处理逻辑
+const beforeRemove = (file) => {
+  return new Promise((resolve, reject) => {
+    Modal.confirm({
+      title: $t('customer.confirmRemoveUpload'),
+      onOk: () => {
+        // 更新 fileList 和 modelValue,移除删除的文件
+        fileList.value = fileList.value.filter(item => item.url !== file.url);
+        if (minx.value === 1) {
+          emit('update:modelValue', fileList.value.length > 0 ? fileList.value[0].url : '');
+        } else {
+          emit('update:modelValue', fileList.value.map(res => res.url).join(','));
+        }
+        resolve(true);  // 确认删除
+      },
+      onCancel: () => reject('cancel') // 取消删除
+    });
+  });
+};
+</script>
+
+<style scoped>
+/* 可自定义样式 */
+</style>

+ 273 - 212
src/i18n/zh/customer.js

@@ -1,214 +1,275 @@
 export default {
-  // 主列表页面
-  customerName: "客户名称",
-  enterCustomerName: "请输入客户名称",
-  operatorType: "运营商类型",
-  selectOperatorType: "请选择运营商类型",
-  addCustomer: "新增客户",
-  batchDelete: "批量删除",
-  searchExecuted: "已执行搜索",
-  searchReset: "搜索条件已重置",
-  batchDeleteWarning: "确定要批量删除选中的客户吗?",
-  statusName: "状态",
-
-  basicInfoSection: "基本信息",
-  smsInfoSection: "手机短信",
-  accountManagement: "账户资费管理",
-  customerData: "客户资料",
-  interfaceParams: "接口参数",
-  billingInfo: "发票信息",
-  purchaseQuality: "购卡资质",
-  warningNumbers: "预警参数",
-
-  // 表格列
-  id: "序号",
-  customerCode: "客户编码",
-  accountNumber: "账号",
-  accountBalance: "账户余额",
-  paymentMethod: "付费方式",
-  customerStatus: "客户状态",
-  validPeriod: "有效期",
-  activeCards: "有效卡数/总卡数",
-  updateTime: "更新时间",
-
-  // 操作按钮
-  recharge: "充值",
-  packageManagement: "套餐管理",
-  edit: "编辑",
-
-  // 状态
-  status: {
-    normal: "正常",
-    disabled: "禁用",
-    pending: "待审",
-    suspended: "暂停",
-  },
-
-  // 运营商类型
-  operatorTypes: {
-    domestic: "国内",
-    international: "国际",
-  },
-
-  // 新增/编辑客户对话框
-  editCustomer: "编辑客户",
-  basicInfo: "基本信息",
-  smsInfo: "手机短信",
-  enterCustomerCode: "请输入客户编码",
-  enterAccountNumber: "请输入账号",
-  password: "登录密码",
-  enterPassword: "请输入登录密码",
-  generatePassword: "重置密码",
-  remark: "号码备注",
-  enterRemark: "请输入号码备注",
-  selectValidPeriod: "请选择有效期",
-
-  smsNumber: "短信子号",
-  enterSmsNumber: "请输入短信子号",
-  smsName: "短信签名",
-  enterSmsName: "请输入短信签名",
-  loginSmsTemplate: "登录短信模板",
-  enterLoginSmsTemplate: "请输入登录短信模板",
-  alarmSmsTemplate: "预警短信模板",
-  enterAlarmSmsTemplate: "请输入预警短信模板",
-
-  // 表单验证消息
-  customerCodeRequired: "请输入客户编码",
-  customerNameRequired: "请输入客户名称",
-  accountNumberRequired: "请输入账号",
-  passwordRequired: "请输入登录密码",
-  validPeriodRequired: "请选择有效期",
-  statusRequired: "请选择客户状态",
-
-  // 其他
-  passwordGenerated: "密码已生成",
-
-  // 账户资费管理相关翻译
-  accountBalance: '账户余额',
-  rechargeLimit: '充值限制',
-  creditLimit: '信用额度',
-  mobileSmsPrice: '手机短信单价',
-  iotSmsPrice: '物联网短信单价',
-  paymentMethod: '付费方式',
-  currency: '元',
-  currencyPerTime: '元/次',
-  currencyPerMessage: '元/条',
-  paymentMethodName: '付费方式名称',
-  paymentMethod: {
-    prepaid: '预付费',
-    postpaid: '后付费'
-  },
-
-  // 客户资料相关翻译
-  platformName: '平台名称',
-  enterPlatformName: '请输入平台名称',
-  companyName: '公司名称',
-  enterCompanyName: '请输入公司名称',
-  servicePhone: '服务电话',
-  enterServicePhone: '请输入服务电话',
-  domain: '域名',
-  enterDomain: '请输入域名',
-  websiteBackend: '网站备案号',
-  enterWebsiteBackend: '请输入网站备案号',
-  customerAddress: '客户地址',
-  enterCustomerAddress: '请输入客户地址',
-
-  contactPerson: '联系人',
-  enterContactPerson: '请输入联系人',
-  contactPhone: '联系人手机号',
-  enterContactPhone: '请输入联系人手机号',
-  contactEmail: '联系人邮箱',
-  enterContactEmail: '请输入联系人邮箱',
-  contactQQ: '联系人QQ号',
-  enterContactQQ: '请输入联系人QQ号',
-
-  billingPerson: '收件人',
-  enterBillingPerson: '请输入收件人',
-  billingPhone: '收件人手机号',
-  enterBillingPhone: '请输入收件人手机号',
-  billingAddress: '收件人地址',
-  enterBillingAddress: '请输入收件人地址',
-
-  // 接口参数相关翻译
-  smsStatusReportUrl: '短信状态报告推送地址',
-  enterSmsStatusReportUrl: '请输入短信状态报告推送地址',
-  reportIp: '报备IP',
-  enterReportIp: '请输入报备IP',
-  deliveryPriority: '推送优先级',
-  selectDeliveryPriority: '请选择推送优先级',
-  deliveryPriorityName: '推送优先级',
-  deliveryPriority: {
-    high: '高',
-    medium: '中',
-    low: '低'
-  },
-  dataReportUrl: '数据推送地址',
-  enterDataReportUrl: '请输入数据推送地址',
-
-  // 发票信息相关翻译
-  invoiceTitle: '发票抬头',
-  enterInvoiceTitle: '请输入发票抬头',
-  taxRegistrationNumber: '税务登记证号',
-  enterTaxRegistrationNumber: '请输入税务登记证号',
-  registeredAddress: '注册场所地址',
-  enterRegisteredAddress: '请输入注册场所地址',
-  registeredPhone: '注册固定电话',
-  enterRegisteredPhone: '请输入注册固定电话',
-  bankName: '开户银行名称',
-  enterBankName: '请输入开户银行名称',
-  bankAccountName: '账户名称',
-  enterBankAccountName: '请输入账户名称',
-  bankAccountNumber: '开户账号',
-  enterBankAccountNumber: '请输入开户账号',
-  taxIdentificationNumber: '纳税人识别号',
-  enterTaxIdentificationNumber: '请输入纳税人识别号',
-  invoiceRecipient: '收票人',
-  enterInvoiceRecipient: '请输入收票人',
-  recipientPhone: '收票人手机号',
-  enterRecipientPhone: '请输入收票人手机号',
-  invoiceAddress: '收票地址',
-  enterInvoiceAddress: '请输入收票地址',
-  invoiceEmail: '收票邮箱',
-  enterInvoiceEmail: '请输入收票邮箱',
-  businessLicenseFile: '营业执照扫描件(加盖公章)',
-  taxRegistrationFile: '税务登记复印件',
-  generalTaxpayerFile: '一般纳税人认定表复印件',
-  uploadFile: '点击上传图片',
-
-  // 购卡资质相关翻译
-  businessLicenseFile: '营业执照扫描件(加盖公章)',
-  legalPersonIdCardFrontFile: '法人身份证人像面(加盖公章)',
-  legalPersonIdCardBackFile: '法人身份证国徽面(加盖公章)',
-  equipmentPurchaseFile: '设备照片(加盖公章)',
-  businessContractFile: '业务合同(加盖公章)',
-  informationSecurityFile: '信息安全承诺书(加盖公章)',
-  customerInformationFile: '客户信息表(加盖公章)',
-  obtainMethod: '获客方式及文字话术',
-  telephoneApplicationForm: '电话业务用户申请登记表',
-  otherDocuments: '其他附件',
-  uploadFile: '点击上传图片',
-  imageUploadDescription: '1.建议上传尺寸为360*240px的图片\n2.图片仅支持jpg或png格式\n3.图片不得大于2M',
-  obtainMethodDescription: '支持扩展名:.rar .zip .doc .docx .ppt .pptx .xls .xlsx .pdf .jpg .jpeg .png .txt\n最多上传10个文件,每个文件不超过2M',
-  telephoneApplicationFormDescription: '支持扩展名:.rar .zip .doc .docx .ppt .pptx .xls .xlsx .pdf .jpg .jpeg .png .txt\n最多上传10个文件,每个文件不超过2M',
-  otherDocumentsDescription: '支持扩展名:.rar .zip .doc .docx .ppt .pptx .xls .xlsx .pdf .jpg .jpeg .png .txt\n最多上传10个文件,每个文件不超过2M',
-
-  // 预警参数相关翻译
-  warningNumbers: '预警参数',
-  accountBalanceWarning: '账号余额预警',
-  reachWarning: '达量预警',
-  stopSending: '达量停机',
-  networkDisconnection: '达量断网',
-  warningPhones: '预警手机',
-  warningEmails: '预警邮箱',
-  enterWarningPhones: '多个逗号隔开,最多3个',
-  enterWarningEmails: '多个逗号隔开,最多3个',
-  noRecovery: '不复机',
-  manualRecovery: '手工恢复',
-  autoRecovery: '自动恢复',
-  // customerInvoice: {
-  //   businessLicenseFile: "营业执照扫描件(加盖公章)"
-  // },
-  // customerCardQualification: {
-  //   legalPersonIdCardFrontFile:
-  // }
+    // 主列表页面
+    customerName: "客户名称",
+    enterCustomerName: "请输入客户名称",
+    operatorType: "运营商类型",
+    selectOperatorType: "请选择运营商类型",
+    addCustomer: "新增客户",
+    batchDelete: "批量删除",
+    searchExecuted: "已执行搜索",
+    searchReset: "搜索条件已重置",
+    batchDeleteWarning: "确定要批量删除选中的客户吗?",
+    statusName: "状态",
+
+    basicInfoSection: "基本信息",
+    smsInfoSection: "手机短信",
+    accountManagement: "账户资费管理",
+    customerData: "客户资料",
+    interfaceParams: "接口参数",
+    billingInfo: "发票信息",
+    purchaseQuality: "购卡资质",
+    warningNumbers: "预警参数",
+
+    // 表格列
+    id: "序号",
+    customerCode: "客户邮编",
+    accountNumber: "账号",
+    accountBalance: "账户余额",
+    paymentMethod: "付费方式",
+    customerStatus: "客户状态",
+    validPeriod: "有效期",
+    activeCards: "有效卡数/总卡数",
+    updateTime: "更新时间",
+
+    // 操作按钮
+    recharge: "充值",
+    packageManagement: "套餐管理",
+    edit: "编辑",
+
+    // 状态
+    status: {
+        normal: "正常",
+        disabled: "禁用",
+        pending: "待审",
+        suspended: "暂停",
+    },
+
+    // 运营商类型
+    operatorTypes: {
+        domestic: "国内",
+        international: "国际",
+    },
+
+    // 新增/编辑客户对话框
+    editCustomer: "编辑客户",
+    basicInfo: "基本信息",
+    smsInfo: "手机短信",
+    enterCustomerCode: "请输入客户邮编",
+    enterAccountNumber: "请输入账号",
+    password: "登录密码",
+    enterPassword: "请输入登录密码",
+    generatePassword: "重置密码",
+    remark: "号码备注",
+    enterRemark: "请输入号码备注",
+    selectValidPeriod: "请选择有效期",
+
+    smsNumber: "短信子号",
+    enterSmsNumber: "请输入短信子号",
+    smsName: "短信签名",
+    enterSmsName: "请输入短信签名",
+    loginSmsTemplate: "登录短信模板",
+    enterLoginSmsTemplate: "请输入登录短信模板",
+    alarmSmsTemplate: "预警短信模板",
+    enterAlarmSmsTemplate: "请输入预警短信模板",
+
+    // 表单验证消息
+    customerCodeRequired: "请输入客户编码",
+    customerNameRequired: "请输入客户名称",
+    accountNumberRequired: "请输入账号",
+    passwordRequired: "请输入登录密码",
+    validPeriodRequired: "请选择有效期",
+    statusRequired: "请选择客户状态",
+
+    // 其他
+    passwordGenerated: "密码已生成",
+
+    // 账户资费管理相关翻译
+    accountBalance: '账户余额',
+    rechargeLimit: '充值限制',
+    creditLimit: '信用额度',
+    mobileSmsPrice: '手机短信单价',
+    iotSmsPrice: '物联网短信单价',
+    paymentMethod: '付费方式',
+    currency: '元',
+    currencyPerTime: '元/次',
+    currencyPerMessage: '元/条',
+    paymentMethodName: '付费方式名称',
+    paymentMethod: {
+        prepaid: '预付费',
+        postpaid: '后付费'
+    },
+
+    // 客户资料相关翻译
+    platformName: '平台名称',
+    enterPlatformName: '请输入平台名称',
+    companyName: '公司名称',
+    enterCompanyName: '请输入公司名称',
+    servicePhone: '服务电话',
+    enterServicePhone: '请输入服务电话',
+    domain: '域名',
+    enterDomain: '请输入域名',
+    websiteBackend: '网站备案号',
+    enterWebsiteBackend: '请输入网站备案号',
+    customerAddress: '客户地址',
+    enterCustomerAddress: '请输入客户地址',
+
+    contactPerson: '联系人',
+    enterContactPerson: '请输入联系人',
+    contactPhone: '联系人手机号',
+    enterContactPhone: '请输入联系人手机号',
+    contactEmail: '联系人邮箱',
+    enterContactEmail: '请输入联系人邮箱',
+    contactQQ: '联系人QQ号',
+    enterContactQQ: '请输入联系人QQ号',
+
+    billingPerson: '收件人',
+    enterBillingPerson: '请输入收件人',
+    billingPhone: '收件人手机号',
+    enterBillingPhone: '请输入收件人手机号',
+    billingAddress: '收件人地址',
+    enterBillingAddress: '请输入收件人地址',
+
+    // 接口参数相关翻译
+    smsStatusReportUrl: '短信状态报告推送地址',
+    enterSmsStatusReportUrl: '请输入短信状态报告推送地址',
+    reportIp: '报备IP',
+    enterReportIp: '请输入报备IP',
+    deliveryPriority: '推送优先级',
+    selectDeliveryPriority: '请选择推送优先级',
+    deliveryPriorityName: '推送优先级',
+    deliveryPriority: {
+        high: '高',
+        medium: '中',
+        low: '低'
+    },
+    dataReportUrl: '数据推送地址',
+    enterDataReportUrl: '请输入数据推送地址',
+
+    // 发票信息相关翻译
+    invoiceTitle: '发票抬头',
+    enterInvoiceTitle: '请输入发票抬头',
+    taxRegistrationNumber: '税务登记证号',
+    enterTaxRegistrationNumber: '请输入税务登记证号',
+    registeredAddress: '注册场所地址',
+    enterRegisteredAddress: '请输入注册场所地址',
+    registeredPhone: '注册固定电话',
+    enterRegisteredPhone: '请输入注册固定电话',
+    bankName: '开户银行名称',
+    enterBankName: '请输入开户银行名称',
+    bankAccountName: '账户名称',
+    enterBankAccountName: '请输入账户名称',
+    bankAccountNumber: '开户账号',
+    enterBankAccountNumber: '请输入开户账号',
+    taxIdentificationNumber: '纳税人识别号',
+    enterTaxIdentificationNumber: '请输入纳税人识别号',
+    invoiceRecipient: '收票人',
+    enterInvoiceRecipient: '请输入收票人',
+    recipientPhone: '收票人手机号',
+    enterRecipientPhone: '请输入收票人手机号',
+    invoiceAddress: '收票地址',
+    enterInvoiceAddress: '请输入收票地址',
+    invoiceEmail: '收票邮箱',
+    enterInvoiceEmail: '请输入收票邮箱',
+    businessLicenseFile: '营业执照扫描件(加盖公章)',
+    taxRegistrationFile: '税务登记复印件',
+    generalTaxpayerFile: '一般纳税人认定表复印件',
+    uploadFile: '点击上传图片',
+
+    // 购卡资质相关翻译
+    businessLicenseFile: '营业执照扫描件(加盖公章)',
+    legalPersonIdCardFrontFile: '法人身份证人像面(加盖公章)',
+    legalPersonIdCardBackFile: '法人身份证国徽面(加盖公章)',
+    equipmentPurchaseFile: '设备照片(加盖公章)',
+    businessContractFile: '业务合同(加盖公章)',
+    informationSecurityFile: '信息安全承诺书(加盖公章)',
+    customerInformationFile: '客户信息表(加盖公章)',
+    obtainMethod: '获客方式及文字话术',
+    telephoneApplicationForm: '电话业务用户申请登记表',
+    otherDocuments: '其他附件',
+    uploadFile: '点击上传图片',
+    imageUploadDescription: '1.建议上传尺寸为360*240px的图片\n2.图片仅支持jpg或png格式\n3.图片不得大于2M',
+    obtainMethodDescription: '支持扩展名:.rar .zip .doc .docx .ppt .pptx .xls .xlsx .pdf .jpg .jpeg .png .txt\n最多上传10个文件,每个文件不超过2M',
+    telephoneApplicationFormDescription: '支持扩展名:.rar .zip .doc .docx .ppt .pptx .xls .xlsx .pdf .jpg .jpeg .png .txt\n最多上传10个文件,每个文件不超过2M',
+    otherDocumentsDescription: '支持扩展名:.rar .zip .doc .docx .ppt .pptx .xls .xlsx .pdf .jpg .jpeg .png .txt\n最多上传10个文件,每个文件不超过2M',
+
+    // 预警参数相关翻译
+    warningNumbers: '预警参数',
+    accountBalanceWarning: '账号余额预警',
+    reachWarning: '达量预警',
+    stopSending: '达量停机',
+    networkDisconnection: '达量断网',
+    warningPhones: '预警手机',
+    warningEmails: '预警邮箱',
+    enterWarningPhones: '多个逗号隔开,最多3个',
+    enterWarningEmails: '多个逗号隔开,最多3个',
+    noRecovery: '不复机',
+    manualRecovery: '手工恢复',
+    autoRecovery: '自动恢复',
+    // customerInvoice: {
+    //   businessLicenseFile: "营业执照扫描件(加盖公章)"
+    // },
+    // customerCardQualification: {
+    //   legalPersonIdCardFrontFile:
+    // }
+
+
+    // 客户管理
+    smsSubCode: '短信',
+    enterSmsSubCode: '请输入短信',
+    TaxRegistration: '税务登记',
+    TaxRegistrationText: '税务登记信息',
+    InvoiceInformation: '发票信息',
+    photocopy: '税务登记复印件',
+    CertificationQualification: '一般纳税人认证资格复印件',
+    address: '地址',
+    addressMessage: '请输入地址',
+    invoice_vatTextType: '发票类型',
+    invoice_vatTextTypeSelect: '请选择发票类型',
+    invoiceCode: '发票邮编',
+    InvoiceCodeName: '请输入发票邮编',
+    invoiceEmailName: '发票邮箱',
+    invoiceEmailNameType: '请输入发票邮箱',
+    BankNumber: '银行账号',
+    BankNumberName: '请输入银行账号',
+    BusinessLicense: '营业执照',
+    stateType: '请选择状态',
+    nameType: '请输入姓名',
+    roleIdsType: '请选择角色',
+    userTypeType: '请选择用户类型',
+    phoneType: '请输入手机号',
+    phoneName:'手机号',
+    emailName:'邮箱',
+    emailType: '请输入邮箱',
+    addrRequired: '请输入地址',
+    amountRequired: '请输入金额',
+    bankAccountRequired: '请输入银行账号',
+    bankBranchRequired: '请输入银行支行',
+    bankNameRequired: '请输入银行名称',
+    businessLicenseRequired: '请上传营业执照',
+    invoiceAddrRequired: '请输入发票地址',
+    invoiceEmailRequired: '请输入发票邮箱',
+    invoiceTitleRequired: '请输入发票抬头',
+    invoiceTypeRequired: '请选择发票类型',
+    invoiceZipRequired: '请输入发票邮政编码',
+    loginSMSTemplateRequired: '请输入登录短信模板',
+    noteRequired: '请输入备注',
+    smsRequired: '请输入短信模板',
+    smsSignatureRequired: '请输入短信签名',
+    warnSMSTemplateRequired: '请输入警告短信模板',
+    zipCodeRequired: '请输入邮政编码',
+    taxRegistrationCertificateRequired: '请上传税务登记证复印件',
+    taxpayerQualificationRequired: '请上传纳税人资格证复印件',
+    confirm: '确定',
+    netxbolck: '下一步',
+    confirmRemoveUpload:'是否删除该文件',
+    roleldsName:'角色',
+    roleldsNamedType:'请选择角色',
+    bank_branchName:'开户支行',
+    bank_branchNameType:'请输入开户支行',
+    userTypeName:'客户类型',
+    userTypeNameType:'请选择用户类型',
+    userAdmin:'客户账号',
+    startTime:'创建时间',
+    platform:'平台',
+    client:'客户'
 };

+ 3 - 2
src/main.js

@@ -16,7 +16,8 @@ import '@/assets/iconsvg/iconfont'
 import SvgIcon from '@/components/Svg-icon/SvgIcon.vue'
 // 额外引入图标库
 import ArcoVueIcon from '@arco-design/web-vue/es/icon'
-
+// 引入上传组件
+import upload from './components/upload/index.vue'
 async function appInit() {
   const app = createApp(App)
   // 注入组件
@@ -27,7 +28,7 @@ async function appInit() {
   app.use(ArcoVue)
   app.use(ArcoVueIcon)
   app.use(i18n)
-  
+  app.component('upload',upload)
   window['$t'] = i18n.global.t
 
 

+ 25 - 0
src/store/modules/routerTag.js

@@ -0,0 +1,25 @@
+import { defineStore } from 'pinia'
+import { setLocalStorage, getLocalStorage } from "@/utils";
+
+export const RouterTagData = defineStore({
+    id: 'RouterTagData',
+    state: () => ({
+        tagData:  []
+    }),
+    getters: {
+
+    },
+    actions: {
+        tagsPushData(items) {
+            if (!this.tagData.some((res) => res.name === items.name)) {
+                this.tagData.push(items);
+            }
+            setLocalStorage('LAOUT_TAG', this.tagData);
+        },
+        // 删除标签
+        handleRemove(items){
+            this.tagData = this.tagData.filter((res) => res.name!== items.name);
+            setLocalStorage('LAOUT_TAG', this.tagData);
+        }
+    }
+})

+ 4 - 3
src/store/modules/systemStore.js

@@ -111,9 +111,10 @@ export const useSystemStore = defineStore({
       return stsFn
     },
     getRole() {
-      if (this.role) return this.role;
-      this.role = window.localStorage?.role || "";
-      return this.role;
+      // if (this.role) return ;
+      // this.role = window.localStorage?.role || "";
+      // return this.role;
+      return JSON.parse(localStorage.getItem("user_login_information"))?.userType
     },
   },
   actions: {

+ 317 - 621
src/views/customer/NewCustomerForm.vue

@@ -1,667 +1,363 @@
 <template>
-    <a-modal :visible="visible" :title="editMode ? $t('customer.editCustomer') : $t('customer.addCustomer')"
-        :loading="loading" @ok="handleSubmit" @cancel="handleCancel" :width="720">
-        <a-tabs>
-            <a-tab-pane key="1" :title="$t('customer.basicInfo')">
-                <a-form :model="formData" :rules="rules" ref="formRef" :label-col-props="{ span: 6 }"
-                    :wrapper-col-props="{ span: 18 }">
-                    <a-divider>{{ $t('customer.basicInfoSection') }}</a-divider>
-                    <a-form-item field="customerInfo.customerCode" :label="$t('customer.customerCode')" required>
-                        <a-input v-model="formData.customerInfo.customerCode"
-                            :placeholder="$t('customer.enterCustomerCode')" :max-length="60" show-word-limit />
-                    </a-form-item>
-                    <a-form-item field="customerInfo.name" :label="$t('customer.customerName')" required>
-                        <a-input v-model="formData.customerInfo.name" :placeholder="$t('customer.enterCustomerName')"
-                            :max-length="60" show-word-limit />
-                    </a-form-item>
-                    <a-form-item field="userInfo.username" :label="$t('customer.accountNumber')" required>
-                        <a-input v-model="formData.userInfo.username" :placeholder="$t('customer.enterAccountNumber')"
-                            :max-length="60" show-word-limit />
-                    </a-form-item>
-                    <a-form-item field="userInfo.password" :label="$t('customer.password')" required>
-                        <a-input-password v-model="formData.userInfo.password"
-                            :placeholder="$t('customer.enterPassword')" :max-length="60" show-word-limit />
-                        <a-button type="primary" @click="generatePassword">{{ $t('customer.generatePassword')
-                            }}</a-button>
-                    </a-form-item>
-                    <a-form-item field="customerInfo.remark" :label="$t('customer.remark')">
-                        <a-input v-model="formData.customerInfo.remark" :placeholder="$t('customer.enterRemark')"
-                            :max-length="60" show-word-limit />
-                    </a-form-item>
-                    <a-form-item field="customerInfo.exTime" :label="$t('customer.validPeriod')" required>
-                        <a-date-picker v-model="formData.customerInfo.exTime"
-                            :placeholder="$t('customer.selectValidPeriod')" value-format="YYYY-MM-DD" />
-                    </a-form-item>
-                    <a-form-item field="userInfo.state" :label="$t('customer.statusName')" required>
-                        <a-radio-group v-model="formData.userInfo.state">
-                            <a-radio value="1">{{ $t('customer.status.normal') }}</a-radio>
-                            <a-radio value="2">{{ $t('customer.status.disabled') }}</a-radio>
-                            <a-radio value="3">{{ $t('customer.status.pending') }}</a-radio>
-                            <a-radio value="4">{{ $t('customer.status.suspended') }}</a-radio>
-                        </a-radio-group>
-                    </a-form-item>
-
-                    <a-divider>{{ $t('customer.smsInfoSection') }}</a-divider>
-                    <a-form-item field="customerInfo.smsSubCode" :label="$t('customer.smsSubCode')">
-                        <a-input v-model="formData.customerInfo.smsSubCode"
-                            :placeholder="$t('customer.enterSmsSubCode')" :max-length="60" show-word-limit />
-                    </a-form-item>
-                    <a-form-item field="customerInfo.smsName" :label="$t('customer.smsName')">
-                        <a-input v-model="formData.customerInfo.smsName" :placeholder="$t('customer.enterSmsName')"
-                            :max-length="60" show-word-limit />
-                    </a-form-item>
-                    <a-form-item field="customerInfo.loginSmsTemplate" :label="$t('customer.loginSmsTemplate')">
-                        <a-input v-model="formData.customerInfo.loginSmsTemplate"
-                            :placeholder="$t('customer.enterLoginSmsTemplate')" :max-length="60" show-word-limit />
-                    </a-form-item>
-                    <a-form-item field="customerInfo.alarmSmsTemplate" :label="$t('customer.alarmSmsTemplate')">
-                        <a-input v-model="formData.customerInfo.alarmSmsTemplate"
-                            :placeholder="$t('customer.enterAlarmSmsTemplate')" :max-length="60" show-word-limit />
-                    </a-form-item>
-                </a-form>
-            </a-tab-pane>
-            <a-tab-pane key="2" :title="$t('customer.accountManagement')">
-                <a-form :model="formData" :label-col-props="{ span: 6 }" :wrapper-col-props="{ span: 18 }">
-                    <a-form-item field="customerProperty.amount" :label="$t('customer.accountBalance')">
-                        <a-input-number v-model="formData.customerProperty.amount" :min="0" :precision="2" :step="100"
-                            :suffix="$t('customer.currency')" />
-                    </a-form-item>
-                    <a-form-item field="customerProperty.rechargeLimit" :label="$t('customer.rechargeLimit')">
-                        <a-input-number v-model="formData.customerProperty.rechargeLimit" :min="0" :precision="2"
-                            :step="1" :suffix="$t('customer.currencyPerTime')" />
-                    </a-form-item>
-                    <a-form-item field="customerProperty.lineOfCredit" :label="$t('customer.creditLimit')">
-                        <a-input-number v-model="formData.customerProperty.lineOfCredit" :min="0" :precision="2"
-                            :step="100" :suffix="$t('customer.currency')" />
-                    </a-form-item>
-                    <a-form-item field="customerProperty.smsUnitPrice" :label="$t('customer.mobileSmsPrice')">
-                        <a-input-number v-model="formData.customerProperty.smsUnitPrice" :min="0" :precision="2"
-                            :step="0.1" :suffix="$t('customer.currencyPerMessage')" />
-                    </a-form-item>
-                    <a-form-item field="customerProperty.iotSmsUnitPrice" :label="$t('customer.iotSmsPrice')">
-                        <a-input-number v-model="formData.customerProperty.iotSmsUnitPrice" :min="0" :precision="2"
-                            :step="0.1" :suffix="$t('customer.currencyPerMessage')" />
-                    </a-form-item>
-                    <a-form-item field="customerProperty.paymentMethod" :label="$t('customer.paymentMethodName')"
-                        required>
-                        <a-radio-group v-model="formData.customerProperty.paymentMethod">
-                            <a-radio value="prepaid">{{ $t('customer.paymentMethod.prepaid') }}</a-radio>
-                            <a-radio value="postpaid">{{ $t('customer.paymentMethod.postpaid') }}</a-radio>
-                        </a-radio-group>
-                    </a-form-item>
-                </a-form>
-            </a-tab-pane>
-            <a-tab-pane key="3" :title="$t('customer.customerData')">
-                <a-form :model="formData" :label-col-props="{ span: 6 }" :wrapper-col-props="{ span: 18 }">
-                    <a-divider>{{ $t('customer.basicInfoSection') }}</a-divider>
-                    <a-form-item field="customerInfo.platformName" :label="$t('customer.platformName')" required>
-                        <a-input v-model="formData.customerInfo.platformName"
-                            :placeholder="$t('customer.enterPlatformName')" :max-length="60" show-word-limit />
-                    </a-form-item>
-                    <a-form-item field="customerInfo.companyName" :label="$t('customer.companyName')">
-                        <a-input v-model="formData.customerInfo.companyName"
-                            :placeholder="$t('customer.enterCompanyName')" :max-length="60" show-word-limit />
-                    </a-form-item>
-
-                    <a-form-item field="customerInfo.servicePhone" :label="$t('customer.servicePhone')">
-                        <a-input v-model="formData.customerInfo.servicePhone"
-                            :placeholder="$t('customer.enterServicePhone')" :max-length="60" show-word-limit />
-                    </a-form-item>
-                    <a-form-item field="customerInfo.domain" :label="$t('customer.domain')">
-                        <a-input v-model="formData.customerInfo.domain" :placeholder="$t('customer.enterDomain')"
-                            :max-length="60" show-word-limit />
-                    </a-form-item>
-
-                    <a-form-item field="customerInfo.homepageLicenseCode" :label="$t('customer.homepageLicenseCode')">
-                        <a-input v-model="formData.customerInfo.homepageLicenseCode"
-                            :placeholder="$t('customer.enterHomepageLicenseCode')" :max-length="60" show-word-limit />
-                    </a-form-item>
-                    <a-form-item field="customerInfo.companyAddress" :label="$t('customer.companyAddress')">
-                        <a-textarea v-model="formData.customerInfo.companyAddress"
-                            :placeholder="$t('customer.enterCompanyAddress')" :max-length="200" show-word-limit />
-                    </a-form-item>
-
-                    <a-divider>{{ $t('customer.contactPerson') }}</a-divider>
-                    <a-form-item field="customerInfo.contactName" :label="$t('customer.contactName')">
-                        <a-input v-model="formData.customerInfo.contactName"
-                            :placeholder="$t('customer.enterContactName')" :max-length="60" show-word-limit />
-                    </a-form-item>
-                    <a-form-item field="customerInfo.phone" :label="$t('customer.contactPhone')">
-                        <a-input v-model="formData.customerInfo.phone" :placeholder="$t('customer.enterContactPhone')"
-                            :max-length="60" show-word-limit />
-                    </a-form-item>
-                    <a-form-item field="customerInfo.email" :label="$t('customer.contactEmail')">
-                        <a-input v-model="formData.customerInfo.email" :placeholder="$t('customer.enterContactEmail')"
-                            :max-length="60" show-word-limit />
-                    </a-form-item>
-                    <a-form-item field="customerInfo.qq" :label="$t('customer.contactQQ')">
-                        <a-input v-model="formData.customerInfo.qq" :placeholder="$t('customer.enterContactQQ')"
-                            :max-length="60" show-word-limit />
-                    </a-form-item>
-
-                    <a-divider>{{ $t('customer.deliveryInfo') }}</a-divider>
-                    <a-form-item field="customerInfo.deliveryAddress" :label="$t('customer.deliveryAddress')">
-                        <a-textarea v-model="formData.customerInfo.deliveryAddress"
-                            :placeholder="$t('customer.enterDeliveryAddress')" :max-length="200" show-word-limit />
-                    </a-form-item>
-                    <a-form-item field="customerInfo.deliveryPhone" :label="$t('customer.deliveryPhone')">
-                        <a-input v-model="formData.customerInfo.deliveryPhone"
-                            :placeholder="$t('customer.enterDeliveryPhone')" :max-length="60" show-word-limit />
-                    </a-form-item>
-                    <a-form-item field="customerInfo.deliveryName" :label="$t('customer.deliveryName')">
-                        <a-input v-model="formData.customerInfo.deliveryName"
-                            :placeholder="$t('customer.enterDeliveryName')" :max-length="60" show-word-limit />
-                    </a-form-item>
-                </a-form>
-            </a-tab-pane>
-            <a-tab-pane key="4" :title="$t('customer.interfaceParams')">
-                <a-form :model="formData" :label-col-props="{ span: 6 }" :wrapper-col-props="{ span: 18 }">
-                    <a-divider>{{ $t('customer.basicInfoSection') }}</a-divider>
-                    <a-form-item field="customerInterfaceParams.smsStatusReportUrl"
-                        :label="$t('customer.smsStatusReportUrl')">
-                        <a-input v-model="formData.customerInterfaceParams.smsStatusReportUrl"
-                            :placeholder="$t('customer.enterSmsStatusReportUrl')" :max-length="60" show-word-limit />
-                    </a-form-item>
-                    <a-form-item field="customerInterfaceParams.reportIp" :label="$t('customer.reportIp')">
-                        <a-input v-model="formData.customerInterfaceParams.reportIp"
-                            :placeholder="$t('customer.enterReportIp')" :max-length="60" show-word-limit />
-                    </a-form-item>
-                    <a-form-item field="customerInterfaceParams.deliveryPriority"
-                        :label="$t('customer.deliveryPriorityName')">
-                        <a-select v-model="formData.customerInterfaceParams.deliveryPriority"
-                            :placeholder="$t('customer.selectDeliveryPriority')">
-                            <a-option value="high">{{ $t('customer.deliveryPriority.high') }}</a-option>
-                            <a-option value="medium">{{ $t('customer.deliveryPriority.medium') }}</a-option>
-                            <a-option value="low">{{ $t('customer.deliveryPriority.low') }}</a-option>
-                        </a-select>
-                    </a-form-item>
-                    <a-form-item field="customerInterfaceParams.dataReportUrl" :label="$t('customer.dataReportUrl')">
-                        <a-input v-model="formData.customerInterfaceParams.dataReportUrl"
-                            :placeholder="$t('customer.enterDataReportUrl')" :max-length="60" show-word-limit />
-                    </a-form-item>
-                </a-form>
-            </a-tab-pane>
-            <a-tab-pane key="5" :title="$t('customer.billingInfo')">
-                <a-form :model="formData" :label-col-props="{ span: 6 }" :wrapper-col-props="{ span: 18 }">
-                    <a-form-item field="customerInvoice.invoiceTitle" :label="$t('customer.invoiceTitle')">
-                        <a-input v-model="formData.customerInvoice.invoiceTitle"
-                            :placeholder="$t('customer.enterInvoiceTitle')" :max-length="60" show-word-limit />
-                    </a-form-item>
-                    <a-form-item field="customerInvoice.taxRegistrationNumber"
-                        :label="$t('customer.taxRegistrationNumber')">
-                        <a-input v-model="formData.customerInvoice.taxRegistrationNumber"
-                            :placeholder="$t('customer.enterTaxRegistrationNumber')" :max-length="60" show-word-limit />
-                    </a-form-item>
-                    <a-form-item field="customerInvoice.registeredAddress" :label="$t('customer.registeredAddress')">
-                        <a-input v-model="formData.customerInvoice.registeredAddress"
-                            :placeholder="$t('customer.enterRegisteredAddress')" :max-length="60" show-word-limit />
-                    </a-form-item>
-                    <a-form-item field="customerInvoice.registeredPhone" :label="$t('customer.registeredPhone')">
-                        <a-input v-model="formData.customerInvoice.registeredPhone"
-                            :placeholder="$t('customer.enterRegisteredPhone')" :max-length="60" show-word-limit />
-                    </a-form-item>
-                    <a-form-item field="customerInvoice.bankName" :label="$t('customer.bankName')">
-                        <a-input v-model="formData.customerInvoice.bankName" :placeholder="$t('customer.enterBankName')"
-                            :max-length="60" show-word-limit />
-                    </a-form-item>
-                    <a-form-item field="customerInvoice.bankAccountName" :label="$t('customer.bankAccountName')">
-                        <a-input v-model="formData.customerInvoice.bankAccountName"
-                            :placeholder="$t('customer.enterBankAccountName')" :max-length="60" show-word-limit />
-                    </a-form-item>
-                    <a-form-item field="customerInvoice.bankAccountNumber" :label="$t('customer.bankAccountNumber')">
-                        <a-input v-model="formData.customerInvoice.bankAccountNumber"
-                            :placeholder="$t('customer.enterBankAccountNumber')" :max-length="60" show-word-limit />
-                    </a-form-item>
-                    <a-form-item field="customerInvoice.taxIdentificationNumber"
-                        :label="$t('customer.taxIdentificationNumber')">
-                        <a-input v-model="formData.customerInvoice.taxIdentificationNumber"
-                            :placeholder="$t('customer.enterTaxIdentificationNumber')" :max-length="60"
-                            show-word-limit />
-                    </a-form-item>
-                    <a-form-item field="customerInvoice.invoiceRecipient" :label="$t('customer.invoiceRecipient')">
-                        <a-input v-model="formData.customerInvoice.invoiceRecipient"
-                            :placeholder="$t('customer.enterInvoiceRecipient')" :max-length="60" show-word-limit />
-                    </a-form-item>
-                    <a-form-item field="customerInvoice.recipientPhone" :label="$t('customer.recipientPhone')">
-                        <a-input v-model="formData.customerInvoice.recipientPhone"
-                            :placeholder="$t('customer.enterRecipientPhone')" :max-length="60" show-word-limit />
-                    </a-form-item>
-                    <a-form-item field="customerInvoice.invoiceAddress" :label="$t('customer.invoiceAddress')">
-                        <a-input v-model="formData.customerInvoice.invoiceAddress"
-                            :placeholder="$t('customer.enterInvoiceAddress')" :max-length="60" show-word-limit />
-                    </a-form-item>
-                    <a-form-item field="customerInvoice.invoiceEmail" :label="$t('customer.invoiceEmail')">
-                        <a-input v-model="formData.customerInvoice.invoiceEmail"
-                            :placeholder="$t('customer.enterInvoiceEmail')" :max-length="60" show-word-limit />
-                    </a-form-item>
-                    <a-form-item field="customerInvoice.businessLicenseFile"
-                        :label="$t('customer.businessLicenseFile')">
-                        <a-upload :show-file-list="false"
-                            :custom-request="(option) => handleUpload(option, 'business_license')">
-                            <template #upload-button>
-                                <a-button>{{ $t('customer.uploadFile') }}</a-button>
-                            </template>
-                        </a-upload>
-                    </a-form-item>
-                    <a-form-item field="customerInvoice.taxRegistrationFile"
-                        :label="$t('customer.taxRegistrationFile')">
-                        <a-upload :show-file-list="false"
-                            :custom-request="(option) => handleUpload(option, 'tax_registration')">
-                            <template #upload-button>
-                                <a-button>{{ $t('customer.uploadFile') }}</a-button>
-                            </template>
-                        </a-upload>
-                    </a-form-item>
-                    <a-form-item field="customerInvoice.generalTaxpayerFile"
-                        :label="$t('customer.generalTaxpayerFile')">
-                        <a-upload :show-file-list="false"
-                            :custom-request="(option) => handleUpload(option, 'general_taxpayer')">
-                            <template #upload-button>
-                                <a-button>{{ $t('customer.uploadFile') }}</a-button>
-                            </template>
-                        </a-upload>
-                    </a-form-item>
-                </a-form>
-            </a-tab-pane>
-            <a-tab-pane key="6" :title="$t('customer.purchaseQuality')">
-                <a-form :model="formData" :label-col-props="{ span: 8 }" :wrapper-col-props="{ span: 16 }">
-                    <template v-for="(field, index) in imageUploadFields" :key="field">
-                        <a-form-item :field="field"
-                            :label="$t(`customer.${field.split('.')[field.split('.').length - 1]}`)">
-                            <a-upload action="/" :file-list="formData[field] ? [formData[field]] : []"
-                                :show-file-list="false" @change="(_, file) => handleFileUpload(field, file)"
-                                @progress="(file) => handleFileProgress(field, file)">
-                                <template #upload-button>
-                                    <div :class="`arco-upload-list-item${formData[field] && formData[field].status === 'error' ? ' arco-upload-list-item-error' : ''
-                                        }`">
-                                        <div class="arco-upload-list-picture custom-upload-avatar"
-                                            v-if="formData[field] && formData[field].url">
-                                            <img :src="formData[field].url" />
-                                            <div class="arco-upload-list-picture-mask">
-                                                <icon-edit />
-                                            </div>
-                                            <a-progress
-                                                v-if="formData[field].status === 'uploading' && formData[field].percent < 100"
-                                                :percent="formData[field].percent" type="circle" size="mini" :style="{
-                                                    position: 'absolute',
-                                                    left: '50%',
-                                                    top: '50%',
-                                                    transform: 'translateX(-50%) translateY(-50%)',
-                                                }" />
-                                        </div>
-                                        <div class="arco-upload-picture-card" v-else>
-                                            <div class="arco-upload-picture-card-text">
-                                                <icon-plus />
-                                                <div style="margin-top: 10px; font-weight: 600">{{
-                                                    $t('customer.uploadFile') }}</div>
-                                            </div>
-                                        </div>
-                                    </div>
-                                </template>
-                            </a-upload>
-                            <div class="upload-description">
-                                {{ $t('customer.imageUploadDescription') }}
-                            </div>
-                        </a-form-item>
-                    </template>
-
-                    <a-form-item field="customerCardQualification.obtainMethod" :label="$t('customer.obtainMethod')">
-                        <a-upload action="/" :file-list="formData.customerCardQualification.obtainMethod"
-                            @change="handleObtainMethodUpload" multiple>
-                            <template #upload-button>
-                                <a-button>{{ $t('customer.uploadFile') }}</a-button>
-                            </template>
-                        </a-upload>
-                        <div class="upload-description">
-                            {{ $t('customer.obtainMethodDescription') }}
-                        </div>
-                    </a-form-item>
-
-                    <a-form-item field="customerCardQualification.telephoneApplicationForm"
-                        :label="$t('customer.telephoneApplicationForm')">
-                        <a-upload action="/" :file-list="formData.customerCardQualification.telephoneApplicationForm"
-                            @change="handleTelephoneApplicationFormUpload" multiple>
-                            <template #upload-button>
-                                <a-button>{{ $t('customer.uploadFile') }}</a-button>
-                            </template>
-                        </a-upload>
-                        <div class="upload-description">
-                            {{ $t('customer.telephoneApplicationFormDescription') }}
-                        </div>
-                    </a-form-item>
-
-                    <a-form-item field="customerCardQualification.otherDocuments"
-                        :label="$t('customer.otherDocuments')">
-                        <a-upload action="/" :file-list="formData.customerCardQualification.otherDocuments"
-                            @change="handleOtherDocumentsUpload" multiple>
-                            <template #upload-button>
-                                <a-button>{{ $t('customer.uploadFile') }}</a-button>
-                            </template>
-                        </a-upload>
-                        <div class="upload-description">
-                            {{ $t('customer.otherDocumentsDescription') }}
-                        </div>
-                    </a-form-item>
-                </a-form>
-            </a-tab-pane>
-            <a-tab-pane key="7" :title="$t('customer.warningNumbers')">
-                <a-form :model="formData" :label-col-props="{ span: 6 }" :wrapper-col-props="{ span: 18 }">
-                    <a-form-item field="customerWarningParameter.accountBalanceWarning"
-                        :label="$t('customer.accountBalanceWarning')">
-                        <a-input-number v-model="formData.customerWarningParameter.accountBalanceWarning" :min="0"
-                            :precision="2" :step="100" :style="{ width: '100%' }" />
-                    </a-form-item>
-                    <a-form-item field="customerWarningParameter.reachWarning" :label="$t('customer.reachWarning')">
-                        <a-input-number v-model="formData.customerWarningParameter.reachWarning" :min="0" :max="100"
-                            :precision="0" :step="1" :style="{ width: '100%' }">
-                            <template #append>%</template>
-                        </a-input-number>
-                    </a-form-item>
-                    <a-form-item field="customerWarningParameter.stopSending" :label="$t('customer.stopSending')">
-                        <a-space>
-                            <a-input-number v-model="formData.customerWarningParameter.stopSending" :min="0" :max="100"
-                                :precision="0" :step="1" :style="{ width: '100px' }">
-                                <template #append>%</template>
-                            </a-input-number>
-                            <a-radio-group v-model="formData.customerWarningParameter.stopSendingAction">
-                                <a-radio value="noRecovery">{{ $t('customer.noRecovery') }}</a-radio>
-                                <a-radio value="manualRecovery">{{ $t('customer.manualRecovery') }}</a-radio>
-                                <a-radio value="autoRecovery">{{ $t('customer.autoRecovery') }}</a-radio>
-                            </a-radio-group>
-                        </a-space>
-                    </a-form-item>
-                    <a-form-item field="customerWarningParameter.networkDisconnection"
-                        :label="$t('customer.networkDisconnection')">
-                        <a-space>
-                            <a-input-number v-model="formData.customerWarningParameter.networkDisconnection" :min="0"
-                                :max="100" :precision="0" :step="1" :style="{ width: '100px' }">
-                                <template #append>%</template>
-                            </a-input-number>
-                            <a-radio-group v-model="formData.customerWarningParameter.networkDisconnectionAction">
-                                <a-radio value="noRecovery">{{ $t('customer.noRecovery') }}</a-radio>
-                                <a-radio value="manualRecovery">{{ $t('customer.manualRecovery') }}</a-radio>
-                                <a-radio value="autoRecovery">{{ $t('customer.autoRecovery') }}</a-radio>
-                            </a-radio-group>
-                        </a-space>
-                    </a-form-item>
-                    <a-form-item field="customerWarningParameter.warningPhones" :label="$t('customer.warningPhones')">
-                        <a-input v-model="formData.customerWarningParameter.warningPhones"
-                            :placeholder="$t('customer.enterWarningPhones')" :max-length="60" show-word-limit />
-                    </a-form-item>
-                    <a-form-item field="customerWarningParameter.warningEmails" :label="$t('customer.warningEmails')">
-                        <a-input v-model="formData.customerWarningParameter.warningEmails"
-                            :placeholder="$t('customer.enterWarningEmails')" :max-length="60" show-word-limit />
-                    </a-form-item>
-                </a-form>
-            </a-tab-pane>
-        </a-tabs>
-    </a-modal>
+  <a-modal
+      :visible="visible"
+      :title="editMode ? $t('customer.editCustomer') : $t('customer.addCustomer')"
+      :loading="loading"
+      @ok="handleSubmit"
+      @cancel="handleCancel"
+      :width="720"
+      :okText="$t('customer.confirm')"
+  >
+    <a-tabs>
+      <!-- 基本信息 Tab -->
+      <a-tab-pane key="1" :title="$t('customer.basicInfo')">
+        <a-form :model="formData" :rules="rules" ref="formRef" :label-col-props="{ span: 6 }"
+                :wrapper-col-props="{ span: 18 }">
+          <a-divider>{{ $t('customer.basicInfoSection') }}</a-divider>
+          <!-- Customer Code -->
+          <a-form-item field="zip" :label="$t('customer.customerCode')" required validate-trigger="blur">
+            <a-input v-model="formData.zip" :placeholder="$t('customer.enterCustomerCode')" :max-length="60"
+                     show-word-limit/>
+          </a-form-item>
+
+          <a-form-item field="email" :label="$t('customer.emailName')" required validate-trigger="blur">
+            <a-input v-model="formData.email" :placeholder="$t('customer.emailType')" :max-length="60"
+                     show-word-limit/>
+          </a-form-item>
+          <a-form-item field="phone" :label="$t('customer.phoneName')" required validate-trigger="blur">
+            <a-input v-model="formData.phone" :placeholder="$t('customer.phoneType')"  show-word-limit/>
+          </a-form-item>
+          <!-- Customer Name -->
+          <a-form-item field="name" :label="$t('customer.customerName')" required validate-trigger="blur">
+            <a-input v-model="formData.name" :placeholder="$t('customer.enterCustomerName')" :max-length="60"
+                     show-word-limit/>
+          </a-form-item>
+          <!-- Account Number -->
+          <a-form-item field="username" :label="$t('customer.accountNumber')" required validate-trigger="blur">
+            <a-input v-model="formData.username" :placeholder="$t('customer.enterAccountNumber')" :max-length="60"
+                     show-word-limit/>
+          </a-form-item>
+          <!-- Password -->
+          <a-form-item field="password" :label="$t('customer.password')" required validate-trigger="blur">
+            <a-input-password v-model="formData.password" :placeholder="$t('customer.enterPassword')" :max-length="60"
+                              show-word-limit/>
+            <a-button type="primary" @click="generatePassword">{{ $t('customer.generatePassword') }}</a-button>
+          </a-form-item>
+          <!--          role-->
+          <a-form-item field="roleIds" :label="$t('customer.roleldsName')" required validate-trigger="blur">
+            <a-select multiple v-model="formData.roleIds" :style="{width:'100%'}"
+                      :placeholder="$t('customer.roleldsNamedType')">
+              <a-option v-for="item of roles" :value="item.id" :label="item.name"/>
+            </a-select>
+          </a-form-item>
+          <a-form-item field="userType" :label="$t('customer.userTypeName')" required validate-trigger="blur">
+            <a-select  v-model="formData.userType" :style="{width:'100%'}"
+                       :placeholder="$t('customer.userTypeNameType')">
+              <a-option v-for="item of userTypeList" :value="item.value" :label="item.label"/>
+            </a-select>
+          </a-form-item>
+          <!-- Remark -->
+          <a-form-item field="note" :label="$t('customer.remark')" required validate-trigger="blur">
+            <a-input v-model="formData.note" :placeholder="$t('customer.enterRemark')" :max-length="60"
+                     show-word-limit/>
+          </a-form-item>
+          <!-- Account Balance -->
+          <a-form-item field="amount" :label="$t('customer.accountBalance')" required validate-trigger="blur">
+            <a-input-number v-model="formData.amount" :min="0" :precision="2" :step="100"
+                            :suffix="$t('customer.currency')"/>
+          </a-form-item>
+          <!-- Address -->
+          <a-form-item field="addr" :label="$t('customer.address')" required validate-trigger="blur">
+            <a-input v-model="formData.addr" :placeholder="$t('customer.addressMessage')" :max-length="50"
+                     show-word-limit/>
+          </a-form-item>
+          <!-- Status -->
+          <a-form-item field="state" :label="$t('customer.statusName')" required validate-trigger="blur">
+            <a-radio-group v-model="formData.state">
+              <a-radio value="1">{{ $t('customer.status.normal') }}</a-radio>
+              <a-radio value="2">{{ $t('customer.status.disabled') }}</a-radio>
+              <a-radio value="3">{{ $t('customer.status.pending') }}</a-radio>
+              <a-radio value="4">{{ $t('customer.status.suspended') }}</a-radio>
+            </a-radio-group>
+          </a-form-item>
+        </a-form>
+      </a-tab-pane>
+
+      <!-- SMS 信息 Tab -->
+      <a-tab-pane key="2" :title="$t('customer.smsInfoSection')">
+        <a-form :model="formData" :rules="rules" ref="formRef" :label-col-props="{ span: 6 }"
+                :wrapper-col-props="{ span: 18 }">
+          <a-divider>{{ $t('customer.smsInfoSection') }}</a-divider>
+          <a-form-item field="sms" :label="$t('customer.smsSubCode')" required validate-trigger="blur">
+            <a-input v-model="formData.sms" :placeholder="$t('customer.enterSmsSubCode')" :max-length="60"
+                     show-word-limit/>
+          </a-form-item>
+          <a-form-item field="smsSignature" :label="$t('customer.smsName')" required validate-trigger="blur">
+            <a-input v-model="formData.smsSignature" :placeholder="$t('customer.enterSmsName')" :max-length="60"
+                     show-word-limit/>
+          </a-form-item>
+          <a-form-item field="loginSms" :label="$t('customer.loginSmsTemplate')" required validate-trigger="blur">
+            <a-input v-model="formData.loginSms" :placeholder="$t('customer.enterLoginSmsTemplate')" :max-length="60"
+                     show-word-limit/>
+          </a-form-item>
+          <a-form-item field="warnSms" :label="$t('customer.alarmSmsTemplate')" required validate-trigger="blur">
+            <a-input v-model="formData.warnSms" :placeholder="$t('customer.enterAlarmSmsTemplate')" :max-length="60"
+                     show-word-limit/>
+          </a-form-item>
+        </a-form>
+      </a-tab-pane>
+
+      <!-- Billing Information Tab -->
+      <a-tab-pane key="3" :title="$t('customer.billingInfo')">
+        <a-form :model="formData" :rules="rules" ref="formRef" :label-col-props="{ span: 6 }"
+                :wrapper-col-props="{ span: 18 }">
+          <a-divider>{{ $t('customer.InvoiceInformation') }}</a-divider>
+          <a-form-item field="invoiceTitle" :label="$t('customer.invoiceTitle')" required validate-trigger="blur">
+            <a-input v-model="formData.invoiceTitle" :placeholder="$t('customer.enterInvoiceTitle')" :max-length="60"
+                     show-word-limit/>
+          </a-form-item>
+          <a-form-item field="invoice_type" :label="$t('customer.invoice_vatTextType')" required
+                       validate-trigger="blur">
+            <a-select v-model="formData.invoiceType" :style="{width:'100%'}"
+                      :placeholder="$t('customer.invoice_vatTextTypeSelect')">
+              <a-option v-for="item of invoiceList" :value="item.value" :label="item.label"/>
+            </a-select>
+          </a-form-item>
+          <a-form-item field="invoiceAddr" :label="$t('customer.registeredAddress')" required validate-trigger="blur">
+            <a-input v-model="formData.invoiceAddr" :placeholder="$t('customer.enterRegisteredAddress')"
+                     :max-length="60" show-word-limit/>
+          </a-form-item>
+          <a-form-item field="invoiceZip" :label="$t('customer.invoiceCode')" required validate-trigger="blur">
+            <a-input v-model="formData.invoiceZip" :placeholder="$t('customer.InvoiceCodeName')" :max-length="60"
+                     show-word-limit/>
+          </a-form-item>
+          <a-form-item field="invoiceEmail" :label="$t('customer.invoiceEmailName')" required validate-trigger="blur">
+            <a-input v-model="formData.invoiceEmail" :placeholder="$t('customer.invoiceEmailNameType')"
+                     :max-length="60" show-word-limit/>
+          </a-form-item>
+          <a-form-item field="bankName" :label="$t('customer.bankName')" required validate-trigger="blur">
+            <a-input v-model="formData.bankName" :placeholder="$t('customer.enterBankName')" :max-length="60"
+                     show-word-limit/>
+          </a-form-item>
+          <a-form-item field="bankAccount" :label="$t('customer.BankNumber')" required validate-trigger="blur">
+            <a-input v-model="formData.bankAccount" :placeholder="$t('customer.BankNumberName')" :max-length="60"
+                     show-word-limit/>
+          </a-form-item>
+          <a-form-item field="bankBranch" :label="$t('customer.bank_branchName')" required validate-trigger="blur">
+            <a-input v-model="formData.bankBranch" :placeholder="$t('customer.bank_branchNameType')"  show-word-limit/>
+          </a-form-item>
+          <a-form-item field="businessLicense" :label="$t('customer.BusinessLicense')" required
+                       validate-trigger="blur">
+            <upload v-model="formData.businessLicense"/>
+          </a-form-item>
+        </a-form>
+      </a-tab-pane>
+
+      <!-- Tax Registration Tab -->
+      <a-tab-pane key="4" :title="$t('customer.TaxRegistration')">
+        <a-form :model="formData" :rules="rules" ref="formRef" :label-col-props="{ span: 8 }"
+                :wrapper-col-props="{ span: 16 }">
+          <a-divider>{{ $t('customer.TaxRegistrationText') }}</a-divider>
+          <a-form-item field="taxRegistrationCertificate" :label="$t('customer.photocopy')" required
+                       validate-trigger="blur">
+            <upload v-model:modelValue="formData.taxRegistrationCertificate"/>
+          </a-form-item>
+          <a-form-item field="taxpayerQualification" :label="$t('customer.CertificationQualification')" required
+                       validate-trigger="blur">
+            <upload v-model:modelValue="formData.taxpayerQualification"/>
+          </a-form-item>
+        </a-form>
+      </a-tab-pane>
+    </a-tabs>
+  </a-modal>
 </template>
 
-<script setup>
-import { ref, reactive, watch } from 'vue';
-import { Message } from '@arco-design/web-vue';
-import { useI18n } from 'vue-i18n';
-import { IconEdit, IconPlus } from '@arco-design/web-vue/es/icon';
-import dayjs from 'dayjs';
-import { useSystemStore } from '@/store/modules/systemStore'
 
-const { t } = useI18n();
+<script setup>
+import {ref, watch, onMounted} from 'vue';
+import {Message} from '@arco-design/web-vue';
+import {useI18n} from 'vue-i18n';
+import {useSystemStore} from '@/store/modules/systemStore'
+import {dictionaryDetail} from '@/api/path/dict.js'
+import Upload from "@/components/upload/index.vue";
+import {systemFindRoleList} from "@/api/path/system.api";
+import {addCustomer, updateCustomer} from "@/api/customer.js";
+const {t} = useI18n();
 const systemStore = useSystemStore()
-
+import { encryptByDES } from '@/utils/crypto'
 const props = defineProps({
-    visible: Boolean,
-    editMode: Boolean,
-    editData: Object,
-    loading: Boolean,
+  visible: Boolean,
+  editMode: Boolean,
+  editData: Object,
+  loading: Boolean,
 });
 
+const invoiceList = ref([])
+const roles = ref([])
+const userTypeList = ref([])
 watch(
     () => props.editData,
     (newVal) => {
-        if (newVal && props.editMode) {
-            // 深拷贝编辑数据
-            const editDataCopy = JSON.parse(JSON.stringify(newVal));
-
-            // 处理日期格式
-            if (editDataCopy.customerInfo?.exTime) {
-                editDataCopy.customerInfo.exTime = dayjs(editDataCopy.customerInfo.exTime).format('YYYY-MM-DD');
-            }
-
-            // 使用 Object.assign 更新每个子对象
-            Object.keys(formData).forEach(key => {
-                if (editDataCopy[key]) {
-                    Object.assign(formData[key], editDataCopy[key]);
-                }
-            });
+      if (newVal && props.editMode) {
+        // 深拷贝编辑数据
+        const editDataCopy = JSON.parse(JSON.stringify(newVal));
+
+        // 将 formData 中嵌套的 info 展平为一层
+        const flattenedFormData = ref(Object.fromEntries(Object.entries(editDataCopy).flatMap(([key, value]) => typeof value === 'object' && value !== null && !Array.isArray(value) ? Object.entries(value) : [[key, value]])));
+        if(editDataCopy.info) {
+          delete editDataCopy.info;
         }
+        const formDataList = {...editDataCopy,...flattenedFormData.value}
+        console.log(formDataList)
+        formData.value = formDataList
+        // Object.keys(formData.value).forEach(key => {
+        //   if (formDataList[key]) {
+        //     formData.value[key] = formDataList[key];
+        //   }
+        // });
+      }
     },
-    { deep: true, immediate: true }
+    {deep: true, immediate: true}
 );
 
 const emit = defineEmits(['update:visible', 'submit']);
 
 const formRef = ref(null);
-const formData = reactive({
-    userInfo: {
-        username: '',
-        password: '',
-        state: '1',
-        name: '',
-        id: null
-    },
-    customerInfo: {
-        customerCode: '',
-        name: '',
-        platformName: '',
-        companyName: '',
-        servicePhone: '',
-        phone: '',
-        email: '',
-        domain: '',
-        smsName: '',
-        exTime: null,
-        remark: '',
-        homepageLicenseCode: '',
-        companyAddress: '',
-        contactName: '',
-        qq: '',
-        deliveryAddress: '',
-        deliveryPhone: '',
-        deliveryName: '',
-        smsSubCode: '',
-    },
-    customerProperty: {
-        amount: 0,
-        rechargeLimit: 0,
-        lineOfCredit: 0,
-        smsUnitPrice: 0,
-        iotSmsUnitPrice: 0,
-        paymentMethod: 'prepaid',
-    },
-    customerInvoice: {
-        invoiceTitle: '',
-        taxRegistrationNumber: '',
-        registeredAddress: '',
-        registeredPhone: '',
-        bankName: '',
-        bankAccountName: '',
-        bankAccountNumber: '',
-        taxIdentificationNumber: '',
-        invoiceRecipient: '',
-        recipientPhone: '',
-        invoiceAddress: '',
-        invoiceEmail: '',
-        businessLicenseNumber: '',
-        taxRegistrationFile: '',
-        businessLicenseFile: '',
-        generalTaxpayerFile: '',
-    },
-    customerCardQualification: {
-        blImg: null,
-        legalPersonIdCardImgUp: null,
-        legalPersonIdCardImgDown: null,
-        iotImg: null,
-        contractImg: null,
-        commitmentImg: null,
-        customerForm: null,
-        getCustomerText: '',
-        phoneForm: null,
-        otherFile: null,
-    },
-    customerWarningParameter: {
-        accountBalanceWarning: 0,
-        reachWarning: 0,
-        stopSending: 0,
-        stopSendingAction: 'noRecovery',
-        networkDisconnection: 0,
-        networkDisconnectionAction: 'noRecovery',
-        warningPhones: '',
-        warningEmails: '',
-    },
-    customerInterfaceParams: {
-        smsStatusReportUrl: '',
-        reportIp: '',
-        deliveryPriority: '',
-        dataReportUrl: '',
-    },
+const formData = ref({
+  username: "",
+  state: "",
+  name: "",
+  password: "",
+  roleIds: [],
+  userType: '',
+  phone: "",
+  email: "",
+  addr: "",
+  zip: "",
+  note: "",
+  sms: "",
+  smsSignature: "",
+  loginSms: "",
+  warnSms: "",
+  amount: "",
+  invoiceTitle: "",
+  invoiceType: "",
+  invoiceAddr: "",
+  invoiceZip: "",
+  invoiceEmail: "",
+  bankName: "",
+  bankAccount: "",
+  bankBranch: "",
+  businessLicense: "",
+  taxRegistrationCertificate: "",
+  taxpayerQualification: ""
 });
 
 const rules = {
-    'userInfo.username': [{ required: true, message: t('customer.accountNumberRequired') }],
-    'userInfo.password': [{ required: true, message: t('customer.passwordRequired') }],
-    'customerInfo.customerCode': [{ required: true, message: t('customer.customerCodeRequired') }],
-    'customerInfo.name': [{ required: true, message: t('customer.customerNameRequired') }],
-    'customerInfo.exTime': [{ required: true, message: t('customer.validPeriodRequired') }],
-    'userInfo.state': [{ required: true, message: t('customer.statusRequired') }],
-    'customerInfo.platformName': [{ required: true, message: t('customer.platformNameRequired') }],
-    'customerInfo.servicePhone': [{ required: true, message: t('customer.servicePhoneRequired') }],
+  userName: [{required: true, message: t('customer.enterAccountNumber')}],
+  state: [{required: true, message: t('customer.stateType')}],
+  name: [{required: true, message: t('customer.nameType')}],
+  password: [{required: true, message: t('customer.passwordRequired')}],
+  roleIds: [{required: true, message: t('customer.roleIdsType')}],
+  userType: [{required: true, message: t('customer.userTypeType')}],
+  phone: [{required: true, message: t('customer.phoneType')}],
+  email: [{required: true, message: t('customer.emailType')}],
+  addr: [{required: true, message: t('customer.addressRequired')}],
+  amount: [{required: true, message: t('customer.amountRequired')}],
+  bankAccount: [{required: true, message: t('customer.bankAccountRequired')}],
+  bankBranch: [{required: true, message: t('customer.bankBranchRequired')}],
+  bankName: [{required: true, message: t('customer.bankNameRequired')}],
+  businessLicense: [{required: true, message: t('customer.businessLicenseRequired')}],
+  invoiceAddr: [{required: true, message: t('customer.invoiceAddressRequired')}],
+  invoiceEmail: [{required: true, message: t('customer.invoiceEmailRequired')}],
+  invoiceTitle: [{required: true, message: t('customer.invoiceTitleRequired')}],
+  invoiceType: [{required: true, message: t('customer.invoiceTypeRequired')}],
+  invoiceZip: [{required: true, message: t('customer.invoiceZipRequired')}],
+  loginSms: [{required: true, message: t('customer.loginSMSTemplateRequired')}],
+  note: [{required: true, message: t('customer.noteRequired')}],
+  sms: [{required: true, message: t('customer.smsRequired')}],
+  smsSignature: [{required: true, message: t('customer.smsSignatureRequired')}],
+  warnSms: [{required: true, message: t('customer.warnSMSTemplateRequired')}],
+  zip: [{required: true, message: t('customer.zipCodeRequired')}],
+  taxRegistrationCertificate: [{required: true, message: t('customer.taxRegistrationCertificateRequired')}],
+  taxpayerQualification: [{required: true, message: t('customer.taxpayerQualificationRequired')}]
 };
 
-const handleSubmit = () => {
-    formRef.value.validate((errors) => {
-        if (!errors) {
-            // 处理文件字段
-            const processedInvoice = {
-                ...formData.customerInvoice,
-                // 将数组转换为字符串或null
-                taxRegistrationFile: formData.customerInvoice.taxRegistrationFile?.length ?
-                    formData.customerInvoice.taxRegistrationFile[0]?.url || null : null,
-                businessLicenseFile: formData.customerInvoice.businessLicenseFile?.length ?
-                    formData.customerInvoice.businessLicenseFile[0]?.url || null : null,
-                generalTaxpayerFile: formData.customerInvoice.generalTaxpayerFile?.length ?
-                    formData.customerInvoice.generalTaxpayerFile[0]?.url || null : null,
-            };
-            const submitData = {
-                userInfo: {
-                    ...formData.userInfo,
-                    // 设置userInfo.name为customerInfo.name
-                    name: formData.customerInfo.name,
-                    id: props.editMode ? props.editData.userInfo.id : undefined,
-                },
 
-                customerInfo: {
-                    ...formData.customerInfo,
-                    exTime: formData.customerInfo.exTime ?
-                        dayjs(formData.customerInfo.exTime).format('YYYY-MM-DD') :
-                        null
-                },
-                customerProperty: formData.customerProperty,
-                customerInvoice: processedInvoice,
-                customerCardQualification: formData.customerCardQualification,
-                customerWarningParameter: formData.customerWarningParameter,
-                customerInterfaceParams: formData.customerInterfaceParams,
-            };
+const handleSubmit = () => {
+  formRef.value.validate(async  (errors) => {
+    if (!errors) {
+      let response;
+      formData.value.password = encryptByDES(formData.value.password);
+      if (props.editMode) {
+        response = await updateCustomer(formData.value);
+      } else {
+        response = await addCustomer(formData.value);
+      }
+      if (response.code === 200) {
+        Message.success(props.editMode ? t('customer.updateSuccess') : t('customer.addSuccess'));
+        Object.keys(formData.value).forEach(key => {
+          formData.value[key] = ''
+        })
+        emit('submit', true);
+        emit('update:visible', false);
+      } else {
+        Message.error(response.message || (props.editMode ? t('customer.updateFailed') : t('customer.addFailed')));
+      }
 
-            emit('submit', submitData);
-            emit('update:visible', false);
-        }
-    });
+    }
+  });
 };
 
 const handleCancel = () => {
-    emit('update:visible', false);
+  Object.keys(formData.value).forEach(key => {
+    formData.value[key] = ''
+  })
+  formRef.value = null
+  emit('update:visible', false);
 };
 
-const handleUpload = async (option, directory) => {
-    const { file } = option.fileItem;
-    const timestamp = Date.now(); // Get the current timestamp
-    const fileName = `${directory}/${timestamp}_${file.name}`;
-    const key = `customer_uploads/${fileName}`; // Base directory for customer uploads
-
-    const client = await systemStore.getSTSClient();
-    const resClient = await client.putObject({
-        key: key,
-        body: file
-    });
-
-    if (resClient.statusCode === 200) {
-        console.log('File uploaded successfully to', key);
-        formData.customerInvoice[directory + 'File'] = { url: key, name: file.name };
-    }
-};
 
 const generatePassword = () => {
-    formData.userInfo.password = Math.random().toString(36).slice(-8);
-    Message.success(t('customer.passwordGenerated'));
-};
-
-// 文件上传的处理函数
-const handleBusinessLicenseUpload = (fileList) => {
-    formData.customerInvoice.businessLicenseFile = fileList;
-};
-
-const handleTaxRegistrationUpload = (fileList) => {
-    formData.customerInvoice.taxRegistrationFile = fileList;
-};
-
-const handleGeneralTaxpayerUpload = (fileList) => {
-    formData.customerInvoice.generalTaxpayerFile = fileList;
+  formData.password = Math.random().toString(36).slice(-8);
+  Message.success(t('customer.passwordGenerated'));
 };
 
-// 文件上传的 action,需要根据实际的后端 API 进行设置
-const uploadAction = 'url';
-
-const imageUploadFields = [
-    'customerInvoice.businessLicenseFile',
-    'customerCardQualification.legalPersonIdCardFrontFile',
-    'customerCardQualification.legalPersonIdCardBackFile',
-    'customerCardQualification.equipmentPurchaseFile',
-    'customerCardQualification.businessContractFile',
-    'customerCardQualification.informationSecurityFile',
-    'customerCardQualification.customerInformationFile',
-];
-
-const handleFileUpload = (field, file) => {
-    formData.customerCardQualification[field] = {
-        ...file,
-        url: URL.createObjectURL(file.file),
-    };
-};
 
-const handleFileProgress = (field, file) => {
-    formData.customerCardQualification[field] = file;
-};
+const getDistList = async () => {
+  let code = ['invoice_vat', 'user_type'];
 
-const handleObtainMethodUpload = (fileList) => {
-    formData.customerCardQualification.obtainMethod = fileList;
-};
+  for (let i = 0; i < code.length; i++) {
+    let res = await dictionaryDetail({ typeKey: code[i] });
+    if (res.code === 200) {
+      if (code[i] === 'invoice_vat') {
+        invoiceList.value = res.data;
+      } else if (code[i] === 'user_type') {
+        userTypeList.value = res.data;
+      }
+    }
+  }
 
-const handleTelephoneApplicationFormUpload = (fileList) => {
-    formData.customerCardQualification.telephoneApplicationForm = fileList;
-};
 
-const handleOtherDocumentsUpload = (fileList) => {
-    formData.customerCardQualification.otherDocuments = fileList;
-};
+}
 
+const getRolesData = async () => {
+  let res = await systemFindRoleList()
+  if (res.code === 200) {
+    roles.value = res.data
+  }
+}
+onMounted(() => {
+  getDistList();
+  getRolesData()
+})
 
 </script>
 
 <style scoped>
 .upload-description {
-    font-size: 12px;
-    color: #999;
-    margin-top: 4px;
+  font-size: 12px;
+  color: #999;
+  margin-top: 4px;
 }
 </style>

+ 173 - 276
src/views/customer/index.vue

@@ -1,167 +1,136 @@
 <!-- 客户管理-用户管理 -->
 <template>
-    <div class="customer-management">
-        <!-- 搜索条件区 -->
-        <div class="search-section">
-            <a-form :model="searchForm" layout="inline">
-                <a-form-item field="customerName" :label="$t('customer.customerName')">
-                    <a-input v-model="searchForm.customerName" :placeholder="$t('customer.enterCustomerName')"
-                        allow-clear />
-                </a-form-item>
-                <a-form-item field="operatorType" :label="$t('customer.operatorType')">
-                    <a-select v-model="searchForm.operatorType" :placeholder="$t('customer.selectOperatorType')"
-                        allow-clear style="width: 160px">
-                        <a-option v-for="op in operatorTypeOptions" :key="op.value" :value="op.value">
-                            {{ $t(`customer.operatorTypes.${op.value}`) }}
-                        </a-option>
-                    </a-select>
-                </a-form-item>
-                <a-form-item>
-                    <a-button type="primary" @click="handleSearch">{{ $t('global.common.search') }}</a-button>
-                </a-form-item>
-                <a-form-item>
-                    <a-button @click="resetSearch">{{ $t('global.common.reset') }}</a-button>
-                </a-form-item>
-            </a-form>
-        </div>
-
-        <!-- 顶部操作区 -->
-        <div class="top-actions">
-            <a-space>
-                <a-button type="primary" @click="showNewCustomerForm">{{ $t('customer.addCustomer') }}</a-button>
-                <a-button @click="handleBatchDelete">{{ $t('customer.batchDelete') }}</a-button>
-            </a-space>
-        </div>
-
-        <!-- 数据表格 -->
-        <a-table row-key="id" :columns="columns" :data="tableData" :pagination="pagination" :scroll="{ x: 'auto' }"
-            :row-selection="{ type: 'checkbox', showCheckedAll: true }" @page-change="onPageChange">
-            <template #state="{ record }">
-                <a-tag :color="getStatusColor(record.state)">
-                    {{ $t(`customer.status.${getStatusText(record.state)}`) }}
-                </a-tag>
-            </template>
-            <template #operation="{ record }">
-                <a-space>
-                    <a-button type="text" size="small" @click="handleRecharge(record)">{{ $t('customer.recharge')
-                        }}</a-button>
-                    <a-button type="text" size="small" @click="handlePackageManagement(record)">{{
-                        $t('customer.packageManagement') }}</a-button>
-                    <a-button type="text" size="small" @click="handleEdit(record)">{{ $t('global.common.edit')
-                        }}</a-button>
-                </a-space>
-            </template>
-        </a-table>
+  <div class="customer-management">
+    <!-- 搜索条件区 -->
+    <div class="search-section">
+      <a-form :model="searchForm" layout="inline">
+        <a-form-item field="customerName" :label="$t('customer.customerName')">
+          <a-input v-model="searchForm.customerName" :placeholder="$t('customer.enterCustomerName')"
+                   allow-clear/>
+        </a-form-item>
+        <a-form-item field="operatorType" :label="$t('customer.operatorType')">
+          <a-select v-model="searchForm.operatorType" :placeholder="$t('customer.selectOperatorType')"
+                    allow-clear style="width: 160px">
+            <a-option v-for="op in operatorTypeOptions" :key="op.value" :value="op.value">
+              {{ $t(`customer.operatorTypes.${op.value}`) }}
+            </a-option>
+          </a-select>
+        </a-form-item>
+        <a-form-item>
+          <a-button type="primary" @click="handleSearch">{{ $t('global.common.search') }}</a-button>
+        </a-form-item>
+        <a-form-item>
+          <a-button @click="resetSearch">{{ $t('global.common.reset') }}</a-button>
+        </a-form-item>
+      </a-form>
+    </div>
 
-        <!-- 新客户表单对话框 -->
-        <new-customer-form v-model:visible="newCustomerFormVisible" :editMode="editMode" :editData="editData"
-            :loading="loading" @submit="handleNewCustomerSubmit" />
+    <!-- 顶部操作区 -->
+    <div class="top-actions">
+      <a-space>
+        <a-button type="primary" @click="showNewCustomerForm">{{ $t('customer.addCustomer') }}</a-button>
+        <a-button @click="handleBatchDelete">{{ $t('customer.batchDelete') }}</a-button>
+      </a-space>
     </div>
+
+    <!-- 数据表格 -->
+    <a-table row-key="id" :columns="columns" :data="tableData" :pagination="pagination" :scroll="{ x: 'auto' }"
+             :row-selection="{ type: 'checkbox', showCheckedAll: true }" @page-change="onPageChange">
+      <template #state="{ record }">
+        <a-tag :color="getStatusColor(record.state)">
+          {{ $t(`customer.status.${getStatusText(record.state)}`) }}
+        </a-tag>
+      </template>
+      <template #user_type="{ record }">
+        {{$t(`customer.${getUserType(record.user_type)}`)}}
+      </template>
+      <template #operation="{ record }">
+        <a-space>
+          <a-button type="text" size="small" @click="handleRecharge(record)">{{
+              $t('customer.recharge')
+            }}
+          </a-button>
+          <a-button type="text" size="small" @click="handlePackageManagement(record)">{{
+              $t('customer.packageManagement')
+            }}
+          </a-button>
+          <a-button type="text" size="small" @click="handleEdit(record)">{{
+              $t('global.common.edit')
+            }}
+          </a-button>
+        </a-space>
+      </template>
+    </a-table>
+
+    <!-- 新客户表单对话框 -->
+    <new-customer-form v-model:visible="newCustomerFormVisible" :editMode="editMode" :editData="editData"
+                       :loading="loading" @submit="handleNewCustomerSubmit"/>
+  </div>
 </template>
 
 <script setup>
-import { ref, reactive, computed, onMounted } from 'vue';
-import { Message } from '@arco-design/web-vue';
-import { useI18n } from 'vue-i18n';
+import {ref, reactive, computed, onMounted} from 'vue';
+import {Message} from '@arco-design/web-vue';
+import {useI18n} from 'vue-i18n';
 import NewCustomerForm from './NewCustomerForm.vue';
-import { getCustomerList, addCustomer, getCustomer, updateCustomer } from '@/api/customer';
+import {getMessUserList, deleteMessUser} from '@/api/customer';
 
-const { t } = useI18n();
+const {t} = useI18n();
 
 const loading = ref(false);
 
 const columns = computed(() => [
-    { title: t('customer.id'), dataIndex: 'id' },
-    { title: t('customer.customerCode'), dataIndex: 'customerCode' },
-    { title: t('customer.customerName'), dataIndex: 'customerName' },
-    { title: t('customer.accountNumber'), dataIndex: 'accountNumber' },
-    { title: t('customer.accountBalance'), dataIndex: 'accountBalance' },
-    { title: t('customer.paymentMethodName'), dataIndex: 'paymentMethod' },
-    { title: t('customer.customerStatus'), slotName: 'state' },
-    { title: t('customer.validPeriod'), dataIndex: 'validPeriod' },
-    { title: t('customer.activeCards'), dataIndex: 'activeCards' },
-    { title: t('customer.updateTime'), dataIndex: 'updateTime' },
-    { title: t('global.common.operations'), slotName: 'operation', width: 250 },
+  {title: t('customer.id'), dataIndex: 'id'},
+  // {title: t('customer.customerCode'), dataIndex: 'customerCode'},
+  {title: t('customer.customerName'), dataIndex: 'name'},
+  {title: t('customer.userAdmin'), dataIndex: 'username'},
+  // {title: t('customer.accountBalance'), dataIndex: 'accountBalance'},
+  // {title: t('customer.paymentMethodName'), dataIndex: 'paymentMethod'},
+  {title: t('customer.customerStatus'), slotName: 'state'},
+  // {title: t('customer.validPeriod'), dataIndex: 'validPeriod'},
+  // {title: t('customer.activeCards'), dataIndex: 'activeCards'},
+  {title: t('customer.userTypeName'), slotName: 'user_type'},
+  {title: t('customer.startTime'), dataIndex: 'created_at'},
+  {title: t('customer.updateTime'), dataIndex: 'updated_at'},
+  {title: t('global.common.operations'), slotName: 'operation', width: 250},
 ]);
 
 onMounted(() => {
-    // fetchCustomerList();
+  fetchCustomerList();
 });
 
-const tableData = ref([
-    {
-        id: "1", customerCode: "8",
-        customerName: "泰国景和",
-        accountBalance: "TS001",
-        paymentMethod: "预付费",
-        state: "1",
-        validPeriod: "2024-12-54",
-        activeCards: "0/0",
-        updateTime: "2024-09-20 08:05:54"
-    },
-    {
-        id: "2", customerCode: "9",
-        customerName: "泰国景和",
-        accountBalance: "TS001",
-        paymentMethod: "后付费",
-        state: "1",
-        validPeriod: "2024-12-54",
-        activeCards: "0/0",
-        updateTime: "2024-09-20 08:05:54"
-    },
-    {
-        id: "3", customerCode: "10",
-        customerName: "泰国景和",
-        accountBalance: "TS001",
-        paymentMethod: "后付费",
-        state: "1",
-        validPeriod: "2024-12-54",
-        activeCards: "0/0",
-        updateTime: "2024-09-20 08:05:54"
-    },
-    {
-        id: "4", customerCode: "11",
-        customerName: "泰国景和",
-        accountBalance: "TS001",
-        paymentMethod: "后付费",
-        state: "1",
-        validPeriod: "2024-12-54",
-        activeCards: "0/0",
-        updateTime: "2024-09-20 08:05:54"
-    },
-]);
+const tableData = ref([])
 
-// const pagination = reactive({
-//   // total: 100,
-//   current: 1,
-//   pageSize: 10,
-// });
-const pagination = { pageSize: 10 }
+const pagination = reactive({
+  total: 100,
+  current: 1,
+  pageSize: 10,
+});
 const fetchCustomerList = async () => {
-    try {
-        const response = await getCustomerList({
-            current: pagination.current,
-            pageSize: pagination.pageSize,
-            customerName: searchForm.customerName,
-            operatorType: searchForm.operatorType,
-        });
-        if (response.code === 200 && response.data) {
-            tableData.value = response.data.records;
-            pagination.total = response.data.total;
-            pagination.current = response.data.current;
-            pagination.pageSize = response.data.size;
-        } else {
-            Message.error(response.message || 'Failed to fetch customer list');
-        }
-    } catch (error) {
-        Message.error('Failed to fetch customer list');
-        console.error(error);
+  try {
+    const response = await getMessUserList({
+      current: pagination.current,
+      pageSize: pagination.pageSize,
+      customerName: searchForm.customerName,
+      operatorType: searchForm.operatorType,
+    });
+    if (response.code === 200 && response.data) {
+      tableData.value = response.data.records;
+      pagination.total = response.data.total;
+      pagination.current = response.data.current;
+      pagination.pageSize = response.data.size;
+    } else {
+      Message.error(response.message || 'Failed to fetch customer list');
     }
+  } catch (error) {
+    Message.error('Failed to fetch customer list');
+    console.error(error);
+  }
 };
 
 const onPageChange = (page) => {
-    pagination.current = page;
-    fetchCustomerList();
+  pagination.current = page;
+  fetchCustomerList();
 };
 
 const newCustomerFormVisible = ref(false);
@@ -169,188 +138,116 @@ const editMode = ref(false);
 const editData = ref(null);
 
 const searchForm = reactive({
-    customerName: '',
-    operatorType: '',
+  customerName: '',
+  operatorType: '',
 });
 
 const operatorTypeOptions = [
-    { value: 'domestic', label: t('customer.operatorTypes.domestic') },
-    { value: 'international', label: t('customer.operatorTypes.international') },
+  {value: 'domestic', label: t('customer.operatorTypes.domestic')},
+  {value: 'international', label: t('customer.operatorTypes.international')},
 ];
 
 const showNewCustomerForm = () => {
-    editMode.value = false;
-    editData.value = null;
-    newCustomerFormVisible.value = true;
+  editMode.value = false;
+  editData.value = null;
+  newCustomerFormVisible.value = true;
 };
 
 const handleEdit = async (record) => {
-    try {
-        loading.value = true;
-        const response = await getCustomer({ id: record.id });
-        if (response.code === 200) {
-            // 处理返回的数据,确保数据结构匹配表单
-            const formattedData = {
-                userInfo: {
-                    ...response.data.userInfo,
-                    password: '', // 清空密码字段
-                    passwordState: true // 添加密码状态控制
-                },
-                customerInfo: {
-                    ...response.data.customerInfo,
-                    // 确保日期格式正确
-                    exTime: response.data.customerInfo.exTime ? new Date(response.data.customerInfo.exTime) : null
-                },
-                customerProperty: {
-                    ...response.data.customerProperty,
-                    // 确保数值类型正确
-                    amount: Number(response.data.customerProperty?.amount || 0),
-                    rechargeLimit: Number(response.data.customerProperty?.rechargeLimit || 0),
-                    lineOfCredit: Number(response.data.customerProperty?.lineOfCredit || 0),
-                    smsUnitPrice: Number(response.data.customerProperty?.smsUnitPrice || 0),
-                    iotSmsUnitPrice: Number(response.data.customerProperty?.iotSmsUnitPrice || 0),
-                    paymentMethod: response.data.customerProperty?.paymentMethod || 'prepaid'
-                },
-                customerInvoice: {
-                    ...response.data.customerInvoice,
-                    // 处理文件列表
-                    businessLicenseFile: response.data.customerInvoice?.businessLicenseFile ? [response.data.customerInvoice.businessLicenseFile] : [],
-                    taxRegistrationFile: response.data.customerInvoice?.taxRegistrationFile ? [response.data.customerInvoice.taxRegistrationFile] : [],
-                    generalTaxpayerFile: response.data.customerInvoice?.generalTaxpayerFile ? [response.data.customerInvoice.generalTaxpayerFile] : []
-                },
-                customerCardQualification: {
-                    ...response.data.customerCardQualification,
-                    // 处理图片和文件字段
-                    blImg: response.data.customerCardQualification?.blImg || null,
-                    legalPersonIdCardImgUp: response.data.customerCardQualification?.legalPersonIdCardImgUp || null,
-                    legalPersonIdCardImgDown: response.data.customerCardQualification?.legalPersonIdCardImgDown || null,
-                    iotImg: response.data.customerCardQualification?.iotImg || null,
-                    contractImg: response.data.customerCardQualification?.contractImg || null,
-                    commitmentImg: response.data.customerCardQualification?.commitmentImg || null,
-                    customerForm: response.data.customerCardQualification?.customerForm || null,
-                    phoneForm: response.data.customerCardQualification?.phoneForm || null,
-                    otherFile: response.data.customerCardQualification?.otherFile || null
-                },
-                customerWarningParameter: {
-                    ...response.data.customerWarningParameter,
-                    // 确保数值类型正确
-                    accountBalanceWarning: Number(response.data.customerWarningParameter?.accountBalanceWarning || 0),
-                    reachWarning: Number(response.data.customerWarningParameter?.reachWarning || 0),
-                    stopSending: Number(response.data.customerWarningParameter?.stopSending || 0),
-                    networkDisconnection: Number(response.data.customerWarningParameter?.networkDisconnection || 0),
-                    // 设置默认值
-                    stopSendingAction: response.data.customerWarningParameter?.stopSendingAction || 'noRecovery',
-                    networkDisconnectionAction: response.data.customerWarningParameter?.networkDisconnectionAction || 'noRecovery'
-                },
-                customerInterfaceParams: {
-                    ...(response.data.customerInterfaceParams || {}),
-                    // 设置默认值
-                    smsStatusReportUrl: response.data.customerInterfaceParams?.smsStatusReportUrl || '',
-                    reportIp: response.data.customerInterfaceParams?.reportIp || '',
-                    deliveryPriority: response.data.customerInterfaceParams?.deliveryPriority || '',
-                    dataReportUrl: response.data.customerInterfaceParams?.dataReportUrl || ''
-                }
-            };
-
-            editMode.value = true;
-            editData.value = formattedData;
-            newCustomerFormVisible.value = true;
-        } else {
-            Message.error(response.message || t('customer.fetchFailed'));
-        }
-    } catch (error) {
-        console.error('获取客户详情时发生错误:', error);
-        Message.error(t('customer.fetchError'));
-    } finally {
-        loading.value = false;
+  try {
+    loading.value = true;
+    const response = await deleteMessUser({id: record.id});
+    if (response.code === 200) {
+      // 处理返回的数据,确保数据结构匹配表单
+      editMode.value = true;
+      editData.value = response.data;
+      newCustomerFormVisible.value = true;
+    } else {
+      Message.error(response.message || t('customer.fetchFailed'));
     }
+  } catch (error) {
+    console.error('获取客户详情时发生错误:', error);
+    Message.error(t('customer.fetchError'));
+  } finally {
+    loading.value = false;
+  }
 };
 
 const handleRecharge = (record) => {
-    Message.success(`为客户 ${record.customerName} 充值`);
+  Message.success(`为客户 ${record.customerName} 充值`);
 };
 
 const handlePackageManagement = (record) => {
-    Message.success(`管理客户 ${record.customerName} 的套餐`);
+  Message.success(`管理客户 ${record.customerName} 的套餐`);
 };
 
-const handleNewCustomerSubmit = async (formData) => {
-    try {
-        loading.value = true;
-        let response;
-        if (editMode.value) {
-            response = await updateCustomer(formData);
-        } else {
-            response = await addCustomer(formData);
-        }
-
-        if (response.code === 200) {
-            Message.success(editMode.value ? t('customer.updateSuccess') : t('customer.addSuccess'));
-            newCustomerFormVisible.value = false;
-            fetchCustomerList();
-        } else {
-            Message.error(response.message || (editMode.value ? t('customer.updateFailed') : t('customer.addFailed')));
-        }
-    } catch (error) {
-        console.error(editMode.value ? '更新客户时发生错误:' : '添加客户时发生错误:', error);
-        Message.error(editMode.value ? t('customer.updateError') : t('customer.addError'));
-    } finally {
-        loading.value = false;
-    }
+const handleNewCustomerSubmit = (formData) => {
+  if (formData) {
+    newCustomerFormVisible.value = false;
+    fetchCustomerList();
+  }
 };
 
 const handleSearch = () => {
-    pagination.current = 1;
-    fetchCustomerList();
+  pagination.current = 1;
+  fetchCustomerList();
 };
 
 const resetSearch = () => {
-    Object.keys(searchForm).forEach(key => {
-        searchForm[key] = '';
-    });
-    pagination.current = 1;
-    fetchCustomerList();
+  Object.keys(searchForm).forEach(key => {
+    searchForm[key] = '';
+  });
+  pagination.current = 1;
+  fetchCustomerList();
 };
 
 const handleBatchDelete = () => {
-    Message.warning(t('customer.batchDeleteWarning'));
+  Message.warning(t('customer.batchDeleteWarning'));
 };
 
 const getStatusColor = (state) => {
-    const stateColors = {
-        '1': 'green',    // 正常 - 绿色
-        '2': 'red',      // 禁用 - 红色
-        '3': 'orange',   // 待审 - 橙色
-        '4': 'gray'      // 暂停 - 灰色
-    };
-    return stateColors[state] || 'default';
+  const stateColors = {
+    '1': 'green',    // 正常 - 绿色
+    '2': 'red',      // 禁用 - 红色
+    '3': 'orange',   // 待审 - 橙色
+    '4': 'gray'      // 暂停 - 灰色
+  };
+  return stateColors[state] || 'default';
 };
 
+const getUserType = (state) => {
+  const stateType = {
+    '1':'platform',
+    '2':'client'
+  }
+  return stateType[state] || 'undefined';
+}
+
 const getStatusText = (state) => {
-    const stateTexts = {
-        '1': 'normal',     // 正常
-        '2': 'disabled',   // 禁用
-        '3': 'pending',    // 待审
-        '4': 'suspended'   // 暂停
-    };
-    return stateTexts[state] || 'undefined';
+  const stateTexts = {
+    '1': 'normal',     // 正常
+    '2': 'disabled',   // 禁用
+    '3': 'pending',    // 待审
+    '4': 'suspended'   // 暂停
+  };
+  return stateTexts[state] || 'undefined';
 };
 </script>
 
 <style scoped>
 .customer-management {
-    padding: 20px !important;
+  padding: 20px !important;
 }
 
 .top-actions {
-    margin-bottom: 20px;
+  margin-bottom: 20px;
 }
 
 .search-section {
-    margin-bottom: 20px;
+  margin-bottom: 20px;
 }
 
 .customer-management .arco-table-th {
-    white-space: nowrap;
+  white-space: nowrap;
 }
 </style>

Datei-Diff unterdrückt, da er zu groß ist
+ 547 - 537
src/views/flowPool/index.vue


+ 135 - 128
src/views/flowPool/rearFlowPool/index.vue

@@ -116,8 +116,8 @@
                         }}</a-option>
                 </a-select>
             </a-form-item> -->
-            <a-form-item :label="$t('flowPool.simRariff')" field="sim_tariff_id">
-              <a-select v-model="formState.sim_tariff_id"
+            <a-form-item :label="$t('flowPool.simRariff')" field="simTariffId">
+              <a-select v-model="formState.simTariffId"
                         :placeholder="$t('form.cardForm.pleaseSelect') + $t('flowPool.simRariff')">
                 <a-option v-for=" item in tariffIdList" :key="item.id" :value="item.value">{{
                     item.label
@@ -125,13 +125,13 @@
                 </a-option>
               </a-select>
             </a-form-item>
-            <a-form-item :label="$t('flowPool.expireTime')" field="expire_time">
-              <a-date-picker v-model="formState.expire_time" show-time
+            <a-form-item :label="$t('flowPool.expireTime')" field="expireTime">
+              <a-date-picker v-model="formState.expireTime" show-time
                              :time-picker-props="{ defaultValue: '09:09:06' }" format="YYYY-MM-DD HH:mm:ss"/>
             </a-form-item>
-            <a-form-item :label="$t('flowPool.poolSize')" field="poolSize">
-              <a-input v-model="formState.poolSize" :placeholder="$t('flowPool.poolSize')"/>
-              <a-select v-model="formState.poolSizeUnit" style="width: 80px; margin-left: 8px;">
+            <a-form-item :label="$t('flowPool.poolSize')" field="size">
+              <a-input v-model="formState.size" :placeholder="$t('flowPool.poolSize')"/>
+              <a-select v-model="formState.sizeTpye" style="width: 80px; margin-left: 8px;">
                 <a-option value="KB">KB</a-option>
                 <a-option value="MB">MB</a-option>
                 <a-option value="GB">GB</a-option>
@@ -146,110 +146,110 @@
             </a-form-item>
           </a-form>
         </a-tab-pane>
-        <a-tab-pane key="2" :title="$t('flowPool.warnTabs')">
-          <a-form :model="formWarning" direction="inline">
-            <div class="form-pool-tit">
-              <div class="pool-icon"></div>
-              客户端·池预警设置
-            </div>
-            <a-form-item field="totalDosage" tooltip="请输入" label="总用量占比">
-              <a-input-number v-model="formWarning.totalDosage" :style="{ width: '320px' }"
-                              placeholder="请输入" allow-clear hide-button>
-                <template #suffix>
-                  %
-                </template>
-              </a-input-number>
-              <a-checkbox value="1" v-model="formWarning.totalDosageCheck">达量预警</a-checkbox>
-            </a-form-item>
-            <a-form-item field="stoppagePool" label="达量停机">
-              <a-select v-model="formWarning.stoppagePool" placeholder="请选择" :style="{ width: '320px' }"
-                        allow-clear>
-                <a-option v-for="item in earlyList" :key="item.value" :value="item.value"
-                          :label="item.label"/>
-              </a-select>
-              <a-checkbox value="1" v-model="formWarning.stoppagePoolCheck">达量停机</a-checkbox>
-            </a-form-item>
-            <a-form-item field="stopNetworkPool" label="达量断网">
-              <a-select v-model="formWarning.stopNetworkPool" placeholder="请选择"
-                        :style="{ width: '320px' }" allow-clear>
-                <a-option v-for="item in earlyList" :key="item.value" :value="item.value"
-                          :label="item.label"/>
-              </a-select>
-              <a-checkbox value="1" v-model="formWarning.stopNetworkPoolCheck">达量断网</a-checkbox>
-            </a-form-item>
-            <a-form-item field="remindTotal" label="提醒次数">
-              <a-input-number v-model="formWarning.remindTotal" :style="{ width: '320px' }"
-                              placeholder="请输入" allow-clear hide-button>
-                <template #suffix>
-                  次/月
-                </template>
-              </a-input-number>
-            </a-form-item>
-            <div class="form-pool-tit">
-              <div class="pool-icon"></div>
-              客户端·单卡预警设置
-            </div>
-            <a-form-item field="oneCardWarning" tooltip="请输入" label="单卡用量预警">
-              <a-input-number v-model="formWarning.oneCardWarning" :style="{ width: '320px' }"
-                              placeholder="请输入" allow-clear hide-button>
-              </a-input-number>
-              <a-checkbox value="1" v-model="formWarning.outTotalCheck">达量预警</a-checkbox>
-            </a-form-item>
-            <a-form-item field="stoppageCard" label="达量停机">
-              <a-select v-model="formWarning.stoppageCard" placeholder="请选择" :style="{ width: '320px' }"
-                        allow-clear>
-                <a-option v-for="item in earlyList" :key="item.value" :value="item.value"
-                          :label="item.label"/>
-              </a-select>
-              <a-checkbox value="1" v-model="formWarning.stoppageCardCheck">达量停机</a-checkbox>
-            </a-form-item>
-            <a-form-item field="stopNetworkCard" label="达量断网">
-              <a-select v-model="formWarning.stopNetworkCard" placeholder="请选择"
-                        :style="{ width: '320px' }" allow-clear>
-                <a-option v-for="item in earlyList" :key="item.value" :value="item.value"
-                          :label="item.label"/>
-              </a-select>
-              <a-checkbox value="1" v-model="formWarning.stopNetworkCardCheck">达量断网</a-checkbox>
-            </a-form-item>
-            <div class="form-pool-tit">
-              <div class="pool-icon"></div>
-              管理端预警设置
-            </div>
-            <a-form-item field="poolUsedWarning" tooltip="请输入" label="池已用量预警">
-              <a-input-number v-model="formWarning.poolUsedWarning" :style="{ width: '320px' }"
-                              placeholder="请输入" allow-clear hide-button>
-                <template #suffix>
-                  %
-                </template>
-              </a-input-number>
-              <a-checkbox value="1" v-model="formWarning.poolUsedCheck">达量预警</a-checkbox>
-            </a-form-item>
-            <a-form-item field="stoppageManagement" label="达量停机">
-              <a-select v-model="formWarning.stoppageManagement" placeholder="请选择"
-                        :style="{ width: '320px' }" allow-clear>
-                <a-option v-for="item in earlyList" :key="item.value" :value="item.value"
-                          :label="item.label"/>
-              </a-select>
-              <a-checkbox value="1" v-model="formWarning.stoppageManagementCheck">达量停机</a-checkbox>
-            </a-form-item>
-            <a-form-item field="stopNetworkManagement" label="达量断网">
-              <a-select v-model="formWarning.stopNetworkManagement" placeholder="请选择"
-                        :style="{ width: '320px' }" allow-clear>
-                <a-option v-for="item in earlyList" :key="item.value" :value="item.value"
-                          :label="item.label"/>
-              </a-select>
-              <a-checkbox value="1" v-model="formWarning.stopNetworkManagementCheck">达量断网</a-checkbox>
-            </a-form-item>
-            <a-form-item>
-              <a-button type="primary" html-type="submit" @click="resetForm"
-                        style="margin-right: 10px;">{{
-                  $t('form.Confirm')
-                }}
-              </a-button>
-              <a-button @click="resetForm">{{ $t('form.Cancel') }}</a-button>
-            </a-form-item>
-          </a-form>
-        </a-tab-pane>
+        <!--        <a-tab-pane key="2" :title="$t('flowPool.warnTabs')">-->
+        <!--          <a-form :model="formWarning" direction="inline">-->
+        <!--            <div class="form-pool-tit">-->
+        <!--              <div class="pool-icon"></div>-->
+        <!--              客户端·池预警设置-->
+        <!--            </div>-->
+        <!--            <a-form-item field="totalDosage" tooltip="请输入" label="总用量占比">-->
+        <!--              <a-input-number v-model="formWarning.totalDosage" :style="{ width: '320px' }"-->
+        <!--                              placeholder="请输入" allow-clear hide-button>-->
+        <!--                <template #suffix>-->
+        <!--                  %-->
+        <!--                </template>-->
+        <!--              </a-input-number>-->
+        <!--              <a-checkbox value="1" v-model="formWarning.totalDosageCheck">达量预警</a-checkbox>-->
+        <!--            </a-form-item>-->
+        <!--            <a-form-item field="stoppagePool" label="达量停机">-->
+        <!--              <a-select v-model="formWarning.stoppagePool" placeholder="请选择" :style="{ width: '320px' }"-->
+        <!--                        allow-clear>-->
+        <!--                <a-option v-for="item in earlyList" :key="item.value" :value="item.value"-->
+        <!--                          :label="item.label"/>-->
+        <!--              </a-select>-->
+        <!--              <a-checkbox value="1" v-model="formWarning.stoppagePoolCheck">达量停机</a-checkbox>-->
+        <!--            </a-form-item>-->
+        <!--            <a-form-item field="stopNetworkPool" label="达量断网">-->
+        <!--              <a-select v-model="formWarning.stopNetworkPool" placeholder="请选择"-->
+        <!--                        :style="{ width: '320px' }" allow-clear>-->
+        <!--                <a-option v-for="item in earlyList" :key="item.value" :value="item.value"-->
+        <!--                          :label="item.label"/>-->
+        <!--              </a-select>-->
+        <!--              <a-checkbox value="1" v-model="formWarning.stopNetworkPoolCheck">达量断网</a-checkbox>-->
+        <!--            </a-form-item>-->
+        <!--            <a-form-item field="remindTotal" label="提醒次数">-->
+        <!--              <a-input-number v-model="formWarning.remindTotal" :style="{ width: '320px' }"-->
+        <!--                              placeholder="请输入" allow-clear hide-button>-->
+        <!--                <template #suffix>-->
+        <!--                  次/月-->
+        <!--                </template>-->
+        <!--              </a-input-number>-->
+        <!--            </a-form-item>-->
+        <!--            <div class="form-pool-tit">-->
+        <!--              <div class="pool-icon"></div>-->
+        <!--              客户端·单卡预警设置-->
+        <!--            </div>-->
+        <!--            <a-form-item field="oneCardWarning" tooltip="请输入" label="单卡用量预警">-->
+        <!--              <a-input-number v-model="formWarning.oneCardWarning" :style="{ width: '320px' }"-->
+        <!--                              placeholder="请输入" allow-clear hide-button>-->
+        <!--              </a-input-number>-->
+        <!--              <a-checkbox value="1" v-model="formWarning.outTotalCheck">达量预警</a-checkbox>-->
+        <!--            </a-form-item>-->
+        <!--            <a-form-item field="stoppageCard" label="达量停机">-->
+        <!--              <a-select v-model="formWarning.stoppageCard" placeholder="请选择" :style="{ width: '320px' }"-->
+        <!--                        allow-clear>-->
+        <!--                <a-option v-for="item in earlyList" :key="item.value" :value="item.value"-->
+        <!--                          :label="item.label"/>-->
+        <!--              </a-select>-->
+        <!--              <a-checkbox value="1" v-model="formWarning.stoppageCardCheck">达量停机</a-checkbox>-->
+        <!--            </a-form-item>-->
+        <!--            <a-form-item field="stopNetworkCard" label="达量断网">-->
+        <!--              <a-select v-model="formWarning.stopNetworkCard" placeholder="请选择"-->
+        <!--                        :style="{ width: '320px' }" allow-clear>-->
+        <!--                <a-option v-for="item in earlyList" :key="item.value" :value="item.value"-->
+        <!--                          :label="item.label"/>-->
+        <!--              </a-select>-->
+        <!--              <a-checkbox value="1" v-model="formWarning.stopNetworkCardCheck">达量断网</a-checkbox>-->
+        <!--            </a-form-item>-->
+        <!--            <div class="form-pool-tit">-->
+        <!--              <div class="pool-icon"></div>-->
+        <!--              管理端预警设置-->
+        <!--            </div>-->
+        <!--            <a-form-item field="poolUsedWarning" tooltip="请输入" label="池已用量预警">-->
+        <!--              <a-input-number v-model="formWarning.poolUsedWarning" :style="{ width: '320px' }"-->
+        <!--                              placeholder="请输入" allow-clear hide-button>-->
+        <!--                <template #suffix>-->
+        <!--                  %-->
+        <!--                </template>-->
+        <!--              </a-input-number>-->
+        <!--              <a-checkbox value="1" v-model="formWarning.poolUsedCheck">达量预警</a-checkbox>-->
+        <!--            </a-form-item>-->
+        <!--            <a-form-item field="stoppageManagement" label="达量停机">-->
+        <!--              <a-select v-model="formWarning.stoppageManagement" placeholder="请选择"-->
+        <!--                        :style="{ width: '320px' }" allow-clear>-->
+        <!--                <a-option v-for="item in earlyList" :key="item.value" :value="item.value"-->
+        <!--                          :label="item.label"/>-->
+        <!--              </a-select>-->
+        <!--              <a-checkbox value="1" v-model="formWarning.stoppageManagementCheck">达量停机</a-checkbox>-->
+        <!--            </a-form-item>-->
+        <!--            <a-form-item field="stopNetworkManagement" label="达量断网">-->
+        <!--              <a-select v-model="formWarning.stopNetworkManagement" placeholder="请选择"-->
+        <!--                        :style="{ width: '320px' }" allow-clear>-->
+        <!--                <a-option v-for="item in earlyList" :key="item.value" :value="item.value"-->
+        <!--                          :label="item.label"/>-->
+        <!--              </a-select>-->
+        <!--              <a-checkbox value="1" v-model="formWarning.stopNetworkManagementCheck">达量断网</a-checkbox>-->
+        <!--            </a-form-item>-->
+        <!--            <a-form-item>-->
+        <!--              <a-button type="primary" html-type="submit" @click="resetForm"-->
+        <!--                        style="margin-right: 10px;">{{-->
+        <!--                  $t('form.Confirm')-->
+        <!--                }}-->
+        <!--              </a-button>-->
+        <!--              <a-button @click="resetForm">{{ $t('form.Cancel') }}</a-button>-->
+        <!--            </a-form-item>-->
+        <!--          </a-form>-->
+        <!--        </a-tab-pane>-->
       </a-tabs>
 
     </a-modal>
@@ -360,8 +360,8 @@ const intData = async () => {
   const param = {
     current: pagination.value.current,
     size: pagination.value.pageSize,
-    traffic_pool_type: "2",
     ...searchForm.value,
+    type: 2
   }
   const {data} = await trafficPoolList(param)
   dataSource.value = (data.records || []).map((item, index) => {
@@ -479,21 +479,23 @@ const dataExport = reactive([{
 // -------------------------------
 
 const formState = ref({
-  "id": "",
   // 流量包名称
   "label": "",
   // 流量池类型: 1: 前流量池 2: 后流量池
-  "traffic_pool_type": "2",
+  "trafficPoolType": "2",
   // 来源
   "source": "",
   // 流量包状态:1:正常(发布计划状态)2:线下暂停销售
   "status": "",
   // 流量池ID
-  "sim_tariff_id": null,
+  "simTariffId": null,
   // 过期时间
-  "expire_time": "",
+  "expireTime": "",
   // ICCID列表
-  "iccids": ["89852342022040149139", "89852342022060861597"]
+  "iccids": ["89852342022040149139", "89852342022060861597"],
+
+  "size": null,
+  "sizeTpye": ''
 });
 const formWarning = reactive({
   // 总用量占比
@@ -523,7 +525,7 @@ const formWarning = reactive({
 const rules = {
   label: [{required: true, trigger: 'change',}],
   sim_data_plan_id: [{required: true, trigger: 'change',}],
-  user_id: [{required: true, trigger: 'change',}],
+  // user_id: [{required: true, trigger: 'change',}],
   source: [{required: true, trigger: 'change',}],
   traffic_type: [{required: true, trigger: 'change',}],
   billing_type: [{required: true, trigger: 'change',}],
@@ -531,10 +533,12 @@ const rules = {
   billing_cycle: [{required: true, trigger: 'change',}],
   traffic_pool_type: [{required: true, trigger: 'change',}],
   settlement_cycle: [{required: true, trigger: 'change',}],
-  sim_tariff_id: [{required: true, trigger: 'change',}],
-  expire_time: [{required: true, trigger: 'change',}],
+  simTariffId: [{required: true, trigger: 'change',}],
+  expireTime: [{required: true, trigger: 'change',}],
   // pricing: [{ required: true, trigger: 'change', }],
   // currency: [{ required: true, trigger: 'change', }],
+  size: [{required: true, trigger: 'change',}],
+  sizeType: [{required: true, trigger: 'change',}],
 };
 
 const earlyList = [
@@ -586,7 +590,7 @@ const handleUnsubscribeDialog = async (record) => {
 const handleSubmit = ({values, errors}) => {
   formRef.value.validate(async (errors) => {
     if (!errors) {
-      values.user_id = Number(values.user_id)
+      // values.user_id = Number(values.user_id)
       if (formState.value.id) {
         const {code, data} = await updateTrafficPool(values)
 
@@ -595,7 +599,7 @@ const handleSubmit = ({values, errors}) => {
             content: "修改成功!",
             duration: 2000,
           })
-          visible.value = false;
+          resetForm()
           intData()
         }
       } else {
@@ -605,13 +609,12 @@ const handleSubmit = ({values, errors}) => {
             content: "添加成功!",
             duration: 2000,
           })
-          visible.value = false;
+          resetForm()
           intData()
         }
       }
     }
   });
-
 }
 // 弹框
 const dictShowModel = (type, data) => {
@@ -628,14 +631,13 @@ const dictShowModel = (type, data) => {
   });
   // 编辑
   if (type == 2) {
-    // Object.assign(formState.value, data);
     Object.keys(formState.value).forEach(key => {
       if (data[key]) {
         formState.value[key] = data[key]
       }
-    });
+    })
+    formState.value.id = data.id
   }
-
 }
 
 // 获取资费列表选择id
@@ -657,7 +659,12 @@ const handleTariff = async () => {
 // 取消
 const resetForm = () => {
   visible.value = false;
-  formRef.value.resetFields();
+  Object.keys(formState.value).forEach(key => {
+    if (key != 'trafficPoolType' && key != 'iccids') {
+      formState.value[key] = ''
+    }
+  })
+  delete formState.value.id
 }
 
 // 卡详情

+ 9 - 5
src/views/system/dict/index.vue

@@ -125,7 +125,7 @@ const formState = reactive({
 
 const pageData = ref({
   total: 0,
-  pageSize: 15,
+  pageSize: 25,
   current: 1,
 })
 const dataSource = ref([]);
@@ -168,13 +168,17 @@ const handleSubmit = ({values, errors}) => {
   }
   if (typeCurrent.value == 1) {
     dictionaryAdd(submitData).then(res => {
-      intData();
-      resetForm();
+      if(res.code===200){
+        intData();
+        resetForm();
+      }
     })
   } else {
     dictionaryUpdate(submitData).then(res => {
-      intData();
-      resetForm();
+      if(res.code===200){
+        intData();
+        resetForm();
+      }
     })
   }
 

+ 0 - 1
src/views/system/menu/index.vue

@@ -7,7 +7,6 @@
 
     <a-space direction="vertical" :style="{ width: '100%' }">
       <a-upload :show-file-list="false" :custom-request="customRequest" />
-
     </a-space>
     <!-- default-expand-all-rows -->
     <a-table class="table" :columns="columns" :data="refData.dataSource" :pagination="false" row-key="id"

+ 10 - 10
src/views/tariffManagement/index.vue

@@ -117,14 +117,14 @@
         <a-form-item :label="$t('tariffManagement.label')" field="label">
           <a-input v-model="formState.label"/>
         </a-form-item>
-        <a-form-item :label="$t('tariffManagement.userId')" field="user_id">
-          <a-select v-model="formState.user_id">
-            <a-option v-for=" item in userIdList" :key="item.id" :value="item.id">{{
-                item.name
-              }}
-            </a-option>
-          </a-select>
-        </a-form-item>
+<!--        <a-form-item :label="$t('tariffManagement.userId')" field="user_id">-->
+<!--          <a-select v-model="formState.user_id">-->
+<!--            <a-option v-for=" item in userIdList" :key="item.id" :value="item.id">{{-->
+<!--                item.name-->
+<!--              }}-->
+<!--            </a-option>-->
+<!--          </a-select>-->
+<!--        </a-form-item>-->
         <a-form-item :label="$t('tariffManagement.trafficType')" field="traffic_type">
           <a-select v-model="formState.traffic_type">
             <a-option v-for=" item in trafficList" :key="item.id" :value="item.value">{{
@@ -378,7 +378,7 @@ const formState = ref({
   // 流量包ID(必填)
   "sim_data_plan_id": null,
   // 用户ID(必填)
-  "user_id": null,
+  // "user_id": null,
   // 来源(必填)
   "source": "",
   // 流量类型(必填)
@@ -411,7 +411,7 @@ const formState = ref({
 const rules = {
   label: [{required: true, trigger: 'change',}],
   sim_data_plan_id: [{required: true, trigger: 'change',}],
-  user_id: [{required: true, trigger: 'change',}],
+  // user_id: [{required: true, trigger: 'change',}],
   source: [{required: true, trigger: 'change',}],
   traffic_type: [{required: true, trigger: 'change',}],
   billing_type: [{required: true, trigger: 'change',}],

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.