2026-01-27 14:46:33 +08:00
|
|
|
|
<template>
|
|
|
|
|
|
<div class="app-container">
|
|
|
|
|
|
<!-- 循环发送短信列表 -->
|
2026-01-27 15:51:33 +08:00
|
|
|
|
<ComTable
|
|
|
|
|
|
ref="comTableRef"
|
|
|
|
|
|
:form-columns="formColumns"
|
|
|
|
|
|
:table-columns="tableColumns"
|
|
|
|
|
|
:load-data="listLoopSendAPI"
|
|
|
|
|
|
:show-toolbar="true"
|
|
|
|
|
|
:show-action="true"
|
|
|
|
|
|
:action-columns="actionColumns"
|
|
|
|
|
|
>
|
|
|
|
|
|
<template #toolbar>
|
2026-01-27 15:29:24 +08:00
|
|
|
|
<div class="toolbar-left">
|
|
|
|
|
|
<ComButton
|
|
|
|
|
|
type="primary"
|
|
|
|
|
|
icon="Plus"
|
|
|
|
|
|
@click="onHandleAdd"
|
|
|
|
|
|
v-hasPermi="['sms:loopTask:add']"
|
|
|
|
|
|
>
|
|
|
|
|
|
新建
|
|
|
|
|
|
</ComButton>
|
2026-01-27 15:51:33 +08:00
|
|
|
|
<span v-if="smsBalance !== null" class="sms-balance-text">
|
|
|
|
|
|
短信余额剩余 {{ smsBalance }} 条
|
|
|
|
|
|
<span v-if="smsBalance < 10000">,请及时充值!</span>
|
|
|
|
|
|
</span>
|
2026-01-27 15:29:24 +08:00
|
|
|
|
</div>
|
2026-01-27 15:51:33 +08:00
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<template #taskStatus="{ row }">
|
|
|
|
|
|
<el-switch
|
|
|
|
|
|
active-value="0"
|
|
|
|
|
|
inactive-value="1"
|
|
|
|
|
|
:model-value="getTaskStatusValue(row)"
|
|
|
|
|
|
:loading="getSwitchLoading(row.id)"
|
|
|
|
|
|
:disabled="getSwitchLoading(row.id)"
|
|
|
|
|
|
@change="(value) => debouncedStatusChange(value, row)"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</ComTable>
|
2026-01-27 14:46:33 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup name="LoopSend">
|
2026-01-27 15:29:24 +08:00
|
|
|
|
import { ref, computed, getCurrentInstance, onMounted } from 'vue'
|
2026-01-27 14:46:33 +08:00
|
|
|
|
import { useRouter } from 'vue-router'
|
2026-01-27 15:17:28 +08:00
|
|
|
|
import { debounce } from 'lodash-es'
|
2026-01-27 14:46:33 +08:00
|
|
|
|
import {
|
|
|
|
|
|
delLoopSendAPI,
|
2026-01-27 15:29:24 +08:00
|
|
|
|
listLoopSendAPI,
|
|
|
|
|
|
getSmsBalanceAPI,
|
2026-01-27 14:46:33 +08:00
|
|
|
|
updateLoopSendStatusAPI,
|
|
|
|
|
|
} from '@/api/sMsSendManage/loopSend.js'
|
|
|
|
|
|
import config from './config'
|
|
|
|
|
|
import ComTable from '@/components/ComTable/index.vue'
|
|
|
|
|
|
import ComButton from '@/components/ComButton/index.vue'
|
|
|
|
|
|
|
|
|
|
|
|
const router = useRouter()
|
|
|
|
|
|
const { proxy } = getCurrentInstance()
|
|
|
|
|
|
|
|
|
|
|
|
const { tableColumns, buildFormColumns } = config
|
|
|
|
|
|
const comTableRef = ref(null)
|
2026-01-27 15:29:24 +08:00
|
|
|
|
const smsBalance = ref(null) // 短信余额
|
2026-01-27 15:17:28 +08:00
|
|
|
|
const switchLoadingMap = new Map() // 记录每个 switch 的 loading 状态
|
2026-01-27 14:46:33 +08:00
|
|
|
|
|
|
|
|
|
|
// 根据配置构建搜索表单
|
|
|
|
|
|
const formColumns = computed(() => buildFormColumns())
|
|
|
|
|
|
|
|
|
|
|
|
// 操作列配置
|
|
|
|
|
|
const actionColumns = [
|
|
|
|
|
|
{
|
|
|
|
|
|
label: '详情',
|
|
|
|
|
|
type: 'primary',
|
|
|
|
|
|
link: true,
|
|
|
|
|
|
permission: ['sms:loopTask:detail'],
|
|
|
|
|
|
handler: (row) => {
|
|
|
|
|
|
router.push({
|
|
|
|
|
|
path: '/sms/loopSendEdit/index',
|
|
|
|
|
|
query: {
|
|
|
|
|
|
id: row.id,
|
|
|
|
|
|
mode: 'detail',
|
|
|
|
|
|
},
|
|
|
|
|
|
})
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
// {
|
|
|
|
|
|
// label: '编辑',
|
|
|
|
|
|
// type: 'primary',
|
|
|
|
|
|
// link: true,
|
|
|
|
|
|
// permission: ['sms:loopTask:edit'],
|
|
|
|
|
|
// handler: (row) => {
|
|
|
|
|
|
// router.push({
|
|
|
|
|
|
// path: '/sms/loopSendEdit/index',
|
|
|
|
|
|
// query: {
|
|
|
|
|
|
// id: row.id,
|
|
|
|
|
|
// mode: 'edit',
|
|
|
|
|
|
// },
|
|
|
|
|
|
// })
|
|
|
|
|
|
// },
|
|
|
|
|
|
// },
|
|
|
|
|
|
{
|
|
|
|
|
|
label: '删除',
|
|
|
|
|
|
type: 'danger',
|
|
|
|
|
|
link: true,
|
|
|
|
|
|
permission: ['sms:loopTask:remove'],
|
|
|
|
|
|
handler: (row) => {
|
|
|
|
|
|
proxy.$modal.confirm('是否确认删除该循环发送任务?').then(async () => {
|
|
|
|
|
|
const result = await delLoopSendAPI({ id: row.id })
|
|
|
|
|
|
if (result.code === 200) {
|
|
|
|
|
|
proxy.$modal.msgSuccess('删除成功')
|
|
|
|
|
|
comTableRef.value?.refresh()
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
// 新增
|
|
|
|
|
|
const onHandleAdd = () => {
|
|
|
|
|
|
router.push({
|
|
|
|
|
|
path: '/sms/loopSendEdit/index',
|
|
|
|
|
|
query: {
|
|
|
|
|
|
mode: 'add',
|
|
|
|
|
|
},
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-27 15:17:28 +08:00
|
|
|
|
// 获取 taskStatus 的值,统一转换为字符串格式
|
|
|
|
|
|
const getTaskStatusValue = (row) => {
|
|
|
|
|
|
const value = row.taskStatus
|
|
|
|
|
|
if (value === null || value === undefined) {
|
|
|
|
|
|
return '1'
|
|
|
|
|
|
}
|
|
|
|
|
|
// 如果是数字,转换为字符串;如果已经是字符串,直接返回
|
|
|
|
|
|
return String(value)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取 switch 的 loading 状态
|
|
|
|
|
|
const getSwitchLoading = (rowId) => {
|
|
|
|
|
|
return switchLoadingMap.get(rowId) || false
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 设置 switch 的 loading 状态
|
|
|
|
|
|
const setSwitchLoading = (rowId, loading) => {
|
|
|
|
|
|
if (loading) {
|
|
|
|
|
|
switchLoadingMap.set(rowId, true)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
switchLoadingMap.delete(rowId)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 任务状态修改(实际执行的方法)
|
|
|
|
|
|
const onHandleStatusChange = (value, row) => {
|
|
|
|
|
|
// 如果正在加载中,直接返回
|
|
|
|
|
|
if (getSwitchLoading(row.id)) {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 更新 row 数据,保持与 switch 组件的值同步
|
|
|
|
|
|
row.taskStatus = value
|
|
|
|
|
|
|
|
|
|
|
|
// 设置 loading 状态
|
|
|
|
|
|
setSwitchLoading(row.id, true)
|
|
|
|
|
|
|
|
|
|
|
|
// 组装参数
|
|
|
|
|
|
const params = {
|
|
|
|
|
|
id: row.id,
|
|
|
|
|
|
taskStatus: value,
|
|
|
|
|
|
jobId: row.jobId,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
updateLoopSendStatusAPI(params)
|
|
|
|
|
|
.then((res) => {
|
|
|
|
|
|
if (res.code === 200) {
|
|
|
|
|
|
proxy.$modal.msgSuccess(value === '0' ? '启用成功' : '停用成功')
|
|
|
|
|
|
comTableRef.value?.refresh()
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 如果失败,恢复原状态
|
|
|
|
|
|
row.taskStatus = value === '0' ? '1' : '0'
|
|
|
|
|
|
}
|
2026-01-27 14:46:33 +08:00
|
|
|
|
})
|
2026-01-27 15:17:28 +08:00
|
|
|
|
.catch(() => {
|
2026-01-27 14:46:33 +08:00
|
|
|
|
// 如果失败,恢复原状态
|
2026-01-27 15:17:28 +08:00
|
|
|
|
row.taskStatus = value === '0' ? '1' : '0'
|
|
|
|
|
|
})
|
|
|
|
|
|
.finally(() => {
|
|
|
|
|
|
// 清除 loading 状态
|
|
|
|
|
|
setSwitchLoading(row.id, false)
|
|
|
|
|
|
})
|
2026-01-27 14:46:33 +08:00
|
|
|
|
}
|
2026-01-27 15:17:28 +08:00
|
|
|
|
|
|
|
|
|
|
// 使用防抖包装状态修改方法,延迟 300ms
|
|
|
|
|
|
const debouncedStatusChange = debounce(onHandleStatusChange, 300)
|
2026-01-27 15:29:24 +08:00
|
|
|
|
|
|
|
|
|
|
// 获取短信余额
|
|
|
|
|
|
const getSmsBalance = async () => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const result = await getSmsBalanceAPI()
|
|
|
|
|
|
if (result.code === 200) {
|
|
|
|
|
|
smsBalance.value = result.data || result.balance || null
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('获取短信余额失败:', error)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
|
getSmsBalance()
|
|
|
|
|
|
})
|
2026-01-27 14:46:33 +08:00
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
|
|
.app-container {
|
|
|
|
|
|
padding: 20px;
|
|
|
|
|
|
}
|
2026-01-27 15:29:24 +08:00
|
|
|
|
|
|
|
|
|
|
.toolbar-left {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 12px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-27 15:51:33 +08:00
|
|
|
|
.sms-balance-text {
|
|
|
|
|
|
margin-left: 16px;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
color: #f56c6c;
|
2026-01-27 15:29:24 +08:00
|
|
|
|
}
|
2026-01-27 14:46:33 +08:00
|
|
|
|
</style>
|