ソースを参照

流量包管理

wanghairong 5 ヶ月 前
コミット
5b34c9b501

+ 104 - 0
src/views/supplier/trafficList/NewDataPackageForm.vue

@@ -0,0 +1,104 @@
+<template>
+    <a-modal :visible="visible" :title="editMode ? $t('dataPackage.editDataPackage') : $t('dataPackage.addDataPackage')"
+        @ok="handleSubmit" @cancel="handleCancel" :width="720">
+        <a-form :model="formData" :rules="rules" ref="formRef">
+            <a-form-item field="packageName" :label="$t('dataPackage.packageName')" required>
+                <a-input v-model="formData.packageName" :placeholder="$t('dataPackage.enterPackageName')" />
+            </a-form-item>
+            <a-form-item field="source" :label="$t('dataPackage.operatorType')" required>
+                <a-select v-model="formData.source" :placeholder="$t('dataPackage.selectOperatorType')">
+                    <a-option v-for="op in operatorTypeOptions" :key="op.value" :value="op.value">
+                        {{ op.label }}
+                    </a-option>
+                </a-select>
+            </a-form-item>
+            <a-form-item field="status" :label="$t('dataPackage.statusName')" required>
+                <a-select v-model="formData.status" :placeholder="$t('dataPackage.selectStatus')">
+                    <a-option value="1">{{ $t('dataPackage.status.normal') }}</a-option>
+                    <a-option value="2">{{ $t('dataPackage.status.disabled') }}</a-option>
+                    <a-option value="3">{{ $t('dataPackage.status.offline') }}</a-option>
+                </a-select>
+            </a-form-item>
+            <a-form-item field="packageCode" :label="$t('dataPackage.operatorPackageCode')">
+                <a-input v-model="formData.packageCode" :placeholder="$t('dataPackage.enterOperatorPackageCode')" />
+            </a-form-item>
+            <a-form-item field="packageSize" :label="$t('dataPackage.packageSize')" required>
+                <a-input-number v-model="formData.packageSize" :placeholder="$t('dataPackage.enterPackageSize')" />
+                <a-select v-model="formData.packageSizeUnit" style="width: 80px; margin-left: 8px;">
+                    <a-option value="MB">MB</a-option>
+                    <a-option value="GB">GB</a-option>
+                </a-select>
+            </a-form-item>
+            <a-form-item field="standardPrice" :label="$t('dataPackage.standardPrice')" required>
+                <a-input-number v-model="formData.standardPrice" :placeholder="$t('dataPackage.enterStandardPrice')" />
+            </a-form-item>
+        </a-form>
+    </a-modal>
+</template>
+
+<script setup>
+import { ref, reactive, watch } from 'vue';
+import { useI18n } from 'vue-i18n';
+
+const { t } = useI18n();
+
+const props = defineProps({
+    visible: Boolean,
+    editMode: Boolean,
+    editData: Object,
+});
+
+const emit = defineEmits(['update:visible', 'submit']);
+
+const formRef = ref(null);
+const formData = reactive({
+    packageName: '',
+    source: '',
+    status: 'normal',
+    packageCode: '',
+    packageSize: null,
+    packageSizeUnit: 'MB',
+    standardPrice: null,
+});
+
+const rules = {
+    packageName: [{ required: true, message: t('dataPackage.packageNameRequired') }],
+    source: [{ required: true, message: t('dataPackage.operatorTypeRequired') }],
+    status: [{ required: true, message: t('dataPackage.statusRequired') }],
+    packageSize: [{ required: true, message: t('dataPackage.packageSizeRequired') }],
+    standardPrice: [{ required: true, message: t('dataPackage.standardPriceRequired') }],
+};
+
+const operatorTypeOptions = [
+    { value: '1', label: t('dataPackage.operatorTypes.chinamobile') },
+    { value: '2', label: t('dataPackage.operatorTypes.chinaunicom') },
+    { value: '3', label: t('dataPackage.operatorTypes.chinatelecom') },
+    { value: '4', label: t('dataPackage.operatorTypes.international') },
+    { value: '5', label: t('dataPackage.operatorTypes.foreign_local') },
+];
+
+watch(() => props.editData, (newVal) => {
+    if (newVal) {
+        Object.assign(formData, newVal);
+        Object.keys(formData).forEach(key => {
+            if (newVal[key]) {
+                formData[key] = newVal[key]
+            }
+        });
+    }
+}, { deep: true });
+
+const handleSubmit = () => {
+    formRef.value.validate((errors) => {
+        if (!errors) {
+            emit('submit', formData);
+        } else {
+            console.error('Validation failed', errors);
+        }
+    });
+};
+
+const handleCancel = () => {
+    emit('update:visible', false);
+};
+</script>

