ys_sms_sending_web/src/views/sMsSendManage/loopSend/index.vue

229 lines
6.2 KiB
Vue
Raw Normal View History

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>