2025-10-13 01:27:37 +08:00
< template >
< div >
< div class = "flex justify-between items-start my-[10px]" >
< el-form :inline = "true" :model = "tableData.searchParam" ref = "searchFormRef" >
< el-form-item :label = "t('模版ID')" prop = "template_id" >
< el-input v -model .trim = " tableData.searchParam.template_id " :placeholder = "t('请输入模版ID')" / >
< / el-form-item >
< el-form-item :label = "t('模版名称')" prop = "name" >
< el-input v -model .trim = " tableData.searchParam.name " :placeholder = "t('请输入模版名称')" / >
< / el-form-item >
< el-form-item :label = "t('状态')" prop = "status" >
< el-select v-model = "tableData.searchParam.status" :placeholder="t('请选择状态')" >
< el-option :label = "t('全部')" :value = "''" > < / el-option >
< el-option v-for = "(statusText, statusValue) in template_status_list" :key="statusValue" :label="statusText" :value="statusValue" > < / el -option >
< / el-select >
< / el-form-item >
< el-form-item >
< el-button type = "primary" @click ="loadSmsTemplateList()" > {{ t ( " search " ) }} < / el -button >
< el-button @click ="resetForm(searchFormRef)" > {{ t ( " reset " ) }} < / el -button >
< / el-form-item >
< / el-form >
< el-button type = "primary" @click ="syncEvent()" > {{ t ( " 同步模版状态 " ) }} < / el -button >
< / div >
< el-table :data = "pagedData" size = "large" v-loading = "tableData.loading" ref="goodBankListTableRef" >
< template # empty >
< span > { { ! tableData . loading ? t ( "emptyData" ) : "" } } < / span >
< / template >
< el-table-column prop = "template_id" :label = "t('模版ID')" min -width = " 100 " / >
< el-table-column prop = "name" :label = "t('模版名称')" min -width = " 130 " / >
< el-table-column prop = "template_type_name" :label = "t('模版类型')" min -width = " 130 " >
< template # default = "{ row }" >
< div > { { row . template _type _name ? row . template _type _name : '--' } } < / div >
< / template >
< / el-table-column >
< el-table-column prop = "sms" :label = "t('模版内容')" min -width = " 200 " >
< template # default = "{ row }" >
< div > { { row . sms ? . content } } < / div >
< / template >
< / el-table-column >
< el-table-column prop = "audit_info" :label = "t('审核状态')" min -width = " 130 " >
< template # default = "{ row }" >
< div > { { row . audit _info ? . audit _status _name } } < span v-if = "row.audit_info?.error_status_name" class="text-red-600" > ( {{ row.audit_info ? .error_status_name }} ) < / span > < / div >
< / template >
< / el-table-column >
< el-table-column :label = "t('operation')" fixed = "right" align = "right" min -width = " 120 " >
< template # default = "{ row }" >
< el-button type = "primary" v-if = "row.audit_info.audit_status!=2" link @click="reportEvent(row)" > {{ row.audit_info.audit_status ! = 1 & & row.audit_info.audit_status ! = 2 ? t ( " 报备 " ) : t ( " 修改 " ) }} < / el -button >
< el-button type = "primary" v-if = "row.audit_info.audit_status==2" link @click="clearEvent(row)" > {{ t ( ' 清除报备信息 ' ) }} < / el -button >
< el-button type = "primary" link @click ="editEvent(row)" > {{ t ( " 详情 " ) }} < / el -button >
< / template >
< / el-table-column >
< / el-table >
< div class = "mt-[16px] flex justify-end" >
< el-pagination v -model :current-page = "tableData.page" v -model :page-size = "tableData.limit"
layout = "total, sizes, prev, pager, next, jumper" : total = "tableData.total" / >
< / div >
2025-11-16 22:13:57 +08:00
< ModalDetail :class = "'w-[600px]'" :title = "t('模版详情')" >
2025-10-13 01:27:37 +08:00
< el-form label -width = " 100px " ref = "formRef" class = "page-form" >
< el-form-item :label = "t('短信类型')" prop = "template_id" >
2025-11-16 22:13:57 +08:00
< div > { { detail ? . sms _type } } < / div >
2025-10-13 01:27:37 +08:00
< / el-form-item >
< el-form-item :label = "t('模版名称')" prop = "template_id" >
2025-11-16 22:13:57 +08:00
< div > { { detail ? . name } } < / div >
2025-10-13 01:27:37 +08:00
< / el-form-item >
< el-form-item :label = "t('模版类型')" prop = "title" >
2025-11-16 22:13:57 +08:00
< div > { { detail ? . title } } < / div >
2025-10-13 01:27:37 +08:00
< / el-form-item >
2025-11-16 22:13:57 +08:00
< el-form-item :label = "t('短信内容')" prop = "title" v-if = "detail?.sms" >
< div > { { detail ? . sms ? . content } } < / div >
2025-10-13 01:27:37 +08:00
< / el-form-item >
< el-form-item :label = "t('审核状态')" prop = "title" >
2025-11-16 22:13:57 +08:00
< div > { { detail ? . audit _info ? . audit _status _name } } < / div >
2025-10-13 01:27:37 +08:00
< / el-form-item >
< / el-form >
< template # footer >
< span class = "dialog-footer" >
2025-11-16 22:13:57 +08:00
< el-button type = "primary" @click ="detailConfirm" > {{ t ( ' confirm ' ) }} < / el -button >
2025-10-13 01:27:37 +08:00
< / span >
< / template >
2025-11-16 22:13:57 +08:00
< / ModalDetail >
< ModalReport :class = "'w-[820px]'" :title = "t('模版报备')" >
< div v-loading = "reportLoading" >
< el-form label -width = " 100px " ref = "formRef" class = "page-form" >
< el-form-item :label = "t('模版名称')" prop = "template_id" >
< div class = "input-width" > { { detail ? . name } } < / div >
< / el-form-item >
< el-form-item :label = "t('模版类型')" prop = "title" >
< el-radio-group v-model = "reportData.template_type" >
< el-radio v-for = "[key, value] in Object.entries(template_type_list)" :key="key" :label="Number(key)" > {{ value }} < / el -radio >
< / el-radio-group >
< / el-form-item >
< div class = "ml-[100px] mb-[10px] mt-[-10px] text-[12px] text-[#999] leading-[20px]" >
< div > 验证码 : 仅支持验证码类型变量 < / div >
< div > 行业通知 : 不支持验证码类型变量 < / div >
< div > 营销推广 : 不支持变量 < / div >
2025-10-13 01:27:37 +08:00
< / div >
2025-11-16 22:13:57 +08:00
< el-form-item :label = "t('变量类型')" prop = "params_json" v-if = "detail?.variable && Object.keys(detail.variable).length > 0" >
< div v-for = "(label, key) in detail.variable" :key="key" class="mb-2 flex items-center" >
< div class = "flex flex-1 items-center" >
< div class = "w-32 mr-1 " > { { label } } < / div >
< el-select v-model = "reportData.params_json[key]" placeholder="请选择类型" class="flex-1" filterable clearable :disabled="isMarketingWithVariable" >
< el-option v-for = "item in filteredParamTypes" :key="item.type" :label="item.name + '( ' + item.desc + ') '" :value="item.type" />
< / el-select >
< / div >
< / div >
< / el-form-item >
< / el-form >
< / div >
2025-10-13 01:27:37 +08:00
< template # footer >
< span class = "dialog-footer" >
2025-11-16 22:13:57 +08:00
< el-button @click ="reportCancel" > {{ t ( ' cancel ' ) }} < / el -button >
< el-button type = "primary" @click ="reportConfirm" :disabled = "isMarketingWithVariable" > { { t ( 'confirm' ) } } < / el-button >
2025-10-13 01:27:37 +08:00
< / span >
< / template >
2025-11-16 22:13:57 +08:00
< / ModalReport >
< ModalAsync :class = "'w-[800px]'" :title = "t('同步模版状态')" >
2025-10-13 01:27:37 +08:00
< el-alert type = "warning" :closable = "false" class = "!mb-[10px]" >
< template # default >
以下模版名称重复 , 请先调整模版名称后重新同步模版
< / template >
< / el-alert >
< el-form label -width = " 100px " ref = "formRef" class = "page-form" >
< div v-if = "Object.keys(repeatList).length" class="h-[500px] overflow-y-auto" >
< el-table :data = "repeatListArray" border style = "width: 100%;" >
< el-table-column label = "模版名称" prop = "name" / >
< el-table-column label = "插件名称" >
2025-11-16 22:13:57 +08:00
< template # default = "{ row }" >
< el-tag v-for = "item in row.platforms" :key="item" class="mr-1 mb-1" > {{ item }} < / el -tag >
< / template >
2025-10-13 01:27:37 +08:00
< / el-table-column >
< / el-table >
< / div >
< / el-form >
< template # footer >
< span class = "dialog-footer" >
2025-11-16 22:13:57 +08:00
< el-button @click ="asyncCancel" > {{ t ( ' cancel ' ) }} < / el -button >
< el-button type = "primary" @click ="asyncConfirm" > {{ t ( ' confirm ' ) }} < / el -button >
2025-10-13 01:27:37 +08:00
< / span >
< / template >
2025-11-16 22:13:57 +08:00
< / ModalAsync >
2025-10-13 01:27:37 +08:00
< / div >
< / template >
< script lang = "ts" setup >
import { ref , computed , reactive , onMounted , watch } from 'vue'
import { getTemplateList , getTemplateReportConfig , reportTemplate , templateSync , getreportTemplateInfo , clearTemplate } from '@/app/api/notice'
import { t } from '@/lang'
2025-11-16 22:13:57 +08:00
import { useVbenModal } from '@vben/common-ui'
2025-10-13 01:27:37 +08:00
const props = defineProps ( {
username : {
type : String ,
default : ''
} ,
signature : {
type : String ,
default : ''
}
} )
// 表单内容
const tableData = reactive ( {
page : 1 ,
limit : 10 ,
total : 0 ,
loading : false ,
data : [ ] , // 当前页展示的数据(通过 computed 生成)
allData : [ ] , // 原始完整数据
searchParam : {
template _id : '' ,
name : '' ,
status : ''
}
} )
const filterData = ( ) => {
const { template _id , name , status } = tableData . searchParam
return tableData . allData . filter ( item => {
const matchId = ! template _id || String ( item . template _id || '' ) . includes ( template _id )
const matchName = ! name || String ( item . name || '' ) . includes ( name )
const matchStatus = ! status || item . audit _info . audit _status == status
return matchId && matchName && matchStatus
} )
}
watch ( ( ) => [ tableData . limit , tableData . page ] , ( ) => {
pagedDataChange ( )
} )
// 获取列表
const loadSmsTemplateList = ( ) => {
tableData . loading = true
getTemplateList ( { sms _type : 'niuyun' , username : props . username } ) . then ( ( res ) => {
tableData . allData = res . data
tableData . page = 1 // 搜索后回到第一页
pagedDataChange ( )
} ) . catch ( ( ) => {
tableData . loading = false
} )
}
const searchFormRef = ref ( null )
const resetForm = ( formRef ) => {
if ( ! formRef ) return
tableData . searchParam = {
template _id : '' ,
name : '' ,
status : ''
}
loadSmsTemplateList ( )
}
const pagedData = ref ( [ ] )
const pagedDataChange = ( ) => {
const filtered = filterData ( ) // 使用筛选后的数据
tableData . total = filtered . length
const start = ( tableData . page - 1 ) * tableData . limit
const end = start + tableData . limit
pagedData . value = filtered . slice ( start , end )
tableData . loading = false
}
onMounted ( ( ) => {
if ( props . username ) {
loadSmsTemplateList ( )
}
} )
2025-11-16 22:13:57 +08:00
const [ ModalDetail , modalDetailApi ] = useVbenModal ( )
const [ ModalReport , modalReportApi ] = useVbenModal ( )
const [ ModalAsync , modalAsyncApi ] = useVbenModal ( )
2025-10-13 01:27:37 +08:00
const repeatList = ref ( { } )
const syncEvent = ( ) => {
templateSync ( 'niuyun' , props . username ) . then ( ( res ) => {
repeatList . value = res . data . repeat _list
if ( repeatList . value && Object . keys ( repeatList . value ) . length > 0 ) {
2025-11-16 22:13:57 +08:00
modalAsyncApi . open ( )
2025-10-13 01:27:37 +08:00
} else {
loadSmsTemplateList ( )
}
} )
}
const repeatListArray = computed ( ( ) => {
return Object . entries ( repeatList . value ) . map ( ( [ name , platforms ] ) => ( {
name ,
platforms
} ) )
} )
// 详情
const detail = ref ( null )
const editEvent = ( row : any ) => {
detail . value = row
2025-11-16 22:13:57 +08:00
modalDetailApi . open ( )
2025-10-13 01:27:37 +08:00
}
// 清除报备
const clearEvent = ( row : any ) => {
ElMessageBox . confirm ( t ( '确定要清除报备信息吗' ) , t ( '提示' ) , {
confirmButtonText : t ( '确定' ) ,
cancelButtonText : t ( '取消' ) ,
type : 'warning'
} ) . then ( ( ) => {
clearTemplate ( props . username , row . template _id ) . then ( ( ) => {
loadSmsTemplateList ( )
} )
} ) . catch ( ( ) => {
} )
}
// 报备
const template _params _type _list = ref ( { } )
const template _type _list = ref ( { } )
const template _status _list = ref ( { } )
const reportData = ref ( {
template _type : 1 ,
template _key : '' ,
params _json : { }
} )
const getTemplateReportConfigFn = ( ) => {
getTemplateReportConfig ( ) . then ( ( res ) => {
template _params _type _list . value = res . data . template _params _type _list
template _type _list . value = res . data . template _type _list
template _status _list . value = res . data . template _status _list
} )
}
getTemplateReportConfigFn ( )
const filteredParamTypes = computed ( ( ) => {
if ( reportData . value . template _type === 1 ) {
return template _params _type _list . value . filter ( item => item . type === 'valid_code' )
} else {
return template _params _type _list . value
}
} )
const isMarketingWithVariable = computed ( ( ) => {
return reportData . value . template _type === 3 && detail . value . variable && Object . keys ( detail . value . variable ) . length > 0
} )
watch ( isMarketingWithVariable , ( val ) => {
if ( val ) {
ElMessage . error ( '营销推广类型不支持变量' )
}
} )
const reportLoading = ref ( false )
const reportEvent = ( row : any ) => {
reportLoading . value = true
const signature = props . signature
if ( ! signature ) {
ElMessage . error ( '请先配置签名' )
} else {
2025-11-16 22:13:57 +08:00
detail . value = row
modalReportApi . open ( )
2025-10-13 01:27:37 +08:00
if ( row . template _id ) {
getreportTemplateInfo ( 'niuyun' , props . username , { template _key : row . key } ) . then ( ( res ) => {
const paramJson = res . data ? . param _json ? ? { }
reportData . value . template _key = res . data . template _key
reportData . value . template _type = Number ( res . data . template _type )
reportData . value . params _json = { }
if ( detail . value . variable ) {
for ( const key in detail . value . variable ) {
reportData . value . params _json [ key ] = paramJson [ key ] ? ? ''
}
}
reportLoading . value = false
} )
} else {
reportLoading . value = false
reportData . value . template _type = 1
reportData . value . template _key = detail . value . key
reportData . value . params _json = { }
}
}
}
const reportTemplateFn = ( ) => {
if ( ! detail . value . sms ) {
ElMessage . error ( '请先配置模版内容' )
return
}
// 校验每个变量是否已选择类型
const missingParams = Object . entries ( detail . value . variable ) . some (
( [ key ] ) => ! reportData . value . params _json [ key ]
)
if ( missingParams ) {
ElMessage . error ( '请为每个变量选择类型' )
return
}
if ( detail . value . template _id ) {
reportData . value . template _id = Number ( detail . value . template _id )
}
reportTemplate ( detail . value . sms _type , props . username , reportData . value ) . then ( ( res ) => {
2025-11-16 22:13:57 +08:00
modalReportApi . close ( )
2025-10-13 01:27:37 +08:00
loadSmsTemplateList ( )
} )
}
2025-11-16 22:13:57 +08:00
const detailConfirm = ( ) => { modalDetailApi . close ( ) }
const reportCancel = ( ) => { modalReportApi . close ( ) }
const reportConfirm = ( ) => { reportTemplateFn ( ) }
const asyncCancel = ( ) => { modalAsyncApi . close ( ) }
const asyncConfirm = ( ) => { modalAsyncApi . close ( ) }
2025-10-13 01:27:37 +08:00
< / script >
< style lang = "scss" scoped >
< / style >