+ 19 - 0
src/views/supplier/trafficList/config.js

@@ -0,0 +1,19 @@
+export const columns = [
+  { title: window.$t('dataPackage.id'), dataIndex: 'id', align: 'center', width: 200 },
+  { title: window.$t('dataPackage.packageCode'), dataIndex: 'packageCode', align: 'center', width: 200 },
+  { title: window.$t('dataPackage.packageName'), dataIndex: 'packageName', align: 'center', width: 200 },
+  { title: window.$t('dataPackage.operatorName'), dataIndex: 'sourceName', align: 'center', width: 200 },
+  { title: window.$t('dataPackage.packageSize'), dataIndex: 'packageSize', align: 'center', width: 200 },
+  { title: window.$t('dataPackage.standardPrice'), dataIndex: 'standardPrice', align: 'center', width: 200 },
+  { title: window.$t('dataPackage.statusName'), dataIndex: 'statusName', align: 'center', width: 200 },
+  {
+    title: window.$t('global.common.operations'),
+    dataIndex: 'id',
+    slotName: 'id',
+    align: 'center',
+    width: 180,
+    fixed: "right",
+  }
+]
+
+

+ 216 - 0
src/views/supplier/trafficList/index.vue

@@ -0,0 +1,216 @@
+<!-- 流量包管理 -->
+<template>
+  <div class="container">
+    <div class="head-title">
+      <span>{{ route.meta.title }} </span>
+    </div>
+    <!-- 搜索条件区 -->
+    <div class="search-section">
+      <a-form :model="searchForm" ref="formRef" layout="inline">
+        <a-form-item field="status" :label="$t('dataPackage.price')">
+          <a-input v-model="searchForm.price" :placeholder="$t('form.PleaseEnterThe') + $t('dataPackage.price')"
+            allow-clear />
+        </a-form-item>
+        <a-form-item field="periodType" :label="$t('dataPackage.operatorType')">
+          <a-input v-model="searchForm.periodType"
+            :placeholder="$t('form.PleaseEnterThe') + $t('dataPackage.operatorType')" allow-clear />
+        </a-form-item>
+        <a-form-item>
+          <a-space>
+            <a-button type="primary" @click="handleSearch">{{ $t('form.Search') }}</a-button>
+            <a-button @click="resetSearch">{{ $t('form.Reset') }}</a-button>
+          </a-space>
+        </a-form-item>
+      </a-form>
+    </div>
+    <div class="audit-btn">
+      <a-button @click="showNewDataPackageForm" type="text">
+        <template #icon>
+          <icon-plus-circle />
+        </template>
+        <template #default>{{ $t('form.Add') }}</template>
+      </a-button>
+    </div>
+
+    <a-table :data="dataSource" :columns="columns" :pagination="pagination" :scroll="{ x: 'auto' }"
+      @page-change="evChangePage">
+      <template #id="{ record }">
+        <a-button type="text" size="small" @click="handleEdit(record)">{{ $t('global.common.edit') }}</a-button>
+        <a-button type="text" size="small" @click="handleDelete(record)">{{ $t('global.common.delete') }}</a-button>
+
+
+      </template>
+
+    </a-table>
+
+    <!-- New data package form dialog -->
+    <new-data-package-form v-model:visible="newDataPackageFormVisible" :editMode="editMode" :editData="editData"
+      @submit="handleNewDataPackageSubmit" />
+  </div>
+</template>
+
+<script setup>
+import { onMounted, ref, getCurrentInstance } from "vue";
+import { useRoute } from "vue-router";
+import { columns } from "./config";
+import { Message, Notification } from '@arco-design/web-vue'
+import { dataPlanList } from "@/api/path/lotCard.api"
+import NewDataPackageForm from './NewDataPackageForm.vue';
+import { useI18n } from 'vue-i18n';
+
+
+const { t } = useI18n();
+const { proxy } = getCurrentInstance()
+const formRef = ref()
+const searchForm = ref({
+  "status": "",
+  "periodType": "",
+});
+
+const dataSource = ref([]);
+const route = useRoute();
+const pagination = ref({
+  total: 0,
+  pageSize: 10,
+  current: 1,
+})
+
+// 运营商
+const operatorTypeOptions = [
+  { value: '1', label: t('dataPackage.operatorTypes.chinamobile') },
+  { value: '2', label: t('dataPackage.operatorTypes.chinaunicom') },
+  { value: '3', label: t('dataPackage.operatorTypes.chinatelecom') },
+  { value: '4', label: t('dataPackage.operatorTypes.international') },
+  { value: '5', label: t('dataPackage.operatorTypes.foreign_local') },
+];
+// 状态
+const statusList = [
+  { value: '1', label: t('dataPackage.status.offline') },
+  { value: '2', label: t('dataPackage.status.disabled') },
+  { value: '3', label: t('dataPackage.status.normal') },
+]
+
+
+const intData = async () => {
+  const param = {
+    current: pagination.value.current,
+    size: pagination.value.pageSize,
+    ...searchForm.value,
+  }
+  const { data } = await dataPlanList(param)
+  dataSource.value = (data?.records || []).map((item, index) => {
+    const sourceName = operatorTypeOptions.find(val => val.value == item.source)?.label
+    const statusName = statusList.find(val => val.value == item.status)?.label
+    return {
+      ...item,
+      packageCode: "NR0" + (index + 1),
+      packageName: '监控1G月租',
+      providerName: '泰国AIS',
+      packageType: '定向',
+      billingType: '流量',
+      billingPeriod: '按月',
+      packageSize: '1.00',
+      packageUnit: 'G',
+      standardPrice: '150.00',
+      statusName,
+      sourceName
+
+    }
+  })
+  pagination.value.total = data.total
+}
+
+
+const evChangePage = (page) => {
+  pagination.value.current = page
+}
+
+
+
+const resetSearch = () => {
+  proxy.$refs.formRef.resetFields()
+  intData()
+}
+
+const handleSearch = () => {
+  intData()
+}
+
+
+// 弹窗-----------------------------------------------------
+// const showModel = ref(false)
+// const handleModal = () => {
+//   showModel.value = true
+// }
+const newDataPackageFormVisible = ref(false);
+const editMode = ref(false);
+const editData = ref(null);
+
+
+const showNewDataPackageForm = () => {
+  editMode.value = false;
+  editData.value = null;
+  newDataPackageFormVisible.value = true;
+};
+const handleEdit = (record) => {
+  editMode.value = true;
+  record.packageSize = Number(record.packageSize)
+  record.standardPrice = Number(record.standardPrice)
+  editData.value = { ...record };
+  newDataPackageFormVisible.value = true;
+};
+const handleDelete = (record) => {
+  // Implement delete logic
+  Message.success(t('dataPackage.packageDeleted', { name: record.packageName }));
+};
+
+const handleNewDataPackageSubmit = (formData) => {
+  if (editMode.value) {
+    // Implement update logic
+    Message.success(t('dataPackage.packageUpdated', { name: formData.packageName }));
+  } else {
+    // Implement add logic
+    Message.success(t('dataPackage.packageAdded', { name: formData.packageName }));
+  }
+  newDataPackageFormVisible.value = false;
+};
+// -----------------------------------------------------
+
+
+onMounted(() => {
+  intData()
+})
+</script>
+
+<style scoped lang="less">
+.search-section {
+  margin-top: 20px;
+  margin-bottom: 20px;
+}
+
+.container {
+  .head-title {
+    display: flex;
+    justify-content: space-between;
+  }
+
+  .form-row {
+    display: flex;
+
+    .form-row-col {
+      width: 25%;
+      display: flex;
+      align-items: center;
+
+      .form-row-label {
+        width: 120px;
+        text-align: right;
+      }
+    }
+  }
+}
+
+.audit-btn {
+  margin-bottom: 10px;
+}
+</style>