wuyi 1 жил өмнө
parent
commit
5b58874955

+ 9 - 0
src/router/index.js

@@ -1,6 +1,7 @@
 import { createRouter, createWebHistory } from 'vue-router'
 import { createRouter, createWebHistory } from 'vue-router'
 import { useUserStore } from '@/stores/user'
 import { useUserStore } from '@/stores/user'
 import { http } from '@/plugins/http'
 import { http } from '@/plugins/http'
+
 const router = createRouter({
 const router = createRouter({
     history: createWebHistory(import.meta.env.BASE_URL),
     history: createWebHistory(import.meta.env.BASE_URL),
     routes: [
     routes: [
@@ -78,6 +79,14 @@ const router = createRouter({
                         title: '设备列表'
                         title: '设备列表'
                     }
                     }
                 },
                 },
+                {
+                    path: '/channel',
+                    name: 'channel',
+                    component: () => import('../views/ChannelView.vue'),
+                    meta: {
+                        title: '渠道列表'
+                    }
+                },
                 {
                 {
                     path: '/rcsNumber',
                     path: '/rcsNumber',
                     name: 'rcsNumber',
                     name: 'rcsNumber',

+ 118 - 0
src/views/ChannelView.vue

@@ -0,0 +1,118 @@
+<template>
+    <PagingTable url="/channel" :where="where" ref="table">
+        <template #filter>
+            <ElButton :icon="Plus" @click="onEdit()">添加</ElButton>
+        </template>
+        <ElTableColumn prop="id" label="#" width="80" />
+        <ElTableColumn prop="mcc" label="MCC" />
+        <ElTableColumn prop="mnc" label="MNC" />
+        <ElTableColumn prop="country" label="国家" />
+        <ElTableColumn prop="operator" label="运营商" />
+        <ElTableColumn prop="createdAt" label="创建时间" :formatter="timeFormatter" width="150" />
+        <ElTableColumn label="操作" align="center" width="200">
+            <template #default="{ row }">
+                <ElButton type="danger" size="small" @click="del(row)">删除</ElButton>
+            </template>
+        </ElTableColumn>
+    </PagingTable>
+    <EditDialog v-model="showEditDialog" :model="model" :rules="rules" :on-submit="submit" @success="table.refresh()">
+        <ElFormItem prop="mcc" label="MCC">
+            <ElInput v-model="model.mcc" placeholder="请输入MCC" />
+        </ElFormItem>
+        <ElFormItem prop="mnc" label="MNC">
+            <ElInput v-model="model.mnc" placeholder="请输入MNC" />
+        </ElFormItem>
+        <ElFormItem prop="country" label="国家">
+            <ElInput v-model="model.country" placeholder="请输入国家" />
+        </ElFormItem>
+        <ElFormItem prop="operator" label="运营商">
+            <ElInput v-model="model.operator" placeholder="请输入运营商" />
+        </ElFormItem>
+        <ElFormItem prop="remark" label="备注">
+            <ElInput v-model="model.remark" placeholder="请输入备注" />
+        </ElFormItem>
+    </EditDialog>
+</template>
+<script setup>
+import { ref } from 'vue'
+import PagingTable from '@/components/PagingTable.vue'
+import { useTimeFormatter } from '@/utils/formatter'
+import { Plus } from '@vicons/tabler'
+import EditDialog from '@/components/EditDialog.vue'
+import { setupEditDialog } from '@/utils/editDialog'
+import EnumSelect from '@/components/EnumSelect.vue'
+import { UserRole } from '@/enums'
+import { http } from '@/plugins/http'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import { useClipboard } from '@vueuse/core'
+
+const where = ref({})
+const timeFormatter = useTimeFormatter()
+const table = ref(null)
+const model = ref({})
+const rules = {
+    mcc: [{ required: true, message: '请输入MCC', trigger: 'blur' }],
+    mnc: [{ required: true, message: '请输入MNC', trigger: 'blur' }],
+    country: [{ required: true, message: '请输入国家码', trigger: 'blur' }],
+    operator: [{ required: true, message: '请输入运营商', trigger: 'blur' }]
+}
+const { showEditDialog, onEdit } = setupEditDialog(model)
+
+async function submit() {
+    await http.put('/channel', model.value)
+    ElMessage.success('保存成功')
+}
+
+function del(row) {
+    ElMessageBox.confirm('确定删除吗?', '提示', {
+        type: 'warning'
+    }).then(() => {
+        http.delete(`/phone-list/${row.id}`).then(() => {
+            ElMessage.success('删除成功')
+            table.value.refresh()
+        })
+    })
+}
+
+const selectedRow = ref(null)
+const showDetailDialog = ref(false)
+const phoneTable = ref(null)
+
+const phoneModel = ref({})
+const phoneRules = {
+    number: [{ required: true, message: '请输入号码', trigger: 'blur' }]
+}
+const { showEditDialog: showPhoneEditDialog, onEdit: onPhoneEdit } = setupEditDialog(phoneModel)
+
+async function submitPhone() {
+    phoneModel.value.listId = selectedRow.value.id
+    await http.put('/phone-list/phone', phoneModel.value)
+    ElMessage.success('保存成功')
+}
+
+function delPhone(row) {
+    ElMessageBox.confirm('确定删除吗?', '提示', {
+        type: 'warning'
+    }).then(() => {
+        http.delete(`/phone-list/phone/${row.id}`).then(() => {
+            ElMessage.success('删除成功')
+            phoneTable.value.refresh()
+        })
+    })
+}
+
+function importList() {
+    const input = document.createElement('input')
+    input.type = 'file'
+    input.accept = '.txt'
+    input.onchange = async () => {
+        const file = input.files[0]
+        const formData = new FormData()
+        formData.append('file', file)
+        await http.post(`/phone-list/${selectedRow.value.id}/import`, formData)
+        ElMessage.success('导入成功')
+        phoneTable.value.refresh()
+    }
+    input.click()
+}
+</script>

+ 5 - 1
src/views/MainView.vue

@@ -20,7 +20,8 @@
                     </el-breadcrumb-item>
                     </el-breadcrumb-item>
                 </el-breadcrumb>
                 </el-breadcrumb>
                 <div class="grow"></div>
                 <div class="grow"></div>
-                <div class="balance-display" v-if="user.roles.includes('user')" style="display: inline-block; width: 15%; text-align: center;">
+                <div class="balance-display" v-if="user.roles.includes('user')"
+                     style="display: inline-block; width: 15%; text-align: center;">
                     已发送: {{ user.send }}, 余额: {{ user.balance }}
                     已发送: {{ user.send }}, 余额: {{ user.balance }}
                 </div>
                 </div>
                 <DarkSwitch class="mr-4" />
                 <DarkSwitch class="mr-4" />
@@ -94,6 +95,9 @@ if (roles.includes('admin')) {
                 {
                 {
                     name: '/device',
                     name: '/device',
                     title: '设备列表'
                     title: '设备列表'
+                }, {
+                    name: '/channel',
+                    title: '渠道列表'
                 },
                 },
                 {
                 {
                     name: '/rcsNumber',
                     name: '/rcsNumber',

+ 26 - 1
src/views/TaskView.vue

@@ -2,7 +2,7 @@
     <PagingTable url="/task" :where="where" ref="table">
     <PagingTable url="/task" :where="where" ref="table">
         <template #filter>
         <template #filter>
             <ElButton :icon="Refresh" @click="table.refresh()"></ElButton>
             <ElButton :icon="Refresh" @click="table.refresh()"></ElButton>
-            <ElButton :icon="Plus" @click="onEdit(), getPhoneList()"> 添加 </ElButton>
+            <ElButton :icon="Plus" @click="onEdit(), getPhoneList()"> 添加</ElButton>
         </template>
         </template>
         <ElTableColumn prop="id" label="#" width="80" />
         <ElTableColumn prop="id" label="#" width="80" />
         <ElTableColumn prop="name" label="名称" min-width="120" />
         <ElTableColumn prop="name" label="名称" min-width="120" />
@@ -62,6 +62,12 @@
                 <ElOption v-for="item in phoneList" :key="item.id" :label="item.name" :value="item.id" />
                 <ElOption v-for="item in phoneList" :key="item.id" :label="item.name" :value="item.id" />
             </ElSelect>
             </ElSelect>
         </ElFormItem>
         </ElFormItem>
+        <ElFormItem prop="listId" label="渠道列表">
+            <ElSelect v-model="model.channelId" placeholder="请选择渠道列表">
+                <ElOption v-for="item in operatorList" :key="item.id"
+                          :label="item.mcc+'-'+item.mnc+'-'+item.country+'-'+item.operator" :value="item.id" />
+            </ElSelect>
+        </ElFormItem>
         <ElFormItem prop="message" label="内容">
         <ElFormItem prop="message" label="内容">
             <ElInput v-model="model.message" placeholder="请输入内容" type="textarea" />
             <ElInput v-model="model.message" placeholder="请输入内容" type="textarea" />
         </ElFormItem>
         </ElFormItem>
@@ -130,6 +136,7 @@ const model = ref({})
 const rules = {
 const rules = {
     name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
     name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
     listId: [{ required: true, message: '请选择发送列表', trigger: 'blur' }],
     listId: [{ required: true, message: '请选择发送列表', trigger: 'blur' }],
+    channelId: [{ required: true, message: '请选择渠道列表', trigger: 'blur' }],
     message: [{ required: true, message: '请输入内容', trigger: 'blur' }],
     message: [{ required: true, message: '请输入内容', trigger: 'blur' }],
     rcsWait: [{ required: true, message: '请输入RCS等待时间', trigger: 'blur' }],
     rcsWait: [{ required: true, message: '请输入RCS等待时间', trigger: 'blur' }],
     rcsInterval: [{ required: true, message: '请输入RCS发送间隔', trigger: 'blur' }],
     rcsInterval: [{ required: true, message: '请输入RCS发送间隔', trigger: 'blur' }],
@@ -137,19 +144,32 @@ const rules = {
     requestNumberInterval: [{ required: true, message: '请输入请求号码间隔', trigger: 'blur' }]
     requestNumberInterval: [{ required: true, message: '请输入请求号码间隔', trigger: 'blur' }]
 }
 }
 const { showEditDialog, onEdit } = setupEditDialog(model)
 const { showEditDialog, onEdit } = setupEditDialog(model)
+
 async function submit() {
 async function submit() {
     model.value.userId = user.id
     model.value.userId = user.id
     await http.put('/task', model.value)
     await http.put('/task', model.value)
     ElMessage.success('保存成功')
     ElMessage.success('保存成功')
 }
 }
+
 const phoneList = ref([])
 const phoneList = ref([])
+
 async function getPhoneList() {
 async function getPhoneList() {
     phoneList.value = (await http.post('/phone-list')).items
     phoneList.value = (await http.post('/phone-list')).items
 }
 }
+
 getPhoneList()
 getPhoneList()
+const operatorList = ref([])
+
+async function getOperatorList() {
+    operatorList.value = (await http.post('/channel')).items
+}
+
+getOperatorList()
+
 function phoneListFormatter(row, column, cellValue, index) {
 function phoneListFormatter(row, column, cellValue, index) {
     return phoneList.value.find((item) => item.id === cellValue)?.name
     return phoneList.value.find((item) => item.id === cellValue)?.name
 }
 }
+
 function del(row) {
 function del(row) {
     ElMessageBox.confirm('确定删除吗?', '提示', {
     ElMessageBox.confirm('确定删除吗?', '提示', {
         type: 'warning'
         type: 'warning'
@@ -164,6 +184,7 @@ function del(row) {
 const selectedRow = ref(null)
 const selectedRow = ref(null)
 const showDetailDialog = ref(false)
 const showDetailDialog = ref(false)
 const phoneTable = ref(null)
 const phoneTable = ref(null)
+
 function detail(row) {
 function detail(row) {
     selectedRow.value = row
     selectedRow.value = row
     showDetailDialog.value = true
     showDetailDialog.value = true
@@ -174,6 +195,7 @@ const phoneRules = {
     number: [{ required: true, message: '请输入号码', trigger: 'blur' }]
     number: [{ required: true, message: '请输入号码', trigger: 'blur' }]
 }
 }
 const { showEditDialog: showPhoneEditDialog, onEdit: onPhoneEdit } = setupEditDialog(phoneModel)
 const { showEditDialog: showPhoneEditDialog, onEdit: onPhoneEdit } = setupEditDialog(phoneModel)
+
 function taskStatusFormatter(row, column, cellValue, index) {
 function taskStatusFormatter(row, column, cellValue, index) {
     switch (cellValue) {
     switch (cellValue) {
         case 'idle':
         case 'idle':
@@ -188,6 +210,7 @@ function taskStatusFormatter(row, column, cellValue, index) {
             return '未知'
             return '未知'
     }
     }
 }
 }
+
 function taskItemStatusFormatter(row, column, cellValue, index) {
 function taskItemStatusFormatter(row, column, cellValue, index) {
     switch (cellValue) {
     switch (cellValue) {
         case 'idle':
         case 'idle':
@@ -202,6 +225,7 @@ function taskItemStatusFormatter(row, column, cellValue, index) {
             return '未知'
             return '未知'
     }
     }
 }
 }
+
 async function start(row) {
 async function start(row) {
     await ElMessageBox.confirm('确定开始发送吗?', '提示', {
     await ElMessageBox.confirm('确定开始发送吗?', '提示', {
         type: 'warning'
         type: 'warning'
@@ -209,6 +233,7 @@ async function start(row) {
     await http.post(`/task/${row.id}/start`)
     await http.post(`/task/${row.id}/start`)
     table.value.refresh()
     table.value.refresh()
 }
 }
+
 async function pause(row) {
 async function pause(row) {
     await ElMessageBox.confirm('确定暂停发送吗?', '提示', {
     await ElMessageBox.confirm('确定暂停发送吗?', '提示', {
         type: 'warning'
         type: 'warning'