feat:1,新增游戏配置 2,新增币种 3,新增角色权限管理
parent
c6102d995f
commit
4c54307fc5
|
|
@ -38,8 +38,9 @@ export function uploadImgFile(data) {
|
||||||
// 图片上传
|
// 图片上传
|
||||||
const baseUrlq = getLocalStorage('uploadUrl');
|
const baseUrlq = getLocalStorage('uploadUrl');
|
||||||
export function uploadImgFileCommon(data, type) {
|
export function uploadImgFileCommon(data, type) {
|
||||||
|
console.log(baseUrlq);
|
||||||
return request({
|
return request({
|
||||||
url: baseUrlq + `/file/upload/localSysFile/${type}`,
|
url: `/file/upload/localSysFile/${type}`,
|
||||||
method: 'post',
|
method: 'post',
|
||||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||||
data: data
|
data: data
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
// 查询游戏配置表
|
||||||
|
export function getGameSecretList(query) {
|
||||||
|
return request({
|
||||||
|
url: '/game/secret/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//配置详情
|
||||||
|
export function getGameSecretInfo(id) {
|
||||||
|
return request({
|
||||||
|
url: `/game/secret/${id}`,
|
||||||
|
method: 'get',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 新增游戏配置
|
||||||
|
export function postGameSecret(data) {
|
||||||
|
return request({
|
||||||
|
url: '/game/secret',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修改游戏配置
|
||||||
|
export function updateGameSecret(data) {
|
||||||
|
return request({
|
||||||
|
url: '/game/secret',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//删除
|
||||||
|
export function deleteGameSecret(id) {
|
||||||
|
return request({
|
||||||
|
url: `/game/secret/${id}`,
|
||||||
|
method: 'delete',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
// 查询用户头像管理 列表
|
||||||
|
export function listAvatar(query) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/avatar/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询用户头像管理 详细
|
||||||
|
export function getAvatar(id) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/avatar/' + id,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增用户头像管理
|
||||||
|
export function addAvatar(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/avatar',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修改用户头像管理
|
||||||
|
export function updateAvatar(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/avatar',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除用户头像管理
|
||||||
|
export function delAvatar(id) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/avatar/' + id,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,656 @@
|
||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
// 全局子域名搜索
|
||||||
|
export function getSonDomainSearch(query) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/get',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------域名管理---------------------//
|
||||||
|
|
||||||
|
// 域名管理商列表
|
||||||
|
export function getSupplierList(query) {
|
||||||
|
return request({
|
||||||
|
url: '/domain/supplier/select',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//域名信息查询
|
||||||
|
export function getDomainConfig(query) {
|
||||||
|
return request({
|
||||||
|
url: '/domain/supplier/config',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 开通域名管理商
|
||||||
|
export function tenantSupplier(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/tenant',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 开通域名管理商ALB
|
||||||
|
export function tenantSupplierALB(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/tenant/alb',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 域名列表
|
||||||
|
export function getDomainList(query) {
|
||||||
|
return request({
|
||||||
|
url: '/domain/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 域名验证
|
||||||
|
export function getDomainVerify(data) {
|
||||||
|
return request({
|
||||||
|
url: '/domain/check',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 刷新域名过期时间
|
||||||
|
export function getDomainExpireTime(data) {
|
||||||
|
return request({
|
||||||
|
url: '/domain/expired',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 强制停用
|
||||||
|
export function setDomainStop(data) {
|
||||||
|
return request({
|
||||||
|
url: '/domain/stop',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 彻底删除管理域名
|
||||||
|
export function delDomain(ids) {
|
||||||
|
return request({
|
||||||
|
url: '/domain/' + ids,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增域名
|
||||||
|
export function addDomain(data) {
|
||||||
|
return request({
|
||||||
|
url: '/domain',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取供应商节点下域名
|
||||||
|
export function getSupplierDomainList(query) {
|
||||||
|
return request({
|
||||||
|
url: '/domain/select',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取域名NS
|
||||||
|
export function getDomainNS(id) {
|
||||||
|
return request({
|
||||||
|
url: '/domain/get/ns/' + id,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------WEB大厅---------------------//
|
||||||
|
|
||||||
|
// web大厅子域名列表
|
||||||
|
export function getWebDomainList(query) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/web/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 刷新解析说明
|
||||||
|
export function refreshWebDomainAnalysis(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/web/analysis',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// web大厅列表开关
|
||||||
|
export function webDomainSwitch(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/web/switch',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// web大厅子域名新增
|
||||||
|
export function addWebDomain(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/web',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// web大厅子域名状态修改
|
||||||
|
export function setWebDomainStatus(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/web/status',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// web大厅子域名绑定代理
|
||||||
|
export function bindWebDomainAgent(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/web/bind/agent',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// web大厅子域名清理缓存
|
||||||
|
export function clearWebDomainCache(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/web/clear/cache',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// web大厅子域名删除
|
||||||
|
export function delWebDomain(ids) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/web/' + ids,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// web大厅子域名修改
|
||||||
|
export function updateWebDomain(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/web',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// web大厅子域名批量更换端口
|
||||||
|
export function changeWebDomainPort(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/web/port',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// web系统参数
|
||||||
|
export function getWebSystemParam() {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/web/configKey/batch',
|
||||||
|
method: 'post'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// web系统参数修改
|
||||||
|
export function updateWebSystemParam(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/web/configKey/batch',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------后端加速域名---------------------//
|
||||||
|
|
||||||
|
// 后端加速域名列表
|
||||||
|
export function getBackendDomainList(query) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/backend/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 后端加速域名刷新解析说明
|
||||||
|
export function refreshBackendDomainAnalysis(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/backend/analysis',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 后端加速域名状态修改
|
||||||
|
export function setBackendDomainStatus(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/backend/status',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 后端加速域名清理缓存
|
||||||
|
export function clearBackendDomainCache(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/backend/clear/cache',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 后端加速域名删除
|
||||||
|
export function delBackendDomain(ids) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/backend/' + ids,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 后端加速域名新增
|
||||||
|
export function addBackendDomain(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/backend',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 后端加速域名修改
|
||||||
|
export function updateBackendDomain(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/backend',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------App大厅域名---------------------//
|
||||||
|
|
||||||
|
// App大厅域名列表
|
||||||
|
export function getAppDomainList(query) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/app/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// App大厅刷新解析说明
|
||||||
|
export function refreshAppDomainAnalysis(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/app/analysis',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// App大厅域名状态修改
|
||||||
|
export function setAppDomainStatus(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/app/status',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// App大厅域名清理缓存
|
||||||
|
export function clearAppDomainCache(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/app/clear/cache',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// App大厅域名删除
|
||||||
|
export function delAppDomain(ids) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/app/' + ids,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// App大厅域名新增
|
||||||
|
export function addAppDomain(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/app',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// App大厅域名修改
|
||||||
|
export function updateAppDomain(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/app',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------OSS加速域名---------------------//
|
||||||
|
|
||||||
|
// OSS加速域名列表
|
||||||
|
export function getOssDomainList(query) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/oss/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// OSS加速域名刷新解析说明
|
||||||
|
export function refreshOssDomainAnalysis(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/oss/analysis',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// OSS加速域名状态修改
|
||||||
|
export function setOssDomainStatus(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/oss/status',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// OSS加速域名清理缓存
|
||||||
|
export function clearOssDomainCache(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/oss/clear/cache',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// OSS加速域名删除
|
||||||
|
export function delOssDomain(ids) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/oss/' + ids,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// OSS加速域名新增
|
||||||
|
export function addOssDomain(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/oss',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// OSS加速域名修改
|
||||||
|
export function updateOssDomain(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/oss',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------下载站域名---------------------//
|
||||||
|
|
||||||
|
// 下载站域名列表
|
||||||
|
export function getDownloadDomainList(query) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/download/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 下载站域名刷新解析说明
|
||||||
|
export function refreshDownloadDomainAnalysis(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/download/analysis',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 下载站域名状态修改
|
||||||
|
export function setDownloadDomainStatus(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/download/status',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 下载站域名清理缓存
|
||||||
|
export function clearDownloadDomainCache(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/download/clear/cache',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 下载站域名删除
|
||||||
|
export function delDownloadDomain(ids) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/download/' + ids,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 下载站域名新增
|
||||||
|
export function addDownloadDomain(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/download',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 下载站域名修改
|
||||||
|
export function updateDownloadDomain(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/download',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 下载站域名列表开关
|
||||||
|
export function downloadDomainSwitch(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/download/switch',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 下载站绑定代理
|
||||||
|
export function bindDownloadDomainAgent(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/download/bind/agent',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------支付域名---------------------//
|
||||||
|
|
||||||
|
// 支付域名列表
|
||||||
|
export function getPayDomainList(query) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/pay/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 支付域名刷新解析说明
|
||||||
|
export function refreshPayDomainAnalysis(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/pay/analysis',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 支付域名状态修改
|
||||||
|
export function setPayDomainStatus(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/pay/status',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 支付域名清理缓存
|
||||||
|
export function clearPayDomainCache(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/pay/clear/cache',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 支付域名删除
|
||||||
|
export function delPayDomain(ids) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/pay/' + ids,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 支付域名新增
|
||||||
|
export function addPayDomain(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/pay',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 支付域名修改
|
||||||
|
export function updatePayDomain(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/pay',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 支付域名设为主域名
|
||||||
|
export function setPayDomainMain(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/son/pay/main/son',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------外部白名单域名---------------------//
|
||||||
|
|
||||||
|
// 外部白名单域名列表
|
||||||
|
export function getWhiteDomainList(query) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/white/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 外部白名单域名新增
|
||||||
|
export function addWhiteDomain(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/white',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 外部白名单域名修改
|
||||||
|
export function updateWhiteDomain(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/white',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 外部白名单域名批量修改
|
||||||
|
export function updateWhiteDomainBatch(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/white/all',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 外部白名单域名删除
|
||||||
|
export function delWhiteDomain(ids) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/white/' + ids,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------自定义解析---------------------//
|
||||||
|
|
||||||
|
// 自定义解析列表
|
||||||
|
export function getCustomParsingList(query) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/analysis/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 自定义解析新增
|
||||||
|
export function addCustomParsing(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/analysis',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 自定义解析修改
|
||||||
|
export function updateCustomParsing(data) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/analysis',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 自定义解析删除
|
||||||
|
export function delCustomParsing(ids) {
|
||||||
|
return request({
|
||||||
|
url: '/operation/analysis/' + ids,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
// 域名供应商列表
|
||||||
|
export function getDomainSupplierList(query) {
|
||||||
|
return request({
|
||||||
|
url: '/domain/supplier/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 添加域名供应商
|
||||||
|
export function addDomainSupplier(data) {
|
||||||
|
return request({
|
||||||
|
url: '/domain/supplier',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修改域名供应商
|
||||||
|
export function putDomainSupplier(data) {
|
||||||
|
return request({
|
||||||
|
url: '/domain/supplier',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//供应商详情
|
||||||
|
export function getDomainSupplierInfo(id) {
|
||||||
|
return request({
|
||||||
|
url: `/domain/supplier/${id}`,
|
||||||
|
method: 'get',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 域名供应商开关
|
||||||
|
export function switchDomainSupplier(data) {
|
||||||
|
return request({
|
||||||
|
url: '/domain/supplier/switch',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除域名供应商
|
||||||
|
export function delDomainSupplier(ids) {
|
||||||
|
return request({
|
||||||
|
url: '/domain/supplier/' + ids,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 域名供应商配置
|
||||||
|
export function configDomainSupplier(data) {
|
||||||
|
return request({
|
||||||
|
url: '/domain/supplier/config',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//配置详情
|
||||||
|
export function getDomainSupplierConfig(query) {
|
||||||
|
return request({
|
||||||
|
url: '/domain/supplier/config',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -171,3 +171,29 @@ export function postSiteDeleteApiGame(data) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//站点列表
|
||||||
|
export function getSiteSelectList(query) {
|
||||||
|
return request({
|
||||||
|
url: '/site/select',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//停用
|
||||||
|
export function postSiteStopApiGameInfo(data) {
|
||||||
|
return request({
|
||||||
|
url: '/site/stop/api/game/info',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//启用
|
||||||
|
export function postSiteOpenApiGameInfo(data) {
|
||||||
|
return request({
|
||||||
|
url: '/site/open/api/game/info',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
// 数据源列表
|
||||||
|
export function listDataSource(query) {
|
||||||
|
return request({
|
||||||
|
url: '/site/data/source/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增数据源
|
||||||
|
export function addDataSourceSave(data) {
|
||||||
|
return request({
|
||||||
|
url: '/site/data/source/save',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修改数据源
|
||||||
|
export function updateDataSource(data) {
|
||||||
|
return request({
|
||||||
|
url: '/site/data/source/update',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 修改开关
|
||||||
|
export function switchDataSource(data) {
|
||||||
|
return request({
|
||||||
|
url: '/site/data/source/switch',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -8,6 +8,22 @@ export function listRole(query) {
|
||||||
params: query
|
params: query
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
// 获取角色选择框列表
|
||||||
|
export function optionselect(query) {
|
||||||
|
return request({
|
||||||
|
url: '/system/role/optionselect',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取菜单角色
|
||||||
|
export function getMenu(roleId) {
|
||||||
|
return request({
|
||||||
|
url: '/system/role/getMenu/' + roleId,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// 查询角色详细
|
// 查询角色详细
|
||||||
export function getRole(roleId) {
|
export function getRole(roleId) {
|
||||||
|
|
@ -97,7 +113,15 @@ export function authUserCancelAll(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/role/authUser/cancelAll',
|
url: '/system/role/authUser/cancelAll',
|
||||||
method: 'put',
|
method: 'put',
|
||||||
params: data
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 批量清除关联账号
|
||||||
|
export function authRolecancelAll(data) {
|
||||||
|
return request({
|
||||||
|
url: '/system/role/authRole/cancelAll',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -106,7 +130,7 @@ export function authUserSelectAll(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/role/authUser/selectAll',
|
url: '/system/role/authUser/selectAll',
|
||||||
method: 'put',
|
method: 'put',
|
||||||
params: data
|
data: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,13 +43,36 @@ export function delUser(userId) {
|
||||||
method: 'delete'
|
method: 'delete'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
//删除账户/批量删除
|
||||||
|
export function deleteUserSystem(data) {
|
||||||
|
return request({
|
||||||
|
url: '/system/user/delete',
|
||||||
|
method: 'delete',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//冻结账户
|
||||||
|
export function changeStatus(data) {
|
||||||
|
return request({
|
||||||
|
url: '/system/user/changeStatus',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//清空角色
|
||||||
|
export function resetRole(data) {
|
||||||
|
return request({
|
||||||
|
url: '/system/user/resetRole',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// 用户密码重置
|
// 用户密码重置
|
||||||
export function resetUserPwd(userId, password,codeGoogle) {
|
export function resetUserPwd(userId,inputGoogleCode) {
|
||||||
const data = {
|
const data = {
|
||||||
userId,
|
userId,
|
||||||
password,
|
inputGoogleCode
|
||||||
codeGoogle
|
|
||||||
}
|
}
|
||||||
return request({
|
return request({
|
||||||
url: '/system/user/resetPwd',
|
url: '/system/user/resetPwd',
|
||||||
|
|
@ -58,6 +81,20 @@ export function resetUserPwd(userId, password,codeGoogle) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 用户重置谷歌验证码
|
||||||
|
export function resetGoogle(userId,inputGoogleCode) {
|
||||||
|
const data = {
|
||||||
|
userId,
|
||||||
|
inputGoogleCode
|
||||||
|
}
|
||||||
|
return request({
|
||||||
|
url: '/system/user/resetGoogle',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// 用户状态修改
|
// 用户状态修改
|
||||||
export function changeUserStatus(userId, status) {
|
export function changeUserStatus(userId, status) {
|
||||||
const data = {
|
const data = {
|
||||||
|
|
@ -89,10 +126,11 @@ export function updateUserProfile(data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 用户密码重置
|
// 用户密码重置
|
||||||
export function updateUserPwd(oldPassword, newPassword) {
|
export function updateUserPwd(oldPassword, newPassword,codeGoogle) {
|
||||||
const data = {
|
const data = {
|
||||||
oldPassword,
|
oldPassword,
|
||||||
newPassword
|
newPassword,
|
||||||
|
codeGoogle
|
||||||
}
|
}
|
||||||
return request({
|
return request({
|
||||||
url: '/system/user/profile/updatePwd',
|
url: '/system/user/profile/updatePwd',
|
||||||
|
|
@ -101,6 +139,18 @@ export function updateUserPwd(oldPassword, newPassword) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 修改密码
|
||||||
|
export function updateUserPassword(newPassword) {
|
||||||
|
const data = {
|
||||||
|
newPassword
|
||||||
|
}
|
||||||
|
return request({
|
||||||
|
url: '/system/user/profile/change/password',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// 用户头像上传
|
// 用户头像上传
|
||||||
export function uploadAvatar(data) {
|
export function uploadAvatar(data) {
|
||||||
return request({
|
return request({
|
||||||
|
|
@ -136,11 +186,10 @@ export function deptTreeSelect() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 修改密码
|
// 用户名称检查
|
||||||
export function updateUserPassword(data) {
|
export function getSystemUserCheck(userName) {
|
||||||
return request({
|
return request({
|
||||||
url: '/resetPwd',
|
url: '/system/user/check/' + userName,
|
||||||
method: 'post',
|
method: 'get'
|
||||||
data: data
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,9 @@ a:hover {
|
||||||
div:focus {
|
div:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
li {
|
||||||
|
list-style-type: none;
|
||||||
|
}
|
||||||
.fr {
|
.fr {
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -249,11 +249,14 @@ file_picker_callback: (cb, value, meta) => {
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style>
|
||||||
.tinymce-wrapper {
|
.tinymce-wrapper {
|
||||||
position: relative; /* ✅ 关键 */
|
position: relative; /* ✅ 关键 */
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-height: 500px;
|
min-height: 500px;
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
}
|
}
|
||||||
|
.tox-tinymce-aux {
|
||||||
|
z-index: 2600 !important;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
@ -0,0 +1,155 @@
|
||||||
|
<template>
|
||||||
|
<el-dialog :title="t('上传头像')" v-model="open" width="800px" align-center append-to-body @opened="modalOpened" @close="closeDialog">
|
||||||
|
<el-row>
|
||||||
|
<el-col :xs="24" :md="12" :style="{ height: '350px' }">
|
||||||
|
<vue-cropper ref="cropper" :img="options.img" :info="true" :autoCrop="options.autoCrop"
|
||||||
|
:autoCropWidth="options.autoCropWidth" :autoCropHeight="options.autoCropHeight"
|
||||||
|
:fixedBox="options.fixedBox" :outputType="options.outputType" @realTime="realTime" v-if="visible" />
|
||||||
|
</el-col>
|
||||||
|
<el-col :xs="24" :md="12" :style="{ height: '350px' }">
|
||||||
|
<div class="avatar-upload-preview">
|
||||||
|
<img :src="options.previews.url" :style="options.previews.img" />
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<br />
|
||||||
|
<el-row>
|
||||||
|
<el-col :lg="2" :md="2">
|
||||||
|
<el-upload action="#" :http-request="requestUpload" :show-file-list="false" :before-upload="beforeUpload">
|
||||||
|
<el-button>
|
||||||
|
{{ t('选择') }}
|
||||||
|
<el-icon class="el-icon--right">
|
||||||
|
<Upload />
|
||||||
|
</el-icon>
|
||||||
|
</el-button>
|
||||||
|
</el-upload>
|
||||||
|
</el-col>
|
||||||
|
<el-col :lg="{ span: 1, offset: 2 }" :md="2">
|
||||||
|
<el-button icon="Plus" @click="changeScale(1)"></el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :lg="{ span: 1, offset: 1 }" :md="2">
|
||||||
|
<el-button icon="Minus" @click="changeScale(-1)"></el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :lg="{ span: 1, offset: 1 }" :md="2">
|
||||||
|
<el-button icon="RefreshLeft" @click="rotateLeft()"></el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :lg="{ span: 1, offset: 1 }" :md="2">
|
||||||
|
<el-button icon="RefreshRight" @click="rotateRight()"></el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :lg="{ span: 2, offset: 6 }" :md="2">
|
||||||
|
<el-button type="primary" @click="saveUploadImg()">{{ t('提 交') }}</el-button>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import "vue-cropper/dist/index.css";
|
||||||
|
import { VueCropper } from "vue-cropper";
|
||||||
|
import { uploadImgFile,uploadImgFileCommon } from "@/api/common";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
imgInfo: {
|
||||||
|
type: Object,
|
||||||
|
default: {
|
||||||
|
img: '',
|
||||||
|
filename: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
autoCropWidth: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: 200
|
||||||
|
},
|
||||||
|
autoCropHeight: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: 200
|
||||||
|
},
|
||||||
|
typeUpImg: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: 3
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits(['saveUpload', 'close']);
|
||||||
|
const { proxy } = getCurrentInstance();
|
||||||
|
const open = ref(true);
|
||||||
|
const visible = ref(false);
|
||||||
|
|
||||||
|
//图片裁剪数据
|
||||||
|
const options = reactive({
|
||||||
|
img: props.imgInfo.img, // 裁剪图片的地址
|
||||||
|
autoCrop: true, // 是否默认生成截图框
|
||||||
|
autoCropWidth: props.autoCropWidth, // 默认生成截图框宽度
|
||||||
|
autoCropHeight: props.autoCropHeight, // 默认生成截图框高度
|
||||||
|
fixedBox: true, // 固定截图框大小 不允许改变
|
||||||
|
outputType: "png", // 默认生成截图为PNG格式
|
||||||
|
filename: props.imgInfo.filename, // 文件名称
|
||||||
|
previews: {} //预览数据
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 打开弹出层结束时的回调 */
|
||||||
|
function modalOpened() {
|
||||||
|
visible.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 覆盖默认上传行为 */
|
||||||
|
function requestUpload() { }
|
||||||
|
|
||||||
|
/** 向左旋转 */
|
||||||
|
function rotateLeft() {
|
||||||
|
proxy.$refs.cropper.rotateLeft();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 向右旋转 */
|
||||||
|
function rotateRight() {
|
||||||
|
proxy.$refs.cropper.rotateRight();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 图片缩放 */
|
||||||
|
function changeScale(num) {
|
||||||
|
num = num || 1;
|
||||||
|
proxy.$refs.cropper.changeScale(num);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 上传预处理 */
|
||||||
|
function beforeUpload(file) {
|
||||||
|
if (file.type.indexOf("image/") == -1) {
|
||||||
|
proxy.$modal.msgError(proxy.t('文件格式错误,请上传图片类型,如:JPG,PNG后缀的文件'));
|
||||||
|
} else {
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.readAsDataURL(file);
|
||||||
|
reader.onload = () => {
|
||||||
|
options.img = reader.result;
|
||||||
|
options.filename = file.name;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 上传图片 */
|
||||||
|
function saveUploadImg() {
|
||||||
|
proxy.$refs.cropper.getCropBlob(data => {
|
||||||
|
let formData = new FormData();
|
||||||
|
formData.append("file", data, options.filename);
|
||||||
|
|
||||||
|
uploadImgFileCommon(formData,props.typeUpImg||3).then(res => {
|
||||||
|
open.value = false;
|
||||||
|
visible.value = false;
|
||||||
|
emit('saveUpload', res);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 实时预览 */
|
||||||
|
function realTime(data) {
|
||||||
|
options.previews = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 关闭窗口 */
|
||||||
|
function closeDialog() {
|
||||||
|
open.value = false;
|
||||||
|
visible.value = false;
|
||||||
|
emit('close');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang='scss' scoped></style>
|
||||||
|
|
@ -1,60 +1,58 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="component-upload-image">
|
<div class="component-upload-image">
|
||||||
<el-upload
|
<el-upload multiple :action="uploadImgUrl" :disabled="disabled" list-type="picture-card" :on-success="handleUploadSuccess"
|
||||||
multiple
|
:before-upload="handleBeforeUpload" :limit="limit" :on-error="handleUploadError" :on-exceed="handleExceed"
|
||||||
:action="uploadImgUrl"
|
ref="imageUpload" :before-remove="handleDelete" :show-file-list="true" :headers="headers" :file-list="fileList"
|
||||||
list-type="picture-card"
|
:on-preview="handlePictureCardPreview" :class="{ hide: fileList.length >= limit }">
|
||||||
:on-success="handleUploadSuccess"
|
<el-icon class="avatar-uploader-icon">
|
||||||
:before-upload="handleBeforeUpload"
|
<plus />
|
||||||
:limit="limit"
|
</el-icon>
|
||||||
:on-error="handleUploadError"
|
|
||||||
:on-exceed="handleExceed"
|
|
||||||
ref="imageUpload"
|
|
||||||
:before-remove="handleDelete"
|
|
||||||
:show-file-list="true"
|
|
||||||
:headers="headers"
|
|
||||||
:file-list="fileList"
|
|
||||||
:on-preview="handlePictureCardPreview"
|
|
||||||
:class="{ hide: fileList.length >= limit }"
|
|
||||||
>
|
|
||||||
<el-icon class="avatar-uploader-icon"><plus /></el-icon>
|
|
||||||
</el-upload>
|
</el-upload>
|
||||||
<!-- 上传提示 -->
|
<!-- 上传提示 -->
|
||||||
<div class="el-upload__tip" v-if="showTip">
|
<div class="el-upload__tip" v-if="showTip">
|
||||||
请上传
|
{{ t('请上传') }}
|
||||||
<template v-if="fileSize">
|
<template v-if="fileSize">
|
||||||
大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b>
|
{{ t('大小不超过') }} <b style="color: #f56c6c">{{ fileSize }}MB</b>
|
||||||
</template>
|
</template>
|
||||||
<template v-if="fileType">
|
<template v-if="fileType">
|
||||||
格式为 <b style="color: #f56c6c">{{ fileType.join("/") }}</b>
|
{{ t('格式为') }} <b style="color: #f56c6c">{{ fileType.join("/") }}</b>
|
||||||
</template>
|
</template>
|
||||||
的文件
|
{{ t('的文件') }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-dialog
|
<el-dialog v-model="dialogVisible" :title="t('预览')" width="800px" append-to-body>
|
||||||
v-model="dialogVisible"
|
<img :src="dialogImageUrl" style="display: block; max-width: 100%; margin: 0 auto" />
|
||||||
title="预览"
|
|
||||||
width="800px"
|
|
||||||
append-to-body
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
:src="dialogImageUrl"
|
|
||||||
style="display: block; max-width: 100%; margin: 0 auto"
|
|
||||||
/>
|
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { getToken } from "@/utils/auth";
|
import { getToken, getLocalStorage } from "@/utils/auth";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
disabled: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
modelValue: [String, Object, Array],
|
modelValue: [String, Object, Array],
|
||||||
// 图片数量限制
|
// 图片数量限制
|
||||||
limit: {
|
limit: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: 5,
|
default: 5,
|
||||||
},
|
},
|
||||||
|
// 图片宽高
|
||||||
|
imgSize: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({
|
||||||
|
width: 0,
|
||||||
|
height: 0
|
||||||
|
})
|
||||||
|
},
|
||||||
|
//字符和数字
|
||||||
|
typeUpImg:{
|
||||||
|
type: [Number, String],
|
||||||
|
default: "1"
|
||||||
|
},
|
||||||
// 大小限制(MB)
|
// 大小限制(MB)
|
||||||
fileSize: {
|
fileSize: {
|
||||||
type: Number,
|
type: Number,
|
||||||
|
|
@ -63,13 +61,17 @@ const props = defineProps({
|
||||||
// 文件类型, 例如['png', 'jpg', 'jpeg']
|
// 文件类型, 例如['png', 'jpg', 'jpeg']
|
||||||
fileType: {
|
fileType: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default: () => ["png", "jpg", "jpeg"],
|
default: () => ["png", "jpg", "jpeg", "gif", "webp",'ico','mp4','mp3'],
|
||||||
},
|
},
|
||||||
// 是否显示提示
|
// 是否显示提示
|
||||||
isShowTip: {
|
isShowTip: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: true
|
||||||
},
|
},
|
||||||
|
disabled: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance();
|
const { proxy } = getCurrentInstance();
|
||||||
|
|
@ -78,14 +80,14 @@ const number = ref(0);
|
||||||
const uploadList = ref([]);
|
const uploadList = ref([]);
|
||||||
const dialogImageUrl = ref("");
|
const dialogImageUrl = ref("");
|
||||||
const dialogVisible = ref(false);
|
const dialogVisible = ref(false);
|
||||||
const baseUrl = import.meta.env.VITE_APP_BASE_API;
|
const baseUrl = getLocalStorage('fileUrl');
|
||||||
const uploadImgUrl = ref(import.meta.env.VITE_APP_BASE_API + "/common/upload"); // 上传的图片服务器地址
|
const uploadUrl = getLocalStorage('uploadUrl');
|
||||||
|
const uploadImgUrl = ref(uploadUrl + `/file/upload/localSysFile/${props.typeUpImg}`); // 上传的图片服务器地址
|
||||||
const headers = ref({ Authorization: "Bearer " + getToken() });
|
const headers = ref({ Authorization: "Bearer " + getToken() });
|
||||||
const fileList = ref([]);
|
const fileList = ref([]);
|
||||||
const showTip = computed(
|
const showTip = computed(
|
||||||
() => props.isShowTip && (props.fileType || props.fileSize)
|
() => props.isShowTip && (props.fileType || props.fileSize)
|
||||||
);
|
);
|
||||||
|
|
||||||
watch(() => props.modelValue, val => {
|
watch(() => props.modelValue, val => {
|
||||||
if (val) {
|
if (val) {
|
||||||
// 首先将值转为数组
|
// 首先将值转为数组
|
||||||
|
|
@ -105,11 +107,13 @@ watch(() => props.modelValue, val => {
|
||||||
fileList.value = [];
|
fileList.value = [];
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
},{ deep: true, immediate: true });
|
}, { deep: true, immediate: true });
|
||||||
|
|
||||||
// 上传前loading加载
|
// 上传前loading加载
|
||||||
function handleBeforeUpload(file) {
|
function handleBeforeUpload(file) {
|
||||||
let isImg = false;
|
let isImg = false;
|
||||||
|
|
||||||
|
// 检查图片类型
|
||||||
if (props.fileType.length) {
|
if (props.fileType.length) {
|
||||||
let fileExtension = "";
|
let fileExtension = "";
|
||||||
if (file.name.lastIndexOf(".") > -1) {
|
if (file.name.lastIndexOf(".") > -1) {
|
||||||
|
|
@ -123,12 +127,15 @@ function handleBeforeUpload(file) {
|
||||||
} else {
|
} else {
|
||||||
isImg = file.type.indexOf("image") > -1;
|
isImg = file.type.indexOf("image") > -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isImg) {
|
if (!isImg) {
|
||||||
proxy.$modal.msgError(
|
proxy.$modal.msgError(
|
||||||
`文件格式不正确, 请上传${props.fileType.join("/")}图片格式文件!`
|
`文件格式不正确, 请上传${props.fileType.join("/")}图片格式文件!`
|
||||||
);
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检查图片大小
|
||||||
if (props.fileSize) {
|
if (props.fileSize) {
|
||||||
const isLt = file.size / 1024 / 1024 < props.fileSize;
|
const isLt = file.size / 1024 / 1024 < props.fileSize;
|
||||||
if (!isLt) {
|
if (!isLt) {
|
||||||
|
|
@ -136,8 +143,29 @@ function handleBeforeUpload(file) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检查图片宽高
|
||||||
|
const checkSize = new Promise(function (resolve, reject) {
|
||||||
|
// 希望的宽
|
||||||
|
let width = props.imgSize.width;
|
||||||
|
// 希望的高
|
||||||
|
let height = props.imgSize.height;
|
||||||
|
let _URL = window.URL || window.webkitURL;
|
||||||
|
let img = new Image();
|
||||||
|
img.onload = function () {
|
||||||
|
let valid = img.width == width && img.height == height;
|
||||||
|
// 符合要求 或者 没有限制宽高
|
||||||
|
valid || (width === 0 && height === 0) ? resolve() : reject();
|
||||||
|
}
|
||||||
|
img.src = _URL.createObjectURL(file);
|
||||||
|
}).then(() => {
|
||||||
proxy.$modal.loading("正在上传图片,请稍候...");
|
proxy.$modal.loading("正在上传图片,请稍候...");
|
||||||
number.value++;
|
number.value++;
|
||||||
|
}, () => {
|
||||||
|
proxy.$modal.msgError(`上传图片尺寸必须为${props.imgSize.width}x${props.imgSize.height}px!`);
|
||||||
|
return Promise.reject();
|
||||||
|
});
|
||||||
|
return checkSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 文件个数超出
|
// 文件个数超出
|
||||||
|
|
@ -148,7 +176,7 @@ function handleExceed() {
|
||||||
// 上传成功回调
|
// 上传成功回调
|
||||||
function handleUploadSuccess(res, file) {
|
function handleUploadSuccess(res, file) {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
uploadList.value.push({ name: res.fileName, url: res.fileName });
|
uploadList.value.push({ name: res.fileName, url: res.url });
|
||||||
uploadedSuccessfully();
|
uploadedSuccessfully();
|
||||||
} else {
|
} else {
|
||||||
number.value--;
|
number.value--;
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,9 @@
|
||||||
@clear="handleQuery" :maxlength="inputConfig.maxlength" :isCalculable="false" :show-word-limit="inputConfig.showWordLimit">
|
@clear="handleQuery" :maxlength="inputConfig.maxlength" :isCalculable="false" :show-word-limit="inputConfig.showWordLimit">
|
||||||
</NumberInput>
|
</NumberInput>
|
||||||
<!-- 下拉选择框字典放到inputConfig.dictKey -->
|
<!-- 下拉选择框字典放到inputConfig.dictKey -->
|
||||||
<custom-select v-else-if="inputType === 'select'" :placeholder="t(inputPlaceholder || `请选择${currentLabel}`)" v-model="queryParams[queryParams[keyName]]" @change="handleQuery" clearable
|
<custom-select v-else-if="inputType === 'select' && loadingShow" filterable :placeholder="t(inputPlaceholder || `请选择${currentLabel}`)" v-model="queryParams[queryParams[keyName]]" @change="handleQuery" clearable
|
||||||
@clear="handleQuery" :options="inputConfig.options"></custom-select>
|
@clear="handleQuery" :options="inputConfig.options"></custom-select>
|
||||||
|
|
||||||
<!-- 普通输入框 -->
|
<!-- 普通输入框 -->
|
||||||
<el-input v-else v-model="queryParams[queryParams[keyName]]"
|
<el-input v-else v-model="queryParams[queryParams[keyName]]"
|
||||||
:placeholder="t(inputPlaceholder || `请输入${currentLabel}`)" @keyup.enter="handleQuery" clearable
|
:placeholder="t(inputPlaceholder || `请输入${currentLabel}`)" @keyup.enter="handleQuery" clearable
|
||||||
|
|
@ -55,6 +56,7 @@ const currentLabel = ref(''), inputPlaceholder = ref(''); // 输入框提示
|
||||||
const inputType = ref(''); // 输入框类型
|
const inputType = ref(''); // 输入框类型
|
||||||
const inputConfig = ref({}); // input框配置
|
const inputConfig = ref({}); // input框配置
|
||||||
|
|
||||||
|
const loadingShow = ref(true);
|
||||||
// 参数切换
|
// 参数切换
|
||||||
const keyChange = (type) => {
|
const keyChange = (type) => {
|
||||||
props.queryParamsList.forEach(item => {
|
props.queryParamsList.forEach(item => {
|
||||||
|
|
@ -69,6 +71,10 @@ const keyChange = (type) => {
|
||||||
// value和输入框配置
|
// value和输入框配置
|
||||||
inputType.value = item.inputType || '';
|
inputType.value = item.inputType || '';
|
||||||
inputConfig.value = item.inputConfig || {}
|
inputConfig.value = item.inputConfig || {}
|
||||||
|
loadingShow.value = false;
|
||||||
|
nextTick(() => {
|
||||||
|
loadingShow.value = true;
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
// 把其他的值清空
|
// 把其他的值清空
|
||||||
queryParams.value[item.value] = null
|
queryParams.value[item.value] = null
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import { isHttp } from '@/utils/validate'
|
||||||
import { isRelogin } from '@/utils/request'
|
import { isRelogin } from '@/utils/request'
|
||||||
import useUserStore from '@/store/modules/user'
|
import useUserStore from '@/store/modules/user'
|
||||||
import useSettingsStore from '@/store/modules/settings'
|
import useSettingsStore from '@/store/modules/settings'
|
||||||
import { getLangSelect,getTimeZone,getCurrencySelect,getMaterialGroupSelect } from '@/api/siteManagement'
|
import { getLangSelect,getTimeZone,getCurrencySelect,getMaterialGroupSelect,getSiteSelectList } from '@/api/siteManagement'
|
||||||
import usePermissionStore from '@/store/modules/permission'
|
import usePermissionStore from '@/store/modules/permission'
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -41,6 +41,16 @@ router.beforeEach((to, from, next) => {
|
||||||
getCurrencySelect().then((resCurrency) => {
|
getCurrencySelect().then((resCurrency) => {
|
||||||
setLocalStorage('currencySelect', resCurrency.data);
|
setLocalStorage('currencySelect', resCurrency.data);
|
||||||
})
|
})
|
||||||
|
getSiteSelectList().then((resSite) => {
|
||||||
|
let siteSelect = resSite.data.map((item) => {
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
value: item.id,
|
||||||
|
label: item.siteName,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
setLocalStorage('siteSelect', siteSelect);
|
||||||
|
})
|
||||||
useUserStore().getDict().then(res => {
|
useUserStore().getDict().then(res => {
|
||||||
setLocalStorage('dict', res.data);
|
setLocalStorage('dict', res.data);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@
|
||||||
<el-dialog v-model="goodDialogVisible" align-center :title="t('温馨提示')" width="418" :before-close="handleClose">
|
<el-dialog v-model="goodDialogVisible" align-center :title="t('温馨提示')" width="418" :before-close="handleClose">
|
||||||
<div style="width: 90%;margin-bottom: 20px;">{{ t('请用手机打开客服端Google身份验证器,输入验证码') }}</div>
|
<div style="width: 90%;margin-bottom: 20px;">{{ t('请用手机打开客服端Google身份验证器,输入验证码') }}</div>
|
||||||
<div class="">
|
<div class="">
|
||||||
<number-input v-model="gooleCode" style="width: 90%" :placeholder="t('验证码只能为数字')" ></number-input>
|
<number-input v-model="gooleCode" style="width: 90%" :maxlength="6" :placeholder="t('验证码只能为数字')" ></number-input>
|
||||||
</div>
|
</div>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="dialog-footer">
|
<div class="dialog-footer">
|
||||||
|
|
@ -90,7 +90,7 @@
|
||||||
</div>
|
</div>
|
||||||
<el-form ref="authenticatorRef" :model="authenticatorForm" :rules="authenticatorRules">
|
<el-form ref="authenticatorRef" :model="authenticatorForm" :rules="authenticatorRules">
|
||||||
<el-form-item label="谷歌验证码" prop="authenticatorCode">
|
<el-form-item label="谷歌验证码" prop="authenticatorCode">
|
||||||
<number-input v-model="authenticatorForm.authenticatorCode" style="width: 100%;height: 36px;" :placeholder="t('验证码只能为数字')" ></number-input>
|
<number-input v-model="authenticatorForm.authenticatorCode" :maxlength="6" style="width: 100%;height: 36px;" :placeholder="t('验证码只能为数字')" ></number-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<div class="" style="margin-top: 20px;margin-bottom: 20px;">
|
<div class="" style="margin-top: 20px;margin-bottom: 20px;">
|
||||||
|
|
|
||||||
|
|
@ -120,12 +120,26 @@ const currencySelectArr = getLocalStorage('currencySelect')?.map(item => {
|
||||||
});
|
});
|
||||||
const openView = ref(false);
|
const openView = ref(false);
|
||||||
|
|
||||||
|
const siteList = ref(getLocalStorage('siteSelect'));
|
||||||
const queryParamsList = ref([{
|
const queryParamsList = ref([{
|
||||||
label: proxy.t('站点名称'),
|
label: proxy.t('站点名称'),
|
||||||
value: 'siteName',
|
value: 'siteName',
|
||||||
|
inputType: 'select',
|
||||||
|
inputConfig:{
|
||||||
|
options: siteList.value.map(item => {
|
||||||
|
return {
|
||||||
|
label: item.label,
|
||||||
|
value: item.label,
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
}
|
||||||
},{
|
},{
|
||||||
label: proxy.t('站点ID'),
|
label: proxy.t('站点ID'),
|
||||||
value: 'siteId',
|
value: 'siteId',
|
||||||
|
inputType: 'select',
|
||||||
|
inputConfig:{
|
||||||
|
options: siteList.value,
|
||||||
|
}
|
||||||
}]);
|
}]);
|
||||||
const data = reactive({
|
const data = reactive({
|
||||||
form: {},
|
form: {},
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,47 @@
|
||||||
<template>
|
<template>
|
||||||
<!-- 厅主公告详情 -->
|
<!-- 详情 -->
|
||||||
<el-dialog :title="t('厅主公告详情')" :close-on-click-modal="false" align-center v-model="showDialog" width="900px" append-to-body>
|
<el-dialog :title="t('详情')" :close-on-click-modal="false" align-center v-model="showDialog" width="900px" append-to-body>
|
||||||
<el-scrollbar max-height="700px" >
|
<el-scrollbar max-height="700px" >
|
||||||
<div style="font-size: 20px; font-weight: bold; margin-bottom: 20px;width: 100%;text-align: center;">{{ modifyDate.title }}</div>
|
<div style="font-size: 20px; font-weight: bold; margin-bottom: 20px;width: 100%;text-align: center;">{{ modifyDate.title }}</div>
|
||||||
|
|
||||||
<el-descriptions :column="1">
|
<el-descriptions :column="1" border label-width="150px">
|
||||||
<el-descriptions-item label="公告类型">
|
<el-descriptions-item label-class-name="label-class-name" label="会员ID">
|
||||||
<span v-if="modifyDate.noticeType == 1">{{ t('日常公告') }}</span>
|
|
||||||
<span v-if="modifyDate.noticeType == 2">{{ t('不停机维护') }}</span>
|
{{ modifyDate.id }}
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
<el-descriptions-item label="发送时间">
|
<el-descriptions-item label-class-name="label-class-name" label="会员账号">
|
||||||
{{ parseTime(modifyDate.noticeStartTime) }}
|
{{ modifyDate.memberAccount }}
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
<el-descriptions-item label="公告状态">
|
<el-descriptions-item label-class-name="label-class-name" label="币种">
|
||||||
<dict-tag :options="noticeStatusArr" :value="modifyDate.noticeStatus" />
|
{{ modifyDate.currencyType }}
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
<el-descriptions-item label="内容">
|
<el-descriptions-item label-class-name="label-class-name" label="LineCode">
|
||||||
<div style="width: 100%;overflow: hidden;">
|
--
|
||||||
<div v-html="modifyDate.content"></div>
|
</el-descriptions-item>
|
||||||
</div>
|
<el-descriptions-item label-class-name="label-class-name" label="所属站点(ID)">
|
||||||
|
{{ modifyDate.siteName }}({{ modifyDate.siteId }})
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label-class-name="label-class-name" label="总余额">
|
||||||
|
{{ modifyDate.balance==null?'--':modifyDate.balance }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label-class-name="label-class-name" label="总输赢">
|
||||||
|
{{ modifyDate.failAndWin== null ? '--' : modifyDate.failAndWin }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label-class-name="label-class-name" label="总打码">
|
||||||
|
{{ modifyDate.betAmount == null ?'--': modifyDate.betAmount }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label-class-name="label-class-name" label="在线状态">
|
||||||
|
<span v-if="modifyDate.presenceStatus== 0">离线</span>
|
||||||
|
<span v-if="modifyDate.presenceStatus== 1">在线</span>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label-class-name="label-class-name" label="最后登录">
|
||||||
|
{{ formatTime(modifyDate.loginDate) }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label-class-name="label-class-name" label="注册时间">
|
||||||
|
{{ formatTime(modifyDate.registeTime) }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label-class-name="label-class-name" label="备注">
|
||||||
|
{{ modifyDate.remark == null ? '--' : modifyDate.remark }}
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
|
|
||||||
</el-descriptions>
|
</el-descriptions>
|
||||||
|
|
@ -159,6 +182,10 @@ const closeDialog = () => {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.label-class-name{
|
||||||
|
width: 180px;
|
||||||
|
text-align: right !important;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
<style >
|
<style >
|
||||||
.el-form-ge .el-form-item__content{
|
.el-form-ge .el-form-item__content{
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column :label="t('所属站点(ID)')" min-width="100" align="center" >
|
<el-table-column :label="t('所属站点(ID)')" min-width="100" align="center" >
|
||||||
<template #default="{row}">
|
<template #default="{row}">
|
||||||
{{ row.siteName }}
|
{{ row.siteName }}({{ row.siteId }})
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column :label="t('币种')" min-width="100" align="center" prop="currencyType" >
|
<el-table-column :label="t('币种')" min-width="100" align="center" prop="currencyType" >
|
||||||
|
|
@ -309,7 +309,7 @@ const getSiteSelects = () => {
|
||||||
|
|
||||||
const handleView = (row) => {
|
const handleView = (row) => {
|
||||||
openView.value = true;
|
openView.value = true;
|
||||||
// modifyDate.value = row;
|
modifyDate.value = row;
|
||||||
}
|
}
|
||||||
/** 搜索按钮操作 */
|
/** 搜索按钮操作 */
|
||||||
function handleQuery() {
|
function handleQuery() {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,267 @@
|
||||||
|
<template>
|
||||||
|
<div class="tp-content-box">
|
||||||
|
<el-tabs v-model="activeName" @tab-change="handleChange">
|
||||||
|
<el-tab-pane name="1" :label="t('男头像')"></el-tab-pane>
|
||||||
|
<el-tab-pane name="2" :label="t('女头像')"></el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
|
||||||
|
<!-- 列表组件 -->
|
||||||
|
<div class="cpt-main">
|
||||||
|
<div class="avatar-list">
|
||||||
|
<li v-for="item in dataList" :key="item.id">
|
||||||
|
<img :class="item.stopStatus !== 1 ? 'img-disable' : ''" :src="fileHost + item.imgUrl">
|
||||||
|
<span class="img-tag" v-if="item.systemType"></span>
|
||||||
|
<div class="mask-box mb-disable" v-if="item.stopStatus !== 1">
|
||||||
|
<p class="disable-text">{{ t('已停用') }}</p>
|
||||||
|
</div>
|
||||||
|
<div class="mask-box mb-btn">
|
||||||
|
<el-button @click="changeStatus(item, 0)" v-if="item.stopStatus === 1 && item.systemType"
|
||||||
|
type="danger">{{
|
||||||
|
t('停用') }}</el-button>
|
||||||
|
<el-button @click="changeStatus(item, 1)" v-if="item.stopStatus === 0 && item.systemType"
|
||||||
|
type="success">{{
|
||||||
|
t('启用') }}</el-button>
|
||||||
|
<el-button v-if="!item.systemType" type="info" @click="deleteAvatar(item)">{{ t('删除') }}</el-button>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li style="border: #dddddd dashed 1px;">
|
||||||
|
<div class="upload-box">
|
||||||
|
<el-upload action="#" :http-request="requestUpload" :show-file-list="false"
|
||||||
|
:before-upload="beforeUpload">
|
||||||
|
<el-icon color="#666666" size="26">
|
||||||
|
<Plus />
|
||||||
|
</el-icon>
|
||||||
|
<div class="upload-tips">
|
||||||
|
<div>{{ t('图标大小200*200') }}</div>
|
||||||
|
<div>{{ t('PNG或JPG格式') }}</div>
|
||||||
|
</div>
|
||||||
|
</el-upload>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 头像上传裁剪 -->
|
||||||
|
<image-crop v-if="isShowCrop" :imgInfo="uploadInfo" @saveUpload="saveUpload" @close="isShowCrop = false"></image-crop>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 头像管理 -->
|
||||||
|
<script setup name="Avatar">
|
||||||
|
import ImageCrop from "@/components/ImageCrop/index.vue";
|
||||||
|
import { getLocalStorage } from "@/utils/auth";
|
||||||
|
import { listAvatar, addAvatar, delAvatar, updateAvatar } from "@/api/operation/avatar";
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance();
|
||||||
|
const activeName = ref('1'); // 当前tab页
|
||||||
|
|
||||||
|
// 获取头像列表
|
||||||
|
const queryParams = reactive({
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 200,
|
||||||
|
sex: '1'
|
||||||
|
});
|
||||||
|
const dataList = ref([]), loading = ref(false);
|
||||||
|
|
||||||
|
// 男女头像切换
|
||||||
|
const handleChange = () => {
|
||||||
|
queryParams.sex = activeName.value;
|
||||||
|
getAvatarList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 请求头像列表
|
||||||
|
const getAvatarList = () => {
|
||||||
|
loading.value = true;
|
||||||
|
listAvatar(queryParams).then(res => {
|
||||||
|
dataList.value = res.rows;
|
||||||
|
loading.value = false;
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
getAvatarList();
|
||||||
|
|
||||||
|
// 图片上传
|
||||||
|
const fileHost = getLocalStorage('fileUrl') || ''; // 文件host
|
||||||
|
const isShowCrop = ref(false);
|
||||||
|
const uploadInfo = ref({
|
||||||
|
img: '',
|
||||||
|
filename: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
// 覆盖默认上传行为
|
||||||
|
function requestUpload() { }
|
||||||
|
|
||||||
|
// 上传预处理
|
||||||
|
function beforeUpload(file) {
|
||||||
|
if (file.type.indexOf("image/") == -1) {
|
||||||
|
proxy.$modal.msgError(proxy.t('文件格式错误,请上传图片类型,如:JPG,PNG后缀的文件'));
|
||||||
|
} else {
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.readAsDataURL(file);
|
||||||
|
reader.onload = () => {
|
||||||
|
uploadInfo.value.img = reader.result;
|
||||||
|
uploadInfo.value.filename = file.name;
|
||||||
|
isShowCrop.value = true; // 去裁剪
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增头像
|
||||||
|
const saveUpload = (data) => {
|
||||||
|
const params = {
|
||||||
|
imgUrl: data.url,
|
||||||
|
sex: activeName.value
|
||||||
|
}
|
||||||
|
addAvatar(params).then(res => {
|
||||||
|
isShowCrop.value = false;
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('头像新增成功'));
|
||||||
|
getAvatarList();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 头像启用停用
|
||||||
|
const changeStatus = (row, status) => {
|
||||||
|
proxy.$modal.confirm(proxy.t('确认{}该头像吗?', status === 0 ? '停用' : '启用')).then(() => {
|
||||||
|
const params = {
|
||||||
|
imgUrl: row.imgUrl,
|
||||||
|
sex: row.sex,
|
||||||
|
id: row.id,
|
||||||
|
stopStatus: status
|
||||||
|
}
|
||||||
|
|
||||||
|
updateAvatar(params).then(res => {
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('{}头像成功!', status === 0 ? '停用' : '启用'));
|
||||||
|
getAvatarList();
|
||||||
|
})
|
||||||
|
}).catch(() => { });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除头像
|
||||||
|
const deleteAvatar = (row) => {
|
||||||
|
proxy.$modal.confirm(proxy.t('确认删除该头像吗?')).then(() => {
|
||||||
|
delAvatar(row.id).then(res => {
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('删除头像成功!'));
|
||||||
|
getAvatarList();
|
||||||
|
})
|
||||||
|
}).catch(() => { });
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang='scss'>
|
||||||
|
.tp-content-box {
|
||||||
|
padding: 15px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
.cpt-main {
|
||||||
|
height: calc(100% - 55px);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.avatar-list {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
li {
|
||||||
|
min-width: 140px;
|
||||||
|
min-height: 140px;
|
||||||
|
width: calc(10% - 10px);
|
||||||
|
margin: 5px;
|
||||||
|
position: relative;
|
||||||
|
border-radius: 16px;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
object-fit: contain;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.img-disable {
|
||||||
|
filter: grayscale(100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
.mask-box {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb-disable {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.img-tag {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 30%;
|
||||||
|
height: 30%;
|
||||||
|
background: url(../../../assets/images/avatar-tag.png) no-repeat right top;
|
||||||
|
background-size: contain;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mask-box {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
background-color: rgba(0, 0, 0, .6);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
transition: all .2s ease-in-out;
|
||||||
|
|
||||||
|
.disable-text {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
color: #b90505;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 8px 0;
|
||||||
|
background-color: #ffffff;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb-disable{
|
||||||
|
background-color: rgba(0, 0, 0, .3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb-btn {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-box {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
>div {
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-upload) {
|
||||||
|
height: 100%;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-tips {
|
||||||
|
text-align: center;
|
||||||
|
width: 100%;
|
||||||
|
color: #999;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.5;
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,382 @@
|
||||||
|
<template>
|
||||||
|
<!-- 新增子域名 -->
|
||||||
|
<el-dialog :title="t('新增域名')" v-model="isShowDialog" width="800px" append-to-body @close="closeDialog">
|
||||||
|
<el-scrollbar max-height="600px" v-loading="loading">
|
||||||
|
<el-form ref="formRef" :rules="rules" :model="formData" label-width="120" class="mr0">
|
||||||
|
<el-form-item label-width="0" prop="domainSupplierId" class="clt-item">
|
||||||
|
<span slot="label" class="label-box">
|
||||||
|
<i style="color: #f56c6c; margin-right: 4px;">*</i>{{ t('选择节点') }}
|
||||||
|
<icon-tips>
|
||||||
|
<div class="node-tips">
|
||||||
|
<p>{{ t('(1)中国市场(含港澳台):推荐使用alb域名(aws防封)、三方公共域名(aws与azure防封)、Wangsu (CDN+IP)、A8、Yundun(云盾)、Funnull(方能)、superEdge、大陆阿里云。')}}</p>
|
||||||
|
<p>{{ t('(2)全球市场(即非中国):推荐使用使用alb域名(aws与aliyun防封)、三方公共域名(aws与azure防封)、AWS、CF、腾讯云、 阿里云、Google、Azure、华为云 、Wangsu(CDN+IP)、Yundun (云盾)。')}}</p>
|
||||||
|
<p>{{ t('(3)Wangsu独立IP:提供独立IP地址,适用于会封禁域名,但不会封禁IP的国家(例如:印尼、中国、巴西、越南等),国际和中国大陆市场均可使用(即全球通用200USDT/IP/月),若超过7天未启用系统自动回收。') }}
|
||||||
|
</p>
|
||||||
|
<p>{{ t('(4)开放回源(仅限web大厅):提供开放独立源服务,可使用外部三方CDN,需申请开通(300U/月),需要专业人士配置websocket、HTTP2、缓存等,详见域名管理教程。') }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</icon-tips>:
|
||||||
|
</span>
|
||||||
|
<div class="item-right">
|
||||||
|
<supplier-select v-model="formData.domainSupplierId" @change="supplierChange"
|
||||||
|
:supplierList="supplierList" type="addSonDomain"></supplier-select>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="t('选择域名:')" prop="domainId" class="mr0">
|
||||||
|
<!-- 非防封 -->
|
||||||
|
<checkbox-select v-if="!nodeProhibitStatus" class="w100" :disabled="!supplierDomainList.length"
|
||||||
|
:options="supplierDomainList" v-model="formData.domainId" :placeholder="t('节点下域名')"
|
||||||
|
@change="selectDomain" @allSelect="selectDomain"></checkbox-select>
|
||||||
|
|
||||||
|
<!-- 防封 -->
|
||||||
|
<el-checkbox-group v-else v-model="formData.domainId" style="width: 100%" @change="selectDomain">
|
||||||
|
<template v-for="item in supplierDomainList" :key="item.value">
|
||||||
|
<el-checkbox :value="item.value" :label="item.label">
|
||||||
|
{{ item.label }}
|
||||||
|
<icon-tips trigger="hover" v-if="item.value == -1 || item.value == -2">
|
||||||
|
{{ item.value == -1 ? t('由系统固定分配独立ALB域名与端口,启用成功开始计费') : t('由系统随机分配云平台原生域名,启用成功开始计费') }}
|
||||||
|
</icon-tips>
|
||||||
|
</el-checkbox>
|
||||||
|
</template>
|
||||||
|
</el-checkbox-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="t('域名用途:')" class="mr0">
|
||||||
|
{{ domainTypeName }}
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="t('生效域名:')" prop="domainNames" class="mr0">
|
||||||
|
<span v-if="!formData.domainNames.length">
|
||||||
|
{{ t('您当前未添加域名,请先到') }}
|
||||||
|
<el-button link type="primary" @click="goDomainManage">{{ t('域名管理') }}</el-button>
|
||||||
|
{{ t('添加主域名和验证后再来设置') }}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<!-- 生效域名增删 -->
|
||||||
|
<template v-else>
|
||||||
|
<el-row v-for="(item, index) in formData.domainNames" :key="index" class="domain-list">
|
||||||
|
<el-col :span="18" class="et-col">
|
||||||
|
<el-form-item :prop="`domainNames[${index}].sonTitle`" :rules="rules.sonTitle" class="w100 mr0"
|
||||||
|
label-width="0">
|
||||||
|
<el-input v-model="item.sonTitle" :placeholder="t('例如:* 或 @ 或 www')" clearable>
|
||||||
|
<template #append><b>.</b>{{ item.sonDomain }}</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6" style="text-align: right;">
|
||||||
|
<el-button type="primary" icon="Plus" style="margin-right: 10px;"
|
||||||
|
@click="setDomainName(index, 'add')" />
|
||||||
|
<el-button icon="Close" style="margin-left: 0;" @click="setDomainName(index, 'delete')" />
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</template>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-scrollbar>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button @click="closeDialog">{{ t('关 闭') }}</el-button>
|
||||||
|
<el-button type="primary" @click="submitForm" :loading="loading">{{ t('确 认') }}</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="AddSonDomain">
|
||||||
|
import SupplierSelect from '../components/SupplierSelect.vue';
|
||||||
|
import IconTips from "@/components/IconTips"; // 小图标提示
|
||||||
|
import CheckboxSelect from "@/components/CheckboxSelect"; // 下拉多选框
|
||||||
|
import {
|
||||||
|
getSupplierDomainList, // 供应商节点下域名
|
||||||
|
addWebDomain, // 添加web大厅域名
|
||||||
|
addBackendDomain, // 添加后端加速域名
|
||||||
|
addAppDomain, // 添加app大厅域名
|
||||||
|
addOssDomain, // 添加oss域名
|
||||||
|
addDownloadDomain, // 添加下载站域名
|
||||||
|
addPayDomain, // 添加支付域名
|
||||||
|
}
|
||||||
|
from "@/api/operation/domain";
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance();
|
||||||
|
const loading = ref(false);
|
||||||
|
const isShowDialog = ref(true); // 弹窗是否显示
|
||||||
|
const formRef = ref();
|
||||||
|
|
||||||
|
// 接收参数
|
||||||
|
const props = defineProps({
|
||||||
|
supplierList: {
|
||||||
|
type: Array,
|
||||||
|
default: []
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 域名用途
|
||||||
|
const domainTypeName = computed(() => {
|
||||||
|
if (props.type == 'webHall') {
|
||||||
|
return proxy.t('Web大厅域名');
|
||||||
|
} else if (props.type == 'backend') {
|
||||||
|
return proxy.t('后端加速域名');
|
||||||
|
} else if (props.type == 'appHall') {
|
||||||
|
return proxy.t('App大厅域名');
|
||||||
|
} else if (props.type == 'oss') {
|
||||||
|
return proxy.t('OSS加速域名');
|
||||||
|
} else if (props.type == 'downloadSite') {
|
||||||
|
return proxy.t('下载站域名');
|
||||||
|
} else if (props.type == 'payment') {
|
||||||
|
return proxy.t('支付域名');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 表单参数
|
||||||
|
const formData = reactive({
|
||||||
|
domainSupplierId: '',
|
||||||
|
domainId: [],
|
||||||
|
domainNames: []
|
||||||
|
});
|
||||||
|
|
||||||
|
// 表单校验
|
||||||
|
const rules = reactive({
|
||||||
|
domainSupplierId: [
|
||||||
|
{ required: true, message: proxy.t('请选择节点'), trigger: 'change' },
|
||||||
|
],
|
||||||
|
domainId: [
|
||||||
|
{ required: true, message: proxy.t('请选择域名'), trigger: 'change' }
|
||||||
|
],
|
||||||
|
sonTitle: [
|
||||||
|
{ required: true, message: proxy.t('请输入子域名'), trigger: ['change', 'blur'] },
|
||||||
|
{
|
||||||
|
pattern: /^[\w\*@]+$/,
|
||||||
|
message: proxy.t('只能包含字母、数字、下划线、星号和@'),
|
||||||
|
trigger: ['change', 'blur']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
validator: (rule, value, callback) => {
|
||||||
|
const _index = +rule.field.toString().match(/\d+/)[0], _domainNames = formData.domainNames;
|
||||||
|
let isHas = false;
|
||||||
|
|
||||||
|
_domainNames.forEach((item, index) => {
|
||||||
|
if (index != _index && item.sonTitle != '' && item.sonTitle + '.' + item.sonDomain == _domainNames[_index].sonTitle + '.' + _domainNames[_index].sonDomain) {
|
||||||
|
isHas = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (isHas) {
|
||||||
|
callback(new Error(proxy.t('子域名不能重复')));
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
trigger: ['change', 'blur']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
// 选择供应商节点
|
||||||
|
const supplierDomainList = ref([]),
|
||||||
|
nodeProhibitStatus = ref(false); // 当前节点是否防封
|
||||||
|
const supplierChange = (val) => {
|
||||||
|
// 清空表单
|
||||||
|
formData.domainId = [];
|
||||||
|
formData.domainNames = [];
|
||||||
|
|
||||||
|
// 查找当前节点是否防封
|
||||||
|
nodeProhibitStatus.value = props.supplierList.find(v => v.id == val).prohibit;
|
||||||
|
|
||||||
|
getSupplierDomainList({ domainSupplierId: val }).then(res => {
|
||||||
|
supplierDomainList.value = res.data.map(v => {
|
||||||
|
return {
|
||||||
|
label: v.name,
|
||||||
|
value: v.id
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 如果是防封节点,则增加选项
|
||||||
|
if (nodeProhibitStatus.value) {
|
||||||
|
const _domainList = [{
|
||||||
|
label: proxy.t('三方公共域名(防封)'),
|
||||||
|
value: '-2'
|
||||||
|
}];
|
||||||
|
|
||||||
|
// 如果是web大厅则增加选项
|
||||||
|
if (props.type == 'webHall') {
|
||||||
|
_domainList.unshift({
|
||||||
|
label: proxy.t('ALB防封域名'),
|
||||||
|
value: '-1'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
supplierDomainList.value = [..._domainList, ...supplierDomainList.value];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 选择域名
|
||||||
|
const selectDomain = (val) => {
|
||||||
|
const _domainNames = [];
|
||||||
|
|
||||||
|
// 查找当前选中的域名信息
|
||||||
|
val.forEach(thisId => {
|
||||||
|
if (thisId != -1 && thisId != -2) { // 防封状态没有子域名
|
||||||
|
const domainInfo = supplierDomainList.value.find(v => v.value == thisId);
|
||||||
|
let isHas = false;
|
||||||
|
|
||||||
|
// 查找当前选中的域名是否已存在
|
||||||
|
formData.domainNames.forEach(item => {
|
||||||
|
if (item.domainId == domainInfo.value) {
|
||||||
|
isHas = true;
|
||||||
|
_domainNames.push({...item});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 不存在则新增
|
||||||
|
if (!isHas) {
|
||||||
|
_domainNames.push({
|
||||||
|
domainId: thisId,
|
||||||
|
sonTitle: '',
|
||||||
|
sonDomain: domainInfo.label
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
formData.domainNames = _domainNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 子域名增删
|
||||||
|
const setDomainName = (index, type) => {
|
||||||
|
if (type === 'add') {
|
||||||
|
// 当前位置后面复制一份
|
||||||
|
const copyItem = JSON.parse(JSON.stringify(formData.domainNames[index]));
|
||||||
|
|
||||||
|
copyItem.sonTitle = '';
|
||||||
|
formData.domainNames.splice(index + 1, 0, copyItem);
|
||||||
|
} else {
|
||||||
|
// 如果当前domainNames记录删完了,则删除对应formData.domainId
|
||||||
|
const _domainNameId = formData.domainNames[index].domainId;
|
||||||
|
|
||||||
|
formData.domainNames.splice(index, 1);
|
||||||
|
formData.domainNames.findIndex(v => v.domainId == _domainNameId) == -1 && formData.domainId.splice(formData.domainId.findIndex(v => v == _domainNameId), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交
|
||||||
|
const submitForm = () => {
|
||||||
|
formRef.value.validate(valid => {
|
||||||
|
if (valid) {
|
||||||
|
// 组装参数
|
||||||
|
const operationDomainSons = [];
|
||||||
|
|
||||||
|
// 防封状态
|
||||||
|
formData.domainId.forEach(item => {
|
||||||
|
if (item == -1 || item == -2) {
|
||||||
|
operationDomainSons.push({
|
||||||
|
domainSupplierId: formData.domainSupplierId,
|
||||||
|
domainId: item
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 非防封状态
|
||||||
|
formData.domainNames.forEach(item => {
|
||||||
|
operationDomainSons.push({
|
||||||
|
domainSupplierId: formData.domainSupplierId,
|
||||||
|
domainId: item.domainId,
|
||||||
|
name: item.sonTitle + '.' + item.sonDomain,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// 提交
|
||||||
|
loading.value = true;
|
||||||
|
switch (props.type) {
|
||||||
|
case 'webHall':
|
||||||
|
submitSuccess(addWebDomain({ operationDomainSons: operationDomainSons }));
|
||||||
|
break;
|
||||||
|
case 'backend':
|
||||||
|
submitSuccess(addBackendDomain({ operationDomainSons: operationDomainSons }));
|
||||||
|
break;
|
||||||
|
case 'appHall':
|
||||||
|
submitSuccess(addAppDomain({ operationDomainSons: operationDomainSons }));
|
||||||
|
break;
|
||||||
|
case 'oss':
|
||||||
|
submitSuccess(addOssDomain({ operationDomainSons: operationDomainSons }));
|
||||||
|
break;
|
||||||
|
case 'downloadSite':
|
||||||
|
submitSuccess(addDownloadDomain({ operationDomainSons: operationDomainSons }));
|
||||||
|
break;
|
||||||
|
case 'payment':
|
||||||
|
submitSuccess(addPayDomain({ operationDomainSons: operationDomainSons }));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交后回调
|
||||||
|
function submitSuccess(apiFn) {
|
||||||
|
apiFn.then(() => {
|
||||||
|
loading.value = false;
|
||||||
|
proxy.$message.success(proxy.t('添加成功'));
|
||||||
|
closeDialog('submit');
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭弹窗
|
||||||
|
const emit = defineEmits(['closeDialog', 'goDomainManage']);
|
||||||
|
const closeDialog = (type) => {
|
||||||
|
emit('closeDialog', type);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 前往域名管理
|
||||||
|
const goDomainManage = () => {
|
||||||
|
emit('goDomainManage');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
// 自定义表单label
|
||||||
|
.clt-item {
|
||||||
|
.label-box {
|
||||||
|
width: 120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-right {
|
||||||
|
width: calc(100% - 120px);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 校验提示位置
|
||||||
|
:deep(.el-form-item__error) {
|
||||||
|
padding-left: 120px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.node-tips {
|
||||||
|
width: 550px;
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 0;
|
||||||
|
padding: 5px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生效域名列表
|
||||||
|
.domain-list {
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 18px;
|
||||||
|
|
||||||
|
.et-col {
|
||||||
|
line-height: 32px;
|
||||||
|
padding-right: 5px;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
padding-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-child(3) {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,265 @@
|
||||||
|
<template>
|
||||||
|
<!-- 批量操作弹窗 -->
|
||||||
|
<el-dialog :title="dialogTitle" v-model="isShowDialog" width="800px" append-to-body @close="closeDialog">
|
||||||
|
<el-scrollbar max-height="600px" v-loading="loading">
|
||||||
|
<el-table row-key="id" stripe border :data="tableList">
|
||||||
|
<el-table-column :label="t('主域名')" align="center" min-width="150"
|
||||||
|
v-if="batchOpType == 'port' || batchOpType == 'clearCache' || batchOpType == 'delete' || batchOpType == 'stop' || batchOpType == 'enable'">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ row.mainName || '-' }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column :label="t('CDN节点')" prop="cdnNodeName" align="center" min-width="150"></el-table-column>
|
||||||
|
<el-table-column :label="t('子域名')" prop="name" align="center" min-width="150"></el-table-column>
|
||||||
|
<el-table-column :label="t('其他担保域名列表')" align="center" min-width="150"
|
||||||
|
v-if="batchOpType == 'showSecurity' || batchOpType == 'hideSecurity'">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ row.backupDomain ? t('展示') : t('隐藏') }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column :label="t('作为推广域名')" align="center" min-width="150"
|
||||||
|
v-if="batchOpType == 'showPromotion' || batchOpType == 'hidePromotion'">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ row.marketingDomain ? t('开启') : t('关闭') }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column :label="t('启用入口')" align="center" min-width="150" v-if="batchOpType == 'edit'">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<dict-select class="w100" v-model="row.startEntrance" dictKey="ff_operation_start_entrance"
|
||||||
|
:disabled="row.usageStatus != 4"></dict-select>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column :label="t('屏蔽设备')" align="center" min-width="150" v-if="batchOpType == 'edit'">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<dict-select class="w100" v-model="row.blockDevice" dictKey="ff_operation_block_device"
|
||||||
|
:disabled="row.usageStatus != 4 || row.startEntrance == 2"></dict-select>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column :label="t('强制绑定代理账号(选填)')" align="center" min-width="150"
|
||||||
|
v-if="batchOpType == 'bindAgent'">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-input v-model="row.agentAccount" :placeholder="t('请输入代理账号')" clearable></el-input>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-scrollbar>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button @click="closeDialog">{{ t('关 闭') }}</el-button>
|
||||||
|
<el-button type="primary" @click="submitForm" :loading="loading">{{ t('确 认') }}</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="BatchOperation">
|
||||||
|
import {
|
||||||
|
changeWebDomainPort, // 批量更换端口
|
||||||
|
clearWebDomainCache, // 批量清理缓存
|
||||||
|
delWebDomain, // 批量删除
|
||||||
|
setWebDomainStatus, // 批量修改状态
|
||||||
|
webDomainSwitch, // 批量开关
|
||||||
|
bindWebDomainAgent, // 批量绑定代理
|
||||||
|
} from "@/api/operation/domain";
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance();
|
||||||
|
const loading = ref(false);
|
||||||
|
const isShowDialog = ref(true);
|
||||||
|
|
||||||
|
// 接收参数
|
||||||
|
const props = defineProps({
|
||||||
|
selectionData: {
|
||||||
|
type: Array,
|
||||||
|
default: []
|
||||||
|
},
|
||||||
|
batchOpType: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 监听参数
|
||||||
|
const tableList = ref([]);
|
||||||
|
watch(() => props.selectionData, newVal => {
|
||||||
|
const _tableList = JSON.parse(JSON.stringify(newVal)); // 以免影响原表格数据
|
||||||
|
|
||||||
|
switch (props.batchOpType) {
|
||||||
|
case 'port':
|
||||||
|
// 防封域名不能更换端口
|
||||||
|
tableList.value = _tableList.filter(v => v.sonType != -1 && v.sonType != -2);
|
||||||
|
break
|
||||||
|
case 'stop':
|
||||||
|
// 过滤已停用的域名
|
||||||
|
tableList.value = _tableList.filter(v => v.usageStatus != 5);
|
||||||
|
break
|
||||||
|
case 'enable':
|
||||||
|
// 过滤已启用的域名
|
||||||
|
tableList.value = _tableList.filter(v => v.usageStatus != 4);
|
||||||
|
break
|
||||||
|
case 'showSecurity':
|
||||||
|
// 关闭状态并且启用成功的域名
|
||||||
|
tableList.value = _tableList.filter(v => !v.backupDomain && v.usageStatus == 4);
|
||||||
|
break
|
||||||
|
case 'hideSecurity':
|
||||||
|
// 开启状态并且启用成功的域名
|
||||||
|
tableList.value = _tableList.filter(v => v.backupDomain && v.usageStatus == 4);
|
||||||
|
break
|
||||||
|
case 'showPromotion':
|
||||||
|
// 关闭状态/启用成功/启用入口不是仅极速APP的域名
|
||||||
|
tableList.value = _tableList.filter(v => !v.marketingDomain && v.usageStatus == 4 && v.startEntrance != 2);
|
||||||
|
break
|
||||||
|
case 'hidePromotion':
|
||||||
|
// 开启状态/启用成功/启用入口不是仅极速APP的域名
|
||||||
|
tableList.value = _tableList.filter(v => v.marketingDomain && v.usageStatus == 4 && v.startEntrance != 2);
|
||||||
|
break
|
||||||
|
case 'bindAgent':
|
||||||
|
// 启用状态才能绑定代理
|
||||||
|
tableList.value = _tableList.filter(v => v.usageStatus == 4);
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
tableList.value = _tableList;
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}, { immediate: true });
|
||||||
|
|
||||||
|
// 弹窗标题
|
||||||
|
const dialogTitle = computed(() => {
|
||||||
|
if (props.batchOpType === 'port') {
|
||||||
|
return proxy.t('批量更换端口');
|
||||||
|
} else if (props.batchOpType === 'clearCache') {
|
||||||
|
return proxy.t('批量清理缓存');
|
||||||
|
} else if (props.batchOpType === 'delete') {
|
||||||
|
return proxy.t('批量删除');
|
||||||
|
} else if (props.batchOpType === 'stop') {
|
||||||
|
return proxy.t('批量停用');
|
||||||
|
} else if (props.batchOpType === 'enable') {
|
||||||
|
return proxy.t('批量启用');
|
||||||
|
} else if (props.batchOpType === 'issued') {
|
||||||
|
return proxy.t('批量锁定下发');
|
||||||
|
} else if (props.batchOpType === 'showSecurity') {
|
||||||
|
return proxy.t('批量展示其他担保列表');
|
||||||
|
} else if (props.batchOpType === 'hideSecurity') {
|
||||||
|
return proxy.t('批量隐藏其他担保列表');
|
||||||
|
} else if (props.batchOpType === 'showPromotion') {
|
||||||
|
return proxy.t('批量开启推广域名');
|
||||||
|
} else if (props.batchOpType === 'hidePromotion') {
|
||||||
|
return proxy.t('批量关闭推广域名');
|
||||||
|
} else if (props.batchOpType === 'edit') {
|
||||||
|
return proxy.t('批量修改');
|
||||||
|
} else if (props.batchOpType === 'bindAgent') {
|
||||||
|
return proxy.t('批量绑定代理');
|
||||||
|
} else {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 提交
|
||||||
|
const submitForm = () => {
|
||||||
|
loading.value = true;
|
||||||
|
const params = {
|
||||||
|
ids: tableList.value.map(item => item.id)
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (props.batchOpType) {
|
||||||
|
case 'port':
|
||||||
|
submitSuccess(changeWebDomainPort(params), proxy.t('批量端口更换成功'));
|
||||||
|
break;
|
||||||
|
case 'clearCache':
|
||||||
|
submitSuccess(clearWebDomainCache(params), proxy.t('批量清理缓存成功'));
|
||||||
|
break;
|
||||||
|
case 'delete':
|
||||||
|
submitSuccess(delWebDomain(params.ids.join(',')), proxy.t('批量删除成功'));
|
||||||
|
break;
|
||||||
|
case 'stop':
|
||||||
|
params.usageStatus = 5;
|
||||||
|
submitSuccess(setWebDomainStatus(params), proxy.t('批量停用成功'));
|
||||||
|
break;
|
||||||
|
case 'enable':
|
||||||
|
params.usageStatus = 4;
|
||||||
|
submitSuccess(setWebDomainStatus(params), proxy.t('批量启用成功'));
|
||||||
|
break;
|
||||||
|
case 'showSecurity':
|
||||||
|
const _showParams = [];
|
||||||
|
params.ids.forEach(id => {
|
||||||
|
_showParams.push({
|
||||||
|
id: id,
|
||||||
|
backupDomain: true
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
submitSuccess(webDomainSwitch({ operationDomainSons: _showParams }), proxy.t('批量展示其他担保列表成功'));
|
||||||
|
break;
|
||||||
|
case 'hideSecurity':
|
||||||
|
const _hideParams = [];
|
||||||
|
params.ids.forEach(id => {
|
||||||
|
_hideParams.push({
|
||||||
|
id: id,
|
||||||
|
backupDomain: false
|
||||||
|
})
|
||||||
|
});
|
||||||
|
submitSuccess(webDomainSwitch({ operationDomainSons: _hideParams }), proxy.t('批量隐藏其他担保列表成功'));
|
||||||
|
break;
|
||||||
|
case 'showPromotion':
|
||||||
|
const _showPromotionParams = [];
|
||||||
|
params.ids.forEach(id => {
|
||||||
|
_showPromotionParams.push({
|
||||||
|
id: id,
|
||||||
|
marketingDomain: true
|
||||||
|
})
|
||||||
|
});
|
||||||
|
submitSuccess(webDomainSwitch({ operationDomainSons: _showPromotionParams }), proxy.t('批量开启推广域名成功'));
|
||||||
|
break;
|
||||||
|
case 'hidePromotion':
|
||||||
|
const _hidePromotionParams = [];
|
||||||
|
params.ids.forEach(id => {
|
||||||
|
_hidePromotionParams.push({
|
||||||
|
id: id,
|
||||||
|
marketingDomain: false
|
||||||
|
})
|
||||||
|
});
|
||||||
|
submitSuccess(webDomainSwitch({ operationDomainSons: _hidePromotionParams }), proxy.t('批量关闭推广域名成功'));
|
||||||
|
case 'edit':
|
||||||
|
const _editParams = [];
|
||||||
|
params.ids.forEach(id => {
|
||||||
|
const item = tableList.value.find(v => v.id == id);
|
||||||
|
_editParams.push({
|
||||||
|
id: id,
|
||||||
|
startEntrance: item.startEntrance,
|
||||||
|
blockDevice: item.blockDevice
|
||||||
|
})
|
||||||
|
});
|
||||||
|
submitSuccess(webDomainSwitch({ operationDomainSons: _editParams }), proxy.t('批量修改成功'));
|
||||||
|
break;
|
||||||
|
case 'bindAgent':
|
||||||
|
const _agentParams = [];
|
||||||
|
params.ids.forEach(id => {
|
||||||
|
const item = tableList.value.find(v => v.id == id);
|
||||||
|
_agentParams.push({
|
||||||
|
id: id,
|
||||||
|
agentAccount: item.agentAccount
|
||||||
|
})
|
||||||
|
});
|
||||||
|
submitSuccess(bindWebDomainAgent({ operationDomainSons: _agentParams }), proxy.t('批量绑定代理成功'));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交后回调
|
||||||
|
function submitSuccess(apiFn, msg) {
|
||||||
|
apiFn.then(() => {
|
||||||
|
loading.value = false;
|
||||||
|
proxy.$message.success(msg);
|
||||||
|
closeDialog('batchSubmit');
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭弹窗
|
||||||
|
const emit = defineEmits(['closeDialog']);
|
||||||
|
const closeDialog = (type) => {
|
||||||
|
emit('closeDialog', type);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss"></style>
|
||||||
|
|
@ -0,0 +1,126 @@
|
||||||
|
<template>
|
||||||
|
<!-- 绑定代理 -->
|
||||||
|
<el-dialog :title="t('绑定代理')" v-model="isShowDialog" width="700px" append-to-body @close="closeDialog">
|
||||||
|
<el-scrollbar max-height="600px" v-loading="loading">
|
||||||
|
<el-form ref="formRef" :model="formData" label-width="120">
|
||||||
|
<el-form-item :label="t('当前节点:')">
|
||||||
|
{{ currentDomainInfo.cdnNodeName }}
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="t('生效域名:')">
|
||||||
|
{{ currentDomainInfo.name }}
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="t('域名用途:')">
|
||||||
|
{{ domainTypeName }}
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label-width="0" class="clt-item">
|
||||||
|
<span slot="label" class="label-box">
|
||||||
|
{{ t('强制绑定代理账号(选填):') }}
|
||||||
|
</span>
|
||||||
|
<div class="item-right">
|
||||||
|
<el-input v-model="formData.agentAccount" :placeholder="t('请输入代理账号')" clearable />
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="t('功能说明:')">
|
||||||
|
{{ t('线下代理专属域名,上级归属的优先级:推广链接的上级 > 渠道ID的强制绑定上级 > 域名管理的强制绑定上级(无上级时,域名管理的才生效)') }}
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-scrollbar>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button @click="closeDialog">{{ t('关 闭') }}</el-button>
|
||||||
|
<el-button type="primary" @click="submitForm" :loading="loading">{{ t('确 认') }}</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="BindAgent">
|
||||||
|
import { bindWebDomainAgent, bindDownloadDomainAgent } from "@/api/operation/domain";
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance();
|
||||||
|
const loading = ref(false);
|
||||||
|
const isShowDialog = ref(true); // 弹窗是否显示
|
||||||
|
const formRef = ref();
|
||||||
|
|
||||||
|
// 接收参数
|
||||||
|
const props = defineProps({
|
||||||
|
currentDomainInfo: {
|
||||||
|
type: Object,
|
||||||
|
default: () => { }
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 域名用途
|
||||||
|
const domainTypeName = computed(() => {
|
||||||
|
if (props.type == 'webHall') {
|
||||||
|
return proxy.t('Web大厅域名');
|
||||||
|
} else if (props.type == 'downloadSite') {
|
||||||
|
return proxy.t('下载站域名');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 表单参数
|
||||||
|
const formData = reactive({
|
||||||
|
agentAccount: props.currentDomainInfo.agentAccount
|
||||||
|
});
|
||||||
|
|
||||||
|
// 提交
|
||||||
|
const submitForm = () => {
|
||||||
|
const params = {
|
||||||
|
operationDomainSons: [{
|
||||||
|
id: props.currentDomainInfo.id,
|
||||||
|
agentAccount: formData.agentAccount
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交
|
||||||
|
loading.value = true;
|
||||||
|
switch (props.type) {
|
||||||
|
case 'webHall':
|
||||||
|
submitSuccess(bindWebDomainAgent(params));
|
||||||
|
break;
|
||||||
|
case 'downloadSite':
|
||||||
|
submitSuccess(bindDownloadDomainAgent(params));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交后回调
|
||||||
|
function submitSuccess(apiFn) {
|
||||||
|
apiFn.then(() => {
|
||||||
|
loading.value = false;
|
||||||
|
proxy.$message.success(proxy.t('代理绑定成功'));
|
||||||
|
closeDialog('submit');
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭弹窗
|
||||||
|
const emit = defineEmits(['closeDialog']);
|
||||||
|
const closeDialog = (type) => {
|
||||||
|
emit('closeDialog', type);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
// 自定义表单label
|
||||||
|
.clt-item {
|
||||||
|
.label-box {
|
||||||
|
width: 120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-right {
|
||||||
|
width: calc(100% - 120px);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 校验提示位置
|
||||||
|
:deep(.el-form-item__error) {
|
||||||
|
padding-left: 120px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,174 @@
|
||||||
|
<template>
|
||||||
|
<!-- 修改域名 -->
|
||||||
|
<el-dialog :title="t('修改域名')" v-model="isShowDialog" width="600px" append-to-body @close="closeDialog">
|
||||||
|
<el-scrollbar max-height="600px" v-loading="loading">
|
||||||
|
<el-form ref="formRef" :rules="rules" :model="formData" label-width="100">
|
||||||
|
<el-form-item :label="t('当前节点:')">
|
||||||
|
{{ currentDomainInfo.cdnNodeName }}
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="t('主域名:')">
|
||||||
|
{{ domainStr[1] }}
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="t('域名用途:')">
|
||||||
|
{{ domainTypeName }}
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="t('生效域名:')" prop="name" class="mr0">
|
||||||
|
<el-input class="w100" v-model="formData.name" :placeholder="t('例如:* 或 @ 或 www')" clearable>
|
||||||
|
<template #append><b>.</b>{{ domainStr[1] }}</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-scrollbar>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button @click="closeDialog">{{ t('关 闭') }}</el-button>
|
||||||
|
<el-button type="primary" @click="submitForm" :loading="loading">{{ t('确 认') }}</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="EditSonDomain">
|
||||||
|
import {
|
||||||
|
updateWebDomain, // 修改web大厅域名
|
||||||
|
updateBackendDomain, // 修改后端加速域名
|
||||||
|
updateAppDomain, // 修改app大厅域名
|
||||||
|
updateOssDomain, // 修改oss加速域名
|
||||||
|
updateDownloadDomain, // 修改下载站域名
|
||||||
|
updatePayDomain, // 修改支付域名
|
||||||
|
} from "@/api/operation/domain";
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance();
|
||||||
|
const loading = ref(false);
|
||||||
|
const isShowDialog = ref(true); // 弹窗是否显示
|
||||||
|
const formRef = ref();
|
||||||
|
|
||||||
|
// 接收参数
|
||||||
|
const props = defineProps({
|
||||||
|
currentDomainInfo: {
|
||||||
|
type: Object,
|
||||||
|
default: () => { }
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 域名用途
|
||||||
|
const domainTypeName = computed(() => {
|
||||||
|
if (props.type == 'webHall') {
|
||||||
|
return proxy.t('Web大厅域名');
|
||||||
|
} else if (props.type == 'backend') {
|
||||||
|
return proxy.t('后端加速域名');
|
||||||
|
} else if (props.type == 'appHall') {
|
||||||
|
return proxy.t('App大厅域名');
|
||||||
|
} else if (props.type == 'oss') {
|
||||||
|
return proxy.t('OSS加速域名');
|
||||||
|
} else if (props.type == 'downloadSite') {
|
||||||
|
return proxy.t('下载站域名');
|
||||||
|
} else if (props.type == 'payment') {
|
||||||
|
return proxy.t('支付域名');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 拆分成域名主体和前缀
|
||||||
|
const domainStr = computed(() => {
|
||||||
|
const _domainName = props.currentDomainInfo.name;
|
||||||
|
|
||||||
|
if (_domainName) {
|
||||||
|
const index = _domainName.indexOf('.');
|
||||||
|
if (index !== -1) {
|
||||||
|
return [_domainName.substring(0, index), _domainName.substring(index + 1)]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
});
|
||||||
|
|
||||||
|
// 表单参数
|
||||||
|
const formData = reactive({
|
||||||
|
name: domainStr.value[0]
|
||||||
|
});
|
||||||
|
|
||||||
|
// 表单校验
|
||||||
|
const rules = reactive({
|
||||||
|
name: [
|
||||||
|
{ required: true, message: proxy.t('请输入子域名'), trigger: ['change', 'blur'] },
|
||||||
|
{
|
||||||
|
pattern: /^[\w\*@]+$/,
|
||||||
|
message: proxy.t('只能包含字母、数字、下划线、星号和@'),
|
||||||
|
trigger: ['change', 'blur']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
// 提交
|
||||||
|
const submitForm = () => {
|
||||||
|
formRef.value.validate(valid => {
|
||||||
|
if (valid) {
|
||||||
|
const params = {
|
||||||
|
id: props.currentDomainInfo.id,
|
||||||
|
name: formData.name + '.' + domainStr.value[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交
|
||||||
|
loading.value = true;
|
||||||
|
switch (props.type) {
|
||||||
|
case 'webHall':
|
||||||
|
submitSuccess(updateWebDomain(params));
|
||||||
|
break;
|
||||||
|
case 'backend':
|
||||||
|
submitSuccess(updateBackendDomain(params));
|
||||||
|
break;
|
||||||
|
case 'appHall':
|
||||||
|
submitSuccess(updateAppDomain(params));
|
||||||
|
break;
|
||||||
|
case 'oss':
|
||||||
|
submitSuccess(updateOssDomain(params));
|
||||||
|
break;
|
||||||
|
case 'downloadSite':
|
||||||
|
submitSuccess(updateDownloadDomain(params));
|
||||||
|
break;
|
||||||
|
case 'payment':
|
||||||
|
submitSuccess(updatePayDomain(params));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交后回调
|
||||||
|
function submitSuccess(apiFn) {
|
||||||
|
apiFn.then(() => {
|
||||||
|
loading.value = false;
|
||||||
|
proxy.$message.success(proxy.t('修改成功'));
|
||||||
|
closeDialog('submit');
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭弹窗
|
||||||
|
const emit = defineEmits(['closeDialog']);
|
||||||
|
const closeDialog = (type) => {
|
||||||
|
emit('closeDialog', type);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
// 自定义表单label
|
||||||
|
.clt-item {
|
||||||
|
.label-box {
|
||||||
|
width: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-right {
|
||||||
|
width: calc(100% - 100px);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 校验提示位置
|
||||||
|
:deep(.el-form-item__error) {
|
||||||
|
padding-left: 100px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,124 @@
|
||||||
|
<template>
|
||||||
|
<!-- 列表左侧域名供应商选择按钮 -->
|
||||||
|
<el-radio-group v-model="domainSupplierId" size="large" class="supplier-button" @change="changeVal">
|
||||||
|
<el-radio-button value="" :label="t('全部')" />
|
||||||
|
<template v-for="item in supplierList" :key="item.id">
|
||||||
|
<el-radio-button :value="item.id">
|
||||||
|
<template #default>
|
||||||
|
<span>{{ item.supplierName }}</span>
|
||||||
|
<span class="rb-tag"
|
||||||
|
:style="'background-color:' + (item.supplierType == 1 ? '#F56C6C' : item.supplierType == 2 ? '#409EFF' : '#67C23A')">
|
||||||
|
{{ item.supplierTypeName }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-radio-button>
|
||||||
|
</template>
|
||||||
|
</el-radio-group>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { getSupplierList } from "@/api/operation/domain";
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance();
|
||||||
|
const domainSupplierId = defineModel(); // 选中域名供应商ID
|
||||||
|
|
||||||
|
// 初始化列表
|
||||||
|
onMounted(() => {
|
||||||
|
getSupplierInfo();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 域名供应商列表
|
||||||
|
const supplierList = ref([]);
|
||||||
|
const supplierTips = reactive({
|
||||||
|
'Az': proxy.t('此节点属于微软官方CDN,国际和中国大陆市场均可使用(即全球通用)。微软防封:此节点提供了第三方公共域名,该域名随机生成,可防封防屏蔽(即无需使用自己域名),国际和中国大陆市场均可使用(即全球通用)。'),
|
||||||
|
'ALY-CN': proxy.t('此节点是大陆专用的阿里云,只适合中国大陆市场,存活期间不会出现被封,速度最快最稳定,但需要自行购买备案域名和大陆阿里云账号来配置(即购买阿里云小号,一般存活一个多月后被封,所以可能需要频繁换备案域名或换号)。'),
|
||||||
|
'WS': proxy.t('此节点覆盖中国大陆和国际市场,国际和中国大陆市场均可使用(即全球通用)。'),
|
||||||
|
'AliYun': proxy.t('此节点只适合海外市场,且禁止中国地区访问和使用(含港澳台)。'),
|
||||||
|
'WSIP': proxy.t('此节点提供独立IP地址,适用于会封禁域名,但不会封禁IP的国家(例如:印尼、中国、巴西、越南等),国际和中国大陆市场均可使用(即全球通用)。'),
|
||||||
|
'A8': proxy.t('此节点属于大陆到香港CN2专线,只推荐中国大陆市场使用,海外市场不推荐。'),
|
||||||
|
'AWS': proxy.t('此节点属于亚马逊官方CDN,国际和中国大陆市场均可使用(即全球通用)。'),
|
||||||
|
'SE': proxy.t('此节点具备独家移动清洗线路功能,即可以防止中国大陆运营商屏蔽,仅限于中国大陆市场使用。'),
|
||||||
|
'CF': proxy.t('全球最大CDN供应商,主要可以抗攻击,国际和中国大陆市场均可使用(即全球通用)。'),
|
||||||
|
'YD': proxy.t('节点主要分布在推荐东南亚与印度、中国大陆市场,推荐东南亚和大陆使用。'),
|
||||||
|
'FN': proxy.t('此节点属于大陆到香港CN2专线,只推荐中国大陆市场使用,海外市场不推荐。'),
|
||||||
|
'HWCloud': proxy.t('此节点只适合海外市场,且禁止中国地区访问和使用(含港澳台)。'),
|
||||||
|
'TCCloud': proxy.t('此节点只适合海外市场,且禁止中国地区访问和使用(含港澳台)。'),
|
||||||
|
'GC': proxy.t('仅限于国际市场使用,不能用在中国市场。'),
|
||||||
|
'OSR': proxy.t('我方提供独立源服务IP信息,您可使用外部三方CDN绑定到我方源站,所以仅限web大厅使用(不支持原生APP),需要有专业知识才能配置websocket、HTTP2、缓存等信息,详见域名管理教程。')
|
||||||
|
});
|
||||||
|
|
||||||
|
// 获取域名供应商列表
|
||||||
|
const getSupplierInfo = () => {
|
||||||
|
getSupplierList().then(res => {
|
||||||
|
const _data = res.data;
|
||||||
|
|
||||||
|
if (_data.length) {
|
||||||
|
const supplierType = [
|
||||||
|
{ value: 1, label: '全球' },
|
||||||
|
{ value: 2, label: '大陆' },
|
||||||
|
{ value: 3, label: '国际' }
|
||||||
|
]; // 供应商类型
|
||||||
|
|
||||||
|
// 供应商类型名称和描述
|
||||||
|
_data.forEach(item => {
|
||||||
|
item.tips = supplierTips[item.supplierCode];
|
||||||
|
item.supplierTypeName = supplierType.find(i => i.value == item.supplierType).label;
|
||||||
|
});
|
||||||
|
|
||||||
|
supplierList.value = _data;
|
||||||
|
console.log(supplierList.value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 当前供应商节点
|
||||||
|
const curSupplierNode = computed(() => {
|
||||||
|
return supplierList.value.find(item => item.id == domainSupplierId.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(['getCurSupplierNode']);
|
||||||
|
const changeVal = () => {
|
||||||
|
emit('getCurSupplierNode', curSupplierNode.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 暴露方法
|
||||||
|
defineExpose({
|
||||||
|
getSupplierInfo,
|
||||||
|
supplierList
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang='scss'>
|
||||||
|
.supplier-button {
|
||||||
|
width: calc(100% - 15px);
|
||||||
|
|
||||||
|
:deep(.el-radio-button) {
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
|
||||||
|
.el-radio-button__inner {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid #dcdfe6 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-active .el-radio-button__inner {
|
||||||
|
box-shadow: none;
|
||||||
|
border: 1px solid #409EFF !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.rb-tag {
|
||||||
|
display: inline-block;
|
||||||
|
position: absolute;
|
||||||
|
right: -5px;
|
||||||
|
top: -5px;
|
||||||
|
color: #ffffff;
|
||||||
|
font-size: 10px;
|
||||||
|
padding: 0 5px;
|
||||||
|
line-height: 1.5;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,153 @@
|
||||||
|
<template>
|
||||||
|
<el-radio-group v-model="supplierId" class="supplier-box">
|
||||||
|
<el-radio v-for="item in supplierList" :value="item.id" size="large" border
|
||||||
|
:disabled="!item.isOpen || item.stopStatus" @change="changeSupplier(item)" :class="type == 'addSonDomain' ? 'son-radio' : ''">
|
||||||
|
<template #default>
|
||||||
|
{{ item.supplierName }}
|
||||||
|
<icon-tips trigger="hover">
|
||||||
|
<p class="c-clear" style="width: 400px;">{{ item.tips }}</p>
|
||||||
|
</icon-tips>
|
||||||
|
<span class="rb-tag"
|
||||||
|
:style="'background-color:' + (item.supplierType == 1 ? '#F56C6C' : item.supplierType == 2 ? '#409EFF' : '#67C23A')">
|
||||||
|
{{ item.supplierTypeName }}
|
||||||
|
</span>
|
||||||
|
<span v-if="item.prohibit" class="prohibit">{{ t('防封') }}</span>
|
||||||
|
<!-- 非维护状态,且不是增加子域名弹窗 -->
|
||||||
|
<p class="sl-bottom" v-if="!item.stopStatus && type != 'addSonDomain'">
|
||||||
|
<span>{{ item.domainCount > 0 ? item.domainCount + t('条') : t('无域名') }} </span>
|
||||||
|
<el-button v-hasPermi="['operation:tenant:edit']" style="margin-left: 5px;" link type="primary" v-if="item.domainCount == 0" @click="supplierSet(item)">{{ item.isOpen &&
|
||||||
|
item.domainCount == 0 ?
|
||||||
|
t('关闭') : t('开通') }}</el-button>
|
||||||
|
<el-button v-hasPermi="['operation:tenant:alb']" style="margin-left: 5px;" link type="primary" @click="albSet(item)"
|
||||||
|
v-if="item.domainCount > 0 && item.isOpen && item.supportAlb">{{ item.albStatus ?
|
||||||
|
t('ALB关闭') : t('ALB开通') }}</el-button>
|
||||||
|
</p>
|
||||||
|
<div class="stop-box" v-if="item.stopStatus">
|
||||||
|
<el-icon size="18">
|
||||||
|
<WarnTriangleFilled />
|
||||||
|
</el-icon>
|
||||||
|
<p class="c-clear" style="line-height: 1;">{{ t('维护中...') }}</p>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { tenantSupplierALB, tenantSupplier } from "@/api/operation/domain";
|
||||||
|
import IconTips from "@/components/IconTips"; // 小图标提示
|
||||||
|
|
||||||
|
// 接收参数
|
||||||
|
const props = defineProps({
|
||||||
|
supplierList: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance();
|
||||||
|
const loading = ref(false);
|
||||||
|
const supplierId = defineModel();
|
||||||
|
const emits = defineEmits(['changeSupplier']);
|
||||||
|
const changeSupplier = (item) => {
|
||||||
|
emits('changeSupplier', item);
|
||||||
|
};
|
||||||
|
// alb开通/关闭
|
||||||
|
const albSet = (item) => {
|
||||||
|
proxy.$modal.confirm(proxy.t('确认') + (item.albStatus ? proxy.t('关闭') : proxy.t('开通')) + '节点ALB?' ).then(() => {
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
tenantSupplierALB({ supplierId: item.id, albStatus: !item.albStatus }).then(res => {
|
||||||
|
loading.value = false;
|
||||||
|
item.albStatus = !item.albStatus;
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('操作成功!'));
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}).catch(() => { });
|
||||||
|
};
|
||||||
|
|
||||||
|
// 供应商开通/关闭
|
||||||
|
const supplierSet = (item) => {
|
||||||
|
const content = item.isOpen ? proxy.t('默认提供')+item.freeNode+proxy.t('个免费节点,该节点无域名解析数据可进行关闭。') : proxy.t('免费提供') + item.freeNode +proxy.t('个免费节点,超出部分额外收取')+ item.exceedCost + proxy.t('USDT/节点/月,每个节点都是独立云,都能扛攻击,建议平均分配。');
|
||||||
|
const title = (item.isOpen? proxy.t('确认关闭') : proxy.t('确认开通')) + item.supplierName + proxy.t('节点') + '?';
|
||||||
|
|
||||||
|
proxy.$modal.confirm(content, title).then(() => {
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
tenantSupplier({ supplierId: item.id, isOpen:!item.isOpen }).then(res => {
|
||||||
|
loading.value = false;
|
||||||
|
item.isOpen =!item.isOpen;
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('操作成功!'));
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}).catch(() => { });
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang='scss'>
|
||||||
|
.supplier-box {
|
||||||
|
:deep(.el-radio) {
|
||||||
|
display: inline-block;
|
||||||
|
height: 60px;
|
||||||
|
margin: 10px 10px 0 0;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.son-radio) {
|
||||||
|
height: 40px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prohibit,
|
||||||
|
.rb-tag {
|
||||||
|
display: inline-block;
|
||||||
|
position: absolute;
|
||||||
|
color: #ffffff;
|
||||||
|
font-size: 10px;
|
||||||
|
padding: 0 5px;
|
||||||
|
line-height: 1.5;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rb-tag {
|
||||||
|
right: -5px;
|
||||||
|
top: -8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prohibit {
|
||||||
|
left: -5px;
|
||||||
|
top: -8px;
|
||||||
|
background-color: #42b983;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sl-bottom {
|
||||||
|
position: absolute;
|
||||||
|
margin: 0;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stop-box {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
text-align: center;
|
||||||
|
color: #ffffff;
|
||||||
|
border-radius: 4px;
|
||||||
|
|
||||||
|
:deep(.el-icon) {
|
||||||
|
transform: translateY(5px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,329 @@
|
||||||
|
<template>
|
||||||
|
<!-- 新增/修改自定义解析 -->
|
||||||
|
<el-dialog :title="dialogTitle" v-model="isShowDialog" width="700px" append-to-body @close="closeDialog">
|
||||||
|
<el-scrollbar max-height="600px" v-loading="loading">
|
||||||
|
<el-form ref="formRef" :model="formData" :rules="rules" label-width="120">
|
||||||
|
<el-form-item :label="t('选择节点:')" prop="domainSupplierId" class="mr0">
|
||||||
|
<el-radio-group v-model="formData.domainSupplierId" @change="changeCdnNode">
|
||||||
|
<template v-for="item in supplierList" :key="item.value">
|
||||||
|
<el-radio :value="item.value">{{ t(item.label) }}</el-radio>
|
||||||
|
</template>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="t('选择域名:')" prop="domainId" class="mr0">
|
||||||
|
<el-select class="w100" v-model="formData.domainId" :placeholder="t('请选择域名')" @change="changeDomain"
|
||||||
|
:disabled="!supplierDomainList.length">
|
||||||
|
<el-option v-for="item in supplierDomainList" :key="item.value" :label="item.label"
|
||||||
|
:value="item.value" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="t('主机记录:')" prop="hostRecord" class="mr0">
|
||||||
|
<el-input v-model="formData.hostRecord" clearable :placeholder="t('请输入主机记录')"
|
||||||
|
:disabled="!formData.domainId">
|
||||||
|
<template #append v-if="formData.domainId"><b>.</b>{{ formData.domainName }}</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="t('解析类型:')" prop="analysisType" class="mr0">
|
||||||
|
<dict-select class="w100" v-model="formData.analysisType" :placeholder="t('请选择解析类型')"
|
||||||
|
dictKey="ff_operation_domain_analysis_type" @change="analysisTypeChange"></dict-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="t('解析记录值:')" prop="recordValue" class="mr0" v-if="formData.analysisType != 6">
|
||||||
|
<el-input v-model="formData.recordValue" clearable :placeholder="rvPlaceholder" />
|
||||||
|
</el-form-item>
|
||||||
|
<!-- SRV解析类型 -->
|
||||||
|
<template v-if="formData.analysisType == 6">
|
||||||
|
<el-form-item :label="t('协议:')" prop="protocolType" class="mr0" v-if="nodeAnalysisType == 2">
|
||||||
|
<dict-select class="w100" v-model="formData.protocolType" :placeholder="t('请选择协议类型')"
|
||||||
|
dictKey="ff_operation_domain_analysis_protocol_type"></dict-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="t('优先级:')" prop="priority" :rules="rules.srvNumber" class="mr0">
|
||||||
|
<number-input v-model="formData.priority" maxlength="5" clearable :placeholder="t('请输入0-65535')" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="t('权重:')" prop="weight" :rules="rules.srvNumber" class="mr0">
|
||||||
|
<number-input v-model="formData.weight" maxlength="5" clearable :placeholder="t('请输入0-65535')" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="t('端口:')" prop="port" :rules="rules.srvNumber" class="mr0">
|
||||||
|
<number-input v-model="formData.port" maxlength="5" clearable :placeholder="t('请输入0-65535')" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="t('服务:')" prop="service" class="mr0" v-if="nodeAnalysisType == 2">
|
||||||
|
<el-input v-model="formData.service" clearable :placeholder="t('请输入例如:_serviceName')" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="t('目标:')" prop="target" class="mr0">
|
||||||
|
<el-input v-model="formData.target" clearable :placeholder="t('请输入目标')" />
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
<el-form-item :label="t('TTL:')" prop="ttl" class="mr0">
|
||||||
|
<number-input v-model="formData.ttl" maxlength="10" clearable :placeholder="t('请输入大于等于600的整数')" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-scrollbar>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button @click="closeDialog">{{ t('关 闭') }}</el-button>
|
||||||
|
<el-button type="primary" @click="submitForm" :loading="loading">{{ t('确 认') }}</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="AddEditParsing">
|
||||||
|
import {
|
||||||
|
getSupplierDomainList, // 供应商节点下域名
|
||||||
|
addCustomParsing,
|
||||||
|
updateCustomParsing
|
||||||
|
} from "@/api/operation/domain";
|
||||||
|
import NumberInput from "@/components/NumberInput/index.vue"; // 数字输入框
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance();
|
||||||
|
const loading = ref(false);
|
||||||
|
const isShowDialog = ref(true); // 弹窗是否显示
|
||||||
|
const formRef = ref();
|
||||||
|
const oldForm = shallowRef({ });
|
||||||
|
// 接收参数
|
||||||
|
const props = defineProps({
|
||||||
|
supplierList: {
|
||||||
|
type: Array,
|
||||||
|
default: []
|
||||||
|
},
|
||||||
|
currentParsingInfo: {
|
||||||
|
type: Object,
|
||||||
|
default: {}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 弹窗标题
|
||||||
|
const dialogTitle = computed(() => {
|
||||||
|
if (props.currentParsingInfo.id) {
|
||||||
|
return proxy.t('修改域名解析');
|
||||||
|
} else {
|
||||||
|
return proxy.t('新增域名解析');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 表单参数
|
||||||
|
const formData = reactive({
|
||||||
|
domainSupplierId: '', // 节点id
|
||||||
|
domainId: '', // 域名id
|
||||||
|
domainName: '', // 域名名称
|
||||||
|
hostRecord: '', // 主机记录
|
||||||
|
analysisType: '', // 解析类型
|
||||||
|
recordValue: '', // 解析记录值
|
||||||
|
protocolType: '', // 协议类型
|
||||||
|
priority: '', // 优先级
|
||||||
|
weight: '', // 权重
|
||||||
|
port: '', // 端口
|
||||||
|
service: '', // 服务
|
||||||
|
target: '', // 目标
|
||||||
|
ttl: '', // ttl
|
||||||
|
});
|
||||||
|
|
||||||
|
// 初始化修改状态
|
||||||
|
let initEditStatus = ref(false);
|
||||||
|
|
||||||
|
// 表单校验
|
||||||
|
const rules = reactive({
|
||||||
|
domainSupplierId: [
|
||||||
|
{ required: true, message: proxy.t('请选择节点'), trigger: 'change' }
|
||||||
|
],
|
||||||
|
domainId: [
|
||||||
|
{ required: true, message: proxy.t('请选择域名'), trigger: 'change' }
|
||||||
|
],
|
||||||
|
hostRecord: [
|
||||||
|
{ required: true, message: proxy.t('请输入主机记录'), trigger: ['change', 'blur'] },
|
||||||
|
// 符合规范的主机记录
|
||||||
|
{
|
||||||
|
validator: (rule, value, callback) => {
|
||||||
|
const reg = /^[a-zA-Z0-9\-\_]+$/;
|
||||||
|
if (value != '' && !reg.test(value)) {
|
||||||
|
callback(new Error(proxy.t('主机记录只能包含字母、数字、下划线、横线')));
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}, trigger: ['change', 'blur']
|
||||||
|
}
|
||||||
|
],
|
||||||
|
analysisType: [
|
||||||
|
{ required: true, message: proxy.t('请选择解析类型'), trigger: 'change' }
|
||||||
|
],
|
||||||
|
recordValue: [
|
||||||
|
{ required: true, message: proxy.t('请输入解析记录值'), trigger: ['change', 'blur'] }
|
||||||
|
],
|
||||||
|
protocolType: [
|
||||||
|
{ required: true, message: proxy.t('请选择协议类型'), trigger: 'change' }
|
||||||
|
],
|
||||||
|
srvNumber: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
validator: (rule, value, callback) => {
|
||||||
|
if (value == '' || (value < 0 || value > 65535)) {
|
||||||
|
callback(new Error(proxy.t('请输入0-65535的整数')));
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}, trigger: ['change', 'blur']
|
||||||
|
}
|
||||||
|
],
|
||||||
|
service: [
|
||||||
|
{ required: true, message: proxy.t('请输入服务'), trigger: ['change', 'blur'] }
|
||||||
|
],
|
||||||
|
target: [
|
||||||
|
{ required: true, message: proxy.t('请输入目标'), trigger: ['change', 'blur'] }
|
||||||
|
],
|
||||||
|
ttl: [
|
||||||
|
{
|
||||||
|
validator: (rule, value, callback) => {
|
||||||
|
if (value !== '' && value < 600) {
|
||||||
|
callback(new Error(proxy.t('请输入大于等于600的整数')));
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}, trigger: ['change', 'blur']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
// 切换节点,获取域名
|
||||||
|
const supplierDomainList = ref([]),
|
||||||
|
nodeAnalysisType = ref(1); // 当前节点下域名解析类型
|
||||||
|
|
||||||
|
const changeCdnNode = (val) => {
|
||||||
|
// 清空已选中的域名和主机记录
|
||||||
|
formData.domainId = '';
|
||||||
|
formData.domainName = '';
|
||||||
|
formData.hostRecord = '';
|
||||||
|
|
||||||
|
// 当前节点下域名解析类型,SRV类型输入框增加
|
||||||
|
nodeAnalysisType.value = props.supplierList.find(v => v.value == val).analysisType;
|
||||||
|
|
||||||
|
// 当前节点下域名列表
|
||||||
|
getSupplierDomainList({ domainSupplierId: val }).then(res => {
|
||||||
|
supplierDomainList.value = res.data.map(v => {
|
||||||
|
return {
|
||||||
|
label: v.name,
|
||||||
|
value: v.id
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 初始化修改状态数据
|
||||||
|
if (initEditStatus.value) {
|
||||||
|
const _currentParsingInfo = props.currentParsingInfo;
|
||||||
|
|
||||||
|
formData.domainId = _currentParsingInfo.domainId;
|
||||||
|
formData.domainName = _currentParsingInfo.domainName;
|
||||||
|
formData.hostRecord = _currentParsingInfo.hostRecord;
|
||||||
|
formData.analysisType = _currentParsingInfo.analysisType + '';
|
||||||
|
formData.recordValue = _currentParsingInfo.recordValue;
|
||||||
|
formData.protocolType = _currentParsingInfo.protocolType ? _currentParsingInfo.protocolType + '' : '';
|
||||||
|
formData.priority = _currentParsingInfo.priority;
|
||||||
|
formData.weight = _currentParsingInfo.weight;
|
||||||
|
formData.port = _currentParsingInfo.port;
|
||||||
|
formData.service = _currentParsingInfo.service;
|
||||||
|
formData.target = _currentParsingInfo.target;
|
||||||
|
formData.ttl = _currentParsingInfo.ttl || '';
|
||||||
|
initEditStatus.value = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 切换域名
|
||||||
|
const changeDomain = (val) => {
|
||||||
|
const findDomain = supplierDomainList.value.find(v => v.value == val);
|
||||||
|
|
||||||
|
formData.domainId = findDomain.value;
|
||||||
|
formData.domainName = findDomain.label;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析类型切换时,更改解析记录值placeholder
|
||||||
|
const rvPlaceholder = ref(proxy.t('请输入IPv4地址'));
|
||||||
|
const analysisTypeChange = (val) => {
|
||||||
|
const _label = proxy.useDict('ff_operation_domain_analysis_type').ff_operation_domain_analysis_type.find(v => v.value == val).label;
|
||||||
|
|
||||||
|
if (_label == 'AAAA') {
|
||||||
|
rvPlaceholder.value = proxy.t('请输入IPv6地址');
|
||||||
|
} else if (_label == 'CNAME') {
|
||||||
|
rvPlaceholder.value = proxy.t('请输入域名地址');
|
||||||
|
} else if (_label == 'NS') {
|
||||||
|
rvPlaceholder.value = proxy.t('请输入域名服务器地址');
|
||||||
|
} else {
|
||||||
|
rvPlaceholder.value = proxy.t('请输入IPv4地址');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 提交
|
||||||
|
const submitForm = () => {
|
||||||
|
formRef.value.validate((valid) => {
|
||||||
|
if (!valid) return;
|
||||||
|
|
||||||
|
const params = {
|
||||||
|
domainId: formData.domainId,
|
||||||
|
hostRecord: formData.hostRecord,
|
||||||
|
analysisType: formData.analysisType,
|
||||||
|
ttl: formData.ttl,
|
||||||
|
};
|
||||||
|
|
||||||
|
// 解析类型为SRV类型时,参数增加
|
||||||
|
if (formData.analysisType == 6) {
|
||||||
|
params.priority = formData.priority;
|
||||||
|
params.weight = formData.weight;
|
||||||
|
params.port = formData.port;
|
||||||
|
params.target = formData.target;
|
||||||
|
|
||||||
|
// 节点下域名解析类型为2时,参数增加
|
||||||
|
if (nodeAnalysisType.value == 2) {
|
||||||
|
params.protocolType = formData.protocolType;
|
||||||
|
params.service = formData.service;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
params.recordValue = formData.recordValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
loading.value = true;
|
||||||
|
if (props.currentParsingInfo.id) {
|
||||||
|
// 修改
|
||||||
|
params.id = props.currentParsingInfo.id;
|
||||||
|
if (JSON.stringify(formData) != oldForm.value) {
|
||||||
|
submitSuccess(updateCustomParsing(params), proxy.t('修改成功'));
|
||||||
|
}else{
|
||||||
|
loading.value = false;
|
||||||
|
closeDialog('cancel');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 新增
|
||||||
|
submitSuccess(addCustomParsing(params), proxy.t('添加成功'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交后回调
|
||||||
|
function submitSuccess(apiFn, msg) {
|
||||||
|
apiFn.then(() => {
|
||||||
|
loading.value = false;
|
||||||
|
proxy.$message.success(msg);
|
||||||
|
closeDialog('submit');
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭弹窗
|
||||||
|
const emit = defineEmits(['closeDialog']);
|
||||||
|
const closeDialog = (type) => {
|
||||||
|
emit('closeDialog', type);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 监听修改状态数据
|
||||||
|
watch(() => props.currentParsingInfo, (val) => {
|
||||||
|
if (val.id) {
|
||||||
|
// 触发节点下域名请求,去返回函数内回填其他数据
|
||||||
|
formData.domainSupplierId = val.domainSupplierId;
|
||||||
|
changeCdnNode(val.domainSupplierId);
|
||||||
|
initEditStatus.value = true;
|
||||||
|
setTimeout(() => {
|
||||||
|
let objForm = { ...formData }
|
||||||
|
oldForm.value = JSON.stringify(objForm);
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
}, { immediate: true });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss"></style>
|
||||||
|
|
@ -0,0 +1,259 @@
|
||||||
|
<template>
|
||||||
|
<!-- 自定义解析列表 -->
|
||||||
|
<table-search-card :model="queryParams" @getList="getList" :leftSpan="16" :rightSpan="8" @handleQuery="handleQuery()"
|
||||||
|
@resetQuery="resetQuery">
|
||||||
|
<template #left>
|
||||||
|
<table-search-date ref="searchDateRef" dateType="datetimerange" v-model:dateRange="dateRange"
|
||||||
|
v-model:operateTimeType="operateTimeType" @dateChange="handleQuery"></table-search-date>
|
||||||
|
<select-input-form :queryParamsList="queryParamsList" v-model:queryParams="queryParams" :width="[130, 260]"
|
||||||
|
@handleQuery="handleQuery"></select-input-form>
|
||||||
|
<el-form-item prop="analysisType" style="width: 120px;">
|
||||||
|
<dict-select clearable v-model="queryParams.analysisType" :placeholder="t('解析类型')"
|
||||||
|
dictKey="ff_operation_domain_analysis_type" @change="handleQuery"></dict-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item prop="domainSupplierId" style="width: 150px;">
|
||||||
|
<el-select v-model="queryParams.domainSupplierId" :placeholder="t('CDN节点')" @change="handleQuery">
|
||||||
|
<el-option v-for="item in supplierList" :key="item.value" :label="item.label" :value="item.value" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
<template #right>
|
||||||
|
<el-button type="success" plain icon="Plus" @click="isShowAddEdit = true"
|
||||||
|
v-hasPermi="['operation:analysis:add']">{{
|
||||||
|
t('新增') }}</el-button>
|
||||||
|
</template>
|
||||||
|
</table-search-card>
|
||||||
|
|
||||||
|
<!-- 查询表格 -->
|
||||||
|
<el-table ref="tableRef" class="c-table-main" v-loading="loading" row-key="id" stripe border :data="dataList"
|
||||||
|
@select="tableSelect" @select-all="tableSelect">
|
||||||
|
<el-table-column align="center" type="selection" width="55" />
|
||||||
|
<el-table-column :label="t('CDN节点名称')" prop="cdnNodeName" align="center" min-width="160"></el-table-column>
|
||||||
|
<el-table-column :label="t('主域名')" prop="domainName" align="center" min-width="160"></el-table-column>
|
||||||
|
<el-table-column :label="t('主机记录')" prop="hostRecord" align="center" min-width="180">
|
||||||
|
<template #default="{row}">
|
||||||
|
<div style="width: 100%;">{{ row.hostRecord }}</div>
|
||||||
|
<div style="width: 100%;font-weight: 600;" v-for="(item, index) in row.operationDomainAnalysisDns" :key="index">
|
||||||
|
<p> {{ item.typeValue }}:{{ item.value }}</p>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column :label="t('解析类型')" align="center" min-width="120">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<dict-text dictKey="ff_operation_domain_analysis_type" :value="row.analysisType" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column :label="t('解析记录值')" prop="recordValue" align="center" min-width="160"></el-table-column>
|
||||||
|
<el-table-column :label="t('TTL')" align="center" min-width="100">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{row.ttl || '-'}}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<table-operation></table-operation>
|
||||||
|
<el-table-column :label="t('操作')" align="center" min-width="120">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-button link type="primary" @click="opInfo(row, 'edit')" v-hasPermi="['operation:analysis:edit']">
|
||||||
|
{{ t('修改') }}
|
||||||
|
</el-button>
|
||||||
|
<el-button link type="primary" @click="opInfo(row, 'delete')" v-hasPermi="['operation:analysis:remove']">
|
||||||
|
{{ t('删除') }}
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<!-- 批量操作 -->
|
||||||
|
<table-batch-operate v-if="total > 0" v-model:batchOpType="batchOpType" v-model:isAllSelection="isAllSelection"
|
||||||
|
@allSelectionChange="allSelectionChange" @opTypeChange="opTypeChange" :selectionData="selectionData"
|
||||||
|
:opTypeOptions="opTypeOptions"></table-batch-operate>
|
||||||
|
<!-- 列表分页 -->
|
||||||
|
<pagination v-if="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize"
|
||||||
|
@pagination="getList" />
|
||||||
|
|
||||||
|
<!-- 添加解析 -->
|
||||||
|
<add-edit-parsing v-if="isShowAddEdit" :supplierList="supplierList" :currentParsingInfo="currentParsingInfo"
|
||||||
|
@closeDialog="closeDialog"></add-edit-parsing>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="CustomParsingList">
|
||||||
|
import {
|
||||||
|
getSupplierList, // 供应商列表
|
||||||
|
getCustomParsingList, // 域名列表
|
||||||
|
delCustomParsing, // 删除域名
|
||||||
|
} from "@/api/operation/domain";
|
||||||
|
import TableSearchDate from "@/components/TableSearchDate"; // 日期选择
|
||||||
|
import TableBatchOperate from '@/components/TableBatchOperate'; // 批量操作
|
||||||
|
import AddEditParsing from "./AddEditParsing.vue"; // 添加解析
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance();
|
||||||
|
const loading = ref(true); // loading状态
|
||||||
|
const isShowAddEdit = ref(false); // 各弹窗状态
|
||||||
|
|
||||||
|
// 获取供应商列表
|
||||||
|
const supplierList = ref([]);
|
||||||
|
getSupplierList().then(res => {
|
||||||
|
supplierList.value = res.data.filter(i => i.isOpen).map(v => {
|
||||||
|
return {
|
||||||
|
label: v.supplierName,
|
||||||
|
value: v.id,
|
||||||
|
analysisType: v.analysisType
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// 日期选择
|
||||||
|
const searchDateRef = ref(), dateRange = ref([]), operateTimeType = ref('');
|
||||||
|
|
||||||
|
// 根据下拉框条件输入搜索
|
||||||
|
const queryParamsList = ref([
|
||||||
|
{
|
||||||
|
label: proxy.t('主域名'),
|
||||||
|
value: 'domainName'
|
||||||
|
}, {
|
||||||
|
label: proxy.t('主机记录'),
|
||||||
|
value: 'hostRecord'
|
||||||
|
}, {
|
||||||
|
label: proxy.t('解析记录值'),
|
||||||
|
value: 'recordValue'
|
||||||
|
}, {
|
||||||
|
label: proxy.t('操作人'),
|
||||||
|
value: 'updateBy'
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 搜索配置
|
||||||
|
const queryParams = reactive({
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 20,
|
||||||
|
searchType: 'domainName',
|
||||||
|
domainName: '',
|
||||||
|
hostRecord: '',
|
||||||
|
recordValue: '',
|
||||||
|
updateBy: '',
|
||||||
|
domainSupplierId: '', // CDN节点
|
||||||
|
analysisType: '', // 解析类型
|
||||||
|
orderByColumn: 'createTime',
|
||||||
|
isAsc: 'desc'
|
||||||
|
});
|
||||||
|
|
||||||
|
// 请求列表
|
||||||
|
const dataList = ref([]), total = ref(0);
|
||||||
|
const getList = () => {
|
||||||
|
const params = proxy.addDateRange(queryParams, dateRange.value); // 日期参数
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
getCustomParsingList(params).then(res => {
|
||||||
|
loading.value = false;
|
||||||
|
dataList.value = res.rows;
|
||||||
|
total.value = +res.total;
|
||||||
|
clearBatchOp(); // 清空批量操作痕迹
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
dataList.value = [];
|
||||||
|
total.value = 0;
|
||||||
|
clearBatchOp(); // 清空批量操作痕迹
|
||||||
|
});
|
||||||
|
}
|
||||||
|
getList();
|
||||||
|
|
||||||
|
// 操作信息
|
||||||
|
const currentParsingInfo = ref({}); // 当前操作的域名信息
|
||||||
|
const opInfo = (row, type) => {
|
||||||
|
switch (type) {
|
||||||
|
case 'edit':
|
||||||
|
// 修改域名
|
||||||
|
currentParsingInfo.value = row;
|
||||||
|
isShowAddEdit.value = true;
|
||||||
|
break;
|
||||||
|
case 'delete':
|
||||||
|
// 删除域名
|
||||||
|
let msg = proxy.t('确定要删除该域名吗!')
|
||||||
|
if (row.batchOpType) {
|
||||||
|
msg = proxy.t('确定要批量删除选中的域名吗!')
|
||||||
|
}
|
||||||
|
|
||||||
|
proxy.$modal.confirm(msg).then(() => {
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
delCustomParsing(row.id).then(res => {
|
||||||
|
loading.value = false;
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('删除成功!'));
|
||||||
|
getList();
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
batchOpType.value = '';
|
||||||
|
});
|
||||||
|
}).catch(() => {
|
||||||
|
batchOpType.value = '';
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 批量操作
|
||||||
|
const tableRef = ref(),
|
||||||
|
isAllSelection = ref(false), // 是否全选
|
||||||
|
selectionData = ref([]), // 选中的表格数据
|
||||||
|
batchOpType = ref(''); // 选中的批量操作类型
|
||||||
|
|
||||||
|
// 批量操作选项
|
||||||
|
const opTypeOptions = ref([
|
||||||
|
{ label: proxy.t('批量删除'), value: 'delete' }
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 勾选表格
|
||||||
|
const tableSelect = (val) => {
|
||||||
|
selectionData.value = val;
|
||||||
|
|
||||||
|
if (val.length === dataList.value.length) {
|
||||||
|
isAllSelection.value = true;
|
||||||
|
} else {
|
||||||
|
isAllSelection.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 全选表格
|
||||||
|
const allSelectionChange = () => {
|
||||||
|
tableRef.value.toggleAllSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 选择批量数据操作类型
|
||||||
|
const opTypeChange = () => {
|
||||||
|
opInfo({id: selectionData.value.map(item => item.id).join(','), batchOpType: true}, batchOpType.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清空批量操作痕迹
|
||||||
|
const clearBatchOp = () => {
|
||||||
|
isAllSelection.value = false;
|
||||||
|
selectionData.value = [];
|
||||||
|
batchOpType.value = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 搜索按钮操作
|
||||||
|
const handleQuery = () => {
|
||||||
|
queryParams.pageNum = 1;
|
||||||
|
getList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置按钮操作
|
||||||
|
const resetQuery = () => {
|
||||||
|
searchDateRef.value.dateResetQuery(); // 日期选择重置
|
||||||
|
handleQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭弹窗
|
||||||
|
const closeDialog = (type) => {
|
||||||
|
isShowAddEdit.value = false; // 新增域名弹窗
|
||||||
|
currentParsingInfo.value = {}; // 当前操作的域名信息
|
||||||
|
batchOpType.value = ''; // 批量操作类型
|
||||||
|
|
||||||
|
// 批量操作清空
|
||||||
|
if (type === 'batchSubmit') clearBatchOp();
|
||||||
|
// 提交后刷新列表
|
||||||
|
if (type === 'submit' || type === 'batchSubmit') {
|
||||||
|
getList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang='scss'></style>
|
||||||
|
|
@ -0,0 +1,205 @@
|
||||||
|
<template>
|
||||||
|
<!-- 新增域名 -->
|
||||||
|
<el-dialog :title="t('新增域名')" v-model="isShowDialog" width="800px" align-center append-to-body @close="closeDialog">
|
||||||
|
<el-scrollbar max-height="600px" v-loading="loading">
|
||||||
|
<el-form ref="formRef" :rules="rules" :model="formData" label-width="100">
|
||||||
|
<el-form-item label-width="0" prop="domainSupplierId" class="clt-item mr0">
|
||||||
|
<span slot="label" class="label-box">
|
||||||
|
<span class="label-name"><i style="color: #f56c6c; margin-right: 4px;">*</i>{{ t('选择节点') }}</span>
|
||||||
|
<span class="label-open">({{ t('已开通') }}<b class="c-orange">{{ openCount }}</b>{{ t('个') }})</span>
|
||||||
|
<span class="label-ds c-blue">{{ t('节点说明') }}</span>
|
||||||
|
</span>
|
||||||
|
<div class="item-right">
|
||||||
|
<supplier-select v-model="formData.domainSupplierId" @changeSupplier="changeSupplier" :supplierList="supplierList"></supplier-select>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="t('主域名')" prop="domainNames" class="mr0">
|
||||||
|
<el-input type="textarea" :rows="5" v-model="formData.domainNames"
|
||||||
|
:placeholder="t('支持批量添加,最多20个,多个域名请换行,例如:\n123.com\n123.com.hk\n123.in')" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<div class="add-tips">
|
||||||
|
<h3>{{ t('收费和用法教程:') }}</h3>
|
||||||
|
<p><b>{{t('1、限顶级域名:')}}</b>{{ t('此处只能添加独立的顶级域名,请勿添加子域名,例如: 只能添加123.com,不是www.123.com,详见域名管理教程') }}</p>
|
||||||
|
<p><b>{{t('2、节点说明')}}</b></p>
|
||||||
|
<p><b>{{t('(1)中国市场(含港澳台):')}}</b>{{ t('推荐使用alb域名(aws防封)、三方公共域名(aws与azure防封)、Wangsu (CDN+IP)、A8、Yundun (云盾)、Funnull(方能)、superEdge、大陆阿里云。')}}</p>
|
||||||
|
<p><b>{{t('(2)全球市场(即非中国):')}}</b>{{ t('推荐使用使用alb域名(aws与aliyun防封)、三方公共域名(aws与azure防封)、AWS、CF、腾讯云、 阿里云、 Google、Azure、华为云、Wangsu(CDN + IP)、Yundun (云盾)。')}}</p>
|
||||||
|
<p><b>{{t('(3)Wangsu独立IP:')}}</b>{{ t('提供独立IP地址,适用于会封禁域名,但不会封禁IP的国家(例如:印尼、中国、巴西、越南等),国际和中国大陆市场均可使用(即全球通用200USDT/IP/月),若超过7天未启用系统自动回收。') }}
|
||||||
|
</p>
|
||||||
|
<p><b>{{t('(4)开放回源(仅限web大厅):')}}</b>{{ t('提供开放独立源服务,可使用外部三方CDN,需申请开通(300U/月),需要专业人士配置websocket、HTTP2、缓存等,详见域名管理教程。') }}</p>
|
||||||
|
<p><b>{{t('3、域名解析限额:')}}</b>{{ t('前')+domainNameCnt+t('个域名免费(含子域名),超出部分额外收取')+exceedDomainCost+t('USDT/条解析/月;') }}</p>
|
||||||
|
<p><b>{{t('4、流量限额:')}}</b>{{ t('每月前') +trafficG+ t('G免费,超出部分额外收取') + exceedTrafficCost +t('USDT/G/月;') }}</p>
|
||||||
|
<p><b>{{t('5、节点限制:')}}</b>{{ t('免费提供') + freeNode + t('个节点,超出部分额外收取') + exceedCost + t('USDT/节点/月,每个节点都是独立云,都能扛攻击,建议均匀分配。') }}</p>
|
||||||
|
</div>
|
||||||
|
</el-scrollbar>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button @click="closeDialog('close')">{{ t('关 闭') }}</el-button>
|
||||||
|
<el-button type="primary" @click="submitForm" :loading="loading">{{ t('确 认') }}</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="AddDomain">
|
||||||
|
import SupplierSelect from '../components/SupplierSelect.vue';
|
||||||
|
import { addDomain } from "@/api/operation/domain";
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance();
|
||||||
|
|
||||||
|
// 接收参数
|
||||||
|
const props = defineProps({
|
||||||
|
supplierList: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
supplierConfig: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const domainNameCnt = ref(0),exceedDomainCost = ref(0),trafficG = ref(0),exceedTrafficCost = ref(0),freeNode = ref(0),exceedCost = ref(0);
|
||||||
|
|
||||||
|
const loading = ref(false);
|
||||||
|
const isShowDialog = ref(true); // 弹窗是否显示
|
||||||
|
const formRef = ref();
|
||||||
|
|
||||||
|
// 表单参数
|
||||||
|
const formData = reactive({
|
||||||
|
domainSupplierId: '',
|
||||||
|
domainNames: []
|
||||||
|
});
|
||||||
|
|
||||||
|
// 开通状态的节点数量
|
||||||
|
const openCount = computed(() => {
|
||||||
|
return props.supplierList.filter(item => item.isOpen).length;
|
||||||
|
});
|
||||||
|
nextTick(()=>{
|
||||||
|
console.log(props.supplierConfig)
|
||||||
|
domainNameCnt.value = props.supplierConfig.domainNameCnt;
|
||||||
|
exceedDomainCost.value = props.supplierConfig.exceedDomainCost;
|
||||||
|
trafficG.value = props.supplierConfig.trafficG;
|
||||||
|
exceedTrafficCost.value = props.supplierConfig.exceedTrafficCost;
|
||||||
|
})
|
||||||
|
|
||||||
|
const changeSupplier = (item) => {
|
||||||
|
freeNode.value = item.freeNode;
|
||||||
|
exceedCost.value = item.exceedCost;
|
||||||
|
};
|
||||||
|
// 表单校验
|
||||||
|
const rules = reactive({
|
||||||
|
domainSupplierId: [
|
||||||
|
{ required: true, message: proxy.t('请选择节点'), trigger: 'change' }
|
||||||
|
],
|
||||||
|
domainNames: [
|
||||||
|
{ required: true, message: proxy.t('域名不能为空'), trigger: ['blur', 'change'] },
|
||||||
|
// 域名校验
|
||||||
|
{
|
||||||
|
validator: (rule, value, callback) => {
|
||||||
|
const reg = /^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,6}$/;
|
||||||
|
if (value) {
|
||||||
|
if (value.split('\n').length > 20) {
|
||||||
|
callback(new Error(proxy.t('最多支持20个域名')));
|
||||||
|
} else {
|
||||||
|
const arr = value.split('\n');
|
||||||
|
for (let i = 0; i < arr.length; i++) {
|
||||||
|
if (!reg.test(arr[i])) {
|
||||||
|
callback(new Error(proxy.t('请输入正确的域名')));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
trigger: ['blur', 'change']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
// 提交
|
||||||
|
const submitForm = () => {
|
||||||
|
formRef.value.validate(valid => {
|
||||||
|
if (valid) {
|
||||||
|
const params = {
|
||||||
|
domainSupplierId: formData.domainSupplierId,
|
||||||
|
domainNames: formData.domainNames.split('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果domainNames出现重复的,提示用户
|
||||||
|
if (params.domainNames.length !== new Set(params.domainNames).size) {
|
||||||
|
proxy.$message.error(proxy.t('域名不能重复'));
|
||||||
|
} else {
|
||||||
|
loading.value = true;
|
||||||
|
addDomain(params).then(() => {
|
||||||
|
loading.value = false;
|
||||||
|
proxy.$message.success(proxy.t('添加成功'));
|
||||||
|
closeDialog('submit');
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭弹窗
|
||||||
|
const emit = defineEmits(['closeDialog']);
|
||||||
|
const closeDialog = (type) => {
|
||||||
|
emit('closeDialog', type);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
// 自定义表单label
|
||||||
|
.clt-item {
|
||||||
|
.label-box {
|
||||||
|
width: 100px;
|
||||||
|
|
||||||
|
span {
|
||||||
|
display: inline-block;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label-open {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #909399;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label-ds {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-right {
|
||||||
|
width: calc(100% - 100px);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 校验提示位置
|
||||||
|
:deep(.el-form-item__error) {
|
||||||
|
padding-left: 100px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-tips{
|
||||||
|
background-color: #ededee;
|
||||||
|
padding: 10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
|
||||||
|
h3{
|
||||||
|
margin: 0;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
line-height: 26px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,105 @@
|
||||||
|
<template>
|
||||||
|
<!-- 限额说明 -->
|
||||||
|
<el-dialog :title="t('限额说明')" v-model="isShowDialog" width="900px" append-to-body @close="closeDialog">
|
||||||
|
<el-scrollbar max-height="600px" v-loading="loading">
|
||||||
|
<div class="limit-box">
|
||||||
|
<h3>{{ t('1.域名不是越多越好:') }}</h3>
|
||||||
|
<div class="lb-text">
|
||||||
|
<p>
|
||||||
|
{{ t('因为每个节点的域名都要检测网络质量,然后再根据网络质量排序,若节点域名数量过多,每次巡检都要浪费1-2秒来测速,进而会导致网络卡顿的情况,建议每个功能用途控制在2-10个/节点。') }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<h3>{{ t('2.历史旧域名过多如何处理?:') }}</h3>
|
||||||
|
<div class="lb-text">
|
||||||
|
<p>
|
||||||
|
{{ t('历史使用过或旧的域名,建议用url转发跳转,不仅能保留权重,也能无限量跳转。') }}
|
||||||
|
</p>
|
||||||
|
<p><span>{{ t('(1)站点后台操作方法:批量选择域名》批量停用(等待5-10分钟生效) 》再批量删除域名即可。') }}</span></p>
|
||||||
|
<p><span>{{ t('(2)域名商后台操作方法:将dns改为域名商默认(如godaddy尊享版DNS)》勾选域名+批量设置转发。') }}</span></p>
|
||||||
|
</div>
|
||||||
|
<h3>{{ t('3.备用域名建议:') }}</h3>
|
||||||
|
<div class="lb-text">
|
||||||
|
<p>
|
||||||
|
{{ t('即暂不启用的域名,建议先只添加到主域名,暂不进行解析,以免还没启用就被拦截、劫持、封锁或被墙;等需要使用的时候再添加到各功能模块使用即可。') }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<h3>{{ t('4.收费说明:') }}</h3>
|
||||||
|
<div class="lb-text">
|
||||||
|
<p>
|
||||||
|
<b>{{ t('1、限顶级域名:') }}</b>
|
||||||
|
</p>
|
||||||
|
<p>{{ t('此处只能添加独立的顶级域名,请勿添加子域名,例如: 只能添加123.com,不是www.123.com,详见域名管理教程') }}</p>
|
||||||
|
<p>
|
||||||
|
<b>{{ t('2、节点说明:') }}</b>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<b>{{ t(' (1)中国市场(含港澳台):') }}</b>
|
||||||
|
{{ t('推荐使用alb域名(aws防封)、三方公共域名(aws与azure防封)、Wangsu (CDN+IP)、A8、Yundun(云盾)、Funnull(方能)、superEdge、大陆阿里云。') }}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<b>{{ t(' (2)全球市场(即非中国):') }}</b>
|
||||||
|
{{ t('推荐使用使用alb域名(aws与aliyun防封)、三方公共域名(aws与azure防封)、AWS、CF、腾讯云、 阿里云、 Google、Azure、华为云、Wangsu(CDN + IP)、Yundun (云盾)。') }}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<b>{{ t(' (3)Wangsu独立IP:') }}</b>
|
||||||
|
{{
|
||||||
|
t('提供独立IP地址,适用于会封禁域名,但不会封禁IP的国家(例如:印尼、中国、巴西、越南等),国际和中国大陆市场均可使用(即全球通用200USDT/IP/月),若超过7天未启用系统自动回收。')
|
||||||
|
}}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<b>{{ t(' (4)开放回源(仅限web大厅):') }}</b>
|
||||||
|
{{ t('提供开放独立源服务,可使用外部三方CDN,需申请开通(300U/月),需要专业人士配置websocket、HTTP2、缓存等,详见域名管理教程。') }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<h3>{{ t('3、域名解析限额:') }}</h3>
|
||||||
|
<div class="lb-text">
|
||||||
|
<p>{{ t('前30个域名免费(含子域名),超出部分额外收取5USDT/条解析/月;') }}</p>
|
||||||
|
</div>
|
||||||
|
<h3>{{ t('4、流量限额:') }}</h3>
|
||||||
|
<div class="lb-text"><p>{{ t('每月前500G免费,超出部分额外收取0.3USDT/G/月;') }}</p></div>
|
||||||
|
<h3>{{ t('5、节点限制:') }}</h3>
|
||||||
|
<div class="lb-text"><p>{{ t('免费提供3个节点,超出部分额外收取300USDT/节点/月,每个节点都是独立云,都能扛攻击,建议均匀分配。') }}</p></div>
|
||||||
|
</div>
|
||||||
|
</el-scrollbar>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button type="primary" @click="closeDialog">{{ t('关 闭') }}</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="ShowInfoDialog">
|
||||||
|
const loading = ref(false);
|
||||||
|
const isShowDialog = ref(true); // 弹窗是否显示
|
||||||
|
|
||||||
|
// 关闭弹窗
|
||||||
|
const emit = defineEmits(['closeDialog']);
|
||||||
|
const closeDialog = (type) => {
|
||||||
|
emit('closeDialog', type);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.limit-box {
|
||||||
|
h3{
|
||||||
|
margin: 0;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lb-text{
|
||||||
|
background-color: #ededee;
|
||||||
|
padding: 5px 10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
p {
|
||||||
|
line-height: 26px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,469 @@
|
||||||
|
<template>
|
||||||
|
<!-- 域名管理列表 -->
|
||||||
|
<table-search-card :model="queryParams" @getList="getList" :leftSpan="16" :rightSpan="8" @handleQuery="handleQuery()"
|
||||||
|
@resetQuery="resetQuery">
|
||||||
|
<template #left>
|
||||||
|
<select-input-form :queryParamsList="queryParamsList" v-model:queryParams="queryParams" :width="[130, 260]"
|
||||||
|
@handleQuery="handleQuery"></select-input-form>
|
||||||
|
<el-form-item prop="domainStatus" style="width: 150px;">
|
||||||
|
<CustomSelect clearable v-model="queryParams.domainStatus" :placeholder="t('主域名状态')"
|
||||||
|
:options="domainStatusOptions" @change="handleQuery"></CustomSelect>
|
||||||
|
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
<template #right>
|
||||||
|
<auto-refresh-time apiName="domainList" @refreshFn="getList" style="margin-right: 10px;"></auto-refresh-time>
|
||||||
|
<el-button type="success" plain icon="Plus" @click="openAddDomain" v-hasPermi="['operation:domain:add']">{{
|
||||||
|
t('新增') }}</el-button>
|
||||||
|
</template>
|
||||||
|
</table-search-card>
|
||||||
|
|
||||||
|
<!-- 查询表格 -->
|
||||||
|
<div class="domain-main">
|
||||||
|
<!-- 左侧供应商 -->
|
||||||
|
<div class="dm-left">
|
||||||
|
<el-scrollbar max-height="600px">
|
||||||
|
<!-- 供应商选择 -->
|
||||||
|
<supplier-button ref="supplierRef" v-model="queryParams.domainSupplierId" @change="handleQuery"
|
||||||
|
@getCurSupplierNode="getCurSupplierNode"></supplier-button>
|
||||||
|
|
||||||
|
<el-button size="large" style="width: calc(100% - 15px);" @click="isShowInfo = true">
|
||||||
|
<el-icon color="#E6A23C" style="margin-right: 5px;">
|
||||||
|
<InfoFilled />
|
||||||
|
</el-icon>{{ t(' 限额说明') }}
|
||||||
|
</el-button>
|
||||||
|
</el-scrollbar>
|
||||||
|
</div>
|
||||||
|
<!-- 右侧表格 -->
|
||||||
|
<div class="dm-right">
|
||||||
|
<el-table ref="tableRef" class="c-table-main" v-loading="loading" row-key="id" stripe border :data="dataList"
|
||||||
|
@select="tableSelect" @select-all="tableSelect">
|
||||||
|
<el-table-column align="center" type="selection" width="55" />
|
||||||
|
<el-table-column align="center" min-width="160">
|
||||||
|
<template #header>
|
||||||
|
<span>{{ t('CDN节点名称') }}</span>
|
||||||
|
<icon-tips v-if="currentNodeTips">
|
||||||
|
<p class="c-clear" style="width: 400px;">{{ currentNodeTips }}</p>
|
||||||
|
</icon-tips>
|
||||||
|
</template>
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ row.cdnNodeName }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column align="center" min-width="280">
|
||||||
|
<template #header>
|
||||||
|
<span>{{ t('主域名') }}</span>
|
||||||
|
<span style="color: #409EFF;"> ({{ t('子域名数') }})</span>
|
||||||
|
</template>
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ row.name }}
|
||||||
|
<!-- 子域名展示 -->
|
||||||
|
<el-popover placement="right" :width="524" trigger="click">
|
||||||
|
<template #reference>
|
||||||
|
<span class="c-blue"> ({{ row.operationDomainSons?.length }})</span>
|
||||||
|
</template>
|
||||||
|
<el-table :data="row.operationDomainSons">
|
||||||
|
<el-table-column width="200" align="center" property="name" :label="t('子域名')" />
|
||||||
|
<el-table-column width="150" align="center" property="date" :label="t('域名用途')">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<dict-text dictKey="operation_domain_son_type" :value="row.domainSonTypeType" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column width="150" align="center" property="date" :label="t('使用状态')">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<dict-text :colorValues="['c-grey', 'c-orange', 'c-orange', 'c-green', 'c-red']"
|
||||||
|
dictKey="operation_domain_son_usage_status" :value="row.usageStatus" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-popover>
|
||||||
|
<!-- 复制 -->
|
||||||
|
<copy-icon :text="row.name" class="copy-ml"></copy-icon>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column :label="t('验证方式')" align="center" min-width="320">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<!-- 正常 -->
|
||||||
|
<p class="c-clear" v-if="row.domainStatus == 2">
|
||||||
|
<!-- ,当前DNS为: -->
|
||||||
|
<span class="c-green">{{ t('验证已生效') }}</span>
|
||||||
|
<el-button link type="primary" @click="row.isShowDns = !row.isShowDns">{{ row.isShowDns ? t('收起') :
|
||||||
|
t('展开')
|
||||||
|
}}</el-button>
|
||||||
|
</p>
|
||||||
|
<!-- 待验证 -->
|
||||||
|
<p class="c-clear" v-if="row.domainStatus == 1">
|
||||||
|
<template v-if="row.dnsList.length">
|
||||||
|
<span>{{ t('请将DNS修改为以下服务器后:') }}</span>
|
||||||
|
<el-button v-if="!row.checkLoading" link type="primary" @click="opInfo(row, 'check')"
|
||||||
|
v-hasPermi="['operation:domain:check']">
|
||||||
|
{{ t('验证') }}
|
||||||
|
</el-button>
|
||||||
|
<el-icon v-else class="c-rotate" style="position: relative; top: 4px;" size="16"
|
||||||
|
color="#409EFF">
|
||||||
|
<Loading />
|
||||||
|
</el-icon>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<el-button v-if="!row.getNSLoading" link type="primary" @click="opInfo(row, 'getNS')"
|
||||||
|
v-hasPermi="['operation:domain:get:ns']">
|
||||||
|
{{ t('获取NS') }}
|
||||||
|
</el-button>
|
||||||
|
<el-icon v-else class="c-rotate" style="position: relative; top: 4px;" size="16"
|
||||||
|
color="#409EFF">
|
||||||
|
<Loading />
|
||||||
|
</el-icon>
|
||||||
|
</template>
|
||||||
|
</p>
|
||||||
|
<!-- 已过期、待找回 -->
|
||||||
|
<p class="c-clear c-grey" v-if="row.domainStatus == 3 || row.domainStatus == 4">{{ t('域名暂不可用') }}</p>
|
||||||
|
<!-- DNS -->
|
||||||
|
<template v-if="row.isShowDns || row.domainStatus == 1">
|
||||||
|
<p class="c-clear c-grey" v-for="(dns, index) in row.dnsList" :key="index">
|
||||||
|
{{ dns.valueType + ':' + dns.value }}
|
||||||
|
<copy-icon :text="dns.value" class="copy-ml"></copy-icon>
|
||||||
|
</p>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column :label="t('主域名状态')" align="center" min-width="150">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<dict-text :colorValues="['c-orange', 'c-green', 'c-grey', 'c-red']"
|
||||||
|
dictKey="ff_operation_domain_status" :value="row.domainStatus" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column :label="t('域名过期日期')" align="center" min-width="160">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ formatTime(row.overdueDate, 'YYYY-MM-DD') }}
|
||||||
|
<el-icon @click="opInfo(row, 'refresh')" :class="row.refreshLoading ? 'c-rotate' : ''"
|
||||||
|
style="position: relative; top: 4px; margin-left: 8px;" size="16" class="c-blue">
|
||||||
|
<Refresh />
|
||||||
|
</el-icon>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column :label="t('证书过期日期')" align="center" min-width="140">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ formatTime(row.certificateOverdueDate, 'YYYY-MM-DD') }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column :label="t('操作')" align="center" min-width="180">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-button v-if="!row.checkLoading && row.domainStatus == 1" link type="primary"
|
||||||
|
@click="opInfo(row, 'check')" v-hasPermi="['operation:domain:check']">
|
||||||
|
{{ t('验证') }}
|
||||||
|
</el-button>
|
||||||
|
<el-icon v-if="row.checkLoading" class="c-rotate" style="position: relative; top: 4px;" size="16"
|
||||||
|
color="#409EFF">
|
||||||
|
<Loading />
|
||||||
|
</el-icon>
|
||||||
|
<el-button v-if="row.domainStatus != 2" link type="primary" @click="opInfo(row, 'delete')"
|
||||||
|
v-hasPermi="['operation:domain:remove']">
|
||||||
|
{{ t('彻底删除') }}
|
||||||
|
</el-button>
|
||||||
|
<el-button v-if="row.domainStatus == 2" link type="primary" @click="opInfo(row, 'stop')"
|
||||||
|
v-hasPermi="['operation:domain:stop']">
|
||||||
|
{{ t('强制停用') }}
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<table-operation></table-operation>
|
||||||
|
</el-table>
|
||||||
|
<!-- 批量操作 -->
|
||||||
|
<table-batch-operate v-if="total > 0" v-model:batchOpType="batchOpType" v-model:isAllSelection="isAllSelection"
|
||||||
|
@allSelectionChange="allSelectionChange" @opTypeChange="opTypeChange" :selectionData="selectionData"
|
||||||
|
:opTypeOptions="opTypeOptions"></table-batch-operate>
|
||||||
|
<!-- 列表分页 -->
|
||||||
|
<pagination v-if="total > 0" :total="total" v-model:page="queryParams.pageNum"
|
||||||
|
v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 限额说明弹窗 -->
|
||||||
|
<show-content v-if="isShowInfo" @closeDialog="closeDialog"></show-content>
|
||||||
|
<!-- 新增域名弹窗 -->
|
||||||
|
<add-domain v-if="isShowAdd" :supplierConfig="supplierConfig" :supplierList="supplierList" @closeDialog="closeDialog"></add-domain>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="DomainManageList">
|
||||||
|
import {
|
||||||
|
getDomainList, // 域名列表
|
||||||
|
getDomainVerify, // 域名验证
|
||||||
|
getDomainExpireTime, // 刷新域名过期日期
|
||||||
|
setDomainStop, // 强制停用
|
||||||
|
getDomainNS, // 获取NS
|
||||||
|
delDomain, // 删除域名
|
||||||
|
getDomainConfig,
|
||||||
|
} from "@/api/operation/domain";
|
||||||
|
import AutoRefreshTime from "@/components/AutoRefreshTime"; // 定时刷新
|
||||||
|
import CopyIcon from "@/components/CopyIcon"; // 小图标复制
|
||||||
|
import IconTips from "@/components/IconTips"; // 小图标提示
|
||||||
|
import TableBatchOperate from '@/components/TableBatchOperate'; // 批量操作
|
||||||
|
import ShowContent from "./ShowContent.vue"; // 限额说明说明弹窗
|
||||||
|
import AddDomain from "./AddDomain.vue"; // 新增域名
|
||||||
|
import SupplierButton from "../components/SupplierButton.vue"; // 供应商选择按钮
|
||||||
|
import DictSelect from '@/components/DictSelect';
|
||||||
|
import DictText from '@/components/DictText';
|
||||||
|
import CustomSelect from '@/components/CustomSelect';
|
||||||
|
import { ref } from "vue";
|
||||||
|
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance();
|
||||||
|
const loading = ref(true); // loading状态
|
||||||
|
|
||||||
|
// 供应商
|
||||||
|
const supplierRef = ref(null), currentNodeTips = ref(''), supplierList = ref([]);
|
||||||
|
const supplierConfig = ref({ });
|
||||||
|
// 获取供应商节点信息
|
||||||
|
const getCurSupplierNode = (data) => {
|
||||||
|
currentNodeTips.value = data?.tips;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据下拉框条件输入搜索
|
||||||
|
const queryParamsList = ref([{
|
||||||
|
label: proxy.t('操作人'),
|
||||||
|
value: 'updateBy'
|
||||||
|
}, {
|
||||||
|
label: proxy.t('主域名'),
|
||||||
|
value: 'name'
|
||||||
|
}]);
|
||||||
|
const domainStatusOptions = ref([
|
||||||
|
{
|
||||||
|
label: proxy.t('待验证'),
|
||||||
|
value: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: proxy.t('正常'),
|
||||||
|
value: 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: proxy.t('已过期'),
|
||||||
|
value: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: proxy.t('待找回'),
|
||||||
|
value: 4
|
||||||
|
}
|
||||||
|
|
||||||
|
]);
|
||||||
|
// 搜索配置
|
||||||
|
const queryParams = reactive({
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 20,
|
||||||
|
searchType: 'updateBy',
|
||||||
|
name: '',
|
||||||
|
updateBy: '',
|
||||||
|
domainStatus: '',
|
||||||
|
orderByColumn: 'createTime',
|
||||||
|
isAsc: 'desc',
|
||||||
|
domainSupplierId: '' // 供应商
|
||||||
|
});
|
||||||
|
|
||||||
|
// 请求列表
|
||||||
|
const dataList = ref([]), total = ref(0);
|
||||||
|
const getList = () => {
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
getDomainList(queryParams).then(res => {
|
||||||
|
loading.value = false;
|
||||||
|
dataList.value = res.rows;
|
||||||
|
total.value = +res.total;
|
||||||
|
clearBatchOp(); // 清空批量操作痕迹
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
dataList.value = [];
|
||||||
|
total.value = 0;
|
||||||
|
clearBatchOp(); // 清空批量操作痕迹
|
||||||
|
});
|
||||||
|
}
|
||||||
|
getList();
|
||||||
|
|
||||||
|
// 新增域名
|
||||||
|
const openAddDomain = () => {
|
||||||
|
getDomainConfig({}).then(res => {
|
||||||
|
supplierConfig.value = res.data
|
||||||
|
supplierList.value = supplierRef.value?.supplierList; // 供应商列表
|
||||||
|
isShowAdd.value = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 操作信息
|
||||||
|
const opInfo = (row, type) => {
|
||||||
|
const _ids = row.id ? [row.id] : row; // 操作的id,有表格内点击和批量操作两种
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case 'check':
|
||||||
|
// 验证域名
|
||||||
|
if (row.id) {
|
||||||
|
row.checkLoading = true;
|
||||||
|
} else {
|
||||||
|
loading.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
getDomainVerify({ ids: _ids }).then(res => {
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('验证成功!'));
|
||||||
|
row.checkLoading = false;
|
||||||
|
getList();
|
||||||
|
}).catch(() => {
|
||||||
|
row.checkLoading = false;
|
||||||
|
loading.value = false;
|
||||||
|
batchOpType.value = '';
|
||||||
|
});
|
||||||
|
break
|
||||||
|
case 'getNS':
|
||||||
|
// 获取NS
|
||||||
|
row.getNSLoading = true;
|
||||||
|
|
||||||
|
getDomainNS(row.id).then(res => {
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('获取NS成功!'));
|
||||||
|
row.getNSLoading = false;
|
||||||
|
getList();
|
||||||
|
}).catch(() => {
|
||||||
|
row.getNSLoading = false;
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
break
|
||||||
|
case 'refresh':
|
||||||
|
// 刷新域名过期日期
|
||||||
|
if (row.id) {
|
||||||
|
row.refreshLoading = true;
|
||||||
|
} else {
|
||||||
|
loading.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
getDomainExpireTime({ ids: _ids }).then(res => {
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('刷新成功!'));
|
||||||
|
row.refreshLoading = false;
|
||||||
|
getList();
|
||||||
|
}).catch(() => {
|
||||||
|
row.refreshLoading = false;
|
||||||
|
loading.value = false;
|
||||||
|
batchOpType.value = '';
|
||||||
|
});
|
||||||
|
break
|
||||||
|
case 'stop':
|
||||||
|
// 强制停用
|
||||||
|
proxy.$modal.confirm(proxy.t('停用将停止解析域名,请谨慎操作!')).then(() => {
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
setDomainStop({ ids: _ids }).then(res => {
|
||||||
|
loading.value = false;
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('域名停用成功!'));
|
||||||
|
getList();
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
batchOpType.value = '';
|
||||||
|
});
|
||||||
|
}).catch(() => { });
|
||||||
|
break
|
||||||
|
case 'delete':
|
||||||
|
// 删除域名
|
||||||
|
proxy.$modal.confirm(proxy.t('删除主域名,子域名解析将被删除,请谨慎操作!')).then(() => {
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
delDomain(_ids.join(',')).then(res => {
|
||||||
|
loading.value = false;
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('删除成功!'));
|
||||||
|
getList();
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
batchOpType.value = '';
|
||||||
|
});
|
||||||
|
}).catch(() => { });
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 批量操作
|
||||||
|
const tableRef = ref(),
|
||||||
|
isAllSelection = ref(false), // 是否全选
|
||||||
|
selectionData = ref([]), // 选中的表格数据
|
||||||
|
batchOpType = ref(''); // 选中的批量操作类型
|
||||||
|
|
||||||
|
// 批量操作选项
|
||||||
|
const opTypeOptions = ref([
|
||||||
|
{ label: proxy.t('检查过期日期'), value: 'refresh' },
|
||||||
|
{ label: proxy.t('域名验证'), value: 'check' },
|
||||||
|
{ label: proxy.t('彻底删除'), value: 'delete' },
|
||||||
|
{ label: proxy.t('强制停用'), value: 'stop' }
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 勾选表格
|
||||||
|
const tableSelect = (val) => {
|
||||||
|
selectionData.value = val;
|
||||||
|
|
||||||
|
if (val.length === dataList.value.length) {
|
||||||
|
isAllSelection.value = true;
|
||||||
|
} else {
|
||||||
|
isAllSelection.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 全选表格
|
||||||
|
const allSelectionChange = () => {
|
||||||
|
tableRef.value.toggleAllSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 选择批量数据操作类型
|
||||||
|
const opTypeChange = () => {
|
||||||
|
const ids = selectionData.value.map(v => v.id);
|
||||||
|
opInfo(ids, batchOpType.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清空批量操作痕迹
|
||||||
|
const clearBatchOp = () => {
|
||||||
|
isAllSelection.value = false;
|
||||||
|
selectionData.value = [];
|
||||||
|
batchOpType.value = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 搜索按钮操作
|
||||||
|
const handleQuery = () => {
|
||||||
|
queryParams.pageNum = 1;
|
||||||
|
getList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置按钮操作
|
||||||
|
const resetQuery = () => {
|
||||||
|
handleQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭弹窗
|
||||||
|
const isShowInfo = ref(false), isShowAdd = ref(false);
|
||||||
|
const closeDialog = (type) => {
|
||||||
|
isShowAdd.value = false;
|
||||||
|
isShowInfo.value = false;
|
||||||
|
// getList();
|
||||||
|
if (type == 'submit') {
|
||||||
|
getList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang='scss'>
|
||||||
|
.domain-main {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
// 左侧
|
||||||
|
.dm-left {
|
||||||
|
width: 145px;
|
||||||
|
height: 100%;
|
||||||
|
border-right: 1px solid #e5e5e5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 右侧
|
||||||
|
.dm-right {
|
||||||
|
width: calc(100% - 160px);
|
||||||
|
margin-left: 15px;
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.copy-ml {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,370 @@
|
||||||
|
<template>
|
||||||
|
<table-search-card :model="queryParams" @getList="getList" @handleQuery="handleQuery()"
|
||||||
|
@resetQuery="resetQuery">
|
||||||
|
<template #left>
|
||||||
|
<el-form-item prop="supplierCode">
|
||||||
|
<el-input v-model="queryParams.supplierCode" placeholder="请输入服务商code" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
<template #right>
|
||||||
|
<el-button type="primary" plain icon="Plus" @click="openAddDomainNameProvider" v-hasPermi="['operation:supplier:add']">{{
|
||||||
|
t('新增') }}</el-button>
|
||||||
|
<el-button type="primary" @click="openConfigSupplier" v-hasPermi="['operation:supplier:config:query']">{{
|
||||||
|
t('配置信息') }}</el-button>
|
||||||
|
</template>
|
||||||
|
</table-search-card>
|
||||||
|
<el-table
|
||||||
|
v-loading="loading"
|
||||||
|
class="c-table-main"
|
||||||
|
:data="deptList"
|
||||||
|
row-key="id"
|
||||||
|
border
|
||||||
|
stripe
|
||||||
|
>
|
||||||
|
|
||||||
|
<el-table-column prop="supplierCode" label="服务商code" min-width="160"></el-table-column>
|
||||||
|
|
||||||
|
<el-table-column prop="supplierName" label="供应商名称" min-width="160"></el-table-column>
|
||||||
|
<el-table-column prop="currencyCode" label="币种代码" min-width="110"></el-table-column>
|
||||||
|
<el-table-column prop="freeNode" label="免费节点数量" min-width="150">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ row.freeNode }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column :label="t('停用状态')" align="center" prop="stopStatus" v-hasPermi="['operation:supplier:switch']" label-class-name="text-warning">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<base-switch v-model="row.stopStatus" :active-value="true" :inactive-value="false"
|
||||||
|
:before-change="() => beforeSwitchChange(row, 'stopStatus')" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="status" label="超出自由节点" min-width="150">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ row.exceedFreeNode }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="exceedCost" label="超出费用/节点/月" width="200">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ row.exceedCost }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="创建时间" align="center" prop="createTime" width="200">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ parseTime(scope.row.createTime)||'--' }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" align="center" min-width="150" class-name="small-padding fixed-width">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button link type="primary" @click="handleUpdate(scope.row)" v-hasPermi="['operation:supplier:edit']">修改</el-button>
|
||||||
|
<el-button v-if="scope.row.parentId != 0" link type="primary" @click="handleDelete(scope.row)" v-hasPermi="['operation:supplier:remove']">删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<pagination
|
||||||
|
v-show="total > 0"
|
||||||
|
:total="total"
|
||||||
|
v-model:page="queryParams.pageNum"
|
||||||
|
v-model:limit="queryParams.pageSize"
|
||||||
|
@pagination="getList"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 添加或修改部门对话框 -->
|
||||||
|
<el-dialog :title="title" align-center v-model="open" width="800px" append-to-body>
|
||||||
|
<el-form ref="deptRef" :model="form" :rules="rules" label-width="170px">
|
||||||
|
<el-form-item label="供应商名称" prop="supplierName">
|
||||||
|
<el-input v-model="form.supplierName" placeholder="请输入供应商名称" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="服务商code" prop="supplierCode">
|
||||||
|
<el-input v-model="form.supplierCode" placeholder="请输入服务商code" />
|
||||||
|
</el-form-item>
|
||||||
|
<!-- <el-form-item label="币种" prop="deptName">
|
||||||
|
<custom-select v-model="form.currencyType" :options="currencySelectArr" style="width: 220px;"></custom-select>
|
||||||
|
</el-form-item> -->
|
||||||
|
<el-form-item label="供应商类型" prop="supplierType">
|
||||||
|
<custom-select v-model="form.supplierType" :options="supplierTypeSelectArr" style=""></custom-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="自定义解析类型" prop="analysisType">
|
||||||
|
<custom-select v-model="form.analysisType" :options="analysisTypeSelectArr" style=""></custom-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="免费节点数量" prop="freeNode">
|
||||||
|
<el-input v-model="form.freeNode" placeholder="请输入免费节点数量" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="允许超出免费节点数量" prop="exceedFreeNode">
|
||||||
|
<el-input v-model="form.exceedFreeNode" placeholder="请输入允许超出免费节点数量" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="超出费用/节点/月" prop="exceedCost">
|
||||||
|
<el-input v-model="form.exceedCost" placeholder="请输入超出费用/节点/月" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="防封" prop="prohibit">
|
||||||
|
<el-switch v-model="form.prohibit" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="是否支持alb负载均衡" prop="supportAlb">
|
||||||
|
<el-switch v-model="form.supportAlb" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="停用状态" prop="stopStatus">
|
||||||
|
<el-switch v-model="form.stopStatus" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||||
|
<el-button @click="cancel">取 消</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
<el-dialog :title="t('配置信息')" align-center v-model="showConfigSupplier" width="700px" append-to-body>
|
||||||
|
<el-form ref="configRef" :model="formConfig" :rules="rulesConfig" label-width="170px">
|
||||||
|
<el-form-item label="域名解析数量" prop="domainNameCnt">
|
||||||
|
<el-input v-model="formConfig.domainNameCnt" placeholder="请输入域名解析数量" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="超出域名数量收费" prop="exceedDomainCost">
|
||||||
|
<el-input v-model="formConfig.exceedDomainCost" placeholder="请输入超出域名数量收费" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="流量G" prop="trafficG">
|
||||||
|
<el-input v-model="formConfig.trafficG" placeholder="请输入流量G" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="超出流量部分收费" prop="exceedTrafficCost">
|
||||||
|
<el-input v-model="formConfig.exceedTrafficCost" placeholder="请输入超出流量部分收费" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button type="primary" @click="submitConfig">确 定</el-button>
|
||||||
|
<el-button @click="cancelConfig">取 消</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="Dept">
|
||||||
|
import { listDept, getDept, delDept, addDept, updateDept, listDeptExcludeChild } from "@/api/system/dept";
|
||||||
|
import { getDomainSupplierList,switchDomainSupplier,addDomainSupplier,putDomainSupplier,delDomainSupplier,getDomainSupplierInfo,getDomainSupplierConfig,configDomainSupplier } from "@/api/operation/domainNameProvider";
|
||||||
|
import baseSwitch from "@/components/BaseSwitch";
|
||||||
|
import CustomSelect from '@/components/CustomSelect';
|
||||||
|
const { proxy } = getCurrentInstance();
|
||||||
|
const { sys_normal_disable } = proxy.useDict("sys_normal_disable");
|
||||||
|
|
||||||
|
const deptList = ref([]);
|
||||||
|
const total = ref(0);
|
||||||
|
const open = ref(false);
|
||||||
|
const loading = ref(true);
|
||||||
|
const showSearch = ref(true);
|
||||||
|
const title = ref("");
|
||||||
|
const deptOptions = ref([]);
|
||||||
|
const isExpandAll = ref(true);
|
||||||
|
const refreshTable = ref(true);
|
||||||
|
const oldForm = shallowRef({ });
|
||||||
|
const showConfigSupplier = ref(false);
|
||||||
|
const formConfig = ref({
|
||||||
|
});
|
||||||
|
const rulesConfig = reactive({
|
||||||
|
domainNameCnt: [
|
||||||
|
{ required: true, message: "请输入域名数量", trigger: "change" },
|
||||||
|
],
|
||||||
|
exceedDomainCost: [
|
||||||
|
{ required: true, message: "请输入超出域名单价", trigger: "change" },
|
||||||
|
],
|
||||||
|
trafficG: [
|
||||||
|
{ required: true, message: "请输入流量单价", trigger: "change" },
|
||||||
|
],
|
||||||
|
exceedTrafficCost: [
|
||||||
|
{ required: true, message: "请输入超出流量单价", trigger: "change" },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
const data = reactive({
|
||||||
|
form: {},
|
||||||
|
queryParams: {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 20,
|
||||||
|
orderByColumn:'createTime',
|
||||||
|
isAsc:'desc'
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
supplierName: [
|
||||||
|
{ required: true, message: "请输入供应商名称", trigger: "change" },
|
||||||
|
{ min: 2, max: 20, message: "长度在 2 到 20 个字符", trigger: "change" },
|
||||||
|
],
|
||||||
|
supplierCode: [
|
||||||
|
{ required: true, message: "请输入供应商编号", trigger: "change" },
|
||||||
|
],
|
||||||
|
supplierType: [
|
||||||
|
{ required: true, message: "请选择供应商类型", trigger: "change" },
|
||||||
|
],
|
||||||
|
analysisType: [
|
||||||
|
{ required: true, message: "请选择供应商类型", trigger: "change" },
|
||||||
|
],
|
||||||
|
freeNode: [
|
||||||
|
{ required: true, message: "请选择供应商类型", trigger: "change" },
|
||||||
|
],
|
||||||
|
exceedFreeNode: [
|
||||||
|
{ required: true, message: "请选择供应商类型", trigger: "change" },
|
||||||
|
],
|
||||||
|
exceedCost: [
|
||||||
|
{ required: true, message: "请选择供应商类型", trigger: "change" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const { queryParams, form, rules } = toRefs(data);
|
||||||
|
|
||||||
|
const supplierTypeSelectArr = ref([
|
||||||
|
{ label: "全球", value: "1" },
|
||||||
|
{ label: "大陆", value: "2" },
|
||||||
|
{ label: "国际", value: "3" },
|
||||||
|
])
|
||||||
|
const analysisTypeSelectArr = ref([
|
||||||
|
{ label: "正常解析", value: "1" },
|
||||||
|
{ label: "支持更换请求协议", value: "2" },
|
||||||
|
])
|
||||||
|
// const currencySelectArr = getLocalStorage('currencySelect')?.map(item => {
|
||||||
|
// return {
|
||||||
|
// label: `${item.currencyName}(${item.currencyCode})`,
|
||||||
|
// value: item.currencyCode
|
||||||
|
// };
|
||||||
|
// });
|
||||||
|
/** 查询部门列表 */
|
||||||
|
function getList() {
|
||||||
|
loading.value = true;
|
||||||
|
getDomainSupplierList(queryParams.value).then(response => {
|
||||||
|
deptList.value = response.rows;
|
||||||
|
total.value = response.total;
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 取消按钮 */
|
||||||
|
function cancel() {
|
||||||
|
open.value = false;
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 表单重置 */
|
||||||
|
function reset() {
|
||||||
|
form.value = {
|
||||||
|
deptId: undefined,
|
||||||
|
parentId: undefined,
|
||||||
|
deptName: undefined,
|
||||||
|
orderNum: 0,
|
||||||
|
leader: undefined,
|
||||||
|
phone: undefined,
|
||||||
|
email: undefined,
|
||||||
|
status: "0"
|
||||||
|
};
|
||||||
|
proxy.resetForm("deptRef");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 搜索按钮操作 */
|
||||||
|
function handleQuery() {
|
||||||
|
getList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 重置按钮操作 */
|
||||||
|
function resetQuery() {
|
||||||
|
proxy.resetForm("queryRef");
|
||||||
|
handleQuery();
|
||||||
|
}
|
||||||
|
const switchBeforeChange = () => {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
const beforeSwitchChange = async (row, undateKeys) => {
|
||||||
|
const _status = row[undateKeys] == true ? false : true
|
||||||
|
const _data = {
|
||||||
|
id: row.id
|
||||||
|
}
|
||||||
|
_data[undateKeys] = _status
|
||||||
|
try {
|
||||||
|
await switchDomainSupplier(_data).then(() => {
|
||||||
|
proxy.$modal.msgSuccess(_status === 1 ? proxy.t('开启成功') : proxy.t('关闭成功'))
|
||||||
|
getList()
|
||||||
|
})
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(proxy.t('接口调用失败'), error);
|
||||||
|
return false; // 阻止开关状态改变
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/** 新增按钮操作 */
|
||||||
|
function openAddDomainNameProvider(row) {
|
||||||
|
reset();
|
||||||
|
open.value = true;
|
||||||
|
title.value = "新增域名供应商";
|
||||||
|
}
|
||||||
|
//配置
|
||||||
|
const openConfigSupplier = async (row) => {
|
||||||
|
getDomainSupplierConfig({ }).then(res => {
|
||||||
|
formConfig.value = res.data;
|
||||||
|
showConfigSupplier.value = true;
|
||||||
|
oldForm.value = JSON.stringify(formConfig.value);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const cancelConfig = () => {
|
||||||
|
reset();
|
||||||
|
showConfigSupplier.value = false;
|
||||||
|
}
|
||||||
|
const submitConfig = async () => {
|
||||||
|
proxy.$refs["configRef"].validate(valid => {
|
||||||
|
if (valid) {
|
||||||
|
if (JSON.stringify(formConfig.value) != oldForm.value) {
|
||||||
|
configDomainSupplier(formConfig.value).then(res => {
|
||||||
|
proxy.$message.success(proxy.t('修改成功'));
|
||||||
|
cancelConfig();
|
||||||
|
getList();
|
||||||
|
})
|
||||||
|
}else{
|
||||||
|
cancelConfig();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
/** 修改按钮操作 */
|
||||||
|
function handleUpdate(row) {
|
||||||
|
reset();
|
||||||
|
getDomainSupplierInfo(row.id).then(response => {
|
||||||
|
form.value = response.data;
|
||||||
|
open.value = true;
|
||||||
|
title.value = "修改域名供应商";
|
||||||
|
setTimeout(() => {
|
||||||
|
let objForm = form.value
|
||||||
|
oldForm.value = JSON.stringify(objForm);
|
||||||
|
}, 500);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 提交按钮 */
|
||||||
|
function submitForm() {
|
||||||
|
proxy.$refs["deptRef"].validate(valid => {
|
||||||
|
if (valid) {
|
||||||
|
if (form.value.id != undefined) {
|
||||||
|
if (JSON.stringify(form.value) != oldForm.value) {
|
||||||
|
putDomainSupplier(form.value).then(response => {
|
||||||
|
proxy.$modal.msgSuccess("修改成功");
|
||||||
|
open.value = false;
|
||||||
|
getList();
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
open.value = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
addDomainSupplier(form.value).then(response => {
|
||||||
|
proxy.$modal.msgSuccess("新增成功");
|
||||||
|
open.value = false;
|
||||||
|
getList();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除按钮操作 */
|
||||||
|
function handleDelete(row) {
|
||||||
|
proxy.$modal.confirm('是否确认删除名称为"' + row.supplierName + '"的数据项?').then(function() {
|
||||||
|
return delDomainSupplier(row.id);
|
||||||
|
}).then(() => {
|
||||||
|
getList();
|
||||||
|
proxy.$modal.msgSuccess("删除成功");
|
||||||
|
}).catch(() => {});
|
||||||
|
}
|
||||||
|
|
||||||
|
getList();
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,109 @@
|
||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<!-- 全局搜索 -->
|
||||||
|
<el-input v-model="domainName" class="domain-search-input" :placeholder="t('全局搜索域名')">
|
||||||
|
<template #suffix>
|
||||||
|
<el-icon @click="searchDomain" :class="'el-input__icon ' + (searchLoading ? 'c-rotate' : '')"
|
||||||
|
style="cursor: pointer;">
|
||||||
|
<Search v-if="!searchLoading" />
|
||||||
|
<Loading v-else />
|
||||||
|
</el-icon>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
|
||||||
|
<!-- 标签页 -->
|
||||||
|
<el-tabs v-model="activeName" @tab-click="tabClick">
|
||||||
|
<el-tab-pane name="domainManage" :label="t('域名管理')" v-hasPermi="['operation:domain:list']"></el-tab-pane>
|
||||||
|
<el-tab-pane name="DomainNameProvider" :label="t('域名供应商管理')" v-hasPermi="['operation:son:web:list']"></el-tab-pane>
|
||||||
|
<!-- <el-tab-pane name="webHall" :label="t('Web大厅')" v-hasPermi="['operation:son:web:list']"></el-tab-pane> -->
|
||||||
|
<!-- <el-tab-pane name="backend" :label="t('后端加速域名')" v-hasPermi="['operation:son:backend:list']"></el-tab-pane>
|
||||||
|
<el-tab-pane name="appHall" :label="t('App大厅')" v-hasPermi="['operation:son:app:list']"></el-tab-pane>
|
||||||
|
<el-tab-pane name="oss" :label="t('OSS加速域名')" v-hasPermi="['operation:son:oss:list']"></el-tab-pane>
|
||||||
|
<el-tab-pane name="downloadSite" :label="t('下载站域名')" v-hasPermi="['operation:son:download:list']"></el-tab-pane>
|
||||||
|
<el-tab-pane name="payment" :label="t('支付域名')" v-hasPermi="['operation:son:pay:list']"></el-tab-pane>
|
||||||
|
<el-tab-pane name="whiteList" :label="t('外部白名单域名(含担保)')" v-hasPermi="['operation:whitelist:list']"></el-tab-pane>
|
||||||
|
<el-tab-pane name="customParsing" :label="t('自定义解析')" v-hasPermi="['operation:analysis:list']"></el-tab-pane> -->
|
||||||
|
</el-tabs>
|
||||||
|
|
||||||
|
<!-- 列表组件 -->
|
||||||
|
<div class="tabs-main-box">
|
||||||
|
<domain-manage-list v-if="activeName === 'domainManage'"></domain-manage-list>
|
||||||
|
<domainName-provider v-if="activeName === 'DomainNameProvider'"></domainName-provider>
|
||||||
|
<!-- <web-hall-list v-if="activeName === 'webHall'" @goDomainManage="goDomainManage" :searchResult="searchResult"></web-hall-list>
|
||||||
|
<backend-list v-if="activeName === 'backend'" @goDomainManage="goDomainManage" :searchResult="searchResult"></backend-list>
|
||||||
|
<app-hall-list v-if="activeName === 'appHall'" @goDomainManage="goDomainManage" :searchResult="searchResult"></app-hall-list>
|
||||||
|
<oss-list v-if="activeName === 'oss'" @goDomainManage="goDomainManage" :searchResult="searchResult"></oss-list>
|
||||||
|
<download-site-list v-if="activeName === 'downloadSite'" @goDomainManage="goDomainManage" :searchResult="searchResult"></download-site-list>
|
||||||
|
<payment-list v-if="activeName === 'payment'" @goDomainManage="goDomainManage" :searchResult="searchResult"></payment-list>
|
||||||
|
<white-list v-if="activeName === 'whiteList'"></white-list>
|
||||||
|
<custom-parsing v-if="activeName === 'customParsing'"></custom-parsing> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 域名管理 -->
|
||||||
|
<script setup name="Domain">
|
||||||
|
import { getSonDomainSearch } from "@/api/operation/domain"; // 子域名搜索
|
||||||
|
import DomainManageList from './domainManage/index.vue'; // 域名管理列表
|
||||||
|
import DomainNameProvider from './domainNameProvider/index.vue'; // 域名提供方
|
||||||
|
import WebHallList from './sonDomainList/WebHallList.vue'; // web大厅列表
|
||||||
|
import BackendList from './sonDomainList/BackendList.vue'; // 后端加速列表
|
||||||
|
import AppHallList from './sonDomainList/AppHallList.vue'; // app大厅列表
|
||||||
|
import OssList from './sonDomainList/OssList.vue'; // oss加速列表
|
||||||
|
import DownloadSiteList from './sonDomainList/DownloadSiteList.vue'; // 下载站列表
|
||||||
|
import PaymentList from './sonDomainList/PaymentList.vue' // 支付域名列表
|
||||||
|
import WhiteList from './whiteList/index.vue'; // 外部白名单
|
||||||
|
import CustomParsing from './customParsing/index.vue'; // 自定义解析
|
||||||
|
|
||||||
|
// 默认tab页
|
||||||
|
const activeName = ref('domainManage');
|
||||||
|
|
||||||
|
// 子组件跳转过来,展示域名管理tab页
|
||||||
|
const goDomainManage = () => {
|
||||||
|
activeName.value = 'domainManage';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 全局搜索域名
|
||||||
|
const tabNames = ['webHall', 'backend', 'appHall', 'oss', 'downloadSite', 'payment'], // 根据返回域名类型,来定位,顺序不能更改 字典 operation_domain_son_type
|
||||||
|
searchLoading = ref(false), // 搜索loading状态
|
||||||
|
domainName = ref(''), // 搜索域名
|
||||||
|
searchResult = ref({}); // 搜索结果
|
||||||
|
|
||||||
|
const searchDomain = () => {
|
||||||
|
if (!domainName.value) return;
|
||||||
|
searchLoading.value = true;
|
||||||
|
|
||||||
|
getSonDomainSearch({ name: domainName.value }).then(res => {
|
||||||
|
searchLoading.value = false;
|
||||||
|
|
||||||
|
// 搜索结果定位
|
||||||
|
activeName.value = tabNames[res.data.domainSonTypeType - 1];
|
||||||
|
searchResult.value = {
|
||||||
|
type: 'domainName',
|
||||||
|
domainName: domainName.value,
|
||||||
|
domainSupplierId: res.data.domainSupplierId
|
||||||
|
};
|
||||||
|
}).catch(() => {
|
||||||
|
searchLoading.value = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// tab切换
|
||||||
|
const tabClick = () => {
|
||||||
|
searchResult.value = {};
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang='scss'>
|
||||||
|
.app-container {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.domain-search-input {
|
||||||
|
width: 240px;
|
||||||
|
position: absolute;
|
||||||
|
right: 15px;
|
||||||
|
top: 15px;
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,404 @@
|
||||||
|
<template>
|
||||||
|
<!-- APP大厅域名列表 -->
|
||||||
|
<table-search-card :model="queryParams" @getList="getList" :leftSpan="16" :rightSpan="8" @handleQuery="handleQuery()"
|
||||||
|
@resetQuery="resetQuery">
|
||||||
|
<template #left>
|
||||||
|
<select-input-form :queryParamsList="queryParamsList" v-model:queryParams="queryParams" :width="[130, 260]"
|
||||||
|
@handleQuery="handleQuery"></select-input-form>
|
||||||
|
<el-form-item prop="usageStatus" style="width: 150px;">
|
||||||
|
<dict-select clearable v-model="queryParams.usageStatus" :placeholder="t('使用状态')"
|
||||||
|
dictKey="operation_domain_son_usage_status" @change="handleQuery"></dict-select>
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
<template #right>
|
||||||
|
<auto-refresh-time apiName="appDomainList" @refreshFn="getList"
|
||||||
|
style="margin-right: 10px;"></auto-refresh-time>
|
||||||
|
<el-button type="success" plain icon="Plus" @click="openAddDomain" v-hasPermi="['operation:son:app:add']">{{
|
||||||
|
t('新增') }}</el-button>
|
||||||
|
</template>
|
||||||
|
</table-search-card>
|
||||||
|
|
||||||
|
<!-- 查询表格 -->
|
||||||
|
<div class="domain-main">
|
||||||
|
<!-- 左侧供应商 -->
|
||||||
|
<div class="dm-left">
|
||||||
|
<el-scrollbar max-height="600px">
|
||||||
|
<!-- 供应商选择 -->
|
||||||
|
<supplier-button ref="supplierRef" v-model="queryParams.domainSupplierId" @change="handleQuery"
|
||||||
|
@getCurSupplierNode="getCurSupplierNode"></supplier-button>
|
||||||
|
</el-scrollbar>
|
||||||
|
</div>
|
||||||
|
<!-- 右侧表格 -->
|
||||||
|
<div class="dm-right">
|
||||||
|
<el-alert v-if="currentNodeTips" style="margin-bottom: 15px;" :title="currentNodeTips" :closable="false"
|
||||||
|
type="warning" show-icon />
|
||||||
|
|
||||||
|
<el-table ref="tableRef" class="c-table-main" v-loading="loading" row-key="id" stripe border :data="dataList"
|
||||||
|
@select="tableSelect" @select-all="tableSelect">
|
||||||
|
<el-table-column align="center" type="selection" width="55" />
|
||||||
|
<el-table-column :label="t('CDN节点名称')" align="center" min-width="160">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ row.cdnNodeName }}
|
||||||
|
<dict-text class="c-green" dictKey="ff_operation_son_type" :value="row.sonType" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column align="center" min-width="280">
|
||||||
|
<template #header>
|
||||||
|
<span>{{ t('生效域名') }}</span>
|
||||||
|
</template>
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ row.name }}<copy-icon :text="row.name" class="copy-ml"></copy-icon>
|
||||||
|
<p :class="'c-clear ' + (row.analyzeStatus ? 'c-green' : 'c-red')">{{ row.analyzeStatus ? t('已解析') :
|
||||||
|
t('待解析') }}</p>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column align="center" min-width="220">
|
||||||
|
<template #header>
|
||||||
|
<span>{{ t('解析说明(生效状态和网速)') }}</span>
|
||||||
|
</template>
|
||||||
|
<template #default="{ row }">
|
||||||
|
<span :class="'c-clear ' + (row.analyzeInvalid ? 'c-green' : 'c-red')">{{ row.analyzeInvalid ?
|
||||||
|
t('已生效') : t('未生效') }}</span>
|
||||||
|
<el-icon @click="opInfo(row, 'refresh')" :class="row.refreshLoading ? 'c-rotate' : ''"
|
||||||
|
style="position: relative; top: 4px; margin-left: 8px;" size="16" class="c-blue">
|
||||||
|
<Refresh />
|
||||||
|
</el-icon>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column :label="t('使用状态')" align="center" min-width="120">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<dict-text :colorValues="['c-grey', 'c-orange', 'c-orange', 'c-green', 'c-red']"
|
||||||
|
dictKey="operation_domain_son_usage_status" :value="row.usageStatus" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<table-operation></table-operation>
|
||||||
|
<el-table-column :label="t('操作')" align="center" min-width="220" fixed="right">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-button v-if="row.usageStatus == 4" link type="primary" @click="opInfo(row, 'clearCache')"
|
||||||
|
v-hasPermi="['operation:son:app:clear']">
|
||||||
|
{{ t('清理缓存') }}
|
||||||
|
</el-button>
|
||||||
|
<el-tooltip v-if="row.usageStatus == 1 || row.usageStatus == 5" effect="dark"
|
||||||
|
:content="t('提示:启用后请等待1分钟再操作')" placement="top">
|
||||||
|
<el-button link type="primary" @click="opInfo(row, 'status')"
|
||||||
|
v-hasPermi="['operation:son:app:status']">
|
||||||
|
{{ t('启用') }}
|
||||||
|
</el-button>
|
||||||
|
</el-tooltip>
|
||||||
|
<el-tooltip v-if="row.usageStatus == 2 || row.usageStatus == 3 || row.usageStatus == 4" effect="dark"
|
||||||
|
:content="t('提示:停用后请等待1分钟再操作')" placement="top">
|
||||||
|
<el-button link type="primary" @click="opInfo(row, 'status')"
|
||||||
|
v-hasPermi="['operation:son:app:status']">
|
||||||
|
{{ t('停用') }}
|
||||||
|
</el-button>
|
||||||
|
</el-tooltip>
|
||||||
|
<el-button v-if="row.usageStatus == 1 && row.sonType != -1 && row.sonType != -2" link type="primary"
|
||||||
|
@click="opInfo(row, 'edit')" v-hasPermi="['operation:son:app:edit']">
|
||||||
|
{{ t('修改') }}
|
||||||
|
</el-button>
|
||||||
|
<el-button v-if="row.usageStatus == 1 || row.usageStatus == 5" link type="primary"
|
||||||
|
@click="opInfo(row, 'delete')" v-hasPermi="['operation:son:app:remove']">
|
||||||
|
{{ t('删除') }}
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<!-- 批量操作 -->
|
||||||
|
<table-batch-operate v-if="total > 0" v-model:batchOpType="batchOpType" v-model:isAllSelection="isAllSelection"
|
||||||
|
@allSelectionChange="allSelectionChange" @opTypeChange="opTypeChange" :selectionData="selectionData"
|
||||||
|
:opTypeOptions="opTypeOptions"></table-batch-operate>
|
||||||
|
<!-- 列表分页 -->
|
||||||
|
<pagination v-if="total > 0" :total="total" v-model:page="queryParams.pageNum"
|
||||||
|
v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 新增域名弹窗 -->
|
||||||
|
<add-son-domain v-if="isShowAdd" type="appHall" :supplierList="supplierList" @goDomainManage="goDomainManage"
|
||||||
|
@closeDialog="closeDialog"></add-son-domain>
|
||||||
|
|
||||||
|
<!-- 修改域名弹窗 -->
|
||||||
|
<edit-son-domain v-if="isShowEdit" type="appHall" :currentDomainInfo="currentDomainInfo"
|
||||||
|
@closeDialog="closeDialog"></edit-son-domain>
|
||||||
|
|
||||||
|
<!-- 批量操作弹窗 -->
|
||||||
|
<batch-operation v-if="isShowBatchOp" type="appHall" :batchOpType="batchOpType" :selectionData="selectionData"
|
||||||
|
@closeDialog="closeDialog"></batch-operation>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="AppHallList">
|
||||||
|
import {
|
||||||
|
getAppDomainList, // 域名列表
|
||||||
|
refreshAppDomainAnalysis, // 刷新解析说明
|
||||||
|
setAppDomainStatus, // 域名状态切换
|
||||||
|
clearAppDomainCache, // 清理缓存
|
||||||
|
delAppDomain // 删除域名
|
||||||
|
} from "@/api/operation/domain";
|
||||||
|
import AutoRefreshTime from "@/components/AutoRefreshTime"; // 定时刷新
|
||||||
|
import CopyIcon from "@/components/CopyIcon"; // 小图标复制
|
||||||
|
import TableBatchOperate from '@/components/TableBatchOperate'; // 批量操作
|
||||||
|
import SupplierButton from "../components/SupplierButton.vue"; // 供应商选择按钮
|
||||||
|
import AddSonDomain from "../components/AddSonDomain.vue"; // 新增子域名弹窗
|
||||||
|
import EditSonDomain from "../components/EditSonDomain.vue"; // 修改子域名弹窗
|
||||||
|
import BatchOperation from "../components/BatchOperation.vue"; // 批量操作弹窗
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
// 全局搜索结果
|
||||||
|
searchResult: {
|
||||||
|
type: Object,
|
||||||
|
default: {}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance();
|
||||||
|
const loading = ref(true); // loading状态
|
||||||
|
const isShowAdd = ref(false), isShowEdit = ref(false), isShowBatchOp = ref(false); // 各弹窗状态
|
||||||
|
|
||||||
|
// 获取供应商节点信息
|
||||||
|
const supplierRef = ref(null), currentNodeTips = ref(''), supplierList = ref([]);
|
||||||
|
const getCurSupplierNode = (data) => {
|
||||||
|
currentNodeTips.value = data?.tips;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据下拉框条件输入搜索
|
||||||
|
const queryParamsList = ref([{
|
||||||
|
label: proxy.t('操作人'),
|
||||||
|
value: 'updateBy'
|
||||||
|
}, {
|
||||||
|
label: proxy.t('子域名'),
|
||||||
|
value: 'name'
|
||||||
|
}]);
|
||||||
|
|
||||||
|
// 搜索配置
|
||||||
|
const queryParams = reactive({
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 20,
|
||||||
|
searchType: 'updateBy',
|
||||||
|
name: '', // 子域名
|
||||||
|
updateBy: '', // 操作人
|
||||||
|
usageStatus: '', // 使用状态
|
||||||
|
orderByColumn: 'createTime',
|
||||||
|
isAsc: 'desc',
|
||||||
|
domainSupplierId: '' // 供应商
|
||||||
|
});
|
||||||
|
|
||||||
|
// 请求列表
|
||||||
|
const dataList = ref([]), total = ref(0);
|
||||||
|
const getList = () => {
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
getAppDomainList(queryParams).then(res => {
|
||||||
|
loading.value = false;
|
||||||
|
dataList.value = res.rows;
|
||||||
|
total.value = +res.total;
|
||||||
|
clearBatchOp(); // 清空批量操作痕迹
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
dataList.value = [];
|
||||||
|
total.value = 0;
|
||||||
|
clearBatchOp(); // 清空批量操作痕迹
|
||||||
|
});
|
||||||
|
}
|
||||||
|
getList();
|
||||||
|
|
||||||
|
// 新增域名
|
||||||
|
const openAddDomain = () => {
|
||||||
|
supplierList.value = supplierRef.value?.supplierList.filter(v => v.isOpen && !v.stopStatus); // 已开通且不是维护状态的供应商
|
||||||
|
isShowAdd.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 操作信息
|
||||||
|
const currentDomainInfo = ref({}); // 当前操作的域名信息
|
||||||
|
const opInfo = (row, type) => {
|
||||||
|
const _ids = row.id ? [row.id] : row; // 操作的id,有表格内点击和批量操作两种
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case 'status':
|
||||||
|
// 启用/停用
|
||||||
|
let typeName = '', content = '', _usageStatus = '';
|
||||||
|
|
||||||
|
if (row.usageStatus == 1 || row.usageStatus == 5) {
|
||||||
|
typeName = proxy.t('启用');
|
||||||
|
content = proxy.t('确认启用该域名吗!');
|
||||||
|
_usageStatus = 4;
|
||||||
|
} else {
|
||||||
|
typeName = proxy.t('停用');
|
||||||
|
content = proxy.t('确认停用该域名吗!');
|
||||||
|
_usageStatus = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
proxy.$modal.confirm(content).then(() => {
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
setAppDomainStatus({ ids: _ids, usageStatus: _usageStatus }).then(res => {
|
||||||
|
loading.value = false;
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('域名') + typeName + proxy.t('成功!'));
|
||||||
|
getList();
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}).catch(() => { });
|
||||||
|
break
|
||||||
|
case 'refresh':
|
||||||
|
// 刷新域名解析说明
|
||||||
|
row.refreshLoading = true;
|
||||||
|
refreshAppDomainAnalysis({ id: row.id }).then(res => {
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('刷新成功!'));
|
||||||
|
row.refreshLoading = false;
|
||||||
|
getList();
|
||||||
|
}).catch(() => {
|
||||||
|
row.refreshLoading = false;
|
||||||
|
});
|
||||||
|
break
|
||||||
|
case 'clearCache':
|
||||||
|
// 清理缓存
|
||||||
|
proxy.$modal.confirm(proxy.t('确定要清理该记录的缓存吗?')).then(() => {
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
clearAppDomainCache({ ids: _ids }).then(res => {
|
||||||
|
loading.value = false;
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('缓存清理成功!'));
|
||||||
|
getList();
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}).catch(() => { });
|
||||||
|
break
|
||||||
|
case 'delete':
|
||||||
|
// 删除域名
|
||||||
|
proxy.$modal.confirm(proxy.t('确定要删除该域名吗!')).then(() => {
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
delAppDomain(_ids.join(',')).then(res => {
|
||||||
|
loading.value = false;
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('删除成功!'));
|
||||||
|
getList();
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}).catch(() => { });
|
||||||
|
break
|
||||||
|
case 'edit':
|
||||||
|
// 修改域名
|
||||||
|
currentDomainInfo.value = row;
|
||||||
|
isShowEdit.value = true;
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 批量操作
|
||||||
|
const tableRef = ref(),
|
||||||
|
isAllSelection = ref(false), // 是否全选
|
||||||
|
selectionData = ref([]), // 选中的表格数据
|
||||||
|
batchOpType = ref(''); // 选中的批量操作类型
|
||||||
|
|
||||||
|
// 批量操作选项
|
||||||
|
const opTypeOptions = ref([
|
||||||
|
{ label: proxy.t('批量清理缓存'), value: 'clearCache' },
|
||||||
|
{ label: proxy.t('批量删除'), value: 'delete' },
|
||||||
|
{ label: proxy.t('批量停用'), value: 'stop' },
|
||||||
|
{ label: proxy.t('批量启用'), value: 'enable' }
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 勾选表格
|
||||||
|
const tableSelect = (val) => {
|
||||||
|
selectionData.value = val;
|
||||||
|
|
||||||
|
if (val.length === dataList.value.length) {
|
||||||
|
isAllSelection.value = true;
|
||||||
|
} else {
|
||||||
|
isAllSelection.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 全选表格
|
||||||
|
const allSelectionChange = () => {
|
||||||
|
tableRef.value.toggleAllSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 选择批量数据操作类型
|
||||||
|
const opTypeChange = () => {
|
||||||
|
isShowBatchOp.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清空批量操作痕迹
|
||||||
|
const clearBatchOp = () => {
|
||||||
|
isAllSelection.value = false;
|
||||||
|
selectionData.value = [];
|
||||||
|
batchOpType.value = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 搜索按钮操作
|
||||||
|
const handleQuery = () => {
|
||||||
|
queryParams.pageNum = 1;
|
||||||
|
getList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置按钮操作
|
||||||
|
const resetQuery = () => {
|
||||||
|
handleQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭弹窗
|
||||||
|
const closeDialog = (type) => {
|
||||||
|
isShowAdd.value = false; // 新增域名弹窗
|
||||||
|
isShowEdit.value = false; // 修改域名弹窗
|
||||||
|
isShowBatchOp.value = false; // 批量操作弹窗
|
||||||
|
batchOpType.value = ''; // 批量操作类型
|
||||||
|
|
||||||
|
// 批量操作清空
|
||||||
|
if (type === 'batchSubmit') clearBatchOp();
|
||||||
|
// 提交后刷新列表
|
||||||
|
if (type === 'submit' || type === 'batchSubmit') {
|
||||||
|
getList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 跳转域名管理
|
||||||
|
const emit = defineEmits(['goDomainManage']);
|
||||||
|
const goDomainManage = () => {
|
||||||
|
emit('goDomainManage');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 全局搜索展示
|
||||||
|
watch(() => props.searchResult, (val) => {
|
||||||
|
if (val.type == 'domainName') {
|
||||||
|
queryParams.searchType = 'name'
|
||||||
|
queryParams.name = val.domainName;
|
||||||
|
|
||||||
|
nextTick(() => {
|
||||||
|
queryParams.domainSupplierId = val.domainSupplierId;
|
||||||
|
handleQuery();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, { deep: true, immediate: true });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang='scss'>
|
||||||
|
.domain-main {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
// 左侧
|
||||||
|
.dm-left {
|
||||||
|
width: 145px;
|
||||||
|
height: 100%;
|
||||||
|
border-right: 1px solid #e5e5e5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 右侧
|
||||||
|
.dm-right {
|
||||||
|
width: calc(100% - 160px);
|
||||||
|
margin-left: 15px;
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.copy-ml {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,403 @@
|
||||||
|
<template>
|
||||||
|
<!-- 后端加速域名列表 -->
|
||||||
|
<table-search-card :model="queryParams" @getList="getList" :leftSpan="16" :rightSpan="8" @handleQuery="handleQuery()"
|
||||||
|
@resetQuery="resetQuery">
|
||||||
|
<template #left>
|
||||||
|
<select-input-form :queryParamsList="queryParamsList" v-model:queryParams="queryParams" :width="[130, 260]"
|
||||||
|
@handleQuery="handleQuery"></select-input-form>
|
||||||
|
<el-form-item prop="usageStatus" style="width: 150px;">
|
||||||
|
<dict-select clearable v-model="queryParams.usageStatus" :placeholder="t('使用状态')"
|
||||||
|
dictKey="operation_domain_son_usage_status" @change="handleQuery"></dict-select>
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
<template #right>
|
||||||
|
<auto-refresh-time apiName="backendDomainList" @refreshFn="getList" style="margin-right: 10px;"></auto-refresh-time>
|
||||||
|
<el-button type="success" plain icon="Plus" @click="openAddDomain" v-hasPermi="['operation:son:backend:add']">{{
|
||||||
|
t('新增') }}</el-button>
|
||||||
|
</template>
|
||||||
|
</table-search-card>
|
||||||
|
|
||||||
|
<!-- 查询表格 -->
|
||||||
|
<div class="domain-main">
|
||||||
|
<!-- 左侧供应商 -->
|
||||||
|
<div class="dm-left">
|
||||||
|
<el-scrollbar max-height="600px">
|
||||||
|
<!-- 供应商选择 -->
|
||||||
|
<supplier-button ref="supplierRef" v-model="queryParams.domainSupplierId" @change="handleQuery"
|
||||||
|
@getCurSupplierNode="getCurSupplierNode"></supplier-button>
|
||||||
|
</el-scrollbar>
|
||||||
|
</div>
|
||||||
|
<!-- 右侧表格 -->
|
||||||
|
<div class="dm-right">
|
||||||
|
<el-alert v-if="currentNodeTips" style="margin-bottom: 15px;" :title="currentNodeTips" :closable="false"
|
||||||
|
type="warning" show-icon />
|
||||||
|
|
||||||
|
<el-table ref="tableRef" class="c-table-main" v-loading="loading" row-key="id" stripe border :data="dataList"
|
||||||
|
@select="tableSelect" @select-all="tableSelect">
|
||||||
|
<el-table-column align="center" type="selection" width="55" />
|
||||||
|
<el-table-column :label="t('CDN节点名称')" align="center" min-width="160">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ row.cdnNodeName }}
|
||||||
|
<dict-text class="c-green" dictKey="ff_operation_son_type" :value="row.sonType" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column align="center" min-width="280">
|
||||||
|
<template #header>
|
||||||
|
<span>{{ t('生效域名') }}</span>
|
||||||
|
</template>
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ row.name }}<copy-icon :text="row.name" class="copy-ml"></copy-icon>
|
||||||
|
<p :class="'c-clear ' + (row.analyzeStatus ? 'c-green' : 'c-red')">{{ row.analyzeStatus ? t('已解析') :
|
||||||
|
t('待解析') }}</p>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column align="center" min-width="220">
|
||||||
|
<template #header>
|
||||||
|
<span>{{ t('解析说明(生效状态和网速)') }}</span>
|
||||||
|
</template>
|
||||||
|
<template #default="{ row }">
|
||||||
|
<span :class="'c-clear ' + (row.analyzeInvalid ? 'c-green' : 'c-red')">{{ row.analyzeInvalid ?
|
||||||
|
t('已生效') : t('未生效') }}</span>
|
||||||
|
<el-icon @click="opInfo(row, 'refresh')" :class="row.refreshLoading ? 'c-rotate' : ''"
|
||||||
|
style="position: relative; top: 4px; margin-left: 8px;" size="16" class="c-blue">
|
||||||
|
<Refresh />
|
||||||
|
</el-icon>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column :label="t('使用状态')" align="center" min-width="120">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<dict-text :colorValues="['c-grey', 'c-orange', 'c-orange', 'c-green', 'c-red']"
|
||||||
|
dictKey="operation_domain_son_usage_status" :value="row.usageStatus" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<table-operation></table-operation>
|
||||||
|
<el-table-column :label="t('操作')" align="center" min-width="220" fixed="right">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-button v-if="row.usageStatus == 4" link type="primary" @click="opInfo(row, 'clearCache')"
|
||||||
|
v-hasPermi="['operation:son:backend:clear']">
|
||||||
|
{{ t('清理缓存') }}
|
||||||
|
</el-button>
|
||||||
|
<el-tooltip v-if="row.usageStatus == 1 || row.usageStatus == 5" effect="dark"
|
||||||
|
:content="t('提示:启用后请等待1分钟再操作')" placement="top">
|
||||||
|
<el-button link type="primary" @click="opInfo(row, 'status')"
|
||||||
|
v-hasPermi="['operation:son:backend:status']">
|
||||||
|
{{ t('启用') }}
|
||||||
|
</el-button>
|
||||||
|
</el-tooltip>
|
||||||
|
<el-tooltip v-if="row.usageStatus == 2 || row.usageStatus == 3 || row.usageStatus == 4" effect="dark"
|
||||||
|
:content="t('提示:停用后请等待1分钟再操作')" placement="top">
|
||||||
|
<el-button link type="primary" @click="opInfo(row, 'status')"
|
||||||
|
v-hasPermi="['operation:son:backend:status']">
|
||||||
|
{{ t('停用') }}
|
||||||
|
</el-button>
|
||||||
|
</el-tooltip>
|
||||||
|
<el-button v-if="row.usageStatus == 1 && row.sonType != -1 && row.sonType != -2" link type="primary"
|
||||||
|
@click="opInfo(row, 'edit')" v-hasPermi="['operation:son:backend:edit']">
|
||||||
|
{{ t('修改') }}
|
||||||
|
</el-button>
|
||||||
|
<el-button v-if="row.usageStatus == 1 || row.usageStatus == 5" link type="primary"
|
||||||
|
@click="opInfo(row, 'delete')" v-hasPermi="['operation:son:backend:remove']">
|
||||||
|
{{ t('删除') }}
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<!-- 批量操作 -->
|
||||||
|
<table-batch-operate v-if="total > 0" v-model:batchOpType="batchOpType" v-model:isAllSelection="isAllSelection"
|
||||||
|
@allSelectionChange="allSelectionChange" @opTypeChange="opTypeChange" :selectionData="selectionData"
|
||||||
|
:opTypeOptions="opTypeOptions"></table-batch-operate>
|
||||||
|
<!-- 列表分页 -->
|
||||||
|
<pagination v-if="total > 0" :total="total" v-model:page="queryParams.pageNum"
|
||||||
|
v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 新增域名弹窗 -->
|
||||||
|
<add-son-domain v-if="isShowAdd" type="backend" :supplierList="supplierList" @goDomainManage="goDomainManage"
|
||||||
|
@closeDialog="closeDialog"></add-son-domain>
|
||||||
|
|
||||||
|
<!-- 修改域名弹窗 -->
|
||||||
|
<edit-son-domain v-if="isShowEdit" type="backend" :currentDomainInfo="currentDomainInfo"
|
||||||
|
@closeDialog="closeDialog"></edit-son-domain>
|
||||||
|
|
||||||
|
<!-- 批量操作弹窗 -->
|
||||||
|
<batch-operation v-if="isShowBatchOp" type="backend" :batchOpType="batchOpType" :selectionData="selectionData"
|
||||||
|
@closeDialog="closeDialog"></batch-operation>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="BackendList">
|
||||||
|
import {
|
||||||
|
getBackendDomainList, // 域名列表
|
||||||
|
refreshBackendDomainAnalysis, // 刷新解析说明
|
||||||
|
setBackendDomainStatus, // 域名状态切换
|
||||||
|
clearBackendDomainCache, // 清理缓存
|
||||||
|
delBackendDomain // 删除域名
|
||||||
|
} from "@/api/operation/domain";
|
||||||
|
import AutoRefreshTime from "@/components/AutoRefreshTime"; // 定时刷新
|
||||||
|
import CopyIcon from "@/components/CopyIcon"; // 小图标复制
|
||||||
|
import TableBatchOperate from '@/components/TableBatchOperate'; // 批量操作
|
||||||
|
import SupplierButton from "../components/SupplierButton.vue"; // 供应商选择按钮
|
||||||
|
import AddSonDomain from "../components/AddSonDomain.vue"; // 新增子域名弹窗
|
||||||
|
import EditSonDomain from "../components/EditSonDomain.vue"; // 修改子域名弹窗
|
||||||
|
import BatchOperation from "../components/BatchOperation.vue"; // 批量操作弹窗
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
// 全局搜索结果
|
||||||
|
searchResult: {
|
||||||
|
type: Object,
|
||||||
|
default: {}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance();
|
||||||
|
const loading = ref(true); // loading状态
|
||||||
|
const isShowAdd = ref(false), isShowEdit = ref(false), isShowBatchOp = ref(false); // 各弹窗状态
|
||||||
|
|
||||||
|
// 获取供应商节点信息
|
||||||
|
const supplierRef = ref(null), currentNodeTips = ref(''), supplierList = ref([]);
|
||||||
|
const getCurSupplierNode = (data) => {
|
||||||
|
currentNodeTips.value = data?.tips;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据下拉框条件输入搜索
|
||||||
|
const queryParamsList = ref([{
|
||||||
|
label: proxy.t('操作人'),
|
||||||
|
value: 'updateBy'
|
||||||
|
}, {
|
||||||
|
label: proxy.t('子域名'),
|
||||||
|
value: 'name'
|
||||||
|
}]);
|
||||||
|
|
||||||
|
// 搜索配置
|
||||||
|
const queryParams = reactive({
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 20,
|
||||||
|
searchType: 'updateBy',
|
||||||
|
name: '', // 子域名
|
||||||
|
updateBy: '', // 操作人
|
||||||
|
usageStatus: '', // 使用状态
|
||||||
|
orderByColumn: 'createTime',
|
||||||
|
isAsc: 'desc',
|
||||||
|
domainSupplierId: '' // 供应商
|
||||||
|
});
|
||||||
|
|
||||||
|
// 请求列表
|
||||||
|
const dataList = ref([]), total = ref(0);
|
||||||
|
const getList = () => {
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
getBackendDomainList(queryParams).then(res => {
|
||||||
|
loading.value = false;
|
||||||
|
dataList.value = res.rows;
|
||||||
|
total.value = +res.total;
|
||||||
|
clearBatchOp(); // 清空批量操作痕迹
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
dataList.value = [];
|
||||||
|
total.value = 0;
|
||||||
|
clearBatchOp(); // 清空批量操作痕迹
|
||||||
|
});
|
||||||
|
}
|
||||||
|
getList();
|
||||||
|
|
||||||
|
// 新增域名
|
||||||
|
const openAddDomain = () => {
|
||||||
|
supplierList.value = supplierRef.value?.supplierList.filter(v => v.isOpen && !v.stopStatus); // 已开通且不是维护状态的供应商
|
||||||
|
isShowAdd.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 操作信息
|
||||||
|
const currentDomainInfo = ref({}); // 当前操作的域名信息
|
||||||
|
const opInfo = (row, type) => {
|
||||||
|
const _ids = row.id ? [row.id] : row; // 操作的id,有表格内点击和批量操作两种
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case 'status':
|
||||||
|
// 启用/停用
|
||||||
|
let typeName = '', content = '', _usageStatus = '';
|
||||||
|
|
||||||
|
if (row.usageStatus == 1 || row.usageStatus == 5) {
|
||||||
|
typeName = proxy.t('启用');
|
||||||
|
content = proxy.t('确认启用该域名吗!');
|
||||||
|
_usageStatus = 4;
|
||||||
|
} else {
|
||||||
|
typeName = proxy.t('停用');
|
||||||
|
content = proxy.t('确认停用该域名吗!');
|
||||||
|
_usageStatus = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
proxy.$modal.confirm(content).then(() => {
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
setBackendDomainStatus({ ids: _ids, usageStatus: _usageStatus }).then(res => {
|
||||||
|
loading.value = false;
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('域名') + typeName + proxy.t('成功!'));
|
||||||
|
getList();
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}).catch(() => { });
|
||||||
|
break
|
||||||
|
case 'refresh':
|
||||||
|
// 刷新域名解析说明
|
||||||
|
row.refreshLoading = true;
|
||||||
|
refreshBackendDomainAnalysis({ id: row.id }).then(res => {
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('刷新成功!'));
|
||||||
|
row.refreshLoading = false;
|
||||||
|
getList();
|
||||||
|
}).catch(() => {
|
||||||
|
row.refreshLoading = false;
|
||||||
|
});
|
||||||
|
break
|
||||||
|
case 'clearCache':
|
||||||
|
// 清理缓存
|
||||||
|
proxy.$modal.confirm(proxy.t('确定要清理该记录的缓存吗?')).then(() => {
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
clearBackendDomainCache({ ids: _ids }).then(res => {
|
||||||
|
loading.value = false;
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('缓存清理成功!'));
|
||||||
|
getList();
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}).catch(() => { });
|
||||||
|
break
|
||||||
|
case 'delete':
|
||||||
|
// 删除域名
|
||||||
|
proxy.$modal.confirm(proxy.t('确定要删除该域名吗!')).then(() => {
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
delBackendDomain(_ids.join(',')).then(res => {
|
||||||
|
loading.value = false;
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('删除成功!'));
|
||||||
|
getList();
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}).catch(() => { });
|
||||||
|
break
|
||||||
|
case 'edit':
|
||||||
|
// 修改域名
|
||||||
|
currentDomainInfo.value = row;
|
||||||
|
isShowEdit.value = true;
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 批量操作
|
||||||
|
const tableRef = ref(),
|
||||||
|
isAllSelection = ref(false), // 是否全选
|
||||||
|
selectionData = ref([]), // 选中的表格数据
|
||||||
|
batchOpType = ref(''); // 选中的批量操作类型
|
||||||
|
|
||||||
|
// 批量操作选项
|
||||||
|
const opTypeOptions = ref([
|
||||||
|
{ label: proxy.t('批量清理缓存'), value: 'clearCache' },
|
||||||
|
{ label: proxy.t('批量删除'), value: 'delete' },
|
||||||
|
{ label: proxy.t('批量停用'), value: 'stop' },
|
||||||
|
{ label: proxy.t('批量启用'), value: 'enable' }
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 勾选表格
|
||||||
|
const tableSelect = (val) => {
|
||||||
|
selectionData.value = val;
|
||||||
|
|
||||||
|
if (val.length === dataList.value.length) {
|
||||||
|
isAllSelection.value = true;
|
||||||
|
} else {
|
||||||
|
isAllSelection.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 全选表格
|
||||||
|
const allSelectionChange = () => {
|
||||||
|
tableRef.value.toggleAllSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 选择批量数据操作类型
|
||||||
|
const opTypeChange = () => {
|
||||||
|
isShowBatchOp.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清空批量操作痕迹
|
||||||
|
const clearBatchOp = () => {
|
||||||
|
isAllSelection.value = false;
|
||||||
|
selectionData.value = [];
|
||||||
|
batchOpType.value = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 搜索按钮操作
|
||||||
|
const handleQuery = () => {
|
||||||
|
queryParams.pageNum = 1;
|
||||||
|
getList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置按钮操作
|
||||||
|
const resetQuery = () => {
|
||||||
|
handleQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭弹窗
|
||||||
|
const closeDialog = (type) => {
|
||||||
|
isShowAdd.value = false; // 新增域名弹窗
|
||||||
|
isShowEdit.value = false; // 修改域名弹窗
|
||||||
|
isShowBatchOp.value = false; // 批量操作弹窗
|
||||||
|
batchOpType.value = ''; // 批量操作类型
|
||||||
|
|
||||||
|
// 批量操作清空
|
||||||
|
if (type === 'batchSubmit') clearBatchOp();
|
||||||
|
// 提交后刷新列表
|
||||||
|
if (type === 'submit' || type === 'batchSubmit') {
|
||||||
|
getList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 跳转域名管理
|
||||||
|
const emit = defineEmits(['goDomainManage']);
|
||||||
|
const goDomainManage = () => {
|
||||||
|
emit('goDomainManage');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 全局搜索展示
|
||||||
|
watch(() => props.searchResult, (val) => {
|
||||||
|
if (val.type == 'domainName') {
|
||||||
|
queryParams.searchType = 'name'
|
||||||
|
queryParams.name = val.domainName;
|
||||||
|
|
||||||
|
nextTick(() => {
|
||||||
|
queryParams.domainSupplierId = val.domainSupplierId;
|
||||||
|
handleQuery();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, { deep: true, immediate: true });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang='scss'>
|
||||||
|
.domain-main {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
// 左侧
|
||||||
|
.dm-left {
|
||||||
|
width: 145px;
|
||||||
|
height: 100%;
|
||||||
|
border-right: 1px solid #e5e5e5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 右侧
|
||||||
|
.dm-right {
|
||||||
|
width: calc(100% - 160px);
|
||||||
|
margin-left: 15px;
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.copy-ml {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,503 @@
|
||||||
|
<template>
|
||||||
|
<!-- 下载站域名列表 -->
|
||||||
|
<table-search-card :model="queryParams" @getList="getList" :leftSpan="16" :rightSpan="8" @handleQuery="handleQuery()"
|
||||||
|
@resetQuery="resetQuery">
|
||||||
|
<template #left>
|
||||||
|
<select-input-form :queryParamsList="queryParamsList" v-model:queryParams="queryParams" :width="[130, 260]"
|
||||||
|
@handleQuery="handleQuery"></select-input-form>
|
||||||
|
<el-form-item prop="usageStatus" style="width: 150px;">
|
||||||
|
<dict-select clearable v-model="queryParams.usageStatus" :placeholder="t('使用状态')"
|
||||||
|
dictKey="operation_domain_son_usage_status" @change="handleQuery"></dict-select>
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
<template #right>
|
||||||
|
<auto-refresh-time apiName="downloadSiteDomainList" @refreshFn="getList"
|
||||||
|
style="margin-right: 10px;"></auto-refresh-time>
|
||||||
|
<el-button type="success" plain icon="Plus" @click="openAddDomain" v-hasPermi="['operation:son:download:add']">{{
|
||||||
|
t('新增') }}</el-button>
|
||||||
|
</template>
|
||||||
|
</table-search-card>
|
||||||
|
|
||||||
|
<!-- 查询表格 -->
|
||||||
|
<div class="domain-main">
|
||||||
|
<!-- 左侧供应商 -->
|
||||||
|
<div class="dm-left">
|
||||||
|
<el-scrollbar max-height="600px">
|
||||||
|
<!-- 供应商选择 -->
|
||||||
|
<supplier-button ref="supplierRef" v-model="queryParams.domainSupplierId" @change="handleQuery"
|
||||||
|
@getCurSupplierNode="getCurSupplierNode"></supplier-button>
|
||||||
|
</el-scrollbar>
|
||||||
|
</div>
|
||||||
|
<!-- 右侧表格 -->
|
||||||
|
<div class="dm-right">
|
||||||
|
<el-alert v-if="currentNodeTips" style="margin-bottom: 15px;" :title="currentNodeTips" :closable="false"
|
||||||
|
type="warning" show-icon />
|
||||||
|
|
||||||
|
<el-table ref="tableRef" class="c-table-main" v-loading="loading" row-key="id" stripe border :data="dataList"
|
||||||
|
@select="tableSelect" @select-all="tableSelect">
|
||||||
|
<el-table-column align="center" type="selection" width="55" />
|
||||||
|
<el-table-column :label="t('CDN节点名称')" align="center" min-width="160">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ row.cdnNodeName }}
|
||||||
|
<dict-text class="c-green" dictKey="ff_operation_son_type" :value="row.sonType" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column align="center" min-width="280">
|
||||||
|
<template #header>
|
||||||
|
<span>{{ t('生效域名') }}</span>
|
||||||
|
</template>
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ row.name }}<copy-icon :text="row.name" class="copy-ml"></copy-icon>
|
||||||
|
<p :class="'c-clear ' + (row.analyzeStatus ? 'c-green' : 'c-red')">{{ row.analyzeStatus ? t('已解析') :
|
||||||
|
t('待解析') }}</p>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column :label="t('端口类型')" align="center" min-width="120">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<dict-text dictKey="ff_operation_domain_son_port_type" :value="row.portType" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column :label="t('端口号')" prop="portValue" align="center" min-width="120"></el-table-column>
|
||||||
|
<el-table-column align="center" min-width="220">
|
||||||
|
<template #header>
|
||||||
|
<span>{{ t('解析说明(生效状态和网速)') }}</span>
|
||||||
|
</template>
|
||||||
|
<template #default="{ row }">
|
||||||
|
<span :class="'c-clear ' + (row.analyzeInvalid ? 'c-green' : 'c-red')">{{ row.analyzeInvalid ?
|
||||||
|
t('已生效') : t('未生效') }}</span>
|
||||||
|
<el-icon @click="opInfo(row, 'refresh')" :class="row.refreshLoading ? 'c-rotate' : ''"
|
||||||
|
style="position: relative; top: 4px; margin-left: 8px;" size="16" class="c-blue">
|
||||||
|
<Refresh />
|
||||||
|
</el-icon>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column align="center" min-width="160">
|
||||||
|
<template #header>
|
||||||
|
<span>{{ t('其他担保域名列表') }}</span>
|
||||||
|
<icon-tips>
|
||||||
|
<p class="c-clear" style="width: 400px;">
|
||||||
|
{{ t('1.展示:即会员验证担保域名后,会展示一些站点的其他域名列表,方便会员保存记录、找到回家路或信任其他域名(推荐无封锁的国家)。') }}<br />
|
||||||
|
{{ t('2.隐藏:即会员验证担保域名后,只能看到当前域名的验证结果,看不到其他域名列表,防止域名全部暴露,有被拦截和举报的风险。') }}
|
||||||
|
</p>
|
||||||
|
</icon-tips>
|
||||||
|
</template>
|
||||||
|
<template #default="{ row }">
|
||||||
|
<base-switch :active-value="true" :inactive-value="false" v-model="row.backupDomain"
|
||||||
|
:tipText="row.status ? t('确认隐藏吗?') : t('确认展示吗?')" :disabled="row.usageStatus != 4"
|
||||||
|
:before-change="() => beforeSwitchChange(row, 'backupDomain')"></base-switch>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column align="center" min-width="150">
|
||||||
|
<template #header>
|
||||||
|
<span>{{ t('强制绑定代理') }}</span>
|
||||||
|
<icon-tips>
|
||||||
|
<p class="c-clear" style="width: 400px;">
|
||||||
|
{{ t('代理上级归属优先级:推广链接的上级 > 渠道ID的强制绑定上级 > 域名管理的强制绑定上级(无上级时,域名管理的才生效)') }}
|
||||||
|
</p>
|
||||||
|
</icon-tips>
|
||||||
|
</template>
|
||||||
|
<template #default="{ row }">
|
||||||
|
<span v-if="row.agentAccount" class="c-blue" @click="goRoute(row, 'agentAccount')">{{
|
||||||
|
row.agentAccount }}</span>
|
||||||
|
<span v-else>{{ t('无') }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column :label="t('使用状态')" align="center" min-width="120">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<dict-text :colorValues="['c-grey', 'c-orange', 'c-orange', 'c-green', 'c-red']"
|
||||||
|
dictKey="operation_domain_son_usage_status" :value="row.usageStatus" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<table-operation></table-operation>
|
||||||
|
<el-table-column :label="t('操作')" align="center" min-width="220" fixed="right">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-button v-if="row.usageStatus == 4" link type="primary" @click="opInfo(row, 'agent')"
|
||||||
|
v-hasPermi="['operation:son:download:agent']">
|
||||||
|
{{ t('绑定代理') }}
|
||||||
|
</el-button>
|
||||||
|
<el-button v-if="row.usageStatus == 4" link type="primary" @click="opInfo(row, 'clearCache')"
|
||||||
|
v-hasPermi="['operation:son:download:clear']">
|
||||||
|
{{ t('清理缓存') }}
|
||||||
|
</el-button>
|
||||||
|
<el-tooltip v-if="row.usageStatus == 1 || row.usageStatus == 5" effect="dark"
|
||||||
|
:content="t('提示:启用后请等待1分钟再操作')" placement="top">
|
||||||
|
<el-button link type="primary" @click="opInfo(row, 'status')"
|
||||||
|
v-hasPermi="['operation:son:download:status']">
|
||||||
|
{{ t('启用') }}
|
||||||
|
</el-button>
|
||||||
|
</el-tooltip>
|
||||||
|
<el-tooltip v-if="row.usageStatus == 2 || row.usageStatus == 3 || row.usageStatus == 4" effect="dark"
|
||||||
|
:content="t('提示:停用后请等待1分钟再操作')" placement="top">
|
||||||
|
<el-button link type="primary" @click="opInfo(row, 'status')"
|
||||||
|
v-hasPermi="['operation:son:download:status']">
|
||||||
|
{{ t('停用') }}
|
||||||
|
</el-button>
|
||||||
|
</el-tooltip>
|
||||||
|
<el-button v-if="row.usageStatus == 1 && row.sonType != -1 && row.sonType != -2" link type="primary"
|
||||||
|
@click="opInfo(row, 'edit')" v-hasPermi="['operation:son:download:edit']">
|
||||||
|
{{ t('修改') }}
|
||||||
|
</el-button>
|
||||||
|
<el-button v-if="row.usageStatus == 1 || row.usageStatus == 5" link type="primary"
|
||||||
|
@click="opInfo(row, 'delete')" v-hasPermi="['operation:son:download:remove']">
|
||||||
|
{{ t('删除') }}
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<!-- 批量操作 -->
|
||||||
|
<table-batch-operate v-if="total > 0" v-model:batchOpType="batchOpType" v-model:isAllSelection="isAllSelection"
|
||||||
|
@allSelectionChange="allSelectionChange" @opTypeChange="opTypeChange" :selectionData="selectionData"
|
||||||
|
:opTypeOptions="opTypeOptions"></table-batch-operate>
|
||||||
|
<!-- 列表分页 -->
|
||||||
|
<pagination v-if="total > 0" :total="total" v-model:page="queryParams.pageNum"
|
||||||
|
v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 新增域名弹窗 -->
|
||||||
|
<add-son-domain v-if="isShowAdd" type="downloadSite" :supplierList="supplierList" @goDomainManage="goDomainManage"
|
||||||
|
@closeDialog="closeDialog"></add-son-domain>
|
||||||
|
|
||||||
|
<!-- 修改域名弹窗 -->
|
||||||
|
<edit-son-domain v-if="isShowEdit" type="downloadSite" :currentDomainInfo="currentDomainInfo"
|
||||||
|
@closeDialog="closeDialog"></edit-son-domain>
|
||||||
|
|
||||||
|
<!-- 绑定代理弹窗 -->
|
||||||
|
<bind-agent v-if="isShowAgent" type="downloadSite" :currentDomainInfo="currentDomainInfo"
|
||||||
|
@closeDialog="closeDialog"></bind-agent>
|
||||||
|
|
||||||
|
<!-- 批量操作弹窗 -->
|
||||||
|
<batch-operation v-if="isShowBatchOp" type="downloadSite" :batchOpType="batchOpType" :selectionData="selectionData"
|
||||||
|
@closeDialog="closeDialog"></batch-operation>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="DownloadSiteList">
|
||||||
|
import {
|
||||||
|
getDownloadDomainList, // 域名列表
|
||||||
|
refreshDownloadDomainAnalysis, // 刷新解析说明
|
||||||
|
downloadDomainSwitch, // 开关切换
|
||||||
|
setDownloadDomainStatus, // 域名状态切换
|
||||||
|
clearDownloadDomainCache, // 清理缓存
|
||||||
|
delDownloadDomain, // 删除域名
|
||||||
|
} from "@/api/operation/domain";
|
||||||
|
import AutoRefreshTime from "@/components/AutoRefreshTime"; // 定时刷新
|
||||||
|
import CopyIcon from "@/components/CopyIcon"; // 小图标复制
|
||||||
|
import IconTips from "@/components/IconTips"; // 小图标提示
|
||||||
|
import TableBatchOperate from '@/components/TableBatchOperate'; // 批量操作
|
||||||
|
import SupplierButton from "../components/SupplierButton.vue"; // 供应商选择按钮
|
||||||
|
import BaseSwitch from "@/components/BaseSwitch"; // 开关
|
||||||
|
import AddSonDomain from "../components/AddSonDomain.vue"; // 新增子域名弹窗
|
||||||
|
import EditSonDomain from "../components/EditSonDomain.vue"; // 修改子域名弹窗
|
||||||
|
import BindAgent from "../components/BindAgent.vue"; // 绑定代理
|
||||||
|
import BatchOperation from "../components/BatchOperation.vue"; // 批量操作弹窗
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
// 全局搜索结果
|
||||||
|
searchResult: {
|
||||||
|
type: Object,
|
||||||
|
default: {}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance();
|
||||||
|
const loading = ref(true); // loading状态
|
||||||
|
const isShowAdd = ref(false), isShowAgent = ref(false), isShowEdit = ref(false), isShowBatchOp = ref(false); // 各弹窗状态
|
||||||
|
|
||||||
|
// 获取供应商节点信息
|
||||||
|
const supplierRef = ref(null), currentNodeTips = ref(''), supplierList = ref([]);
|
||||||
|
const getCurSupplierNode = (data) => {
|
||||||
|
currentNodeTips.value = data?.tips;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据下拉框条件输入搜索
|
||||||
|
const queryParamsList = ref([{
|
||||||
|
label: proxy.t('操作人'),
|
||||||
|
value: 'updateBy'
|
||||||
|
}, {
|
||||||
|
label: proxy.t('子域名'),
|
||||||
|
value: 'name'
|
||||||
|
}]);
|
||||||
|
|
||||||
|
// 搜索配置
|
||||||
|
const queryParams = reactive({
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 20,
|
||||||
|
searchType: 'updateBy',
|
||||||
|
name: '', // 子域名
|
||||||
|
updateBy: '', // 操作人
|
||||||
|
usageStatus: '', // 使用状态
|
||||||
|
orderByColumn: 'createTime',
|
||||||
|
isAsc: 'desc',
|
||||||
|
domainSupplierId: '' // 供应商
|
||||||
|
});
|
||||||
|
|
||||||
|
// 请求列表
|
||||||
|
const dataList = ref([]), total = ref(0);
|
||||||
|
const getList = () => {
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
getDownloadDomainList(queryParams).then(res => {
|
||||||
|
loading.value = false;
|
||||||
|
|
||||||
|
// 更改特定字段类型
|
||||||
|
res.rows.forEach(item => {
|
||||||
|
item.startEntrance = item.startEntrance.toString();
|
||||||
|
item.blockDevice = item.blockDevice.toString();
|
||||||
|
});
|
||||||
|
|
||||||
|
dataList.value = res.rows;
|
||||||
|
total.value = +res.total;
|
||||||
|
clearBatchOp(); // 清空批量操作痕迹
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
dataList.value = [];
|
||||||
|
total.value = 0;
|
||||||
|
clearBatchOp(); // 清空批量操作痕迹
|
||||||
|
});
|
||||||
|
}
|
||||||
|
getList();
|
||||||
|
|
||||||
|
// 跳转页面
|
||||||
|
const goRoute = (row, type) => {
|
||||||
|
proxy.$router.push({
|
||||||
|
path: '/agent/agent-info',
|
||||||
|
query: {
|
||||||
|
[type]: row.agentAccount,
|
||||||
|
searchType: type
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增域名
|
||||||
|
const openAddDomain = () => {
|
||||||
|
supplierList.value = supplierRef.value?.supplierList.filter(v => v.isOpen && !v.stopStatus); // 已开通且不是维护状态的供应商
|
||||||
|
isShowAdd.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 开启状态切换
|
||||||
|
const beforeSwitchChange = (row, type) => {
|
||||||
|
const params = {
|
||||||
|
id: row.id,
|
||||||
|
[type]: !row[type]
|
||||||
|
}
|
||||||
|
|
||||||
|
downloadDomainSwitch({ operationDomainSons: [params] }).then(res => {
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('操作成功!'));
|
||||||
|
getList();
|
||||||
|
return true;
|
||||||
|
}).catch(() => {
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 操作信息
|
||||||
|
const currentDomainInfo = ref({}); // 当前操作的域名信息
|
||||||
|
const opInfo = (row, type) => {
|
||||||
|
const _ids = row.id ? [row.id] : row; // 操作的id,有表格内点击和批量操作两种
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case 'status':
|
||||||
|
// 启用/停用
|
||||||
|
let typeName = '', content = '', _usageStatus = '';
|
||||||
|
|
||||||
|
if (row.usageStatus == 1 || row.usageStatus == 5) {
|
||||||
|
typeName = proxy.t('启用');
|
||||||
|
content = proxy.t('确认启用该域名吗!');
|
||||||
|
_usageStatus = 4;
|
||||||
|
} else {
|
||||||
|
typeName = proxy.t('停用');
|
||||||
|
content = proxy.t('确认停用该域名吗!');
|
||||||
|
_usageStatus = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
proxy.$modal.confirm(content).then(() => {
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
setDownloadDomainStatus({ ids: _ids, usageStatus: _usageStatus }).then(res => {
|
||||||
|
loading.value = false;
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('域名') + typeName + proxy.t('成功!'));
|
||||||
|
getList();
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}).catch(() => { });
|
||||||
|
break
|
||||||
|
case 'refresh':
|
||||||
|
// 刷新域名解析说明
|
||||||
|
row.refreshLoading = true;
|
||||||
|
refreshDownloadDomainAnalysis({ id: row.id }).then(res => {
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('刷新成功!'));
|
||||||
|
row.refreshLoading = false;
|
||||||
|
getList();
|
||||||
|
}).catch(() => {
|
||||||
|
row.refreshLoading = false;
|
||||||
|
});
|
||||||
|
break
|
||||||
|
case 'agent':
|
||||||
|
// 绑定代理
|
||||||
|
currentDomainInfo.value = row;
|
||||||
|
isShowAgent.value = true;
|
||||||
|
break
|
||||||
|
case 'clearCache':
|
||||||
|
// 清理缓存
|
||||||
|
proxy.$modal.confirm(proxy.t('确定要清理该记录的缓存吗?')).then(() => {
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
clearDownloadDomainCache({ ids: _ids }).then(res => {
|
||||||
|
loading.value = false;
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('缓存清理成功!'));
|
||||||
|
getList();
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}).catch(() => { });
|
||||||
|
break
|
||||||
|
case 'delete':
|
||||||
|
// 删除域名
|
||||||
|
proxy.$modal.confirm(proxy.t('确定要删除该域名吗!')).then(() => {
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
delDownloadDomain(_ids.join(',')).then(res => {
|
||||||
|
loading.value = false;
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('删除成功!'));
|
||||||
|
getList();
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}).catch(() => { });
|
||||||
|
break
|
||||||
|
case 'edit':
|
||||||
|
// 修改域名
|
||||||
|
currentDomainInfo.value = row;
|
||||||
|
isShowEdit.value = true;
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 批量操作
|
||||||
|
const tableRef = ref(),
|
||||||
|
isAllSelection = ref(false), // 是否全选
|
||||||
|
selectionData = ref([]), // 选中的表格数据
|
||||||
|
batchOpType = ref(''); // 选中的批量操作类型
|
||||||
|
|
||||||
|
// 批量操作选项
|
||||||
|
const opTypeOptions = ref([
|
||||||
|
{ label: proxy.t('批量清理缓存'), value: 'clearCache' },
|
||||||
|
{ label: proxy.t('批量删除'), value: 'delete' },
|
||||||
|
{ label: proxy.t('批量停用'), value: 'stop' },
|
||||||
|
{ label: proxy.t('批量启用'), value: 'enable' },
|
||||||
|
{ label: proxy.t('批量展示其他担保列表'), value: 'showSecurity' },
|
||||||
|
{ label: proxy.t('批量隐藏其他担保列表'), value: 'hideSecurity' },
|
||||||
|
{ label: proxy.t('批量绑定代理'), value: 'bindAgent' }
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 勾选表格
|
||||||
|
const tableSelect = (val) => {
|
||||||
|
selectionData.value = val;
|
||||||
|
|
||||||
|
if (val.length === dataList.value.length) {
|
||||||
|
isAllSelection.value = true;
|
||||||
|
} else {
|
||||||
|
isAllSelection.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 全选表格
|
||||||
|
const allSelectionChange = () => {
|
||||||
|
tableRef.value.toggleAllSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 选择批量数据操作类型
|
||||||
|
const opTypeChange = () => {
|
||||||
|
isShowBatchOp.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清空批量操作痕迹
|
||||||
|
const clearBatchOp = () => {
|
||||||
|
isAllSelection.value = false;
|
||||||
|
selectionData.value = [];
|
||||||
|
batchOpType.value = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 搜索按钮操作
|
||||||
|
const handleQuery = () => {
|
||||||
|
queryParams.pageNum = 1;
|
||||||
|
getList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置按钮操作
|
||||||
|
const resetQuery = () => {
|
||||||
|
handleQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭弹窗
|
||||||
|
const closeDialog = (type) => {
|
||||||
|
isShowAdd.value = false; // 新增域名弹窗
|
||||||
|
isShowAgent.value = false; // 绑定代理弹窗
|
||||||
|
isShowEdit.value = false; // 修改域名弹窗
|
||||||
|
isShowBatchOp.value = false; // 批量操作弹窗
|
||||||
|
batchOpType.value = ''; // 批量操作类型
|
||||||
|
|
||||||
|
// 批量操作清空
|
||||||
|
if (type === 'batchSubmit') clearBatchOp();
|
||||||
|
// 提交后刷新列表
|
||||||
|
if (type === 'submit' || type === 'batchSubmit') {
|
||||||
|
getList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 跳转域名管理
|
||||||
|
const emit = defineEmits(['goDomainManage']);
|
||||||
|
const goDomainManage = () => {
|
||||||
|
emit('goDomainManage');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 全局搜索展示
|
||||||
|
watch(() => props.searchResult, (val) => {
|
||||||
|
if (val.type == 'domainName') {
|
||||||
|
queryParams.searchType = 'name'
|
||||||
|
queryParams.name = val.domainName;
|
||||||
|
|
||||||
|
nextTick(() => {
|
||||||
|
queryParams.domainSupplierId = val.domainSupplierId;
|
||||||
|
handleQuery();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, { deep: true, immediate: true });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang='scss'>
|
||||||
|
.right-switch {
|
||||||
|
display: inline-block;
|
||||||
|
color: #606266;
|
||||||
|
font-size: 14px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.domain-main {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
// 左侧
|
||||||
|
.dm-left {
|
||||||
|
width: 145px;
|
||||||
|
height: 100%;
|
||||||
|
border-right: 1px solid #e5e5e5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 右侧
|
||||||
|
.dm-right {
|
||||||
|
width: calc(100% - 160px);
|
||||||
|
margin-left: 15px;
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.copy-ml {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,403 @@
|
||||||
|
<template>
|
||||||
|
<!-- OSS加速域名列表 -->
|
||||||
|
<table-search-card :model="queryParams" @getList="getList" :leftSpan="16" :rightSpan="8" @handleQuery="handleQuery()"
|
||||||
|
@resetQuery="resetQuery">
|
||||||
|
<template #left>
|
||||||
|
<select-input-form :queryParamsList="queryParamsList" v-model:queryParams="queryParams" :width="[130, 260]"
|
||||||
|
@handleQuery="handleQuery"></select-input-form>
|
||||||
|
<el-form-item prop="usageStatus" style="width: 150px;">
|
||||||
|
<dict-select clearable v-model="queryParams.usageStatus" :placeholder="t('使用状态')"
|
||||||
|
dictKey="operation_domain_son_usage_status" @change="handleQuery"></dict-select>
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
<template #right>
|
||||||
|
<auto-refresh-time apiName="ossDomainList" @refreshFn="getList" style="margin-right: 10px;"></auto-refresh-time>
|
||||||
|
<el-button type="success" plain icon="Plus" @click="openAddDomain" v-hasPermi="['operation:son:oss:add']">{{
|
||||||
|
t('新增') }}</el-button>
|
||||||
|
</template>
|
||||||
|
</table-search-card>
|
||||||
|
|
||||||
|
<!-- 查询表格 -->
|
||||||
|
<div class="domain-main">
|
||||||
|
<!-- 左侧供应商 -->
|
||||||
|
<div class="dm-left">
|
||||||
|
<el-scrollbar max-height="600px">
|
||||||
|
<!-- 供应商选择 -->
|
||||||
|
<supplier-button ref="supplierRef" v-model="queryParams.domainSupplierId" @change="handleQuery"
|
||||||
|
@getCurSupplierNode="getCurSupplierNode"></supplier-button>
|
||||||
|
</el-scrollbar>
|
||||||
|
</div>
|
||||||
|
<!-- 右侧表格 -->
|
||||||
|
<div class="dm-right">
|
||||||
|
<el-alert v-if="currentNodeTips" style="margin-bottom: 15px;" :title="currentNodeTips" :closable="false"
|
||||||
|
type="warning" show-icon />
|
||||||
|
|
||||||
|
<el-table ref="tableRef" class="c-table-main" v-loading="loading" row-key="id" stripe border :data="dataList"
|
||||||
|
@select="tableSelect" @select-all="tableSelect">
|
||||||
|
<el-table-column align="center" type="selection" width="55" />
|
||||||
|
<el-table-column :label="t('CDN节点名称')" align="center" min-width="160">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ row.cdnNodeName }}
|
||||||
|
<dict-text class="c-green" dictKey="ff_operation_son_type" :value="row.sonType" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column align="center" min-width="280">
|
||||||
|
<template #header>
|
||||||
|
<span>{{ t('生效域名') }}</span>
|
||||||
|
</template>
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ row.name }}<copy-icon :text="row.name" class="copy-ml"></copy-icon>
|
||||||
|
<p :class="'c-clear ' + (row.analyzeStatus ? 'c-green' : 'c-red')">{{ row.analyzeStatus ? t('已解析') :
|
||||||
|
t('待解析') }}</p>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column align="center" min-width="220">
|
||||||
|
<template #header>
|
||||||
|
<span>{{ t('解析说明(生效状态和网速)') }}</span>
|
||||||
|
</template>
|
||||||
|
<template #default="{ row }">
|
||||||
|
<span :class="'c-clear ' + (row.analyzeInvalid ? 'c-green' : 'c-red')">{{ row.analyzeInvalid ?
|
||||||
|
t('已生效') : t('未生效') }}</span>
|
||||||
|
<el-icon @click="opInfo(row, 'refresh')" :class="row.refreshLoading ? 'c-rotate' : ''"
|
||||||
|
style="position: relative; top: 4px; margin-left: 8px;" size="16" class="c-blue">
|
||||||
|
<Refresh />
|
||||||
|
</el-icon>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column :label="t('使用状态')" align="center" min-width="120">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<dict-text :colorValues="['c-grey', 'c-orange', 'c-orange', 'c-green', 'c-red']"
|
||||||
|
dictKey="operation_domain_son_usage_status" :value="row.usageStatus" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<table-operation></table-operation>
|
||||||
|
<el-table-column :label="t('操作')" align="center" min-width="220" fixed="right">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-button v-if="row.usageStatus == 4" link type="primary" @click="opInfo(row, 'clearCache')"
|
||||||
|
v-hasPermi="['operation:son:oss:clear']">
|
||||||
|
{{ t('清理缓存') }}
|
||||||
|
</el-button>
|
||||||
|
<el-tooltip v-if="row.usageStatus == 1 || row.usageStatus == 5" effect="dark"
|
||||||
|
:content="t('提示:启用后请等待1分钟再操作')" placement="top">
|
||||||
|
<el-button link type="primary" @click="opInfo(row, 'status')"
|
||||||
|
v-hasPermi="['operation:son:oss:status']">
|
||||||
|
{{ t('启用') }}
|
||||||
|
</el-button>
|
||||||
|
</el-tooltip>
|
||||||
|
<el-tooltip v-if="row.usageStatus == 2 || row.usageStatus == 3 || row.usageStatus == 4" effect="dark"
|
||||||
|
:content="t('提示:停用后请等待1分钟再操作')" placement="top">
|
||||||
|
<el-button link type="primary" @click="opInfo(row, 'status')"
|
||||||
|
v-hasPermi="['operation:son:oss:status']">
|
||||||
|
{{ t('停用') }}
|
||||||
|
</el-button>
|
||||||
|
</el-tooltip>
|
||||||
|
<el-button v-if="row.usageStatus == 1 && row.sonType != -1 && row.sonType != -2" link type="primary"
|
||||||
|
@click="opInfo(row, 'edit')" v-hasPermi="['operation:son:oss:edit']">
|
||||||
|
{{ t('修改') }}
|
||||||
|
</el-button>
|
||||||
|
<el-button v-if="row.usageStatus == 1 || row.usageStatus == 5" link type="primary"
|
||||||
|
@click="opInfo(row, 'delete')" v-hasPermi="['operation:son:oss:remove']">
|
||||||
|
{{ t('删除') }}
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<!-- 批量操作 -->
|
||||||
|
<table-batch-operate v-if="total > 0" v-model:batchOpType="batchOpType" v-model:isAllSelection="isAllSelection"
|
||||||
|
@allSelectionChange="allSelectionChange" @opTypeChange="opTypeChange" :selectionData="selectionData"
|
||||||
|
:opTypeOptions="opTypeOptions"></table-batch-operate>
|
||||||
|
<!-- 列表分页 -->
|
||||||
|
<pagination v-if="total > 0" :total="total" v-model:page="queryParams.pageNum"
|
||||||
|
v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 新增域名弹窗 -->
|
||||||
|
<add-son-domain v-if="isShowAdd" type="oss" :supplierList="supplierList" @goDomainManage="goDomainManage"
|
||||||
|
@closeDialog="closeDialog"></add-son-domain>
|
||||||
|
|
||||||
|
<!-- 修改域名弹窗 -->
|
||||||
|
<edit-son-domain v-if="isShowEdit" type="oss" :currentDomainInfo="currentDomainInfo"
|
||||||
|
@closeDialog="closeDialog"></edit-son-domain>
|
||||||
|
|
||||||
|
<!-- 批量操作弹窗 -->
|
||||||
|
<batch-operation v-if="isShowBatchOp" type="oss" :batchOpType="batchOpType" :selectionData="selectionData"
|
||||||
|
@closeDialog="closeDialog"></batch-operation>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="OssList">
|
||||||
|
import {
|
||||||
|
getOssDomainList, // 域名列表
|
||||||
|
refreshOssDomainAnalysis, // 刷新解析说明
|
||||||
|
setOssDomainStatus, // 域名状态切换
|
||||||
|
clearOssDomainCache, // 清理缓存
|
||||||
|
delOssDomain // 删除域名
|
||||||
|
} from "@/api/operation/domain";
|
||||||
|
import AutoRefreshTime from "@/components/AutoRefreshTime"; // 定时刷新
|
||||||
|
import CopyIcon from "@/components/CopyIcon"; // 小图标复制
|
||||||
|
import TableBatchOperate from '@/components/TableBatchOperate'; // 批量操作
|
||||||
|
import SupplierButton from "../components/SupplierButton.vue"; // 供应商选择按钮
|
||||||
|
import AddSonDomain from "../components/AddSonDomain.vue"; // 新增子域名弹窗
|
||||||
|
import EditSonDomain from "../components/EditSonDomain.vue"; // 修改子域名弹窗
|
||||||
|
import BatchOperation from "../components/BatchOperation.vue"; // 批量操作弹窗
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
// 全局搜索结果
|
||||||
|
searchResult: {
|
||||||
|
type: Object,
|
||||||
|
default: {}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance();
|
||||||
|
const loading = ref(true); // loading状态
|
||||||
|
const isShowAdd = ref(false), isShowEdit = ref(false), isShowBatchOp = ref(false); // 各弹窗状态
|
||||||
|
|
||||||
|
// 获取供应商节点信息
|
||||||
|
const supplierRef = ref(null), currentNodeTips = ref(''), supplierList = ref([]);
|
||||||
|
const getCurSupplierNode = (data) => {
|
||||||
|
currentNodeTips.value = data?.tips;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据下拉框条件输入搜索
|
||||||
|
const queryParamsList = ref([{
|
||||||
|
label: proxy.t('操作人'),
|
||||||
|
value: 'updateBy'
|
||||||
|
}, {
|
||||||
|
label: proxy.t('子域名'),
|
||||||
|
value: 'name'
|
||||||
|
}]);
|
||||||
|
|
||||||
|
// 搜索配置
|
||||||
|
const queryParams = reactive({
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 20,
|
||||||
|
searchType: 'updateBy',
|
||||||
|
name: '', // 子域名
|
||||||
|
updateBy: '', // 操作人
|
||||||
|
usageStatus: '', // 使用状态
|
||||||
|
orderByColumn: 'createTime',
|
||||||
|
isAsc: 'desc',
|
||||||
|
domainSupplierId: '' // 供应商
|
||||||
|
});
|
||||||
|
|
||||||
|
// 请求列表
|
||||||
|
const dataList = ref([]), total = ref(0);
|
||||||
|
const getList = () => {
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
getOssDomainList(queryParams).then(res => {
|
||||||
|
loading.value = false;
|
||||||
|
dataList.value = res.rows;
|
||||||
|
total.value = +res.total;
|
||||||
|
clearBatchOp(); // 清空批量操作痕迹
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
dataList.value = [];
|
||||||
|
total.value = 0;
|
||||||
|
clearBatchOp(); // 清空批量操作痕迹
|
||||||
|
});
|
||||||
|
}
|
||||||
|
getList();
|
||||||
|
|
||||||
|
// 新增域名
|
||||||
|
const openAddDomain = () => {
|
||||||
|
supplierList.value = supplierRef.value?.supplierList.filter(v => v.isOpen && !v.stopStatus); // 已开通且不是维护状态的供应商
|
||||||
|
isShowAdd.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 操作信息
|
||||||
|
const currentDomainInfo = ref({}); // 当前操作的域名信息
|
||||||
|
const opInfo = (row, type) => {
|
||||||
|
const _ids = row.id ? [row.id] : row; // 操作的id,有表格内点击和批量操作两种
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case 'status':
|
||||||
|
// 启用/停用
|
||||||
|
let typeName = '', content = '', _usageStatus = '';
|
||||||
|
|
||||||
|
if (row.usageStatus == 1 || row.usageStatus == 5) {
|
||||||
|
typeName = proxy.t('启用');
|
||||||
|
content = proxy.t('确认启用该域名吗!');
|
||||||
|
_usageStatus = 4;
|
||||||
|
} else {
|
||||||
|
typeName = proxy.t('停用');
|
||||||
|
content = proxy.t('确认停用该域名吗!');
|
||||||
|
_usageStatus = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
proxy.$modal.confirm(content).then(() => {
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
setOssDomainStatus({ ids: _ids, usageStatus: _usageStatus }).then(res => {
|
||||||
|
loading.value = false;
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('域名') + typeName + proxy.t('成功!'));
|
||||||
|
getList();
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}).catch(() => { });
|
||||||
|
break
|
||||||
|
case 'refresh':
|
||||||
|
// 刷新域名解析说明
|
||||||
|
row.refreshLoading = true;
|
||||||
|
refreshOssDomainAnalysis({ id: row.id }).then(res => {
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('刷新成功!'));
|
||||||
|
row.refreshLoading = false;
|
||||||
|
getList();
|
||||||
|
}).catch(() => {
|
||||||
|
row.refreshLoading = false;
|
||||||
|
});
|
||||||
|
break
|
||||||
|
case 'clearCache':
|
||||||
|
// 清理缓存
|
||||||
|
proxy.$modal.confirm(proxy.t('确定要清理该记录的缓存吗?')).then(() => {
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
clearOssDomainCache({ ids: _ids }).then(res => {
|
||||||
|
loading.value = false;
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('缓存清理成功!'));
|
||||||
|
getList();
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}).catch(() => { });
|
||||||
|
break
|
||||||
|
case 'delete':
|
||||||
|
// 删除域名
|
||||||
|
proxy.$modal.confirm(proxy.t('确定要删除该域名吗!')).then(() => {
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
delOssDomain(_ids.join(',')).then(res => {
|
||||||
|
loading.value = false;
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('删除成功!'));
|
||||||
|
getList();
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}).catch(() => { });
|
||||||
|
break
|
||||||
|
case 'edit':
|
||||||
|
// 修改域名
|
||||||
|
currentDomainInfo.value = row;
|
||||||
|
isShowEdit.value = true;
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 批量操作
|
||||||
|
const tableRef = ref(),
|
||||||
|
isAllSelection = ref(false), // 是否全选
|
||||||
|
selectionData = ref([]), // 选中的表格数据
|
||||||
|
batchOpType = ref(''); // 选中的批量操作类型
|
||||||
|
|
||||||
|
// 批量操作选项
|
||||||
|
const opTypeOptions = ref([
|
||||||
|
{ label: proxy.t('批量清理缓存'), value: 'clearCache' },
|
||||||
|
{ label: proxy.t('批量删除'), value: 'delete' },
|
||||||
|
{ label: proxy.t('批量停用'), value: 'stop' },
|
||||||
|
{ label: proxy.t('批量启用'), value: 'enable' }
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 勾选表格
|
||||||
|
const tableSelect = (val) => {
|
||||||
|
selectionData.value = val;
|
||||||
|
|
||||||
|
if (val.length === dataList.value.length) {
|
||||||
|
isAllSelection.value = true;
|
||||||
|
} else {
|
||||||
|
isAllSelection.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 全选表格
|
||||||
|
const allSelectionChange = () => {
|
||||||
|
tableRef.value.toggleAllSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 选择批量数据操作类型
|
||||||
|
const opTypeChange = () => {
|
||||||
|
isShowBatchOp.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清空批量操作痕迹
|
||||||
|
const clearBatchOp = () => {
|
||||||
|
isAllSelection.value = false;
|
||||||
|
selectionData.value = [];
|
||||||
|
batchOpType.value = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 搜索按钮操作
|
||||||
|
const handleQuery = () => {
|
||||||
|
queryParams.pageNum = 1;
|
||||||
|
getList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置按钮操作
|
||||||
|
const resetQuery = () => {
|
||||||
|
handleQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭弹窗
|
||||||
|
const closeDialog = (type) => {
|
||||||
|
isShowAdd.value = false; // 新增域名弹窗
|
||||||
|
isShowEdit.value = false; // 修改域名弹窗
|
||||||
|
isShowBatchOp.value = false; // 批量操作弹窗
|
||||||
|
batchOpType.value = ''; // 批量操作类型
|
||||||
|
|
||||||
|
// 批量操作清空
|
||||||
|
if (type === 'batchSubmit') clearBatchOp();
|
||||||
|
// 提交后刷新列表
|
||||||
|
if (type === 'submit' || type === 'batchSubmit') {
|
||||||
|
getList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 跳转域名管理
|
||||||
|
const emit = defineEmits(['goDomainManage']);
|
||||||
|
const goDomainManage = () => {
|
||||||
|
emit('goDomainManage');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 全局搜索展示
|
||||||
|
watch(() => props.searchResult, (val) => {
|
||||||
|
if (val.type == 'domainName') {
|
||||||
|
queryParams.searchType = 'name'
|
||||||
|
queryParams.name = val.domainName;
|
||||||
|
|
||||||
|
nextTick(() => {
|
||||||
|
queryParams.domainSupplierId = val.domainSupplierId;
|
||||||
|
handleQuery();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, { deep: true, immediate: true });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang='scss'>
|
||||||
|
.domain-main {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
// 左侧
|
||||||
|
.dm-left {
|
||||||
|
width: 145px;
|
||||||
|
height: 100%;
|
||||||
|
border-right: 1px solid #e5e5e5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 右侧
|
||||||
|
.dm-right {
|
||||||
|
width: calc(100% - 160px);
|
||||||
|
margin-left: 15px;
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.copy-ml {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,422 @@
|
||||||
|
<template>
|
||||||
|
<!-- 支付域名列表 -->
|
||||||
|
<table-search-card :model="queryParams" @getList="getList" :leftSpan="16" :rightSpan="8" @handleQuery="handleQuery()"
|
||||||
|
@resetQuery="resetQuery">
|
||||||
|
<template #left>
|
||||||
|
<select-input-form :queryParamsList="queryParamsList" v-model:queryParams="queryParams" :width="[130, 260]"
|
||||||
|
@handleQuery="handleQuery"></select-input-form>
|
||||||
|
<el-form-item prop="usageStatus" style="width: 150px;">
|
||||||
|
<dict-select clearable v-model="queryParams.usageStatus" :placeholder="t('使用状态')"
|
||||||
|
dictKey="operation_domain_son_usage_status" @change="handleQuery"></dict-select>
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
<template #right>
|
||||||
|
<auto-refresh-time apiName="paymentDomainList" @refreshFn="getList" style="margin-right: 10px;"></auto-refresh-time>
|
||||||
|
<el-button type="success" plain icon="Plus" @click="openAddDomain" v-hasPermi="['operation:son:pay:add']">{{
|
||||||
|
t('新增') }}</el-button>
|
||||||
|
</template>
|
||||||
|
</table-search-card>
|
||||||
|
|
||||||
|
<!-- 查询表格 -->
|
||||||
|
<div class="domain-main">
|
||||||
|
<!-- 左侧供应商 -->
|
||||||
|
<div class="dm-left">
|
||||||
|
<el-scrollbar max-height="600px">
|
||||||
|
<!-- 供应商选择 -->
|
||||||
|
<supplier-button ref="supplierRef" v-model="queryParams.domainSupplierId" @change="handleQuery"
|
||||||
|
@getCurSupplierNode="getCurSupplierNode"></supplier-button>
|
||||||
|
</el-scrollbar>
|
||||||
|
</div>
|
||||||
|
<!-- 右侧表格 -->
|
||||||
|
<div class="dm-right">
|
||||||
|
<el-alert v-if="currentNodeTips" style="margin-bottom: 15px;" :title="currentNodeTips" :closable="false"
|
||||||
|
type="warning" show-icon />
|
||||||
|
|
||||||
|
<el-table ref="tableRef" class="c-table-main" v-loading="loading" row-key="id" stripe border :data="dataList"
|
||||||
|
@select="tableSelect" @select-all="tableSelect">
|
||||||
|
<el-table-column align="center" type="selection" width="55" />
|
||||||
|
<el-table-column :label="t('CDN节点名称')" align="center" min-width="160">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ row.cdnNodeName }}
|
||||||
|
<dict-text class="c-green" dictKey="ff_operation_son_type" :value="row.sonType" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column align="center" min-width="280">
|
||||||
|
<template #header>
|
||||||
|
<span>{{ t('生效域名') }}</span>
|
||||||
|
</template>
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ row.name }}<copy-icon :text="row.name" class="copy-ml"></copy-icon>
|
||||||
|
<p :class="'c-clear ' + (row.analyzeStatus ? 'c-green' : 'c-red')">{{ row.analyzeStatus ? t('已解析') :
|
||||||
|
t('待解析') }}</p>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column align="center" min-width="220">
|
||||||
|
<template #header>
|
||||||
|
<span>{{ t('解析说明(生效状态和网速)') }}</span>
|
||||||
|
</template>
|
||||||
|
<template #default="{ row }">
|
||||||
|
<span :class="'c-clear ' + (row.analyzeInvalid ? 'c-green' : 'c-red')">{{ row.analyzeInvalid ?
|
||||||
|
t('已生效') : t('未生效') }}</span>
|
||||||
|
<el-icon @click="opInfo(row, 'refresh')" :class="row.refreshLoading ? 'c-rotate' : ''"
|
||||||
|
style="position: relative; top: 4px; margin-left: 8px;" size="16" class="c-blue">
|
||||||
|
<Refresh />
|
||||||
|
</el-icon>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column :label="t('使用状态')" align="center" min-width="120">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<dict-text :colorValues="['c-grey', 'c-orange', 'c-orange', 'c-green', 'c-red']"
|
||||||
|
dictKey="operation_domain_son_usage_status" :value="row.usageStatus" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<table-operation></table-operation>
|
||||||
|
<el-table-column :label="t('操作')" align="center" min-width="220" fixed="right">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-button v-if="row.usageStatus == 4 && !row.mainSon" link type="primary" @click="opInfo(row, 'main')"
|
||||||
|
v-hasPermi="['operation:son:pay:main']">
|
||||||
|
{{ t('设为主域名') }}
|
||||||
|
</el-button>
|
||||||
|
<el-button v-if="row.usageStatus == 4" link type="primary" @click="opInfo(row, 'clearCache')"
|
||||||
|
v-hasPermi="['operation:son:pay:clear']">
|
||||||
|
{{ t('清理缓存') }}
|
||||||
|
</el-button>
|
||||||
|
<el-tooltip v-if="row.usageStatus == 1 || row.usageStatus == 5" effect="dark"
|
||||||
|
:content="t('提示:启用后请等待1分钟再操作')" placement="top">
|
||||||
|
<el-button link type="primary" @click="opInfo(row, 'status')"
|
||||||
|
v-hasPermi="['operation:son:pay:status']">
|
||||||
|
{{ t('启用') }}
|
||||||
|
</el-button>
|
||||||
|
</el-tooltip>
|
||||||
|
<el-tooltip v-if="row.usageStatus == 2 || row.usageStatus == 3 || row.usageStatus == 4" effect="dark"
|
||||||
|
:content="t('提示:停用后请等待1分钟再操作')" placement="top">
|
||||||
|
<el-button link type="primary" @click="opInfo(row, 'status')"
|
||||||
|
v-hasPermi="['operation:son:pay:status']">
|
||||||
|
{{ t('停用') }}
|
||||||
|
</el-button>
|
||||||
|
</el-tooltip>
|
||||||
|
<el-button v-if="row.usageStatus == 1 && row.sonType != -1 && row.sonType != -2" link type="primary"
|
||||||
|
@click="opInfo(row, 'edit')" v-hasPermi="['operation:son:pay:edit']">
|
||||||
|
{{ t('修改') }}
|
||||||
|
</el-button>
|
||||||
|
<el-button v-if="row.usageStatus == 1 || row.usageStatus == 5" link type="primary"
|
||||||
|
@click="opInfo(row, 'delete')" v-hasPermi="['operation:son:pay:remove']">
|
||||||
|
{{ t('删除') }}
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<!-- 批量操作 -->
|
||||||
|
<table-batch-operate v-if="total > 0" v-model:batchOpType="batchOpType" v-model:isAllSelection="isAllSelection"
|
||||||
|
@allSelectionChange="allSelectionChange" @opTypeChange="opTypeChange" :selectionData="selectionData"
|
||||||
|
:opTypeOptions="opTypeOptions"></table-batch-operate>
|
||||||
|
<!-- 列表分页 -->
|
||||||
|
<pagination v-if="total > 0" :total="total" v-model:page="queryParams.pageNum"
|
||||||
|
v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 新增域名弹窗 -->
|
||||||
|
<add-son-domain v-if="isShowAdd" type="payment" :supplierList="supplierList" @goDomainManage="goDomainManage"
|
||||||
|
@closeDialog="closeDialog"></add-son-domain>
|
||||||
|
|
||||||
|
<!-- 修改域名弹窗 -->
|
||||||
|
<edit-son-domain v-if="isShowEdit" type="payment" :currentDomainInfo="currentDomainInfo"
|
||||||
|
@closeDialog="closeDialog"></edit-son-domain>
|
||||||
|
|
||||||
|
<!-- 批量操作弹窗 -->
|
||||||
|
<batch-operation v-if="isShowBatchOp" type="payment" :batchOpType="batchOpType" :selectionData="selectionData"
|
||||||
|
@closeDialog="closeDialog"></batch-operation>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="PaymentList">
|
||||||
|
import {
|
||||||
|
getPayDomainList, // 域名列表
|
||||||
|
setPayDomainMain, // 主域名设置
|
||||||
|
refreshPayDomainAnalysis, // 刷新解析说明
|
||||||
|
setPayDomainStatus, // 域名状态切换
|
||||||
|
clearPayDomainCache, // 清理缓存
|
||||||
|
delPayDomain // 删除域名
|
||||||
|
} from "@/api/operation/domain";
|
||||||
|
import AutoRefreshTime from "@/components/AutoRefreshTime"; // 定时刷新
|
||||||
|
import CopyIcon from "@/components/CopyIcon"; // 小图标复制
|
||||||
|
import TableBatchOperate from '@/components/TableBatchOperate'; // 批量操作
|
||||||
|
import SupplierButton from "../components/SupplierButton.vue"; // 供应商选择按钮
|
||||||
|
import AddSonDomain from "../components/AddSonDomain.vue"; // 新增子域名弹窗
|
||||||
|
import EditSonDomain from "../components/EditSonDomain.vue"; // 修改子域名弹窗
|
||||||
|
import BatchOperation from "../components/BatchOperation.vue"; // 批量操作弹窗
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
// 全局搜索结果
|
||||||
|
searchResult: {
|
||||||
|
type: Object,
|
||||||
|
default: {}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance();
|
||||||
|
const loading = ref(true); // loading状态
|
||||||
|
const isShowAdd = ref(false), isShowEdit = ref(false), isShowBatchOp = ref(false); // 各弹窗状态
|
||||||
|
|
||||||
|
// 获取供应商节点信息
|
||||||
|
const supplierRef = ref(null), currentNodeTips = ref(''), supplierList = ref([]);
|
||||||
|
const getCurSupplierNode = (data) => {
|
||||||
|
currentNodeTips.value = data?.tips;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据下拉框条件输入搜索
|
||||||
|
const queryParamsList = ref([{
|
||||||
|
label: proxy.t('操作人'),
|
||||||
|
value: 'updateBy'
|
||||||
|
}, {
|
||||||
|
label: proxy.t('子域名'),
|
||||||
|
value: 'name'
|
||||||
|
}]);
|
||||||
|
|
||||||
|
// 搜索配置
|
||||||
|
const queryParams = reactive({
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 20,
|
||||||
|
searchType: 'updateBy',
|
||||||
|
name: '', // 子域名
|
||||||
|
updateBy: '', // 操作人
|
||||||
|
usageStatus: '', // 使用状态
|
||||||
|
orderByColumn: 'createTime',
|
||||||
|
isAsc: 'desc',
|
||||||
|
domainSupplierId: '' // 供应商
|
||||||
|
});
|
||||||
|
|
||||||
|
// 请求列表
|
||||||
|
const dataList = ref([]), total = ref(0);
|
||||||
|
const getList = () => {
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
getPayDomainList(queryParams).then(res => {
|
||||||
|
loading.value = false;
|
||||||
|
dataList.value = res.rows;
|
||||||
|
total.value = +res.total;
|
||||||
|
clearBatchOp(); // 清空批量操作痕迹
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
dataList.value = [];
|
||||||
|
total.value = 0;
|
||||||
|
clearBatchOp(); // 清空批量操作痕迹
|
||||||
|
});
|
||||||
|
}
|
||||||
|
getList();
|
||||||
|
|
||||||
|
// 新增域名
|
||||||
|
const openAddDomain = () => {
|
||||||
|
supplierList.value = supplierRef.value?.supplierList.filter(v => v.isOpen && !v.stopStatus); // 已开通且不是维护状态的供应商
|
||||||
|
isShowAdd.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 操作信息
|
||||||
|
const currentDomainInfo = ref({}); // 当前操作的域名信息
|
||||||
|
const opInfo = (row, type) => {
|
||||||
|
const _ids = row.id ? [row.id] : row; // 操作的id,有表格内点击和批量操作两种
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case'main':
|
||||||
|
// 设为主域名
|
||||||
|
proxy.$modal.confirm(proxy.t('确定要设置为主域名吗?')).then(() => {
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
setPayDomainMain({ id: row.id }).then(res => {
|
||||||
|
loading.value = false;
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('设置成功!'));
|
||||||
|
getList();
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}).catch(() => { });
|
||||||
|
break
|
||||||
|
case 'status':
|
||||||
|
// 启用/停用
|
||||||
|
let typeName = '', content = '', _usageStatus = '';
|
||||||
|
|
||||||
|
if (row.usageStatus == 1 || row.usageStatus == 5) {
|
||||||
|
typeName = proxy.t('启用');
|
||||||
|
content = proxy.t('确认启用该域名吗!');
|
||||||
|
_usageStatus = 4;
|
||||||
|
} else {
|
||||||
|
typeName = proxy.t('停用');
|
||||||
|
content = proxy.t('确认停用该域名吗!');
|
||||||
|
_usageStatus = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
proxy.$modal.confirm(content).then(() => {
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
setPayDomainStatus({ ids: _ids, usageStatus: _usageStatus }).then(res => {
|
||||||
|
loading.value = false;
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('域名') + typeName + proxy.t('成功!'));
|
||||||
|
getList();
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}).catch(() => { });
|
||||||
|
break
|
||||||
|
case 'refresh':
|
||||||
|
// 刷新域名解析说明
|
||||||
|
row.refreshLoading = true;
|
||||||
|
refreshPayDomainAnalysis({ id: row.id }).then(res => {
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('刷新成功!'));
|
||||||
|
row.refreshLoading = false;
|
||||||
|
getList();
|
||||||
|
}).catch(() => {
|
||||||
|
row.refreshLoading = false;
|
||||||
|
});
|
||||||
|
break
|
||||||
|
case 'clearCache':
|
||||||
|
// 清理缓存
|
||||||
|
proxy.$modal.confirm(proxy.t('确定要清理该记录的缓存吗?')).then(() => {
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
clearPayDomainCache({ ids: _ids }).then(res => {
|
||||||
|
loading.value = false;
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('缓存清理成功!'));
|
||||||
|
getList();
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}).catch(() => { });
|
||||||
|
break
|
||||||
|
case 'delete':
|
||||||
|
// 删除域名
|
||||||
|
proxy.$modal.confirm(proxy.t('确定要删除该域名吗!')).then(() => {
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
delPayDomain(_ids.join(',')).then(res => {
|
||||||
|
loading.value = false;
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('删除成功!'));
|
||||||
|
getList();
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}).catch(() => { });
|
||||||
|
break
|
||||||
|
case 'edit':
|
||||||
|
// 修改域名
|
||||||
|
currentDomainInfo.value = row;
|
||||||
|
isShowEdit.value = true;
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 批量操作
|
||||||
|
const tableRef = ref(),
|
||||||
|
isAllSelection = ref(false), // 是否全选
|
||||||
|
selectionData = ref([]), // 选中的表格数据
|
||||||
|
batchOpType = ref(''); // 选中的批量操作类型
|
||||||
|
|
||||||
|
// 批量操作选项
|
||||||
|
const opTypeOptions = ref([
|
||||||
|
{ label: proxy.t('批量清理缓存'), value: 'clearCache' },
|
||||||
|
{ label: proxy.t('批量删除'), value: 'delete' },
|
||||||
|
{ label: proxy.t('批量停用'), value: 'stop' },
|
||||||
|
{ label: proxy.t('批量启用'), value: 'enable' }
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 勾选表格
|
||||||
|
const tableSelect = (val) => {
|
||||||
|
selectionData.value = val;
|
||||||
|
|
||||||
|
if (val.length === dataList.value.length) {
|
||||||
|
isAllSelection.value = true;
|
||||||
|
} else {
|
||||||
|
isAllSelection.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 全选表格
|
||||||
|
const allSelectionChange = () => {
|
||||||
|
tableRef.value.toggleAllSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 选择批量数据操作类型
|
||||||
|
const opTypeChange = () => {
|
||||||
|
isShowBatchOp.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清空批量操作痕迹
|
||||||
|
const clearBatchOp = () => {
|
||||||
|
isAllSelection.value = false;
|
||||||
|
selectionData.value = [];
|
||||||
|
batchOpType.value = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 搜索按钮操作
|
||||||
|
const handleQuery = () => {
|
||||||
|
queryParams.pageNum = 1;
|
||||||
|
getList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置按钮操作
|
||||||
|
const resetQuery = () => {
|
||||||
|
handleQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭弹窗
|
||||||
|
const closeDialog = (type) => {
|
||||||
|
isShowAdd.value = false; // 新增域名弹窗
|
||||||
|
isShowEdit.value = false; // 修改域名弹窗
|
||||||
|
isShowBatchOp.value = false; // 批量操作弹窗
|
||||||
|
batchOpType.value = ''; // 批量操作类型
|
||||||
|
|
||||||
|
// 批量操作清空
|
||||||
|
if (type === 'batchSubmit') clearBatchOp();
|
||||||
|
// 提交后刷新列表
|
||||||
|
if (type === 'submit' || type === 'batchSubmit') {
|
||||||
|
getList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 跳转域名管理
|
||||||
|
const emit = defineEmits(['goDomainManage']);
|
||||||
|
const goDomainManage = () => {
|
||||||
|
emit('goDomainManage');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 全局搜索展示
|
||||||
|
watch(() => props.searchResult, (val) => {
|
||||||
|
if (val.type == 'domainName') {
|
||||||
|
queryParams.searchType = 'name'
|
||||||
|
queryParams.name = val.domainName;
|
||||||
|
|
||||||
|
nextTick(() => {
|
||||||
|
queryParams.domainSupplierId = val.domainSupplierId;
|
||||||
|
handleQuery();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, { deep: true, immediate: true });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang='scss'>
|
||||||
|
.domain-main {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
// 左侧
|
||||||
|
.dm-left {
|
||||||
|
width: 145px;
|
||||||
|
height: 100%;
|
||||||
|
border-right: 1px solid #e5e5e5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 右侧
|
||||||
|
.dm-right {
|
||||||
|
width: calc(100% - 160px);
|
||||||
|
margin-left: 15px;
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.copy-ml {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,645 @@
|
||||||
|
<template>
|
||||||
|
<!-- web大厅域名列表 -->
|
||||||
|
<table-search-card :model="queryParams" @getList="getList" :leftSpan="16" :rightSpan="8" @handleQuery="handleQuery()"
|
||||||
|
@resetQuery="resetQuery">
|
||||||
|
<template #left>
|
||||||
|
<select-input-form :queryParamsList="queryParamsList" v-model:queryParams="queryParams" :width="[130, 260]"
|
||||||
|
@handleQuery="handleQuery"></select-input-form>
|
||||||
|
<el-form-item prop="usageStatus" style="width: 150px;">
|
||||||
|
<dict-select clearable v-model="queryParams.usageStatus" :placeholder="t('使用状态')"
|
||||||
|
dictKey="operation_domain_son_usage_status" @change="handleQuery"></dict-select>
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
<template #right>
|
||||||
|
<span class="right-switch" v-if="h5InterceptOpen > 0">
|
||||||
|
{{ t('H5防拦截开关') }}
|
||||||
|
<icon-tips>
|
||||||
|
<p class="c-clear" style="width: 400px;">
|
||||||
|
{{ t('说明:(大陆推荐开启) 同品牌与SEO管理--防拦截模式开关功能同步,因该功能将隐藏敏感信息,所以开启后普通SEO和专业SEO将失效,且无法使用') }}
|
||||||
|
</p>
|
||||||
|
</icon-tips>
|
||||||
|
<base-switch style="margin: 0 12px 0 5px;" :active-value="1" :inactive-value="2" v-model="h5InterceptOpen"
|
||||||
|
:tipText="t('确认') + (h5InterceptOpen == 2 ? t('开启') : t('关闭')) + t('H5防拦截吗?')"
|
||||||
|
:before-change="() => configSwitchChange('h5InterceptOpen')"
|
||||||
|
v-hasPermi="['operation:son:web:system:edit']"></base-switch>
|
||||||
|
</span>
|
||||||
|
<auto-refresh-time apiName="webDomainList" @refreshFn="getList"
|
||||||
|
style="margin-right: 10px;"></auto-refresh-time>
|
||||||
|
<el-button type="success" plain icon="Plus" @click="openAddDomain" v-hasPermi="['operation:son:web:add']">{{
|
||||||
|
t('新增') }}</el-button>
|
||||||
|
</template>
|
||||||
|
</table-search-card>
|
||||||
|
|
||||||
|
<!-- 查询表格 -->
|
||||||
|
<div class="domain-main">
|
||||||
|
<!-- 左侧供应商 -->
|
||||||
|
<div class="dm-left">
|
||||||
|
<el-scrollbar max-height="600px">
|
||||||
|
<!-- 供应商选择 -->
|
||||||
|
<supplier-button ref="supplierRef" v-model="queryParams.domainSupplierId" @change="handleQuery"
|
||||||
|
@getCurSupplierNode="getCurSupplierNode"></supplier-button>
|
||||||
|
</el-scrollbar>
|
||||||
|
</div>
|
||||||
|
<!-- 右侧表格 -->
|
||||||
|
<div class="dm-right">
|
||||||
|
<el-alert v-if="currentNodeTips" style="margin-bottom: 15px;" :title="currentNodeTips" :closable="false"
|
||||||
|
type="warning" show-icon />
|
||||||
|
|
||||||
|
<el-table ref="tableRef" class="c-table-main" v-loading="loading" row-key="id" stripe border :data="dataList"
|
||||||
|
@select="tableSelect" @select-all="tableSelect">
|
||||||
|
<el-table-column align="center" type="selection" width="55" />
|
||||||
|
<el-table-column :label="t('CDN节点名称')" align="center" min-width="160">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ row.cdnNodeName }}
|
||||||
|
<dict-text class="c-green" dictKey="ff_operation_son_type" :value="row.sonType" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column align="center" min-width="280">
|
||||||
|
<template #header>
|
||||||
|
<span>{{ t('生效域名') }}</span>
|
||||||
|
</template>
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ row.name }}<copy-icon :text="row.name" class="copy-ml"></copy-icon>
|
||||||
|
<p :class="'c-clear ' + (row.analyzeStatus ? 'c-green' : 'c-red')">{{ row.analyzeStatus ? t('已解析') :
|
||||||
|
t('待解析') }}</p>
|
||||||
|
<p v-if="row.operationDomainSonDns.length !=0">
|
||||||
|
<div v-for="(item,index) in row.operationDomainSonDns">
|
||||||
|
{{ t('DNS修改为以下服务器后刷新解析:') }} {{ item.typeValue }}:{{ item.value }}
|
||||||
|
</div>
|
||||||
|
</p>
|
||||||
|
<p v-if="row.analyzeStatu && row.operationDomainSonDns.length !=0">
|
||||||
|
<div v-for="(item,index) in row.operationDomainSonDns">
|
||||||
|
{{ t('已解析完成:') }} {{ item.typeValue }}:{{ item.value }}
|
||||||
|
</div>
|
||||||
|
</p>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column :label="t('端口类型')" align="center" min-width="120">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<dict-text dictKey="ff_operation_domain_son_port_type" :value="row.portType" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column :label="t('端口号')" prop="portValue" align="center" min-width="120"></el-table-column>
|
||||||
|
<el-table-column align="center" min-width="220">
|
||||||
|
<template #header>
|
||||||
|
<span>{{ t('解析说明(生效状态和网速)') }}</span>
|
||||||
|
</template>
|
||||||
|
<template #default="{ row }">
|
||||||
|
<span :class="'c-clear ' + (row.analyzeInvalid ? 'c-green' : 'c-red')">{{ row.analyzeInvalid ?
|
||||||
|
t('已生效') : t('未生效') }}</span>
|
||||||
|
<el-icon @click="opInfo(row, 'refresh')" :class="row.refreshLoading ? 'c-rotate' : ''"
|
||||||
|
style="position: relative; top: 4px; margin-left: 8px;" size="16" class="c-blue">
|
||||||
|
<Refresh />
|
||||||
|
</el-icon>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column align="center" min-width="160">
|
||||||
|
<template #header>
|
||||||
|
<span>{{ t('其他担保域名列表') }}</span>
|
||||||
|
<icon-tips>
|
||||||
|
<p class="c-clear" style="width: 400px;">
|
||||||
|
{{ t('1.展示:即会员验证担保域名后,会展示一些站点的其他域名列表,方便会员保存记录、找到回家路或信任其他域名(推荐无封锁的国家)。') }}<br />
|
||||||
|
{{ t('2.隐藏:即会员验证担保域名后,只能看到当前域名的验证结果,看不到其他域名列表,防止域名全部暴露,有被拦截和举报的风险。') }}
|
||||||
|
</p>
|
||||||
|
</icon-tips>
|
||||||
|
</template>
|
||||||
|
<template #default="{ row }">
|
||||||
|
<base-switch :active-value="true" :inactive-value="false" v-model="row.backupDomain"
|
||||||
|
:tipText="row.status ? t('确认隐藏吗?') : t('确认展示吗?')" :disabled="row.usageStatus != 4"
|
||||||
|
:before-change="() => beforeSwitchChange(row, 'backupDomain')"></base-switch>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column align="center" min-width="160">
|
||||||
|
<template #header>
|
||||||
|
<span>{{ t('作为推广域名') }}</span>
|
||||||
|
<icon-tips>
|
||||||
|
{{ t('开启作为前台代理推广域名显示,且建议保持一条域名开启') }}
|
||||||
|
</icon-tips>
|
||||||
|
</template>
|
||||||
|
<template #default="{ row }">
|
||||||
|
<base-switch :active-value="true" :inactive-value="false" v-model="row.marketingDomain"
|
||||||
|
:tipText="row.status ? t('确认关闭吗?') : t('确认开启吗?')"
|
||||||
|
:disabled="row.startEntrance == 2 || row.usageStatus != 4"
|
||||||
|
:before-change="() => beforeSwitchChange(row, 'marketingDomain')"></base-switch>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column align="center" min-width="150">
|
||||||
|
<template #header>
|
||||||
|
<span>{{ t('强制绑定代理') }}</span>
|
||||||
|
<icon-tips>
|
||||||
|
<p class="c-clear" style="width: 400px;">
|
||||||
|
{{ t('代理上级归属优先级:推广链接的上级 > 渠道ID的强制绑定上级 > 域名管理的强制绑定上级(无上级时,域名管理的才生效)') }}
|
||||||
|
</p>
|
||||||
|
</icon-tips>
|
||||||
|
</template>
|
||||||
|
<template #default="{ row }">
|
||||||
|
<span v-if="row.agentAccount" class="c-blue" @click="goRoute(row, 'agentAccount')">{{
|
||||||
|
row.agentAccount }}</span>
|
||||||
|
<span v-else>{{ t('无') }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column align="center" min-width="150">
|
||||||
|
<template #header>
|
||||||
|
<span>{{ t('启用入口') }}</span>
|
||||||
|
<icon-tips>
|
||||||
|
<p class="c-clear" style="width: 400px;">
|
||||||
|
{{ t('1.全部(默认,不限制)') }} <br />
|
||||||
|
{{ t('2.仅极速APP(无法直接访问网址)') }} <br />
|
||||||
|
{{ t('3.H5和PWA(H5和PWA可以访问网址,但不会出现在轮巡列表)') }} <br />
|
||||||
|
{{ t('4.支持CDN节点:阿里云,Funnull,Cloudflare,YunDun,WangSu,腾讯云,CloudFront') }}
|
||||||
|
</p>
|
||||||
|
</icon-tips>
|
||||||
|
</template>
|
||||||
|
<template #default="{ row }">
|
||||||
|
<dict-select class="w100" v-model="row.startEntrance" dictKey="ff_operation_start_entrance"
|
||||||
|
@change="changeRowStatus(row, 'startEntrance')" :disabled="row.usageStatus != 4"></dict-select>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column align="center" min-width="150">
|
||||||
|
<template #header>
|
||||||
|
<span>{{ t('屏蔽设备') }}</span>
|
||||||
|
<icon-tips>
|
||||||
|
<p class="c-clear" style="width: 400px;">
|
||||||
|
{{ t('1.都不屏蔽(默认)') }} <br />
|
||||||
|
{{ t('2.屏蔽PC端(移动端-安卓/ios可访问,PC电脑端不可访问)') }} <br />
|
||||||
|
{{ t('3.屏蔽手机端(PC电脑端可访问,移动端-安卓/ios不可访问)') }} <br />
|
||||||
|
{{ t('4.支持CDN节点:阿里云,Funnull,Cloudflare,YunDun,WangSu,腾讯云,CloudFront') }}
|
||||||
|
</p>
|
||||||
|
</icon-tips>
|
||||||
|
</template>
|
||||||
|
<template #default="{ row }">
|
||||||
|
<dict-select class="w100" v-model="row.blockDevice" dictKey="ff_operation_block_device"
|
||||||
|
@change="changeRowStatus(row, 'blockDevice')"
|
||||||
|
:disabled="row.usageStatus != 4 || row.startEntrance == 2"></dict-select>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column :label="t('使用状态')" align="center" min-width="120">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<dict-text :colorValues="['c-grey', 'c-orange', 'c-orange', 'c-green', 'c-red']"
|
||||||
|
dictKey="operation_domain_son_usage_status" :value="row.usageStatus" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<table-operation></table-operation>
|
||||||
|
<el-table-column :label="t('操作')" align="center" min-width="220" fixed="right">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-button v-if="row.usageStatus == 4" link type="primary" @click="opInfo(row, 'agent')"
|
||||||
|
v-hasPermi="['operation:son:web:agent']">
|
||||||
|
{{ t('绑定代理') }}
|
||||||
|
</el-button>
|
||||||
|
<el-button v-if="row.usageStatus == 4" link type="primary" @click="opInfo(row, 'clearCache')"
|
||||||
|
v-hasPermi="['operation:son:web:clear']">
|
||||||
|
{{ t('清理缓存') }}
|
||||||
|
</el-button>
|
||||||
|
<el-tooltip v-if="row.usageStatus == 1 || row.usageStatus == 5" effect="dark"
|
||||||
|
:content="t('提示:启用后请等待1分钟再操作')" placement="top">
|
||||||
|
<el-button link type="primary" @click="opInfo(row, 'status')"
|
||||||
|
v-hasPermi="['operation:son:web:status']">
|
||||||
|
{{ t('启用') }}
|
||||||
|
</el-button>
|
||||||
|
</el-tooltip>
|
||||||
|
<el-tooltip v-if="row.usageStatus == 2 || row.usageStatus == 3 || row.usageStatus == 4" effect="dark"
|
||||||
|
:content="t('提示:停用后请等待1分钟再操作')" placement="top">
|
||||||
|
<el-button link type="primary" @click="opInfo(row, 'status')"
|
||||||
|
v-hasPermi="['operation:son:web:status']">
|
||||||
|
{{ t('停用') }}
|
||||||
|
</el-button>
|
||||||
|
</el-tooltip>
|
||||||
|
<el-button v-if="row.usageStatus == 1 && row.sonType != -1 && row.sonType != -2" link type="primary"
|
||||||
|
@click="opInfo(row, 'edit')" v-hasPermi="['operation:son:web:edit']">
|
||||||
|
{{ t('修改') }}
|
||||||
|
</el-button>
|
||||||
|
<el-button v-if="row.usageStatus == 1 || row.usageStatus == 5" link type="primary"
|
||||||
|
@click="opInfo(row, 'delete')" v-hasPermi="['operation:son:web:remove']">
|
||||||
|
{{ t('删除') }}
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<!-- 批量操作 -->
|
||||||
|
<table-batch-operate v-if="total > 0" v-model:batchOpType="batchOpType" v-model:isAllSelection="isAllSelection"
|
||||||
|
@allSelectionChange="allSelectionChange" @opTypeChange="opTypeChange" :selectionData="selectionData"
|
||||||
|
:opTypeOptions="opTypeOptions"></table-batch-operate>
|
||||||
|
<!-- 列表分页 -->
|
||||||
|
<pagination v-if="total > 0" :total="total" v-model:page="queryParams.pageNum"
|
||||||
|
v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 新增域名弹窗 -->
|
||||||
|
<add-son-domain v-if="isShowAdd" type="webHall" :supplierList="supplierList" @goDomainManage="goDomainManage"
|
||||||
|
@closeDialog="closeDialog"></add-son-domain>
|
||||||
|
|
||||||
|
<!-- 修改域名弹窗 -->
|
||||||
|
<edit-son-domain v-if="isShowEdit" type="webHall" :currentDomainInfo="currentDomainInfo"
|
||||||
|
@closeDialog="closeDialog"></edit-son-domain>
|
||||||
|
|
||||||
|
<!-- 绑定代理弹窗 -->
|
||||||
|
<bind-agent v-if="isShowAgent" type="webHall" :currentDomainInfo="currentDomainInfo"
|
||||||
|
@closeDialog="closeDialog"></bind-agent>
|
||||||
|
|
||||||
|
<!-- 批量操作弹窗 -->
|
||||||
|
<batch-operation v-if="isShowBatchOp" type="webHall" :batchOpType="batchOpType" :selectionData="selectionData"
|
||||||
|
@closeDialog="closeDialog"></batch-operation>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="WebHallList">
|
||||||
|
import {
|
||||||
|
getWebDomainList, // 域名列表
|
||||||
|
refreshWebDomainAnalysis, // 刷新解析说明
|
||||||
|
webDomainSwitch, // 开关切换
|
||||||
|
setWebDomainStatus, // 域名状态切换
|
||||||
|
clearWebDomainCache, // 清理缓存
|
||||||
|
delWebDomain, // 删除域名
|
||||||
|
getWebSystemParam, // 获取系统参数
|
||||||
|
updateWebSystemParam // 更新系统参数
|
||||||
|
} from "@/api/operation/domain";
|
||||||
|
import AutoRefreshTime from "@/components/AutoRefreshTime"; // 定时刷新
|
||||||
|
import CopyIcon from "@/components/CopyIcon"; // 小图标复制
|
||||||
|
import IconTips from "@/components/IconTips"; // 小图标提示
|
||||||
|
import TableBatchOperate from '@/components/TableBatchOperate'; // 批量操作
|
||||||
|
import SupplierButton from "../components/SupplierButton.vue"; // 供应商选择按钮
|
||||||
|
import BaseSwitch from "@/components/BaseSwitch"; // 开关
|
||||||
|
import AddSonDomain from "../components/AddSonDomain.vue"; // 新增子域名弹窗
|
||||||
|
import EditSonDomain from "../components/EditSonDomain.vue"; // 修改子域名弹窗
|
||||||
|
import BindAgent from "../components/BindAgent.vue"; // 绑定代理
|
||||||
|
import BatchOperation from "../components/BatchOperation.vue"; // 批量操作弹窗
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
// 全局搜索结果
|
||||||
|
searchResult: {
|
||||||
|
type: Object,
|
||||||
|
default: {}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance();
|
||||||
|
const loading = ref(true); // loading状态
|
||||||
|
const isShowAdd = ref(false), isShowAgent = ref(false), isShowEdit = ref(false), isShowBatchOp = ref(false); // 各弹窗状态
|
||||||
|
|
||||||
|
// H5防拦截开关
|
||||||
|
const h5InterceptOpen = ref(0);
|
||||||
|
getWebSystemParam().then(res => {
|
||||||
|
h5InterceptOpen.value = +res.data.h5InterceptOpen;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 切换H5防拦截开关状态
|
||||||
|
const configSwitchChange = (type) => {
|
||||||
|
if (type == 'h5InterceptOpen') {
|
||||||
|
const params = {
|
||||||
|
h5InterceptOpen: h5InterceptOpen.value == 1 ? 2 : 1
|
||||||
|
}
|
||||||
|
updateWebSystemParam(params).then(() => {
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('操作成功!'));
|
||||||
|
h5InterceptOpen.value = params.h5InterceptOpen;
|
||||||
|
}).catch(() => {
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取供应商节点信息
|
||||||
|
const supplierRef = ref(null), currentNodeTips = ref(''), supplierList = ref([]);
|
||||||
|
const getCurSupplierNode = (data) => {
|
||||||
|
currentNodeTips.value = data?.tips;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据下拉框条件输入搜索
|
||||||
|
const queryParamsList = ref([{
|
||||||
|
label: proxy.t('操作人'),
|
||||||
|
value: 'updateBy'
|
||||||
|
}, {
|
||||||
|
label: proxy.t('子域名'),
|
||||||
|
value: 'name'
|
||||||
|
}]);
|
||||||
|
|
||||||
|
// 搜索配置
|
||||||
|
const queryParams = reactive({
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 20,
|
||||||
|
searchType: 'updateBy',
|
||||||
|
name: '', // 子域名
|
||||||
|
updateBy: '', // 操作人
|
||||||
|
usageStatus: '', // 使用状态
|
||||||
|
orderByColumn: 'createTime',
|
||||||
|
isAsc: 'desc',
|
||||||
|
domainSupplierId: '' // 供应商
|
||||||
|
});
|
||||||
|
|
||||||
|
// 请求列表
|
||||||
|
const dataList = ref([]), total = ref(0);
|
||||||
|
const getList = () => {
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
getWebDomainList(queryParams).then(res => {
|
||||||
|
loading.value = false;
|
||||||
|
|
||||||
|
// 更改特定字段类型
|
||||||
|
res.rows.forEach(item => {
|
||||||
|
item.startEntrance = item.startEntrance.toString();
|
||||||
|
item.blockDevice = item.blockDevice.toString();
|
||||||
|
});
|
||||||
|
|
||||||
|
dataList.value = res.rows;
|
||||||
|
total.value = +res.total;
|
||||||
|
clearBatchOp(); // 清空批量操作痕迹
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
dataList.value = [];
|
||||||
|
total.value = 0;
|
||||||
|
clearBatchOp(); // 清空批量操作痕迹
|
||||||
|
});
|
||||||
|
}
|
||||||
|
getList();
|
||||||
|
|
||||||
|
// 跳转页面
|
||||||
|
const goRoute = (row, type) => {
|
||||||
|
proxy.$router.push({
|
||||||
|
path: '/agent/agent-info',
|
||||||
|
query: {
|
||||||
|
[type]: row.agentAccount,
|
||||||
|
searchType: type
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增域名
|
||||||
|
const openAddDomain = () => {
|
||||||
|
supplierList.value = supplierRef.value?.supplierList.filter(v => v.isOpen && !v.stopStatus); // 已开通且不是维护状态的供应商
|
||||||
|
isShowAdd.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 开启状态切换
|
||||||
|
const beforeSwitchChange = (row, type) => {
|
||||||
|
const params = {
|
||||||
|
id: row.id,
|
||||||
|
[type]: !row[type]
|
||||||
|
}
|
||||||
|
|
||||||
|
webDomainSwitch({ operationDomainSons: [params] }).then(res => {
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('操作成功!'));
|
||||||
|
getList();
|
||||||
|
return true;
|
||||||
|
}).catch(() => {
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 启用入口、屏蔽设备切换
|
||||||
|
const changeRowStatus = (row, type) => {
|
||||||
|
const params = {
|
||||||
|
id: row.id,
|
||||||
|
[type]: row[type]
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === 'startEntrance') {
|
||||||
|
// 启用入口
|
||||||
|
const _label = proxy.useDict('ff_operation_start_entrance').ff_operation_start_entrance.find(v => v.value == row.startEntrance).label;
|
||||||
|
|
||||||
|
if (row.startEntrance == 2) params.marketingDomain = false; // 开启入口为仅极速APP时,强制关闭作为推广域名
|
||||||
|
|
||||||
|
proxy.$modal.confirm(proxy.t('是否确认修改此域名启用入口为:') + _label).then(() => {
|
||||||
|
loading.value = true;
|
||||||
|
changeSuccess(webDomainSwitch({ operationDomainSons: [params] }));
|
||||||
|
}).catch(() => {
|
||||||
|
getList();
|
||||||
|
});
|
||||||
|
} else if (type === 'blockDevice') {
|
||||||
|
// 屏蔽设备
|
||||||
|
const _label = proxy.useDict('ff_operation_block_device').ff_operation_block_device.find(v => v.value == row.blockDevice).label;
|
||||||
|
|
||||||
|
proxy.$modal.confirm(proxy.t('是否确认修改此域名屏蔽设备为:') + _label).then(() => {
|
||||||
|
loading.value = true;
|
||||||
|
changeSuccess(webDomainSwitch({ operationDomainSons: [params] }));
|
||||||
|
}).catch(() => {
|
||||||
|
getList();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 切换成功
|
||||||
|
function changeSuccess(apiFn) {
|
||||||
|
apiFn.then(res => {
|
||||||
|
loading.value = false;
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('操作成功!'));
|
||||||
|
getList();
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 操作信息
|
||||||
|
const currentDomainInfo = ref({}); // 当前操作的域名信息
|
||||||
|
const opInfo = (row, type) => {
|
||||||
|
const _ids = row.id ? [row.id] : row; // 操作的id,有表格内点击和批量操作两种
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case 'status':
|
||||||
|
// 启用/停用
|
||||||
|
let typeName = '', content = '', _usageStatus = '';
|
||||||
|
|
||||||
|
if (row.usageStatus == 1 || row.usageStatus == 5) {
|
||||||
|
typeName = proxy.t('启用');
|
||||||
|
content = proxy.t('确认启用该域名吗!');
|
||||||
|
_usageStatus = 4;
|
||||||
|
} else {
|
||||||
|
typeName = proxy.t('停用');
|
||||||
|
content = proxy.t('确认停用该域名吗!');
|
||||||
|
_usageStatus = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
proxy.$modal.confirm(content).then(() => {
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
setWebDomainStatus({ ids: _ids, usageStatus: _usageStatus }).then(res => {
|
||||||
|
loading.value = false;
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('域名') + typeName + proxy.t('成功!'));
|
||||||
|
getList();
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}).catch(() => { });
|
||||||
|
break
|
||||||
|
case 'refresh':
|
||||||
|
// 刷新域名解析说明
|
||||||
|
row.refreshLoading = true;
|
||||||
|
refreshWebDomainAnalysis({ id: row.id }).then(res => {
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('刷新成功!'));
|
||||||
|
row.refreshLoading = false;
|
||||||
|
getList();
|
||||||
|
}).catch(() => {
|
||||||
|
row.refreshLoading = false;
|
||||||
|
});
|
||||||
|
break
|
||||||
|
case 'agent':
|
||||||
|
// 绑定代理
|
||||||
|
currentDomainInfo.value = row;
|
||||||
|
isShowAgent.value = true;
|
||||||
|
break
|
||||||
|
case 'clearCache':
|
||||||
|
// 清理缓存
|
||||||
|
proxy.$modal.confirm(proxy.t('确定要清理该记录的缓存吗?')).then(() => {
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
clearWebDomainCache({ ids: _ids }).then(res => {
|
||||||
|
loading.value = false;
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('缓存清理成功!'));
|
||||||
|
getList();
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}).catch(() => { });
|
||||||
|
break
|
||||||
|
case 'delete':
|
||||||
|
// 删除域名
|
||||||
|
proxy.$modal.confirm(proxy.t('确定要删除该域名吗!')).then(() => {
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
delWebDomain(_ids.join(',')).then(res => {
|
||||||
|
loading.value = false;
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('删除成功!'));
|
||||||
|
getList();
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}).catch(() => { });
|
||||||
|
break
|
||||||
|
case 'edit':
|
||||||
|
// 修改域名
|
||||||
|
currentDomainInfo.value = row;
|
||||||
|
isShowEdit.value = true;
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 批量操作
|
||||||
|
const tableRef = ref(),
|
||||||
|
isAllSelection = ref(false), // 是否全选
|
||||||
|
selectionData = ref([]), // 选中的表格数据
|
||||||
|
batchOpType = ref(''); // 选中的批量操作类型
|
||||||
|
|
||||||
|
// 批量操作选项
|
||||||
|
const opTypeOptions = ref([
|
||||||
|
{ label: proxy.t('批量更换端口'), value: 'port' },
|
||||||
|
{ label: proxy.t('批量清理缓存'), value: 'clearCache' },
|
||||||
|
{ label: proxy.t('批量删除'), value: 'delete' },
|
||||||
|
{ label: proxy.t('批量停用'), value: 'stop' },
|
||||||
|
{ label: proxy.t('批量启用'), value: 'enable' },
|
||||||
|
// { label: proxy.t('批量锁定下发'), value: 'issued' },
|
||||||
|
{ label: proxy.t('批量展示其他担保列表'), value: 'showSecurity' },
|
||||||
|
{ label: proxy.t('批量隐藏其他担保列表'), value: 'hideSecurity' },
|
||||||
|
{ label: proxy.t('批量开启推广域名'), value: 'showPromotion' },
|
||||||
|
{ label: proxy.t('批量关闭推广域名'), value: 'hidePromotion' },
|
||||||
|
{ label: proxy.t('批量修改'), value: 'edit' },
|
||||||
|
{ label: proxy.t('批量绑定代理'), value: 'bindAgent' }
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 勾选表格
|
||||||
|
const tableSelect = (val) => {
|
||||||
|
selectionData.value = val;
|
||||||
|
|
||||||
|
if (val.length === dataList.value.length) {
|
||||||
|
isAllSelection.value = true;
|
||||||
|
} else {
|
||||||
|
isAllSelection.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 全选表格
|
||||||
|
const allSelectionChange = () => {
|
||||||
|
tableRef.value.toggleAllSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 选择批量数据操作类型
|
||||||
|
const opTypeChange = () => {
|
||||||
|
isShowBatchOp.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清空批量操作痕迹
|
||||||
|
const clearBatchOp = () => {
|
||||||
|
isAllSelection.value = false;
|
||||||
|
selectionData.value = [];
|
||||||
|
batchOpType.value = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 搜索按钮操作
|
||||||
|
const handleQuery = () => {
|
||||||
|
queryParams.pageNum = 1;
|
||||||
|
getList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置按钮操作
|
||||||
|
const resetQuery = () => {
|
||||||
|
handleQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭弹窗
|
||||||
|
const closeDialog = (type) => {
|
||||||
|
isShowAdd.value = false; // 新增域名弹窗
|
||||||
|
isShowAgent.value = false; // 绑定代理弹窗
|
||||||
|
isShowEdit.value = false; // 修改域名弹窗
|
||||||
|
isShowBatchOp.value = false; // 批量操作弹窗
|
||||||
|
batchOpType.value = ''; // 批量操作类型
|
||||||
|
|
||||||
|
// 批量操作清空
|
||||||
|
if (type === 'batchSubmit') clearBatchOp();
|
||||||
|
// 提交后刷新列表
|
||||||
|
if (type === 'submit' || type === 'batchSubmit') {
|
||||||
|
getList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 跳转域名管理
|
||||||
|
const emit = defineEmits(['goDomainManage']);
|
||||||
|
const goDomainManage = () => {
|
||||||
|
emit('goDomainManage');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 全局搜索展示
|
||||||
|
watch(() => props.searchResult, (val) => {
|
||||||
|
if (val.type == 'domainName') {
|
||||||
|
queryParams.searchType = 'name'
|
||||||
|
queryParams.name = val.domainName;
|
||||||
|
|
||||||
|
nextTick(() => {
|
||||||
|
queryParams.domainSupplierId = val.domainSupplierId;
|
||||||
|
handleQuery();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, { deep: true, immediate: true });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang='scss'>
|
||||||
|
.right-switch {
|
||||||
|
display: inline-block;
|
||||||
|
color: #606266;
|
||||||
|
font-size: 14px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.domain-main {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
// 左侧
|
||||||
|
.dm-left {
|
||||||
|
width: 145px;
|
||||||
|
height: 100%;
|
||||||
|
border-right: 1px solid #e5e5e5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 右侧
|
||||||
|
.dm-right {
|
||||||
|
width: calc(100% - 160px);
|
||||||
|
margin-left: 15px;
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.copy-ml {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,173 @@
|
||||||
|
<template>
|
||||||
|
<!-- 新增/修改域名白名单 -->
|
||||||
|
<el-dialog :title="dialogTitle" v-model="isShowDialog" width="600px" append-to-body @close="closeDialog">
|
||||||
|
<el-scrollbar max-height="600px" v-loading="loading">
|
||||||
|
<el-form ref="formRef" :model="formData" :rules="rules" label-width="100">
|
||||||
|
<el-form-item :label="t('具体域名:')" prop="name" class="mr0" v-if="currentDomainInfo.id">
|
||||||
|
<el-input v-model="formData.name" :placeholder="t('支持添加主域(test.com)或子域(a.test.com)')" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="t('具体域名:')" prop="names" class="mr0" v-else>
|
||||||
|
<el-input type="textarea" :rows="5" v-model="formData.names"
|
||||||
|
:placeholder="t('支持批量添加,最多20个,多个域名请换行,例如:\n123.com\n123.com.hk\n123.in')" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="t('域名类型:')" prop="domainType" class="mr0" v-if="currentDomainInfo.id">
|
||||||
|
<dict-select class="w100" v-model="formData.domainType" :placeholder="t('请选择域名类型')"
|
||||||
|
dictKey="operation_domain_white_type"></dict-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="t('用途备注:')" prop="remark" class="mr0">
|
||||||
|
<el-input type="textarea" :rows="5" show-word-limit maxlength="500" v-model="formData.remark"
|
||||||
|
:placeholder="t('请输入备注信息')" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="t('用途说明:')">
|
||||||
|
<span style="display: inline-block; line-height: 22px;" class="c-orange">
|
||||||
|
{{ t('因站点服务器前面设有CDN和防火墙,为了防止外部域名调用访问时被拦截,所以可将外部域名添加到白名单,以免被拦截。') }}
|
||||||
|
</span>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-scrollbar>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button @click="closeDialog">{{ t('关 闭') }}</el-button>
|
||||||
|
<el-button type="primary" @click="submitForm" :loading="loading">{{ t('确 认') }}</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="AddEditWhiteList">
|
||||||
|
import { addWhiteDomain, updateWhiteDomain } from "@/api/operation/domain";
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance();
|
||||||
|
const loading = ref(false);
|
||||||
|
const isShowDialog = ref(true); // 弹窗是否显示
|
||||||
|
const formRef = ref();
|
||||||
|
|
||||||
|
// 接收参数
|
||||||
|
const props = defineProps({
|
||||||
|
currentDomainInfo: {
|
||||||
|
type: Object,
|
||||||
|
default: {}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 弹窗标题
|
||||||
|
const dialogTitle = computed(() => {
|
||||||
|
if (props.currentDomainInfo.id) {
|
||||||
|
return proxy.t('修改白名单域名');
|
||||||
|
} else {
|
||||||
|
return proxy.t('新增域名白名单');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 表单参数
|
||||||
|
const formData = reactive({
|
||||||
|
name: '', // 修改时域名
|
||||||
|
names: '', // 新增时域名
|
||||||
|
domainType: '', // 域名类型
|
||||||
|
remark: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
// 初始化表单参数
|
||||||
|
watch(() => props.currentDomainInfo, (val) => {
|
||||||
|
if (val.id) {
|
||||||
|
formData.name = val.name;
|
||||||
|
formData.domainType = val.domainType.toString();
|
||||||
|
formData.remark = val.remark;
|
||||||
|
}
|
||||||
|
}, { immediate: true });
|
||||||
|
|
||||||
|
// 表单校验
|
||||||
|
const reg = /^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,6}$/;
|
||||||
|
const rules = reactive({
|
||||||
|
name: [
|
||||||
|
{ required: true, message: proxy.t('域名不能为空'), trigger: ['blur', 'change'] },
|
||||||
|
// 域名校验
|
||||||
|
{
|
||||||
|
validator: (rule, value, callback) => {
|
||||||
|
if (value) {
|
||||||
|
if (!reg.test(value)) {
|
||||||
|
callback(new Error(proxy.t('请输入正确的域名')));
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
trigger: ['blur', 'change']
|
||||||
|
}
|
||||||
|
],
|
||||||
|
names: [
|
||||||
|
{ required: true, message: proxy.t('域名不能为空'), trigger: ['blur', 'change'] },
|
||||||
|
// 域名校验
|
||||||
|
{
|
||||||
|
validator: (rule, value, callback) => {
|
||||||
|
if (value) {
|
||||||
|
if (value.split('\n').length > 20) {
|
||||||
|
callback(new Error(proxy.t('最多支持20个域名')));
|
||||||
|
} else {
|
||||||
|
const arr = value.split('\n');
|
||||||
|
for (let i = 0; i < arr.length; i++) {
|
||||||
|
if (!reg.test(arr[i])) {
|
||||||
|
callback(new Error(proxy.t('请输入正确的域名')));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
trigger: ['blur', 'change']
|
||||||
|
}
|
||||||
|
],
|
||||||
|
domainType: [
|
||||||
|
{ required: true, message: proxy.t('请选择域名类型'), trigger: 'change' }
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
// 提交
|
||||||
|
const submitForm = () => {
|
||||||
|
formRef.value.validate((valid) => {
|
||||||
|
if (!valid) return;
|
||||||
|
|
||||||
|
loading.value = true;
|
||||||
|
const params = {
|
||||||
|
remark: formData.remark
|
||||||
|
};
|
||||||
|
|
||||||
|
if (props.currentDomainInfo.id) {
|
||||||
|
// 修改
|
||||||
|
params.id = props.currentDomainInfo.id;
|
||||||
|
params.domainType = formData.domainType;
|
||||||
|
params.name = formData.name;
|
||||||
|
|
||||||
|
updateWhiteDomain(params).then(() => {
|
||||||
|
loading.value = false;
|
||||||
|
proxy.$message.success(proxy.t('修改成功'));
|
||||||
|
closeDialog('submit');
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// 新增
|
||||||
|
params.names = formData.names.split('\n');
|
||||||
|
addWhiteDomain(params).then(() => {
|
||||||
|
loading.value = false;
|
||||||
|
proxy.$message.success(proxy.t('添加成功'));
|
||||||
|
closeDialog('submit');
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭弹窗
|
||||||
|
const emit = defineEmits(['closeDialog']);
|
||||||
|
const closeDialog = (type) => {
|
||||||
|
emit('closeDialog', type);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss"></style>
|
||||||
|
|
@ -0,0 +1,108 @@
|
||||||
|
<template>
|
||||||
|
<!-- 批量操作弹窗 -->
|
||||||
|
<el-dialog :title="dialogTitle" v-model="isShowDialog" width="800px" append-to-body @close="closeDialog">
|
||||||
|
<el-scrollbar max-height="600px" v-loading="loading">
|
||||||
|
<el-table row-key="id" stripe border :data="tableList">
|
||||||
|
<el-table-column :label="t('域名')" prop="name" align="center" min-width="150"></el-table-column>
|
||||||
|
<el-table-column :label="t('域名类型')" align="center" min-width="100">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<dict-select class="w100" v-model="row.domainType" dictKey="operation_domain_white_type"></dict-select>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column :label="t('用途备注')" align="center" min-width="200">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-input v-model="row.remark" :placeholder="t('请输入备注')" clearable></el-input>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-scrollbar>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button @click="closeDialog">{{ t('关 闭') }}</el-button>
|
||||||
|
<el-button type="primary" @click="submitForm" :loading="loading">{{ t('确 认') }}</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="BatchOperation">
|
||||||
|
import {
|
||||||
|
updateWhiteDomainBatch // 批量修改白名单
|
||||||
|
} from "@/api/operation/domain";
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance();
|
||||||
|
const loading = ref(false);
|
||||||
|
const isShowDialog = ref(true);
|
||||||
|
|
||||||
|
// 接收参数
|
||||||
|
const props = defineProps({
|
||||||
|
selectionData: {
|
||||||
|
type: Array,
|
||||||
|
default: []
|
||||||
|
},
|
||||||
|
batchOpType: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 表格数据
|
||||||
|
const tableList = ref([]), _tableList = [];
|
||||||
|
|
||||||
|
JSON.parse(JSON.stringify(props.selectionData)).forEach(item => {
|
||||||
|
item.domainType = item.domainType + '';
|
||||||
|
_tableList.push(item);
|
||||||
|
});
|
||||||
|
tableList.value = _tableList;
|
||||||
|
|
||||||
|
// 弹窗标题
|
||||||
|
const dialogTitle = computed(() => {
|
||||||
|
if (props.batchOpType === 'edit') {
|
||||||
|
return proxy.t('批量修改');
|
||||||
|
} else {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 提交
|
||||||
|
const submitForm = () => {
|
||||||
|
loading.value = true;
|
||||||
|
const params = {
|
||||||
|
ids: tableList.value.map(item => item.id)
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (props.batchOpType) {
|
||||||
|
case 'edit':
|
||||||
|
const _editParams = [];
|
||||||
|
params.ids.forEach(id => {
|
||||||
|
const item = tableList.value.find(v => v.id == id);
|
||||||
|
_editParams.push({
|
||||||
|
id: id,
|
||||||
|
domainType: item.domainType,
|
||||||
|
remark: item.remark
|
||||||
|
})
|
||||||
|
});
|
||||||
|
submitSuccess(updateWhiteDomainBatch({ operationDomainWhites: _editParams }), proxy.t('批量修改成功'));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交后回调
|
||||||
|
function submitSuccess(apiFn, msg) {
|
||||||
|
apiFn.then(() => {
|
||||||
|
loading.value = false;
|
||||||
|
proxy.$message.success(msg);
|
||||||
|
closeDialog('batchSubmit');
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭弹窗
|
||||||
|
const emit = defineEmits(['closeDialog']);
|
||||||
|
const closeDialog = (type) => {
|
||||||
|
emit('closeDialog', type);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss"></style>
|
||||||
|
|
@ -0,0 +1,217 @@
|
||||||
|
<template>
|
||||||
|
<!-- 外部白名单域名列表 -->
|
||||||
|
<table-search-card :model="queryParams" @getList="getList" :leftSpan="16" :rightSpan="8" @handleQuery="handleQuery()"
|
||||||
|
@resetQuery="resetQuery">
|
||||||
|
<template #left>
|
||||||
|
<table-search-date ref="searchDateRef" dateType="datetimerange" v-model:dateRange="dateRange"
|
||||||
|
v-model:operateTimeType="operateTimeType" @dateChange="handleQuery"></table-search-date>
|
||||||
|
<el-form-item prop="name" style="width: 200px;">
|
||||||
|
<el-input v-model="queryParams.name" :placeholder="t('请输入域名')" clearable @change="handleQuery"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
<template #right>
|
||||||
|
<el-button type="success" plain icon="Plus" @click="isShowAddEdit = true"
|
||||||
|
v-hasPermi="['operation:white:add']">{{
|
||||||
|
t('新增') }}</el-button>
|
||||||
|
</template>
|
||||||
|
</table-search-card>
|
||||||
|
|
||||||
|
<!-- 查询表格 -->
|
||||||
|
<el-table ref="tableRef" class="c-table-main" v-loading="loading" row-key="id" stripe border :data="dataList"
|
||||||
|
@select="tableSelect" @select-all="tableSelect">
|
||||||
|
<el-table-column align="center" type="selection" width="55" />
|
||||||
|
<el-table-column :label="t('域名')" prop="name" align="center" min-width="160"></el-table-column>
|
||||||
|
<el-table-column :label="t('域名类型')" align="center" min-width="120">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<dict-text dictKey="operation_domain_white_type" :value="row.domainType" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column :label="t('用途备注')" show-overflow-tooltip prop="remark" align="center"
|
||||||
|
min-width="260"></el-table-column>
|
||||||
|
<table-operation></table-operation>
|
||||||
|
<el-table-column :label="t('操作')" align="center" min-width="120">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-button link type="primary" @click="opInfo(row, 'edit')" v-hasPermi="['operation:white:all:edit']">
|
||||||
|
{{ t('修改') }}
|
||||||
|
</el-button>
|
||||||
|
<el-button link type="primary" @click="opInfo(row, 'delete')" v-hasPermi="['operation:white:remove']">
|
||||||
|
{{ t('删除') }}
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<!-- 批量操作 -->
|
||||||
|
<table-batch-operate v-if="total > 0" v-model:batchOpType="batchOpType" v-model:isAllSelection="isAllSelection"
|
||||||
|
@allSelectionChange="allSelectionChange" @opTypeChange="opTypeChange" :selectionData="selectionData"
|
||||||
|
:opTypeOptions="opTypeOptions"></table-batch-operate>
|
||||||
|
<!-- 列表分页 -->
|
||||||
|
<pagination v-if="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize"
|
||||||
|
@pagination="getList" />
|
||||||
|
|
||||||
|
<!-- 新增/修改白名单 -->
|
||||||
|
<add-edit-white-list v-if="isShowAddEdit" :currentDomainInfo="currentDomainInfo" @closeDialog="closeDialog"></add-edit-white-list>
|
||||||
|
|
||||||
|
<!-- 批量操作弹窗 -->
|
||||||
|
<batch-operation v-if="isShowBatchOp" :batchOpType="batchOpType" :selectionData="selectionData"
|
||||||
|
@closeDialog="closeDialog"></batch-operation>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="WhiteList">
|
||||||
|
import {
|
||||||
|
getWhiteDomainList, // 域名列表
|
||||||
|
delWhiteDomain, // 删除域名
|
||||||
|
} from "@/api/operation/domain";
|
||||||
|
import TableSearchDate from "@/components/TableSearchDate"; // 日期选择
|
||||||
|
import TableBatchOperate from '@/components/TableBatchOperate'; // 批量操作
|
||||||
|
import AddEditWhiteList from "./AddEditWhiteList.vue"; // 新增/修改白名单
|
||||||
|
import BatchOperation from "./BatchOperation.vue"; // 批量操作
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance();
|
||||||
|
const loading = ref(true); // loading状态
|
||||||
|
const isShowAddEdit = ref(false), isShowBatchOp = ref(false); // 各弹窗状态
|
||||||
|
|
||||||
|
// 日期选择
|
||||||
|
const searchDateRef = ref(), dateRange = ref([]), operateTimeType = ref('');
|
||||||
|
|
||||||
|
// 搜索配置
|
||||||
|
const queryParams = reactive({
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 20,
|
||||||
|
name: '', // 域名
|
||||||
|
orderByColumn: 'createTime',
|
||||||
|
isAsc: 'desc'
|
||||||
|
});
|
||||||
|
|
||||||
|
// 请求列表
|
||||||
|
const dataList = ref([]), total = ref(0);
|
||||||
|
const getList = () => {
|
||||||
|
const params = proxy.addDateRange(queryParams, dateRange.value); // 日期参数
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
getWhiteDomainList(params).then(res => {
|
||||||
|
loading.value = false;
|
||||||
|
dataList.value = res.rows;
|
||||||
|
total.value = +res.total;
|
||||||
|
clearBatchOp(); // 清空批量操作痕迹
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
dataList.value = [];
|
||||||
|
total.value = 0;
|
||||||
|
clearBatchOp(); // 清空批量操作痕迹
|
||||||
|
});
|
||||||
|
}
|
||||||
|
getList();
|
||||||
|
|
||||||
|
// 操作信息
|
||||||
|
const currentDomainInfo = ref({}); // 当前操作的域名信息
|
||||||
|
const opInfo = (row, type) => {
|
||||||
|
switch (type) {
|
||||||
|
case 'edit':
|
||||||
|
// 修改域名
|
||||||
|
currentDomainInfo.value = row;
|
||||||
|
isShowAddEdit.value = true;
|
||||||
|
break;
|
||||||
|
case 'delete':
|
||||||
|
// 删除域名
|
||||||
|
proxy.$modal.confirm(proxy.t('确定要删除该域名吗!')).then(() => {
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
delWhiteDomain(row.id).then(res => {
|
||||||
|
loading.value = false;
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('删除成功!'));
|
||||||
|
getList();
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}).catch(() => { });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 批量操作
|
||||||
|
const tableRef = ref(),
|
||||||
|
isAllSelection = ref(false), // 是否全选
|
||||||
|
selectionData = ref([]), // 选中的表格数据
|
||||||
|
batchOpType = ref(''); // 选中的批量操作类型
|
||||||
|
|
||||||
|
// 批量操作选项
|
||||||
|
const opTypeOptions = ref([
|
||||||
|
{ label: proxy.t('批量修改'), value: 'edit' },
|
||||||
|
{ label: proxy.t('批量删除'), value: 'delete' }
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 勾选表格
|
||||||
|
const tableSelect = (val) => {
|
||||||
|
selectionData.value = val;
|
||||||
|
|
||||||
|
if (val.length === dataList.value.length) {
|
||||||
|
isAllSelection.value = true;
|
||||||
|
} else {
|
||||||
|
isAllSelection.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 全选表格
|
||||||
|
const allSelectionChange = () => {
|
||||||
|
tableRef.value.toggleAllSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 选择批量数据操作类型
|
||||||
|
const opTypeChange = () => {
|
||||||
|
if (batchOpType.value === 'edit') {
|
||||||
|
isShowBatchOp.value = true;
|
||||||
|
} else if (batchOpType.value === 'delete') {
|
||||||
|
proxy.$modal.confirm(proxy.t('确定要删除选中的域名吗!')).then(() => {
|
||||||
|
loading.value = true;
|
||||||
|
delWhiteDomain(selectionData.value.map(item => item.id).join(',')).then(res => {
|
||||||
|
loading.value = false;
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('删除成功!'));
|
||||||
|
getList();
|
||||||
|
clearBatchOp(); // 清空批量操作痕迹
|
||||||
|
}).catch(() => {
|
||||||
|
loading.value = false;
|
||||||
|
batchOpType.value = '';
|
||||||
|
});
|
||||||
|
}).catch(() => {
|
||||||
|
batchOpType.value = '';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清空批量操作痕迹
|
||||||
|
const clearBatchOp = () => {
|
||||||
|
isAllSelection.value = false;
|
||||||
|
selectionData.value = [];
|
||||||
|
batchOpType.value = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 搜索按钮操作
|
||||||
|
const handleQuery = () => {
|
||||||
|
queryParams.pageNum = 1;
|
||||||
|
getList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置按钮操作
|
||||||
|
const resetQuery = () => {
|
||||||
|
searchDateRef.value.dateResetQuery(); // 日期选择重置
|
||||||
|
handleQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭弹窗
|
||||||
|
const closeDialog = (type) => {
|
||||||
|
isShowAddEdit.value = false; // 新增域名弹窗
|
||||||
|
isShowBatchOp.value = false; // 批量操作弹窗
|
||||||
|
currentDomainInfo.value = {}; // 当前操作的域名信息
|
||||||
|
batchOpType.value = ''; // 批量操作类型
|
||||||
|
|
||||||
|
// 批量操作清空
|
||||||
|
if (type === 'batchSubmit') clearBatchOp();
|
||||||
|
// 提交后刷新列表
|
||||||
|
if (type === 'submit' || type === 'batchSubmit') {
|
||||||
|
getList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang='scss'></style>
|
||||||
|
|
@ -0,0 +1,223 @@
|
||||||
|
<template>
|
||||||
|
<!-- 新增 -->
|
||||||
|
<el-dialog :title="addEditStatus=='add' ? t('新增') : t('修改')" align-center :close-on-click-modal="false" v-model="showDialog"
|
||||||
|
width="800px" append-to-body>
|
||||||
|
<el-scrollbar max-height="900px">
|
||||||
|
<el-form ref="formRef" :model="formAll" :rules="rules" label-width="130px" class="add-form">
|
||||||
|
<el-form-item :label="t('api平台代码')" prop="apiPlatformCode">
|
||||||
|
<el-input v-model="formAll.apiPlatformCode" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="t('平台代码')" prop="platformCode">
|
||||||
|
<el-input v-model="formAll.platformCode" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="t('平台展示代码')" prop="platformShowCode">
|
||||||
|
<el-input v-model="formAll.platformShowCode" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="t('语言信息')" prop="langInfo">
|
||||||
|
<el-input v-model="formAll.langInfo" type="textarea" :rows="5" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="t('货币信息')" prop="currencyInfo">
|
||||||
|
<el-input v-model="formAll.currencyInfo" type="textarea" :rows="5" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-scrollbar>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button type="primary" @click="submitForm" :loading="loadingButton">{{ t('确 定') }}</el-button>
|
||||||
|
<el-button @click="closeDialog">{{ t('取 消') }}</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import { formatTime,finalTimestamp } from '@/utils/ruoyi'; // 时间格式化
|
||||||
|
import ImageUpload from "@/components/ImageUpload";
|
||||||
|
import { updateGame } from "@/api/game/game";
|
||||||
|
import { nextTick, onMounted, ref } from "vue"; // 获取当前实例
|
||||||
|
import { getLocalStorage } from "@/utils/auth";
|
||||||
|
|
||||||
|
const langList = getLocalStorage('langList')?.filter(v => v.langType == 1 && v.langStatus).map(item => {
|
||||||
|
return {
|
||||||
|
label: item.name,
|
||||||
|
value: item.id
|
||||||
|
};
|
||||||
|
}); // 语种选项
|
||||||
|
const loadingButton = ref(false);
|
||||||
|
const oldForm = shallowRef({ });
|
||||||
|
const { proxy } = getCurrentInstance() // 获取当前实例
|
||||||
|
const emits = defineEmits(['submit', 'update:show']) // 自定义事件
|
||||||
|
const props = defineProps({ // 父组件向子组件传值
|
||||||
|
data: {
|
||||||
|
type: Object, // 父组件传值
|
||||||
|
default: {}
|
||||||
|
},
|
||||||
|
show: {
|
||||||
|
type: Boolean, // 显示
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
addEditStatus:{ // 添加/修改
|
||||||
|
type: String,
|
||||||
|
default: 'add'
|
||||||
|
},
|
||||||
|
modifyDate: { //修改数据
|
||||||
|
type: Object,
|
||||||
|
default: {}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const showDialog = computed({ //弹窗显示控制
|
||||||
|
get() {
|
||||||
|
return props.show
|
||||||
|
},
|
||||||
|
set(value) {
|
||||||
|
emits('update:show', value)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const activeNameLang = ref(0);//语言切换选中
|
||||||
|
|
||||||
|
const langOptionAll = ref([]); // 语言tabs切换的数据
|
||||||
|
const formAll = reactive({
|
||||||
|
syncStatus:false,
|
||||||
|
})
|
||||||
|
|
||||||
|
// 修改时数据更新相关内容
|
||||||
|
nextTick(() => {
|
||||||
|
if (props.addEditStatus != 'edit') return;
|
||||||
|
Object.assign(formAll, props.modifyDate)
|
||||||
|
setTimeout(() => {
|
||||||
|
let objForm = { ...formAll }
|
||||||
|
oldForm.value = JSON.stringify(objForm);
|
||||||
|
}, 500);
|
||||||
|
});
|
||||||
|
|
||||||
|
//表单验证规则
|
||||||
|
const rules = reactive({
|
||||||
|
apiPlatformCode: [
|
||||||
|
{ required: true, message: '请输入平台编码', trigger: 'change' },
|
||||||
|
],
|
||||||
|
platformCode: [
|
||||||
|
{ required: true, message: '请输入游戏编码', trigger: 'change' },
|
||||||
|
],
|
||||||
|
platformShowCode: [
|
||||||
|
{ required: true, message: '请输入游戏显示编码', trigger: 'change' },
|
||||||
|
],
|
||||||
|
langInfo: [
|
||||||
|
{ required: true, message: '请输入语言信息', trigger: 'change' },
|
||||||
|
],
|
||||||
|
})
|
||||||
|
// 关闭弹窗
|
||||||
|
const closeDialog = () => {
|
||||||
|
showDialog.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交
|
||||||
|
const formRef = ref(null)
|
||||||
|
|
||||||
|
// 提交修改和新增数据表单
|
||||||
|
const submitForm = () => {
|
||||||
|
// 验证表单
|
||||||
|
formRef.value.validate(valid => {
|
||||||
|
if (valid) {
|
||||||
|
loadingButton.value = true;
|
||||||
|
// 初始化表单数据
|
||||||
|
let formData = {
|
||||||
|
...formAll
|
||||||
|
};
|
||||||
|
if (JSON.stringify(formAll) != oldForm.value) {
|
||||||
|
updateGame(formData).then(res => {
|
||||||
|
loadingButton.value = false;
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('修改成功!'));
|
||||||
|
emits('submit');
|
||||||
|
closeDialog();
|
||||||
|
}).catch(() => {
|
||||||
|
loadingButton.value = false;
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
loadingButton.value = false;
|
||||||
|
closeDialog();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<style scope lang="scss">
|
||||||
|
.w100 {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-box-vioce{
|
||||||
|
height: 90px !important;
|
||||||
|
overflow: hidden;
|
||||||
|
.upload-tips {
|
||||||
|
color: #999;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.5;
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
.component-upload-image .el-upload--picture-card {
|
||||||
|
width: 180px !important;
|
||||||
|
height: 90px !important;
|
||||||
|
}
|
||||||
|
.el-upload-list--picture-card .el-upload-list__item {
|
||||||
|
width: 180px!important;
|
||||||
|
height: 90px!important;
|
||||||
|
}
|
||||||
|
:deep(.el-upload-list) {
|
||||||
|
width:180px!important;
|
||||||
|
height: 90px!important;
|
||||||
|
.el-upload,
|
||||||
|
.el-upload-list--picture-card .el-upload-list__item {
|
||||||
|
width: 180px!important;
|
||||||
|
height: 90px!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-upload-list__item {
|
||||||
|
margin: 0;
|
||||||
|
border: none;
|
||||||
|
width: 180px!important;
|
||||||
|
height: 90px!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-box-vioce11{
|
||||||
|
height: 400px !important;
|
||||||
|
overflow: hidden;
|
||||||
|
.upload-tips {
|
||||||
|
color: #999;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.5;
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
.component-upload-image .el-upload--picture-card {
|
||||||
|
width: 300px !important;
|
||||||
|
height: 400px !important;
|
||||||
|
}
|
||||||
|
.el-upload-list--picture-card .el-upload-list__item {
|
||||||
|
width: 300px!important;
|
||||||
|
height: 400px!important;
|
||||||
|
}
|
||||||
|
:deep(.el-upload-list) {
|
||||||
|
width:300px!important;
|
||||||
|
height: 400px!important;
|
||||||
|
.el-upload,
|
||||||
|
.el-upload-list--picture-card .el-upload-list__item {
|
||||||
|
width: 300px!important;
|
||||||
|
height: 400px!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-upload-list__item {
|
||||||
|
margin: 0;
|
||||||
|
border: none;
|
||||||
|
width: 300px!important;
|
||||||
|
height: 400px!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,167 @@
|
||||||
|
<template>
|
||||||
|
<table-search-card :model="queryParams" @getList="getList" @handleQuery="handleQuery" @resetQuery="resetQuery">
|
||||||
|
<template #left>
|
||||||
|
<el-form-item prop="platformShowCode">
|
||||||
|
<el-input v-model="queryParams.platformShowCode" :placeholder="t('请输入平台')" />
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
<template #right>
|
||||||
|
<el-button type="primary" plain icon="Plus" @click="handleAdd" >{{ t('新增配置') }}</el-button>
|
||||||
|
</template>
|
||||||
|
</table-search-card>
|
||||||
|
|
||||||
|
<el-table v-loading="loading" :data="gameList" class="c-table-main" stripe
|
||||||
|
ref="dragTable" row-key="id" border>
|
||||||
|
<el-table-column :label="t('平台名称')" align="center" prop="platformCode" />
|
||||||
|
<el-table-column :label="t('api平台代码')" align="center" prop="apiPlatformCode" />
|
||||||
|
<el-table-column :label="t('货币信息')" align="center" prop="currencyInfo" />
|
||||||
|
<el-table-column :label="t('语言信息')" align="center" prop="langInfo" />
|
||||||
|
<table-operation></table-operation>
|
||||||
|
<el-table-column :label="t('操作')" align="center" class-name="small-padding fixed-width">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button link type="primary" @click="handleUpdate(scope.row)"
|
||||||
|
v-hasPermi="['game:game:edit']">{{ t('修改') }}</el-button>
|
||||||
|
<el-button link type="primary" @click="handleSynchronous(scope.row)"
|
||||||
|
v-hasPermi="['game:game:sync']">{{ t('删除') }}</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize"
|
||||||
|
@pagination="getList" />
|
||||||
|
<add-dialog v-if="isShowDialog"
|
||||||
|
:addEditStatus="addEditStatus" :modifyDate="modifyDate" @submit="getList"
|
||||||
|
v-model:show="isShowDialog"></add-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="Game">
|
||||||
|
import AddDialog from "./AddDialog"//新增/修改弹窗
|
||||||
|
import * as game from "@/api/game/game";
|
||||||
|
import { platformSelect,getGamePlatformApiSync,getGamePlatformTenantSync } from "@/api/game/platform";
|
||||||
|
import {getGameSecretList,getGameSecretInfo} from "@/api/game/configuration";
|
||||||
|
import useInitDataStore from "@/store/modules/initData";
|
||||||
|
|
||||||
|
const emits = defineEmits(["reset"])
|
||||||
|
|
||||||
|
const useInitData = useInitDataStore();
|
||||||
|
const { proxy } = getCurrentInstance();
|
||||||
|
|
||||||
|
const gameList = ref([]);
|
||||||
|
const open = ref(false);
|
||||||
|
const loading = ref(true);
|
||||||
|
const ids = ref([]);
|
||||||
|
const single = ref(true);
|
||||||
|
const multiple = ref(true);
|
||||||
|
const total = ref(0);
|
||||||
|
const title = ref("");
|
||||||
|
const gameTypeOptions = ref([
|
||||||
|
{ label: '电子', value: '1' },
|
||||||
|
{ label: '棋牌', value: '2' },
|
||||||
|
{ label: '真人', value: '3' },
|
||||||
|
{ label: '捕鱼', value: '4' },
|
||||||
|
{ label: '体育', value: '6' },
|
||||||
|
{ label: '斗鸡', value: '7' },
|
||||||
|
{ label: '电竞', value: '8' },
|
||||||
|
{ label: '彩票', value: '9' },
|
||||||
|
{ label: '区块链', value: '10' },
|
||||||
|
]);
|
||||||
|
const data = reactive({
|
||||||
|
form: {},
|
||||||
|
queryParams: {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 20,
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const { queryParams, form, rules } = toRefs(data);
|
||||||
|
/** 查询平台管理列表 */
|
||||||
|
function getList() {
|
||||||
|
loading.value = true;
|
||||||
|
getGameSecretList(queryParams.value).then(response => {
|
||||||
|
gameList.value = response.rows;
|
||||||
|
total.value = response.total;
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 表单重置
|
||||||
|
function reset() {
|
||||||
|
form.value = {
|
||||||
|
id: null
|
||||||
|
};
|
||||||
|
proxy.resetForm("gameRef");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 搜索按钮操作 */
|
||||||
|
function handleQuery() {
|
||||||
|
queryParams.value.pageNum = 1;
|
||||||
|
getList();
|
||||||
|
useInitData.setStateData('currencyCode', String(queryParams.value.currencyCode));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 重置按钮操作 */
|
||||||
|
function resetQuery() {
|
||||||
|
queryParams.value.gameType = useInitData.dictInitData.platformType
|
||||||
|
queryParams.value.platformId = useInitData.dictInitData.platformId
|
||||||
|
queryParams.value.pageNum = 1;
|
||||||
|
platformListInit(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
const addEditStatus = ref('add'), isShowDialog = ref(false), editDataId = ref(''),modifyDate = ref({});
|
||||||
|
/** 修改按钮操作 */
|
||||||
|
function handleUpdate(row) {
|
||||||
|
reset();
|
||||||
|
const _id = row.id || ids.value
|
||||||
|
game.getGame(_id).then(response => {
|
||||||
|
modifyDate.value = response.data;
|
||||||
|
isShowDialog.value = true;
|
||||||
|
addEditStatus.value = 'edit'
|
||||||
|
title.value = proxy.t('修改平台管理');
|
||||||
|
});
|
||||||
|
// proxy.$modal.msgError("该功能暂未开发")
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleAdd = () => {
|
||||||
|
isShowDialog.value = true;
|
||||||
|
addEditStatus.value = 'add'
|
||||||
|
title.value = proxy.t('新增配置');
|
||||||
|
}
|
||||||
|
const handleSynchronous = (row) => {
|
||||||
|
proxy.$modal.confirm(proxy.t('当前设置宣传图同步到所有币种下生效')).then(() => {
|
||||||
|
game.gameGameSync({id:row.id}).then(() => {
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('同步成功'));
|
||||||
|
getList();
|
||||||
|
})
|
||||||
|
}).catch(() => {})
|
||||||
|
}
|
||||||
|
// 游戏api同步
|
||||||
|
const handleApiGame = () => {
|
||||||
|
proxy.$modal.confirm(proxy.t('是否确认同步?')).then(() => {
|
||||||
|
getGamePlatformApiSync({}).then(() => {
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('同步成功'));
|
||||||
|
getList();
|
||||||
|
})
|
||||||
|
}).catch(() => {})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取游戏平台下拉
|
||||||
|
const platformList = ref([])
|
||||||
|
const platformListInit = async (isFirst = false) => {
|
||||||
|
let { platformId, gameType } = queryParams.value
|
||||||
|
await platformSelect({ platformType: gameType,currencyCode:queryParams.value.currencyCode }).then(res => {
|
||||||
|
platformList.value = res.data
|
||||||
|
queryParams.value.platformId = isFirst && platformId ? platformId : res?.data?.length ? res.data[0].id : null
|
||||||
|
getList();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//初始化
|
||||||
|
onMounted(() => {
|
||||||
|
getList();
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss"></style>
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<!-- 新增 -->
|
<!-- 新增 -->
|
||||||
<el-dialog :title="addEditStatus=='add' ? t('新增') : t('修改')" :close-on-click-modal="false" v-model="showDialog"
|
<el-dialog :title="addEditStatus=='add' ? t('新增') : t('修改')" align-center :close-on-click-modal="false" v-model="showDialog"
|
||||||
width="700px" append-to-body>
|
width="700px" append-to-body>
|
||||||
<el-scrollbar max-height="900px">
|
<el-scrollbar max-height="900px">
|
||||||
<el-form ref="formRef" :model="formAll" :rules="rules" label-width="130px" class="add-form">
|
<el-form ref="formRef" :model="formAll" :rules="rules" label-width="130px" class="add-form">
|
||||||
|
|
@ -22,6 +22,8 @@
|
||||||
<el-form-item :label="t('icon图样式')" prop="iconStyle">
|
<el-form-item :label="t('icon图样式')" prop="iconStyle">
|
||||||
<el-radio-group v-model="formAll.iconStyle">
|
<el-radio-group v-model="formAll.iconStyle">
|
||||||
<el-radio :value="1">{{ t('默认') }}</el-radio>
|
<el-radio :value="1">{{ t('默认') }}</el-radio>
|
||||||
|
<el-radio :value="2">{{ t('自定义') }}</el-radio>
|
||||||
|
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<div v-if="formAll.iconStyle == 1">
|
<div v-if="formAll.iconStyle == 1">
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
<platform v-if="activeName === 'platform'" @toGameManage="toGameManage"></platform>
|
<platform v-if="activeName === 'platform'" @toGameManage="toGameManage"></platform>
|
||||||
<game v-if="activeName === 'game'">
|
<game v-if="activeName === 'game'">
|
||||||
</game>
|
</game>
|
||||||
|
<configuration v-if="activeName === 'configuration'"></configuration>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -26,12 +27,14 @@
|
||||||
import platform from "./platform"
|
import platform from "./platform"
|
||||||
const { proxy } = getCurrentInstance();
|
const { proxy } = getCurrentInstance();
|
||||||
import game from "./game"
|
import game from "./game"
|
||||||
|
import Configuration from "./configuration"
|
||||||
|
|
||||||
const platItem = ref({})
|
const platItem = ref({})
|
||||||
const activeName = ref('platform')
|
const activeName = ref('platform')
|
||||||
const tabs = ref([
|
const tabs = ref([
|
||||||
{ label: proxy.t('平台管理'), name: 'platform' },
|
{ label: proxy.t('平台管理'), name: 'platform' },
|
||||||
{ label: proxy.t('子游戏管理'), name: 'game' },
|
{ label: proxy.t('子游戏管理'), name: 'game' },
|
||||||
|
{ label: proxy.t('配置管理'), name: 'configuration' },
|
||||||
])
|
])
|
||||||
|
|
||||||
// 跳转子游戏管理
|
// 跳转子游戏管理
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,8 @@
|
||||||
@resetQuery="resetQuery">
|
@resetQuery="resetQuery">
|
||||||
<template #left>
|
<template #left>
|
||||||
<!-- 待处理列表没有时间查询 -->
|
<!-- 待处理列表没有时间查询 -->
|
||||||
<span v-show="listType != 'pending'">
|
<!-- <span v-show="listType != 'pending'">
|
||||||
|
</span> -->
|
||||||
<el-form-item prop="timeType">
|
<el-form-item prop="timeType">
|
||||||
<el-select v-model="queryParams.timeType" :placeholder="t('时间类型')" style="width: 150px;"
|
<el-select v-model="queryParams.timeType" :placeholder="t('时间类型')" style="width: 150px;"
|
||||||
@change="handleQuery">
|
@change="handleQuery">
|
||||||
|
|
@ -14,7 +15,7 @@
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<table-search-date ref="searchDateRef" v-model:dateRange="dateRange"
|
<table-search-date ref="searchDateRef" v-model:dateRange="dateRange"
|
||||||
v-model:operateTimeType="operateTimeType" @dateChange="handleQuery"></table-search-date>
|
v-model:operateTimeType="operateTimeType" @dateChange="handleQuery"></table-search-date>
|
||||||
</span>
|
|
||||||
<el-form-item >
|
<el-form-item >
|
||||||
<custom-select style="width: 130px;" v-if="siteSelect.length > 0" collapse-tags collapse-tags-tooltip v-model="queryParams.tenantId" :options="siteSelect" :placeholder="t('请选择')"></custom-select>
|
<custom-select style="width: 130px;" v-if="siteSelect.length > 0" collapse-tags collapse-tags-tooltip v-model="queryParams.tenantId" :options="siteSelect" :placeholder="t('请选择')"></custom-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
@ -157,6 +158,8 @@ import DictSelect from "@/components/DictSelect";
|
||||||
import { getLocalStorage } from "@/utils/auth";
|
import { getLocalStorage } from "@/utils/auth";
|
||||||
import { moneyFormat } from "@/utils"; // 金额格式化
|
import { moneyFormat } from "@/utils"; // 金额格式化
|
||||||
import DetailDialog from "./DetailDialog.vue"; // 详情弹窗
|
import DetailDialog from "./DetailDialog.vue"; // 详情弹窗
|
||||||
|
import { finalTimestamp } from "@/utils/ruoyi";
|
||||||
|
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
listType: {
|
listType: {
|
||||||
|
|
@ -184,14 +187,14 @@ const currencySelectArr = getLocalStorage('currencySelect')?.map(item => {
|
||||||
};
|
};
|
||||||
}); //
|
}); //
|
||||||
// 日期选择
|
// 日期选择
|
||||||
const searchDateRef = ref(null), dateRange = ref([]), operateTimeType = ref('');
|
const searchDateRef = ref(null), dateRange = ref([]), operateTimeType = ref('day');
|
||||||
|
|
||||||
// 搜索配置
|
// 搜索配置
|
||||||
const queryParams = reactive({
|
const queryParams = reactive({
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 20,
|
pageSize: 20,
|
||||||
tenantId: '',
|
tenantId: '',
|
||||||
timeType: '',
|
timeType: '1',
|
||||||
searchType: 'memberAccount', // 搜索类型
|
searchType: 'memberAccount', // 搜索类型
|
||||||
memberAccount: '',
|
memberAccount: '',
|
||||||
feedbackStatus: '', // 反馈状态:1待处理 2-已采纳 3-已忽略
|
feedbackStatus: '', // 反馈状态:1待处理 2-已采纳 3-已忽略
|
||||||
|
|
@ -205,12 +208,15 @@ const queryParams = reactive({
|
||||||
const dataList = ref([]);
|
const dataList = ref([]);
|
||||||
const total = ref(0); // 总数
|
const total = ref(0); // 总数
|
||||||
const getList = () => {
|
const getList = () => {
|
||||||
let params = {}
|
// if (props.listType !== 'pending') { // 非待处理状态才有时间查询
|
||||||
|
// params = proxy.addDateRange(queryParams, dateRange.value);
|
||||||
if (props.listType !== 'pending') { // 非待处理状态才有时间查询
|
// } else {
|
||||||
params = proxy.addDateRange(queryParams, dateRange.value);
|
// params = queryParams;
|
||||||
} else {
|
// }
|
||||||
params = queryParams;
|
let params = {
|
||||||
|
...queryParams,
|
||||||
|
beginTime: finalTimestamp(dateRange.value[0]),
|
||||||
|
endTime: finalTimestamp(dateRange.value[1])
|
||||||
}
|
}
|
||||||
|
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
|
|
@ -375,14 +381,9 @@ const handleQuery = () => {
|
||||||
|
|
||||||
// 重置按钮操作
|
// 重置按钮操作
|
||||||
const resetQuery = () => {
|
const resetQuery = () => {
|
||||||
if (props.listType !== 'pending') {
|
|
||||||
// searchDateRef.value = ; // 日期选择重置
|
|
||||||
searchDateRef.value = null;
|
|
||||||
dateRange.value = [];
|
dateRange.value = [];
|
||||||
operateTimeType.value = '';
|
operateTimeType.value = "day";
|
||||||
}
|
searchDateRef.value.timeTypeChange(operateTimeType.value)
|
||||||
|
|
||||||
handleQuery();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const initByListType = (val) => {
|
const initByListType = (val) => {
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,10 @@
|
||||||
<el-input style="width: 550px;" v-model="formAll.title" placeholder="请输入标题"></el-input>
|
<el-input style="width: 550px;" v-model="formAll.title" placeholder="请输入标题"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="t('内容')" prop="content">
|
<el-form-item :label="t('内容')" prop="content">
|
||||||
|
<div style="width: 600px;">
|
||||||
<editor v-model="formAll.content" :min-height="260"/>
|
<editor v-model="formAll.content" :min-height="260"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="t('公告时间')" prop="ShowStartTime">
|
<el-form-item :label="t('公告时间')" prop="ShowStartTime">
|
||||||
<div >
|
<div >
|
||||||
|
|
|
||||||
|
|
@ -154,9 +154,8 @@
|
||||||
<!-- <div style="width: 100%;"> <el-input style="width: 550px;" v-model="formAll.name" disabled placeholder="请输入确认安全码"></el-input></div> -->
|
<!-- <div style="width: 100%;"> <el-input style="width: 550px;" v-model="formAll.name" disabled placeholder="请输入确认安全码"></el-input></div> -->
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="t('自动额度最小值')" prop="creditQuota">
|
<el-form-item :label="t('自动额度最小值')" prop="creditQuota">
|
||||||
<div style="width: 100%;"> <el-input style="width: 550px;" v-model="formAll.creditQuota" disabled placeholder="请输入"></el-input></div>
|
<div style="width: 100%;"> <el-input style="width: 550px;" v-model="formAll.creditQuota" placeholder="请输入"></el-input></div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item :label="t('备注')">
|
<el-form-item :label="t('备注')">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="formAll.remark"
|
v-model="formAll.remark"
|
||||||
|
|
@ -194,6 +193,7 @@ const fileHost = getLocalStorage('fileUrl') || ''; // 文件host
|
||||||
|
|
||||||
const langList = getLocalStorage('langSelect')?.map(item => {
|
const langList = getLocalStorage('langSelect')?.map(item => {
|
||||||
return {
|
return {
|
||||||
|
...item,
|
||||||
label: item.name,
|
label: item.name,
|
||||||
value: item.id
|
value: item.id
|
||||||
};
|
};
|
||||||
|
|
@ -235,7 +235,7 @@ const formAll = reactive({
|
||||||
currencyPattern:[],
|
currencyPattern:[],
|
||||||
backendDomain:'',
|
backendDomain:'',
|
||||||
creditQuotaType: 1,
|
creditQuotaType: 1,
|
||||||
creditQuota:10000,
|
creditQuota:0,
|
||||||
siteType:0,
|
siteType:0,
|
||||||
})
|
})
|
||||||
const loadingButton = ref(false)
|
const loadingButton = ref(false)
|
||||||
|
|
@ -359,7 +359,7 @@ const changeLangPattern = () => {
|
||||||
let arr = [];
|
let arr = [];
|
||||||
formAll.langPattern.map(item => {
|
formAll.langPattern.map(item => {
|
||||||
let langListname = langList.find(item1 => item1.value == item);
|
let langListname = langList.find(item1 => item1.value == item);
|
||||||
arr.push({ value: item, label: langListname.label });
|
arr.push({ value: item, label: `${langListname.label}(${langListname.langDisplay})` });
|
||||||
|
|
||||||
})
|
})
|
||||||
langListarr.value =arr;
|
langListarr.value =arr;
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,12 @@
|
||||||
{{ row.currencyCode}}
|
{{ row.currencyCode}}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
<el-table-column :label="t('状态')" align="center" min-width="120" prop="quota">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-button v-if="row.status == 1" @click="handleEnable(row)" type="primary">{{t('启用')}}</el-button>
|
||||||
|
<el-button v-if="row.status == 0" @click="handleDisable(row)" type="primary">{{t('停用')}}</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column :label="t('操作时间')" align="center" min-width="120" prop="currencyCode">
|
<el-table-column :label="t('操作时间')" align="center" min-width="120" prop="currencyCode">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
{{ row.updateTime ? formatTime(row.updateTime): formatTime(row.createTime) }}
|
{{ row.updateTime ? formatTime(row.updateTime): formatTime(row.createTime) }}
|
||||||
|
|
@ -32,7 +38,7 @@
|
||||||
<el-table-column :label="t('操作')" align="center" min-width="120" prop="quota">
|
<el-table-column :label="t('操作')" align="center" min-width="120" prop="quota">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-button @click="handleEdit(row)" type="primary">{{t('修改')}}</el-button>
|
<el-button @click="handleEdit(row)" type="primary">{{t('修改')}}</el-button>
|
||||||
<el-button @click="handleDelect(row)" type="primary">{{t('删除')}}</el-button>
|
<!-- <el-button @click="handleDelect(row)" type="primary">{{t('删除')}}</el-button> -->
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
@ -73,7 +79,7 @@ import { formatTime,finalTimestamp } from '@/utils/ruoyi'; // 时间格式化
|
||||||
import CustomSelect from "@/components/CustomSelect"; // 素材列表
|
import CustomSelect from "@/components/CustomSelect"; // 素材列表
|
||||||
import { nextTick, onMounted, ref } from "vue"; // 获取当前实例
|
import { nextTick, onMounted, ref } from "vue"; // 获取当前实例
|
||||||
import { getLocalStorage } from "@/utils/auth";
|
import { getLocalStorage } from "@/utils/auth";
|
||||||
import { postSiteBindApiGame,getSiteBindApiGameInfo,postSiteUpdateApiGame,postSiteDeleteApiGame } from "@/api/siteManagement";
|
import { postSiteBindApiGame,getSiteBindApiGameInfo,postSiteUpdateApiGame,postSiteDeleteApiGame,postSiteOpenApiGameInfo,postSiteStopApiGameInfo } from "@/api/siteManagement";
|
||||||
import { id } from 'element-plus/es/locales.mjs';
|
import { id } from 'element-plus/es/locales.mjs';
|
||||||
|
|
||||||
const currencySelectArr = getLocalStorage('currencySelect')?.map(item => {
|
const currencySelectArr = getLocalStorage('currencySelect')?.map(item => {
|
||||||
|
|
@ -168,6 +174,24 @@ const handleDelect = (row) => {
|
||||||
})
|
})
|
||||||
}).catch(() => {})
|
}).catch(() => {})
|
||||||
}
|
}
|
||||||
|
//
|
||||||
|
const handleDisable = (row) => {
|
||||||
|
proxy.$modal.confirm(proxy.t('确认是否停用?')).then(() => {
|
||||||
|
postSiteStopApiGameInfo({siteId:formAll.siteId,id:row.id}).then(() => {
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('停用成功'));
|
||||||
|
getSiteBindApiGameInfos();
|
||||||
|
})
|
||||||
|
}).catch(() => {})
|
||||||
|
}
|
||||||
|
//
|
||||||
|
const handleEnable = (row) => {
|
||||||
|
proxy.$modal.confirm(proxy.t('确认是否启用?')).then(() => {
|
||||||
|
postSiteOpenApiGameInfo({siteId:formAll.siteId,id:row.id}).then(() => {
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('启用成功'));
|
||||||
|
getSiteBindApiGameInfos();
|
||||||
|
})
|
||||||
|
}).catch(() => {})
|
||||||
|
}
|
||||||
// 关闭弹窗
|
// 关闭弹窗
|
||||||
const closeDialog = () => {
|
const closeDialog = () => {
|
||||||
showDialog.value = false
|
showDialog.value = false
|
||||||
|
|
|
||||||
|
|
@ -147,13 +147,26 @@ const currencySelectArr = getLocalStorage('currencySelect')?.map(item => {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
const openView = ref(false);
|
const openView = ref(false);
|
||||||
|
const siteList = ref(getLocalStorage('siteSelect'));
|
||||||
const queryParamsList = ref([{
|
const queryParamsList = ref([{
|
||||||
label: proxy.t('站点名称'),
|
label: proxy.t('站点名称'),
|
||||||
value: 'siteName',
|
value: 'siteName',
|
||||||
|
inputType: 'select',
|
||||||
|
inputConfig:{
|
||||||
|
options: siteList.value.map(item => {
|
||||||
|
return {
|
||||||
|
label: item.label,
|
||||||
|
value: item.label,
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
}
|
||||||
},{
|
},{
|
||||||
label: proxy.t('站点ID'),
|
label: proxy.t('站点ID'),
|
||||||
value: 'siteId',
|
value: 'siteId',
|
||||||
|
inputType: 'select',
|
||||||
|
inputConfig:{
|
||||||
|
options: siteList.value,
|
||||||
|
}
|
||||||
}]);
|
}]);
|
||||||
const data = reactive({
|
const data = reactive({
|
||||||
form: {},
|
form: {},
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@
|
||||||
v-model:show="openView"></modify-dialog>
|
v-model:show="openView"></modify-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="Agent">
|
<script setup name="BillingRecords">
|
||||||
import {getSiteFlowUserList} from "@/api/report";
|
import {getSiteFlowUserList} from "@/api/report";
|
||||||
import CustomSelect from '@/components/CustomSelect';
|
import CustomSelect from '@/components/CustomSelect';
|
||||||
import CheckboxSelect from "@/components/CheckboxSelect"; // 多选框
|
import CheckboxSelect from "@/components/CheckboxSelect"; // 多选框
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<table-search-card :model="queryParams" @getList="getList" @handleQuery="handleQuery" @resetQuery="resetQuery">
|
<table-search-card :model="queryParams" @getList="getList" @handleQuery="handleQuery" @resetQuery="resetQuery">
|
||||||
<template #left>
|
<template #left>
|
||||||
<table-search-date v-model:dateRange="dateRange" v-model:operateTimeType="operateTimeType"></table-search-date>
|
<table-search-date v-model:dateRange="dateRange" v-model:operateTimeType="operateTimeType"></table-search-date>
|
||||||
<select-input-form ref="selectInputFormRef" :queryParamsList="queryParamsList" :queryParams="queryParams"
|
<select-input-form ref="selectInputFormRef" v-if="loadingShow" :queryParamsList="queryParamsList" :queryParams="queryParams"
|
||||||
@handleQuery="handleQuery">
|
@handleQuery="handleQuery">
|
||||||
</select-input-form>
|
</select-input-form>
|
||||||
<el-form-item prop="changeType">
|
<el-form-item prop="changeType">
|
||||||
|
|
@ -95,7 +95,7 @@
|
||||||
v-model:show="openView"></modify-dialog>
|
v-model:show="openView"></modify-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="Agent">
|
<script setup name="BillingRecords">
|
||||||
import {getSiteFlowQuotasList} from "@/api/report";
|
import {getSiteFlowQuotasList} from "@/api/report";
|
||||||
import CustomSelect from '@/components/CustomSelect';
|
import CustomSelect from '@/components/CustomSelect';
|
||||||
import CheckboxSelect from "@/components/CheckboxSelect"; // 多选框
|
import CheckboxSelect from "@/components/CheckboxSelect"; // 多选框
|
||||||
|
|
@ -103,9 +103,8 @@ import TableSearchDate from '@/components/TableSearchDate'
|
||||||
import AddSiteDialog from "./components/AddSiteDialog"; // 新增站点弹窗
|
import AddSiteDialog from "./components/AddSiteDialog"; // 新增站点弹窗
|
||||||
import ModifyDialog from "./components/ModifyDialog";
|
import ModifyDialog from "./components/ModifyDialog";
|
||||||
import { getLocalStorage } from "@/utils/auth";
|
import { getLocalStorage } from "@/utils/auth";
|
||||||
import Crontab from '@/components/Crontab'
|
|
||||||
import { parseTime,finalTimestamp } from '@/utils/ruoyi'; // 时间格式化
|
import { parseTime,finalTimestamp } from '@/utils/ruoyi'; // 时间格式化
|
||||||
import { onMounted } from "vue";
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { proxy } = getCurrentInstance();
|
const { proxy } = getCurrentInstance();
|
||||||
const agentList = ref([]);
|
const agentList = ref([]);
|
||||||
|
|
@ -113,14 +112,26 @@ const loading = ref(true);
|
||||||
const total = ref(0);
|
const total = ref(0);
|
||||||
|
|
||||||
const openView = ref(false);
|
const openView = ref(false);
|
||||||
|
const siteList = ref(getLocalStorage('siteSelect'));
|
||||||
const queryParamsList = ref([{
|
const queryParamsList = ref([{
|
||||||
label: proxy.t('站点ID'),
|
label: proxy.t('站点ID'),
|
||||||
value: 'siteId',
|
value: 'siteId',
|
||||||
inputType: 'number',
|
inputType: 'select',
|
||||||
|
inputConfig:{
|
||||||
|
options: siteList.value,
|
||||||
|
}
|
||||||
},{
|
},{
|
||||||
label: proxy.t('所属站点'),
|
label: proxy.t('所属站点'),
|
||||||
value: 'siteName',
|
value: 'siteName',
|
||||||
|
inputType: 'select',
|
||||||
|
inputConfig:{
|
||||||
|
options: siteList.value.map(item => {
|
||||||
|
return {
|
||||||
|
label: item.label,
|
||||||
|
value: item.label,
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: proxy.t('编号'),
|
label: proxy.t('编号'),
|
||||||
|
|
@ -191,7 +202,7 @@ total.value = response.total;
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
const loadingShow = ref(true);
|
||||||
/** 搜索按钮操作 */
|
/** 搜索按钮操作 */
|
||||||
function handleQuery() {
|
function handleQuery() {
|
||||||
queryParams.value.pageNum = 1;
|
queryParams.value.pageNum = 1;
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<table-search-date v-model:dateRange="dateRange" v-model:operateTimeType="operateTimeType"></table-search-date>
|
<table-search-date v-model:dateRange="dateRange" v-model:operateTimeType="operateTimeType"></table-search-date>
|
||||||
<select-input-form ref="selectInputFormRef" :queryParamsList="queryParamsList" :queryParams="queryParams"
|
<select-input-form ref="selectInputFormRef" v-if="loadingShow" :queryParamsList="queryParamsList" :queryParams="queryParams"
|
||||||
@handleQuery="handleQuery">
|
@handleQuery="handleQuery">
|
||||||
</select-input-form>
|
</select-input-form>
|
||||||
<select-input-form ref="selectInputFormRef" :queryParamsList="queryParamsList2" keyName="searchType2" :queryParams="queryParams"
|
<select-input-form ref="selectInputFormRef" :queryParamsList="queryParamsList2" keyName="searchType2" :queryParams="queryParams"
|
||||||
|
|
@ -106,7 +106,7 @@
|
||||||
v-model:show="openView"></modify-dialog>
|
v-model:show="openView"></modify-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="Agent">
|
<script setup name="BillingRecords">
|
||||||
import {getSiteFlowGameCurrencyList} from "@/api/report";
|
import {getSiteFlowGameCurrencyList} from "@/api/report";
|
||||||
import CustomSelect from '@/components/CustomSelect';
|
import CustomSelect from '@/components/CustomSelect';
|
||||||
import CheckboxSelect from "@/components/CheckboxSelect"; // 多选框
|
import CheckboxSelect from "@/components/CheckboxSelect"; // 多选框
|
||||||
|
|
@ -123,13 +123,26 @@ const agentList = ref([]);
|
||||||
const loading = ref(true);
|
const loading = ref(true);
|
||||||
const total = ref(0);
|
const total = ref(0);
|
||||||
const openView = ref(false);
|
const openView = ref(false);
|
||||||
|
const siteList = ref(getLocalStorage('siteSelect'));
|
||||||
const queryParamsList = ref([{
|
const queryParamsList = ref([{
|
||||||
label: proxy.t('站点ID'),
|
label: proxy.t('站点ID'),
|
||||||
value: 'siteId',
|
value: 'siteId',
|
||||||
inputType: 'number',
|
inputType: 'select',
|
||||||
|
inputConfig:{
|
||||||
|
options: siteList.value,
|
||||||
|
}
|
||||||
},{
|
},{
|
||||||
label: proxy.t('站点名称'),
|
label: proxy.t('站点名称'),
|
||||||
value: 'siteName',
|
value: 'siteName',
|
||||||
|
inputType: 'select',
|
||||||
|
inputConfig:{
|
||||||
|
options: siteList.value.map(item => {
|
||||||
|
return {
|
||||||
|
label: item.label,
|
||||||
|
value: item.label,
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
}
|
||||||
}]);
|
}]);
|
||||||
const queryParamsList2 = ref([{
|
const queryParamsList2 = ref([{
|
||||||
label: proxy.t('订单号'),
|
label: proxy.t('订单号'),
|
||||||
|
|
@ -198,7 +211,7 @@ function resetQuery() {
|
||||||
proxy.resetForm("queryRef");
|
proxy.resetForm("queryRef");
|
||||||
handleQuery();
|
handleQuery();
|
||||||
}
|
}
|
||||||
|
const loadingShow = ref(true);
|
||||||
//初始化
|
//初始化
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getList();
|
getList();
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
<!-- 列表组件 -->
|
<!-- 列表组件 -->
|
||||||
<div class="tabs-main-box">
|
<div class="tabs-main-box">
|
||||||
<billing-records v-if="activeName == 'BillingRecords'" v-hasPermi="['report:quotas:flow:list']"></billing-records>
|
<billing-records v-if="activeName == 'BillingRecords'" ></billing-records>
|
||||||
<account-changes v-if="activeName == 'AccountChanges'"></account-changes>
|
<account-changes v-if="activeName == 'AccountChanges'"></account-changes>
|
||||||
<deposit-order v-if="activeName == 'DepositOrder'"></deposit-order>
|
<deposit-order v-if="activeName == 'DepositOrder'"></deposit-order>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- 稽核管理 -->
|
<!-- 稽核管理 -->
|
||||||
<script setup name="User">
|
<script setup name="BillingRecords">
|
||||||
import BillingRecords from "./billingRecords/list.vue";
|
import BillingRecords from "./billingRecords/list.vue";
|
||||||
import AccountChanges from "./accountChanges/list.vue";
|
import AccountChanges from "./accountChanges/list.vue";
|
||||||
import DepositOrder from "./depositOrder/list.vue";
|
import DepositOrder from "./depositOrder/list.vue";
|
||||||
|
|
|
||||||
|
|
@ -118,7 +118,7 @@
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
await passwordForm.value.validate();
|
await passwordForm.value.validate();
|
||||||
let objForm = {
|
let objForm = {
|
||||||
password:form.value.newPassword
|
newPassword:form.value.newPassword
|
||||||
}
|
}
|
||||||
// 这里添加实际的API调用
|
// 这里添加实际的API调用
|
||||||
updateUserPassword(objForm).then(response => {
|
updateUserPassword(objForm).then(response => {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,249 @@
|
||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<table-search-card :model="queryParams" @getList="getList" @handleQuery="handleQuery" @resetQuery="resetQuery">
|
||||||
|
<template #left>
|
||||||
|
<el-form-item label="数据名称" prop="dataName">
|
||||||
|
<el-input
|
||||||
|
v-model="queryParams.dataName"
|
||||||
|
placeholder="请输入数据名称"
|
||||||
|
clearable
|
||||||
|
style="width: 200px"
|
||||||
|
@keyup.enter="handleQuery"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
<template #right>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
plain
|
||||||
|
icon="Plus"
|
||||||
|
@click="handleAdd"
|
||||||
|
v-hasPermi="['site:data:source:save']"
|
||||||
|
>新增</el-button>
|
||||||
|
</template>
|
||||||
|
</table-search-card>
|
||||||
|
<el-table v-loading="loading" :data="postList" border>
|
||||||
|
<el-table-column label="数据名称" align="center" prop="dataName" />
|
||||||
|
<el-table-column label="驱动类名" align="center" prop="driverClassName" />
|
||||||
|
<el-table-column label="地址" align="center" prop="address" />
|
||||||
|
<el-table-column label="数据库用户名" align="center" prop="dbUsername" />
|
||||||
|
<el-table-column label="最大使用量" align="center" prop="maxUse" />
|
||||||
|
<el-table-column label="状态" align="center" prop="status">
|
||||||
|
<template #default="scope">
|
||||||
|
<base-switch v-model="scope.row.status" :active-value="1" :inactive-value="0"
|
||||||
|
:before-change="() => beforeSwitchChange(scope.row, 'status')" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" width="180" align="center" class-name="small-padding fixed-width">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button link type="primary" @click="handleUpdate(scope.row)" v-hasPermi="['site:data:source:update']">修改</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<pagination
|
||||||
|
v-show="total > 0"
|
||||||
|
:total="total"
|
||||||
|
v-model:page="queryParams.pageNum"
|
||||||
|
v-model:limit="queryParams.pageSize"
|
||||||
|
@pagination="getList"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 添加或修改岗位对话框 -->
|
||||||
|
<el-dialog :title="title" align-center v-if="open" v-model="open" width="800px" append-to-body>
|
||||||
|
<el-form ref="postRef" :model="form" :rules="rules" label-width="150px">
|
||||||
|
<el-form-item label="数据名称" prop="dataName">
|
||||||
|
<el-input v-model="form.dataName" placeholder="请输入数据名称" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="驱动类名" prop="driverClassName">
|
||||||
|
<el-input v-model="form.driverClassName" placeholder="请输入驱动类名" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="地址" prop="address">
|
||||||
|
<el-input v-model="form.address" placeholder="请输入地址" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="数据库端口" prop="dbPort">
|
||||||
|
<el-input v-model="form.dbPort" placeholder="请输入数据库端口" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="数据库用户名" prop="dbUsername">
|
||||||
|
<el-input v-model="form.dbUsername" placeholder="请输入数据库用户名" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="数据库密码" prop="dbPassword">
|
||||||
|
<el-input v-model="form.dbPassword" type="password" placeholder="请输入数据库密码"/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="最大使用量" prop="maxUse">
|
||||||
|
<el-input v-model="form.maxUse" placeholder="请输入最大使用量" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||||
|
<el-button @click="cancel">取 消</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup name="Post">
|
||||||
|
import { listDataSource, addDataSourceSave, updateDataSource,switchDataSource } from "@/api/system/dataSourceManagement";
|
||||||
|
import baseSwitch from "@/components/BaseSwitch";
|
||||||
|
const { proxy } = getCurrentInstance();
|
||||||
|
const { sys_normal_disable } = proxy.useDict("sys_normal_disable");
|
||||||
|
|
||||||
|
const postList = ref([]);
|
||||||
|
const open = ref(false);
|
||||||
|
const loading = ref(true);
|
||||||
|
const showSearch = ref(true);
|
||||||
|
const ids = ref([]);
|
||||||
|
const single = ref(true);
|
||||||
|
const multiple = ref(true);
|
||||||
|
const total = ref(0);
|
||||||
|
const title = ref("");
|
||||||
|
const oldForm = shallowRef({ });
|
||||||
|
const data = reactive({
|
||||||
|
form: {
|
||||||
|
maxUse:2,
|
||||||
|
},
|
||||||
|
queryParams: {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
dataName: "",
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
dataName: [{ required: true, message: "数据名称不能为空", trigger: "change" }],
|
||||||
|
driverClassName: [{ required: true, message: "驱动类名不能为空", trigger: "change" }],
|
||||||
|
address: [{ required: true, message: "地址不能为空", trigger: "change" }],
|
||||||
|
dbPort: [{ required: true, message: "数据库端口不能为空", trigger: "change" }],
|
||||||
|
dbUsername: [{ required: true, message: "数据库用户名不能为空", trigger: "change" }],
|
||||||
|
dbPassword: [{ required: true, message: "数据库密码不能为空", trigger: "change" }],
|
||||||
|
maxUse: [{ required: true, message: "最大使用量不能为空", trigger: "change" }],
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const { queryParams, form, rules } = toRefs(data);
|
||||||
|
|
||||||
|
/** 查询岗位列表 */
|
||||||
|
function getList() {
|
||||||
|
loading.value = true;
|
||||||
|
listDataSource(queryParams.value).then(response => {
|
||||||
|
postList.value = response.rows;
|
||||||
|
total.value = response.total;
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 取消按钮 */
|
||||||
|
function cancel() {
|
||||||
|
open.value = false;
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 表单重置 */
|
||||||
|
function reset() {
|
||||||
|
form.value = {
|
||||||
|
id: undefined,
|
||||||
|
dataName: undefined,
|
||||||
|
driverClassName:undefined,
|
||||||
|
address: undefined,
|
||||||
|
dbPort: undefined,
|
||||||
|
dbUsername: undefined,
|
||||||
|
dbPassword: undefined,
|
||||||
|
maxUse: 2,
|
||||||
|
};
|
||||||
|
proxy.resetForm("postRef");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 搜索按钮操作 */
|
||||||
|
function handleQuery() {
|
||||||
|
queryParams.value.pageNum = 1;
|
||||||
|
getList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 重置按钮操作 */
|
||||||
|
function resetQuery() {
|
||||||
|
proxy.resetForm("queryRef");
|
||||||
|
handleQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 多选框选中数据 */
|
||||||
|
function handleSelectionChange(selection) {
|
||||||
|
ids.value = selection.map(item => item.postId);
|
||||||
|
single.value = selection.length != 1;
|
||||||
|
multiple.value = !selection.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增按钮操作 */
|
||||||
|
function handleAdd() {
|
||||||
|
reset();
|
||||||
|
open.value = true;
|
||||||
|
title.value = "新增数据源";
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改按钮操作 */
|
||||||
|
function handleUpdate(row) {
|
||||||
|
reset();
|
||||||
|
const id = row.id || ids.value;
|
||||||
|
form.value = row;
|
||||||
|
open.value = true;
|
||||||
|
oldForm.value = JSON.stringify(form.value);
|
||||||
|
title.value = "修改数据源";
|
||||||
|
}
|
||||||
|
// 列表开关事件
|
||||||
|
const beforeSwitchChange = async (row, undateKeys) => {
|
||||||
|
const _status = row[undateKeys] === 1 ? 2 : 1
|
||||||
|
const _data = {
|
||||||
|
id: row.id
|
||||||
|
}
|
||||||
|
_data[undateKeys] = _status
|
||||||
|
try {
|
||||||
|
await switchDataSource(_data).then(() => {
|
||||||
|
proxy.$modal.msgSuccess(_status === 1 ? proxy.t('开启成功') : proxy.t('关闭成功'))
|
||||||
|
getList()
|
||||||
|
})
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(proxy.t('接口调用失败'), error);
|
||||||
|
return false; // 阻止开关状态改变
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/** 提交按钮 */
|
||||||
|
function submitForm() {
|
||||||
|
proxy.$refs["postRef"].validate(valid => {
|
||||||
|
if (valid) {
|
||||||
|
if (form.value.id != undefined) {
|
||||||
|
if (JSON.stringify(form.value) != oldForm.value) {
|
||||||
|
updateDataSource(form.value).then(response => {
|
||||||
|
proxy.$modal.msgSuccess("修改成功");
|
||||||
|
open.value = false;
|
||||||
|
getList();
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
open.value = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
addDataSourceSave(form.value).then(response => {
|
||||||
|
proxy.$modal.msgSuccess("新增成功");
|
||||||
|
open.value = false;
|
||||||
|
getList();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 导出按钮操作 */
|
||||||
|
function handleExport() {
|
||||||
|
proxy.download("system/post/export", {
|
||||||
|
...queryParams.value
|
||||||
|
}, `post_${new Date().getTime()}.xlsx`);
|
||||||
|
}
|
||||||
|
|
||||||
|
getList();
|
||||||
|
</script>
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
<el-table-column label="权限字符" align="center" prop="roleKey" />
|
<el-table-column label="权限字符" align="center" prop="roleKey" />
|
||||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
<span>{{ formatTime(scope.row.createTime) }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ onActivated(() => {
|
||||||
|
|
||||||
// 路由跳转过来
|
// 路由跳转过来
|
||||||
if (Object.keys(routeParams).length) {
|
if (Object.keys(routeParams).length) {
|
||||||
activeName.value = routeParams.activeName || 'auditManage';
|
activeName.value = routeParams.activeName || 'userList';
|
||||||
memberAccount.value = routeParams.memberAccount || '';
|
memberAccount.value = routeParams.memberAccount || '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@
|
||||||
</li>
|
</li>
|
||||||
<li class="list-group-item">
|
<li class="list-group-item">
|
||||||
<svg-icon icon-class="date" />创建日期
|
<svg-icon icon-class="date" />创建日期
|
||||||
<div class="pull-right">{{ state.user.createTime }}</div>
|
<div class="pull-right">{{ formatTime(state.user.createTime) }}</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="user-info-head" @click="editCropper()">
|
<div class="user-info-head" @click="editCropper()">
|
||||||
<img :src="options.img" title="点击上传头像" class="img-circle img-lg" />
|
<img :src="options.img" title="点击上传头像" class="img-circle img-lg" />
|
||||||
<el-dialog :title="title" align-center v-model="open" width="800px" append-to-body @opened="modalOpened" @close="closeDialog">
|
<el-dialog :title="title" v-model="open" width="800px" append-to-body @opened="modalOpened" @close="closeDialog">
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :xs="24" :md="12" :style="{ height: '350px' }">
|
<el-col :xs="24" :md="12" :style="{ height: '350px' }">
|
||||||
<vue-cropper
|
<vue-cropper
|
||||||
|
|
@ -63,17 +63,19 @@ import "vue-cropper/dist/index.css";
|
||||||
import { VueCropper } from "vue-cropper";
|
import { VueCropper } from "vue-cropper";
|
||||||
import { uploadAvatar } from "@/api/system/user";
|
import { uploadAvatar } from "@/api/system/user";
|
||||||
import useUserStore from "@/store/modules/user";
|
import useUserStore from "@/store/modules/user";
|
||||||
|
import { getLocalStorage } from "@/utils/auth";
|
||||||
|
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
const { proxy } = getCurrentInstance();
|
const { proxy } = getCurrentInstance();
|
||||||
|
|
||||||
|
const fileHost = getLocalStorage('fileUrl') || ''; // 文件host
|
||||||
const open = ref(false);
|
const open = ref(false);
|
||||||
const visible = ref(false);
|
const visible = ref(false);
|
||||||
const title = ref("修改头像");
|
const title = ref("修改头像");
|
||||||
|
|
||||||
//图片裁剪数据
|
//图片裁剪数据
|
||||||
const options = reactive({
|
const options = reactive({
|
||||||
img: userStore.avatar, // 裁剪图片的地址
|
img: fileHost + userStore.avatar, // 裁剪图片的地址
|
||||||
autoCrop: true, // 是否默认生成截图框
|
autoCrop: true, // 是否默认生成截图框
|
||||||
autoCropWidth: 200, // 默认生成截图框宽度
|
autoCropWidth: 200, // 默认生成截图框宽度
|
||||||
autoCropHeight: 200, // 默认生成截图框高度
|
autoCropHeight: 200, // 默认生成截图框高度
|
||||||
|
|
@ -133,7 +135,7 @@ function uploadImg() {
|
||||||
formData.append("avatarfile", data, options.filename);
|
formData.append("avatarfile", data, options.filename);
|
||||||
uploadAvatar(formData).then(response => {
|
uploadAvatar(formData).then(response => {
|
||||||
open.value = false;
|
open.value = false;
|
||||||
options.img = import.meta.env.VITE_APP_BASE_API + response.imgUrl;
|
options.img = response.imgUrl;
|
||||||
userStore.avatar = options.img;
|
userStore.avatar = options.img;
|
||||||
proxy.$modal.msgSuccess("修改成功");
|
proxy.$modal.msgSuccess("修改成功");
|
||||||
visible.value = false;
|
visible.value = false;
|
||||||
|
|
@ -148,7 +150,7 @@ function realTime(data) {
|
||||||
|
|
||||||
/** 关闭窗口 */
|
/** 关闭窗口 */
|
||||||
function closeDialog() {
|
function closeDialog() {
|
||||||
options.img = userStore.avatar;
|
options.img = fileHost + userStore.avatar;
|
||||||
options.visible = false;
|
options.visible = false;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -1,221 +0,0 @@
|
||||||
# 权限树状表格组件使用说明
|
|
||||||
|
|
||||||
## 概述
|
|
||||||
|
|
||||||
这个权限树状表格组件实现了类似表格的树形权限管理界面,左侧显示树形菜单结构,右侧显示对应的权限复选框,完全符合您截图中的设计需求。
|
|
||||||
|
|
||||||
## 文件结构
|
|
||||||
|
|
||||||
```
|
|
||||||
src/views/system/user/role/
|
|
||||||
├── render.vue # 核心权限树状表格组件
|
|
||||||
├── permission-dialog.vue # 权限选择对话框组件
|
|
||||||
├── permission-example.vue # 完整使用示例
|
|
||||||
└── README.md # 使用说明
|
|
||||||
```
|
|
||||||
|
|
||||||
## 核心功能
|
|
||||||
|
|
||||||
### 1. 树状表格展示
|
|
||||||
- 表格样式的树形结构展示
|
|
||||||
- 支持多级树形结构
|
|
||||||
- 可展开/收起节点
|
|
||||||
- 支持节点复选框选择(含半选状态)
|
|
||||||
|
|
||||||
### 2. 权限复选框管理
|
|
||||||
- 每个节点可以配置独立的权限项
|
|
||||||
- 权限项以复选框形式展示在右侧
|
|
||||||
- 支持权限项的选中状态管理
|
|
||||||
- 支持热门权限标记
|
|
||||||
|
|
||||||
### 3. 表格式布局
|
|
||||||
- 左侧:菜单名称列(支持树形缩进)
|
|
||||||
- 右侧:权限操作列(权限复选框)
|
|
||||||
- 表格头部标题
|
|
||||||
- 行分隔线和悬停效果
|
|
||||||
|
|
||||||
## 数据结构
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
const treeData = [
|
|
||||||
{
|
|
||||||
id: 1, // 节点唯一标识
|
|
||||||
label: '开站管理', // 节点显示名称
|
|
||||||
children: [ // 子节点(可选)
|
|
||||||
{
|
|
||||||
id: 11,
|
|
||||||
label: '待审核',
|
|
||||||
perms: [] // 权限列表(可选)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 12,
|
|
||||||
label: '待付款',
|
|
||||||
perms: [ // 权限项配置
|
|
||||||
{
|
|
||||||
key: 'pay',
|
|
||||||
label: '付款',
|
|
||||||
checked: false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 15,
|
|
||||||
label: '已上线',
|
|
||||||
perms: [
|
|
||||||
{
|
|
||||||
key: 'add_brand',
|
|
||||||
label: '新增子品牌',
|
|
||||||
checked: false,
|
|
||||||
isHot: true // 热门权限标记
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'edit',
|
|
||||||
label: '修改',
|
|
||||||
checked: false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
## 使用方法
|
|
||||||
|
|
||||||
### 1. 基础使用
|
|
||||||
|
|
||||||
```vue
|
|
||||||
<template>
|
|
||||||
<PermissionTreeTable ref="treeTableRef" />
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref } from 'vue'
|
|
||||||
import PermissionTreeTable from './render.vue'
|
|
||||||
|
|
||||||
const treeTableRef = ref()
|
|
||||||
|
|
||||||
// 获取选中的数据
|
|
||||||
const getSelectedData = () => {
|
|
||||||
if (treeTableRef.value) {
|
|
||||||
return treeTableRef.value.getCheckedData()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 对话框形式使用
|
|
||||||
|
|
||||||
```vue
|
|
||||||
<template>
|
|
||||||
<PermissionDialog
|
|
||||||
v-model="dialogVisible"
|
|
||||||
:role-id="currentRoleId"
|
|
||||||
@confirm="handlePermissionConfirm"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import PermissionDialog from './permission-dialog.vue'
|
|
||||||
|
|
||||||
const dialogVisible = ref(false)
|
|
||||||
const currentRoleId = ref(1)
|
|
||||||
|
|
||||||
const handlePermissionConfirm = (data) => {
|
|
||||||
console.log('选中的权限:', data)
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
```
|
|
||||||
|
|
||||||
## 样式说明
|
|
||||||
|
|
||||||
### 1. 表格式布局
|
|
||||||
- 使用 CSS Grid 布局实现表格效果
|
|
||||||
- 左列:菜单名称(固定宽度 300px)
|
|
||||||
- 右列:权限操作(自适应宽度)
|
|
||||||
- 表格头部和内容分离
|
|
||||||
|
|
||||||
### 2. 主要样式类名
|
|
||||||
- `.permission-tree-table`: 组件容器
|
|
||||||
- `.table-header`: 表格头部
|
|
||||||
- `.table-content`: 表格内容区域
|
|
||||||
- `.table-row`: 每行的容器
|
|
||||||
- `.row-left`: 左侧菜单名称区域
|
|
||||||
- `.row-right`: 右侧权限操作区域
|
|
||||||
- `.expand-icon`: 展开/收起图标
|
|
||||||
- `.hot-tag`: 热门权限标记
|
|
||||||
|
|
||||||
### 3. 核心样式
|
|
||||||
```css
|
|
||||||
.permission-tree-table {
|
|
||||||
border: 1px solid #ebeef5;
|
|
||||||
border-radius: 4px;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-header {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 300px 1fr;
|
|
||||||
background: #f5f7fa;
|
|
||||||
border-bottom: 1px solid #ebeef5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-row {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 300px 1fr;
|
|
||||||
border-bottom: 1px solid #ebeef5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-row:hover {
|
|
||||||
background-color: #f5f7fa;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## API 说明
|
|
||||||
|
|
||||||
### Props
|
|
||||||
- `modelValue`: 对话框显示状态(仅对话框组件)
|
|
||||||
- `roleId`: 角色ID(可选)
|
|
||||||
|
|
||||||
### Events
|
|
||||||
- `confirm`: 确认选择权限时触发,返回选中的权限数据
|
|
||||||
|
|
||||||
### Methods
|
|
||||||
- `getCheckedData()`: 获取当前选中的数据
|
|
||||||
- 返回格式:
|
|
||||||
```javascript
|
|
||||||
{
|
|
||||||
checkedNodes: [ // 选中的节点
|
|
||||||
{ id: 1, label: '开站管理' }
|
|
||||||
],
|
|
||||||
checkedPermissions: { // 选中的权限
|
|
||||||
"12": [
|
|
||||||
{ key: 'pay', label: '付款' }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 扩展功能
|
|
||||||
|
|
||||||
### 1. 权限标记
|
|
||||||
可以为特定权限添加标记(如"热门"标记):
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
const isHot = perm === '新增子品牌'
|
|
||||||
// 在渲染时添加标记
|
|
||||||
h('span', { class: 'hot-tag' }, '热')
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 权限分组
|
|
||||||
可以通过树形结构对权限进行分组管理。
|
|
||||||
|
|
||||||
### 3. 权限搜索
|
|
||||||
可以添加搜索功能来快速定位特定权限。
|
|
||||||
|
|
||||||
## 注意事项
|
|
||||||
|
|
||||||
1. 确保每个节点的 `id` 唯一
|
|
||||||
2. `perms` 数组为空时不会显示权限复选框
|
|
||||||
3. 权限状态通过 `permissionState` 响应式对象管理
|
|
||||||
4. 使用 `:deep()` 选择器来修改 Element Plus 组件的默认样式
|
|
||||||
|
|
@ -70,7 +70,7 @@
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
<span>{{ formatTime(scope.row.createTime) }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||||
|
|
@ -91,7 +91,7 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="User">
|
<script setup name="AuthUser">
|
||||||
import selectUser from "./selectUser";
|
import selectUser from "./selectUser";
|
||||||
import { allocatedUserList, authUserCancel, authUserCancelAll } from "@/api/system/role";
|
import { allocatedUserList, authUserCancel, authUserCancelAll } from "@/api/system/role";
|
||||||
|
|
||||||
|
|
@ -108,7 +108,7 @@ const userIds = ref([]);
|
||||||
|
|
||||||
const queryParams = reactive({
|
const queryParams = reactive({
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 10,
|
pageSize: 20,
|
||||||
roleId: route.params.roleId,
|
roleId: route.params.roleId,
|
||||||
userName: undefined,
|
userName: undefined,
|
||||||
phonenumber: undefined,
|
phonenumber: undefined,
|
||||||
|
|
|
||||||
|
|
@ -1,185 +1,163 @@
|
||||||
<template>
|
<template>
|
||||||
<el-form :model="queryParams" ref="queryRef" v-show="showSearch" :inline="true" label-width="68px">
|
|
||||||
<el-form-item label="角色名称" prop="roleName">
|
|
||||||
<el-input
|
|
||||||
v-model="queryParams.roleName"
|
|
||||||
placeholder="请输入角色名称"
|
|
||||||
clearable
|
|
||||||
style="width: 240px"
|
|
||||||
@keyup.enter="handleQuery"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="权限字符" prop="roleKey">
|
|
||||||
<el-input
|
|
||||||
v-model="queryParams.roleKey"
|
|
||||||
placeholder="请输入权限字符"
|
|
||||||
clearable
|
|
||||||
style="width: 240px"
|
|
||||||
@keyup.enter="handleQuery"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="状态" prop="status">
|
|
||||||
<el-select
|
|
||||||
v-model="queryParams.status"
|
|
||||||
placeholder="角色状态"
|
|
||||||
clearable
|
|
||||||
style="width: 240px"
|
|
||||||
>
|
|
||||||
<el-option
|
|
||||||
v-for="dict in sys_normal_disable"
|
|
||||||
:key="dict.value"
|
|
||||||
:label="dict.label"
|
|
||||||
:value="dict.value"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="创建时间" style="width: 308px">
|
|
||||||
<el-date-picker
|
|
||||||
v-model="dateRange"
|
|
||||||
value-format="YYYY-MM-DD"
|
|
||||||
type="daterange"
|
|
||||||
range-separator="-"
|
|
||||||
start-placeholder="开始日期"
|
|
||||||
end-placeholder="结束日期"
|
|
||||||
></el-date-picker>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
|
||||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
<el-row :gutter="10" class="mb8">
|
|
||||||
<el-col :span="1.5">
|
|
||||||
<el-button
|
|
||||||
type="primary"
|
|
||||||
plain
|
|
||||||
icon="Plus"
|
|
||||||
@click="handleAdd"
|
|
||||||
v-hasPermi="['system:role:add']"
|
|
||||||
>新增</el-button>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="1.5">
|
|
||||||
<el-button
|
|
||||||
type="success"
|
|
||||||
plain
|
|
||||||
icon="Edit"
|
|
||||||
:disabled="single"
|
|
||||||
@click="handleUpdate"
|
|
||||||
v-hasPermi="['system:role:edit']"
|
|
||||||
>修改</el-button>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="1.5">
|
|
||||||
<el-button
|
|
||||||
type="danger"
|
|
||||||
plain
|
|
||||||
icon="Delete"
|
|
||||||
:disabled="multiple"
|
|
||||||
@click="handleDelete"
|
|
||||||
v-hasPermi="['system:role:remove']"
|
|
||||||
>删除</el-button>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="1.5">
|
|
||||||
<el-button
|
|
||||||
type="warning"
|
|
||||||
plain
|
|
||||||
icon="Download"
|
|
||||||
@click="handleExport"
|
|
||||||
v-hasPermi="['system:role:export']"
|
|
||||||
>导出</el-button>
|
|
||||||
</el-col>
|
|
||||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
|
||||||
</el-row>
|
|
||||||
|
|
||||||
|
<table-search-card :model="queryParams" @getList="getList" @handleQuery="handleQuery" @resetQuery="resetQuery">
|
||||||
|
<template #left>
|
||||||
|
<select-input-form ref="selectInputFormRef" :queryParamsList="queryParamsList" :queryParams="queryParams"
|
||||||
|
@handleQuery="handleQuery">
|
||||||
|
</select-input-form>
|
||||||
|
</template>
|
||||||
|
<template #right>
|
||||||
|
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['system:role:add']">新增</el-button>
|
||||||
|
</template>
|
||||||
|
</table-search-card>
|
||||||
|
<el-alert :title="t('提示: 删除权限:后台账号数为0时,才能删除权限')" style="margin-bottom: 10px;" :closable="false" type="warning"
|
||||||
|
show-icon />
|
||||||
<!-- 表格数据 -->
|
<!-- 表格数据 -->
|
||||||
<el-table v-loading="loading" :data="roleList" @selection-change="handleSelectionChange">
|
<el-table v-loading="loading" :data="roleList" ref="tableRef" class="c-table-main" @select="tableSelect"
|
||||||
<el-table-column type="selection" width="55" align="center" />
|
@select-all="tableSelect" stripe border>
|
||||||
<el-table-column label="角色编号" prop="roleId" width="120" />
|
<el-table-column type="selection" width="55" :selectable="rowSelectable" align="center" />
|
||||||
<el-table-column label="角色名称" prop="roleName" :show-overflow-tooltip="true" width="150" />
|
<el-table-column label="权限名称" prop="roleName" min-width="150" align="center" >
|
||||||
<el-table-column label="权限字符" prop="roleKey" :show-overflow-tooltip="true" width="150" />
|
<template #default="{ row }">
|
||||||
<el-table-column label="显示顺序" prop="roleSort" width="100" />
|
<span>{{ row.roleName }} <span v-if="row.defaultStatus == 0">(默认)</span></span>
|
||||||
<el-table-column label="状态" align="center" width="100">
|
|
||||||
<template #default="scope">
|
|
||||||
<el-switch
|
|
||||||
v-model="scope.row.status"
|
|
||||||
active-value="0"
|
|
||||||
inactive-value="1"
|
|
||||||
@change="handleStatusChange(scope.row)"
|
|
||||||
></el-switch>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="创建时间" align="center" prop="createTime">
|
<!-- <el-table-column label="权限类型" prop="roleName" min-width="110" align="center" /> -->
|
||||||
<template #default="scope">
|
<el-table-column label="权限适用范围" prop="roleScope" min-width="150" align="center">
|
||||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
<template #default="{ row }">
|
||||||
|
{{ row.roleScope || '--' }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
<el-table-column label="用户列表" prop="roleSort" min-width="200">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<div v-if="row.sysUsers.length > 0">
|
||||||
|
<span v-for="(item, index) in row.sysUsers.slice(0, 5)" :key="item.userId" @click="handleUserListClick(row)" style="color: rgb(64, 158, 255);cursor: pointer;">
|
||||||
|
{{ item.userName }}
|
||||||
|
<span v-if="index < Math.min(5, row.sysUsers.length) - 1">,</span>
|
||||||
|
</span>
|
||||||
|
<span v-if="row.sysUsers.length > 5"> ...</span>
|
||||||
|
</div>
|
||||||
|
<div v-else>--</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="权限数" prop="menuCount" align="center" min-width="80">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ row.menuCount || '--' }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="备注" prop="remark" min-width="130">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ row.remark || '--' }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" align="center" min-width="200" class-name="small-padding fixed-width">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-tooltip content="修改" placement="top" v-if="scope.row.roleId !== 1">
|
<el-button link type="primary" @click="handleDetail(scope.row)" v-hasPermi="['system:role:edit']">{{ t('详情')
|
||||||
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:role:edit']"></el-button>
|
}}</el-button>
|
||||||
</el-tooltip>
|
<el-button link type="primary" v-if="scope.row.defaultStatus == 1" @click="handleUpdate(scope.row)"
|
||||||
<el-tooltip content="删除" placement="top" v-if="scope.row.roleId !== 1">
|
v-hasPermi="['system:role:edit']">{{ t('修改') }}</el-button>
|
||||||
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:role:remove']"></el-button>
|
<el-button link type="primary" @click="handleManage(scope.row)" v-hasPermi="['system:role:edit']">{{ t('管理')
|
||||||
</el-tooltip>
|
}}</el-button>
|
||||||
<el-tooltip content="数据权限" placement="top" v-if="scope.row.roleId !== 1">
|
<el-button link type="primary" v-if="scope.row.defaultStatus == 1" @click="handleDelete(scope.row)"
|
||||||
<el-button link type="primary" icon="CircleCheck" @click="handleDataScope(scope.row)" v-hasPermi="['system:role:edit']"></el-button>
|
v-hasPermi="['system:role:remove']">{{ t('删除') }}</el-button>
|
||||||
</el-tooltip>
|
|
||||||
<el-tooltip content="分配用户" placement="top" v-if="scope.row.roleId !== 1">
|
|
||||||
<el-button link type="primary" icon="User" @click="handleAuthUser(scope.row)" v-hasPermi="['system:role:edit']"></el-button>
|
|
||||||
</el-tooltip>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize"
|
||||||
<pagination
|
@pagination="getList" />
|
||||||
v-show="total > 0"
|
<!-- 批量操作 -->
|
||||||
:total="total"
|
<table-batch-operate v-if="total > 0" v-model:batchOpType="batchOpType"
|
||||||
v-model:page="queryParams.pageNum"
|
v-model:isAllSelection="isAllSelection" @allSelectionChange="allSelectionChange" @opTypeChange="opTypeChange"
|
||||||
v-model:limit="queryParams.pageSize"
|
:selectionData="selectionData" :opTypeOptions="opTypeOptions"></table-batch-operate>
|
||||||
@pagination="getList"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!-- 添加或修改角色配置对话框 -->
|
<!-- 添加或修改角色配置对话框 -->
|
||||||
<el-dialog :title="title" align-center v-model="open" width="860px" append-to-body>
|
<el-dialog :title="title" align-center v-model="open" width="860px" append-to-body>
|
||||||
<el-scrollbar max-height="600px">
|
<el-scrollbar max-height="800px">
|
||||||
<el-form ref="roleRef" :model="form" :rules="rules" label-width="100px">
|
<el-form ref="roleRef" :model="form" :rules="rules" label-width="100px">
|
||||||
<el-form-item label="角色名称" prop="roleName">
|
<el-form-item label="角色名称" prop="roleName">
|
||||||
<el-input v-model="form.roleName" placeholder="请输入角色名称" />
|
<el-input v-model="form.roleName" :disabled="modifyStatus == 'detail' || modifyStatus == 'Manage'"
|
||||||
|
placeholder="请输入角色名称" maxlength="20" show-word-limit />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item prop="roleKey">
|
<el-form-item label="权限范围">
|
||||||
<template #label>
|
<el-select disabled v-model="form.dataScope" style="width: 350px;" @change="dataScopeSelectChange">
|
||||||
<span>
|
<el-option v-for="item in dataScopeOptions" :key="item.value" :label="item.label"
|
||||||
<el-tooltip content="控制器中定义的权限字符,如:@PreAuthorize(`@ss.hasRole('admin')`)" placement="top">
|
:value="item.value"></el-option>
|
||||||
<el-icon><question-filled /></el-icon>
|
</el-select>
|
||||||
</el-tooltip>
|
|
||||||
权限字符
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<el-input v-model="form.roleKey" placeholder="请输入权限字符" />
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="角色顺序" prop="roleSort">
|
<el-form-item v-if="modifyStatus == 'add'" label="复制权限">
|
||||||
<el-input-number v-model="form.roleSort" controls-position="right" :min="0" />
|
<el-select v-model="form.copyRoleId" style="width: 350px;" clearable @change="changeMenu">
|
||||||
|
<el-option v-for="item in roleOptions" :key="item.value" :label="item.label"
|
||||||
|
:value="item.value"></el-option>
|
||||||
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="状态">
|
<el-form-item label="备注">
|
||||||
<el-radio-group v-model="form.status">
|
<el-input v-model="form.remark" :disabled="modifyStatus == 'detail' || modifyStatus == 'Manage'"
|
||||||
<el-radio
|
type="textarea" placeholder="请输入内容"></el-input>
|
||||||
v-for="dict in sys_normal_disable"
|
|
||||||
:key="dict.value"
|
|
||||||
:value="dict.value"
|
|
||||||
>{{ dict.label }}</el-radio>
|
|
||||||
</el-radio-group>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="菜单权限">
|
<el-form-item v-if="modifyStatus == 'Manage'" label="添加账号">
|
||||||
<!-- <el-checkbox v-model="menuExpand" @change="handleCheckedTreeExpand($event, 'menu')">展开/折叠</el-checkbox> -->
|
<el-row style="width: 100%;">
|
||||||
<el-checkbox v-model="menuNodeAll" @change="handleCheckedTreeNodeAll($event, 'menu')">全选/全不选</el-checkbox>
|
<el-col :span="16">
|
||||||
<el-checkbox v-model="form.menuCheckStrictly" @change="handleCheckedTreeConnect($event, 'menu')">父子联动</el-checkbox>
|
<div style="width: 100%;">
|
||||||
|
<checkbox-select v-if="showLoding" collapse-tags collapse-tags-tooltip style="width: 100%;" v-model="accountLinking"
|
||||||
|
:options="accountOptions" :placeholder="t('请选择账号进行权限关联')"></checkbox-select>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8" style="display: flex;justify-content: right;">
|
||||||
|
<div style="margin-left: 10px;">
|
||||||
|
<el-button type="primary" @click="handleAddAccount">{{ t('添加账户') }}</el-button>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row v-if="sysUsersArr.length > 0" style="width: 100%;margin-top: 20px;">
|
||||||
|
<el-col :span="20">
|
||||||
|
<div style="width: 100%;">
|
||||||
|
<el-input v-model="userNameText" style="width: 100%" :placeholder="t('输入关键字进行用户列表过滤,支持空格隔开的多关键字匹配')" @input="handleFilter" />
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="4" style="display: flex;justify-content: right;">
|
||||||
|
<div style="margin-left: 10px;">
|
||||||
|
<el-button type="primary" @click="handleRemoveAccount">{{ t('移出账户') }}</el-button>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<div class="accounts-about-scroll-container" v-if="sysUsersArr.length > 0">
|
||||||
|
<el-tag v-for="(item,index) in form.sysUsers" :key="item.userId" closable type="info" style="margin-right: 10px;" @close="handleClose(item)">
|
||||||
|
{{ item.userName }}
|
||||||
|
</el-tag>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<div style="display: flex;">
|
||||||
|
<div style="font-size: 14px;font-weight: 600;">{{ t('权限设置') }}</div>
|
||||||
|
<div style="margin-left: 10px;">{{ t('权限数') }}:{{ countTree }}</div>
|
||||||
|
<div @click="handleCheckedTreeExpand($event, 'menu')"
|
||||||
|
style="cursor: pointer;color: rgb(64, 158, 255);margin-left: 10px;">
|
||||||
|
<span v-if="!defaultExpandAll">{{ t('全部展开') }}</span>
|
||||||
|
<span v-if="defaultExpandAll">{{ t('全部收起') }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style="width: 100%;margin-top: 10px;">
|
||||||
|
<el-input v-model="filterText" style="width: 100%" :placeholder="t('输入关键字进行权限过滤,支持空格隔开的多关键字匹配')" />
|
||||||
|
</div>
|
||||||
|
<div style="margin-top: 10px;">
|
||||||
|
<el-checkbox v-model="menuNodeAll" :disabled="modifyStatus == 'Manage' || modifyStatus == 'detail'"
|
||||||
|
@change="handleCheckedTreeNodeAll($event, 'menu')">全选/全不选</el-checkbox>
|
||||||
|
<el-checkbox v-model="form.menuCheckStrictly" :disabled="modifyStatus == 'Manage' || modifyStatus == 'detail'"
|
||||||
|
@change="handleCheckedTreeConnect($event, 'menu')">父子联动</el-checkbox>
|
||||||
<div class="table">
|
<div class="table">
|
||||||
<div class="menu-list">
|
<div class="menu-list">
|
||||||
<el-tree ref="menuRef" :data="menuOptions" default-expand-all :expand-on-click-node='false' check-on-click-node show-checkbox node-key="id"
|
<el-tree ref="menuRef" :data="menuOptions" v-if="defaultExpandShow" :default-expand-all="defaultExpandAll"
|
||||||
:check-strictly="!form.menuCheckStrictly" :props="{ label: 'label', children: 'children' }"></el-tree>
|
:expand-on-click-node='false' check-on-click-node show-checkbox node-key="id"
|
||||||
|
:check-strictly="!form.menuCheckStrictly"
|
||||||
|
:props="{ label: 'label', children: 'children', disabled: (data, node) => modifyStatus == 'Manage' || modifyStatus == 'detail', }"
|
||||||
|
:filter-node-method="filterNode"></el-tree>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- <el-form-item label="菜单权限">
|
||||||
|
<el-checkbox v-model="menuExpand" @change="handleCheckedTreeExpand($event, 'menu')">展开/折叠</el-checkbox>
|
||||||
|
|
||||||
<!-- <el-tree
|
|
||||||
|
<el-tree
|
||||||
class="tree-border"
|
class="tree-border"
|
||||||
:data="menuOptions"
|
:data="menuOptions"
|
||||||
show-checkbox
|
show-checkbox
|
||||||
|
|
@ -189,21 +167,47 @@
|
||||||
empty-text="加载中,请稍候"
|
empty-text="加载中,请稍候"
|
||||||
:render-content="renderContent"
|
:render-content="renderContent"
|
||||||
:props="{ label: 'label', children: 'children' }"
|
:props="{ label: 'label', children: 'children' }"
|
||||||
></el-tree> -->
|
></el-tree>
|
||||||
|
</el-form-item> -->
|
||||||
|
</el-form>
|
||||||
|
</el-scrollbar>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer" style="display: flex;justify-content: center;">
|
||||||
|
<el-button v-if="modifyStatus == 'detail' || modifyStatus == 'Manage'" @click="cancel">关 闭</el-button>
|
||||||
|
<el-button v-if="modifyStatus == 'add' || modifyStatus == 'edit'" type="primary" @click="submitForm">确
|
||||||
|
定</el-button>
|
||||||
|
<el-button v-if="modifyStatus == 'add' || modifyStatus == 'edit'" @click="cancel">取 消</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
<el-dialog :title="t('用户列表')" align-center v-model="openUserList" width="1050px" append-to-body>
|
||||||
|
<el-scrollbar max-height="800px">
|
||||||
|
<el-form ref="roleRef" label-width="100px">
|
||||||
|
<el-form-item label="权限名称">
|
||||||
|
{{ formUserList.roleName }}<span v-if="formUserList.defaultStatus == 0">(默认)</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="备注">
|
<el-form-item label="用户列表">
|
||||||
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容"></el-input>
|
<el-row v-if="sysUsersArr.length > 0" style="width: 100%;margin-top: 20px;">
|
||||||
|
<el-col :span="24">
|
||||||
|
<div style="width: 100%;">
|
||||||
|
<el-input v-model="userListText" style="width: 100%" :placeholder="t('输入关键字进行用户列表过滤,支持空格隔开的多关键字匹配')" @input="handleUserListFilter" />
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<div class="accounts-about-scroll-container" v-if="sysUsersArr.length > 0">
|
||||||
|
<el-tag v-for="(item,index) in formUserList.sysUsers" :key="item.userId" type="info" style="margin-right: 10px;" >
|
||||||
|
{{ item.userName }}
|
||||||
|
</el-tag>
|
||||||
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</el-scrollbar>
|
</el-scrollbar>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="dialog-footer">
|
<div class="dialog-footer" style="display: flex;justify-content: center;">
|
||||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
<el-button @click="cancelUserList">关 闭</el-button>
|
||||||
<el-button @click="cancel">取 消</el-button>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<!-- 分配角色数据权限对话框 -->
|
<!-- 分配角色数据权限对话框 -->
|
||||||
<el-dialog :title="title" align-center v-model="openDataScope" width="500px" append-to-body>
|
<el-dialog :title="title" align-center v-model="openDataScope" width="500px" append-to-body>
|
||||||
<el-form :model="form" label-width="80px">
|
<el-form :model="form" label-width="80px">
|
||||||
|
|
@ -214,30 +218,19 @@
|
||||||
<el-input v-model="form.roleKey" :disabled="true" />
|
<el-input v-model="form.roleKey" :disabled="true" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="权限范围">
|
<el-form-item label="权限范围">
|
||||||
<el-select v-model="form.dataScope" @change="dataScopeSelectChange">
|
<el-select @change="dataScopeSelectChange">
|
||||||
<el-option
|
<el-option v-for="item in dataScopeOptions" :key="item.value" :label="item.label"
|
||||||
v-for="item in dataScopeOptions"
|
:value="item.value"></el-option>
|
||||||
:key="item.value"
|
|
||||||
:label="item.label"
|
|
||||||
:value="item.value"
|
|
||||||
></el-option>
|
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="数据权限" v-show="form.dataScope == 2">
|
<el-form-item label="数据权限" v-show="form.dataScope == 2">
|
||||||
<el-checkbox v-model="deptExpand" @change="handleCheckedTreeExpand($event, 'dept')">展开/折叠</el-checkbox>
|
<el-checkbox v-model="deptExpand" @change="handleCheckedTreeExpand($event, 'dept')">展开/折叠</el-checkbox>
|
||||||
<el-checkbox v-model="deptNodeAll" @change="handleCheckedTreeNodeAll($event, 'dept')">全选/全不选</el-checkbox>
|
<el-checkbox v-model="deptNodeAll" @change="handleCheckedTreeNodeAll($event, 'dept')">全选/全不选</el-checkbox>
|
||||||
<el-checkbox v-model="form.deptCheckStrictly" @change="handleCheckedTreeConnect($event, 'dept')">父子联动</el-checkbox>
|
<el-checkbox v-model="form.deptCheckStrictly"
|
||||||
<el-tree
|
@change="handleCheckedTreeConnect($event, 'dept')">父子联动</el-checkbox>
|
||||||
class="tree-border"
|
<el-tree class="tree-border" :data="deptOptions" show-checkbox default-expand-all ref="deptRef" node-key="id"
|
||||||
:data="deptOptions"
|
:check-strictly="!form.deptCheckStrictly" empty-text="加载中,请稍候"
|
||||||
show-checkbox
|
:props="{ label: 'label', children: 'children' }"></el-tree>
|
||||||
default-expand-all
|
|
||||||
ref="deptRef"
|
|
||||||
node-key="id"
|
|
||||||
:check-strictly="!form.deptCheckStrictly"
|
|
||||||
empty-text="加载中,请稍候"
|
|
||||||
:props="{ label: 'label', children: 'children' }"
|
|
||||||
></el-tree>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
|
|
@ -250,13 +243,16 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="User">
|
<script setup name="User">
|
||||||
import { addRole, changeRoleStatus, dataScope, delRole, getRole, listRole, updateRole, deptTreeSelect } from "@/api/system/role";
|
import { addRole, changeRoleStatus, dataScope, delRole, getRole, listRole, updateRole, deptTreeSelect, optionselect, getMenu, unallocatedUserList,authUserSelectAll,authUserCancelAll,authUserCancel,authRolecancelAll } from "@/api/system/role";
|
||||||
import { roleMenuTreeselect, treeselect as menuTreeselect } from "@/api/system/menu";
|
import { roleMenuTreeselect, treeselect as menuTreeselect } from "@/api/system/menu";
|
||||||
import Render from "./render.vue";
|
import NumberInput from "@/components/NumberInput";
|
||||||
|
import TableBatchOperate from '@/components/TableBatchOperate'; // 批量操作
|
||||||
|
import CheckboxSelect from "@/components/CheckboxSelect"; // 下拉框多/全选
|
||||||
|
import { nextTick, ref } from "vue";
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { proxy } = getCurrentInstance();
|
const { proxy } = getCurrentInstance();
|
||||||
const { sys_normal_disable } = proxy.useDict("sys_normal_disable");
|
const { sys_normal_disable } = proxy.useDict("sys_normal_disable");
|
||||||
|
import { getLocalStorage } from "@/utils/auth";
|
||||||
const roleList = ref([]);
|
const roleList = ref([]);
|
||||||
const open = ref(false);
|
const open = ref(false);
|
||||||
const loading = ref(true);
|
const loading = ref(true);
|
||||||
|
|
@ -276,6 +272,23 @@ const deptOptions = ref([]);
|
||||||
const openDataScope = ref(false);
|
const openDataScope = ref(false);
|
||||||
const menuRef = ref(null);
|
const menuRef = ref(null);
|
||||||
const deptRef = ref(null);
|
const deptRef = ref(null);
|
||||||
|
const filterText = ref('');
|
||||||
|
const modifyStatus = ref('add');
|
||||||
|
const accountLinking = ref([]);
|
||||||
|
const accountOptions = ref([]);
|
||||||
|
const sysUsersArr = ref([]);
|
||||||
|
const formUserList = ref({});
|
||||||
|
const oldForm = shallowRef({ });
|
||||||
|
const queryParamsList = ref([{
|
||||||
|
label: proxy.t('角色名称'),
|
||||||
|
value: 'roleName',
|
||||||
|
}, {
|
||||||
|
label: proxy.t('后台账户'),
|
||||||
|
value: 'account',
|
||||||
|
}, {
|
||||||
|
label: proxy.t('后台呢称'),
|
||||||
|
value: 'nickName',
|
||||||
|
}])
|
||||||
|
|
||||||
/** 数据范围选项*/
|
/** 数据范围选项*/
|
||||||
const dataScopeOptions = ref([
|
const dataScopeOptions = ref([
|
||||||
|
|
@ -289,7 +302,8 @@ const data = reactive({
|
||||||
form: {},
|
form: {},
|
||||||
queryParams: {
|
queryParams: {
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 10,
|
pageSize: 20,
|
||||||
|
searchType: 'roleName',
|
||||||
roleName: undefined,
|
roleName: undefined,
|
||||||
roleKey: undefined,
|
roleKey: undefined,
|
||||||
status: undefined
|
status: undefined
|
||||||
|
|
@ -297,12 +311,73 @@ const data = reactive({
|
||||||
rules: {
|
rules: {
|
||||||
roleName: [{ required: true, message: "角色名称不能为空", trigger: "blur" }],
|
roleName: [{ required: true, message: "角色名称不能为空", trigger: "blur" }],
|
||||||
roleKey: [{ required: true, message: "权限字符不能为空", trigger: "blur" }],
|
roleKey: [{ required: true, message: "权限字符不能为空", trigger: "blur" }],
|
||||||
roleSort: [{ required: true, message: "角色顺序不能为空", trigger: "blur" }]
|
roleSort: [{ required: true, message: "角色顺序不能为空", trigger: "blur" }],
|
||||||
|
roleLevel: [{ required: true, message: "角色级别不能为空", trigger: "blur" }],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const { queryParams, form, rules } = toRefs(data);
|
const { queryParams, form, rules } = toRefs(data);
|
||||||
|
// 批量操作
|
||||||
|
const tableRef = ref(),
|
||||||
|
isAllSelection = ref(false), // 是否全选
|
||||||
|
selectionData = ref([]), // 选中的表格数据
|
||||||
|
batchOpType = ref(''); // 选中的批量操作类型
|
||||||
|
// 批量操作选项
|
||||||
|
const opTypeOptions = ref([
|
||||||
|
{ label: proxy.t('批量清除关联账户'), value: 'update' },
|
||||||
|
{ label: proxy.t('批量删除'), value: 'ignore' },
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 勾选表格
|
||||||
|
const tableSelect = (val) => {
|
||||||
|
selectionData.value = val;
|
||||||
|
// 是否全选中
|
||||||
|
if (val.length == roleList.value.length) {
|
||||||
|
isAllSelection.value = true;
|
||||||
|
} else {
|
||||||
|
isAllSelection.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 全选表格
|
||||||
|
const allSelectionChange = () => {
|
||||||
|
tableRef.value.toggleAllSelection();
|
||||||
|
}
|
||||||
|
// 选择批量数据操作类型
|
||||||
|
const opTypeChange = () => {
|
||||||
|
if (batchOpType.value === 'ignore') {
|
||||||
|
const params = selectionData.value.map(i => i.roleId); // 选中的id集合
|
||||||
|
proxy.$modal.confirm(proxy.t('确认批量删除已选的' + params.length + '条记录吗?')).then(() => {
|
||||||
|
loading.value = true;
|
||||||
|
delRole(params).then(res => {
|
||||||
|
loading.value = false;
|
||||||
|
batchOpType.value = '';
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('操作成功!'));
|
||||||
|
handleQuery();
|
||||||
|
}).catch(() => {
|
||||||
|
batchOpType.value = '';
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}).catch(() => {
|
||||||
|
batchOpType.value = '';
|
||||||
|
});
|
||||||
|
}else if (batchOpType.value === 'update') {
|
||||||
|
const params = selectionData.value.map(i => i.roleId); // 选中的id集合
|
||||||
|
proxy.$modal.confirm(proxy.t(`确认清除这些权限的关联账号(共${params.length}个)?`)).then(() => {
|
||||||
|
loading.value = true;
|
||||||
|
authRolecancelAll({roleIds: params}).then(res => {
|
||||||
|
loading.value = false;
|
||||||
|
batchOpType.value = '';
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('操作成功!'));
|
||||||
|
handleQuery();
|
||||||
|
}).catch(() => {
|
||||||
|
batchOpType.value = '';
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}).catch(() => {
|
||||||
|
batchOpType.value = '';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
/** 查询角色列表 */
|
/** 查询角色列表 */
|
||||||
function getList() {
|
function getList() {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
|
|
@ -313,6 +388,31 @@ function getList() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 监听输入框,调用 el-tree 的 filter
|
||||||
|
watch(filterText, (val) => {
|
||||||
|
menuRef.value && menuRef.value.filter(val);
|
||||||
|
});
|
||||||
|
const rowSelectable = (row, index) => {
|
||||||
|
return row.defaultStatus == 0 ? false:true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const openUserList = ref(false);
|
||||||
|
//打开用户列表
|
||||||
|
const handleUserListClick = (row) => {
|
||||||
|
openUserList.value = true;
|
||||||
|
sysUsersArr.value = row.sysUsers;
|
||||||
|
formUserList.value = row;
|
||||||
|
};
|
||||||
|
const cancelUserList = () => {
|
||||||
|
openUserList.value = false;
|
||||||
|
}
|
||||||
|
// 节点过滤方法
|
||||||
|
const filterNode = (value, data) => {
|
||||||
|
if (!value) return true;
|
||||||
|
// 支持多关键字,用空格分隔
|
||||||
|
const keywords = value.split(" ");
|
||||||
|
return keywords.every((kw) => data.label.includes(kw));
|
||||||
|
};
|
||||||
/** 搜索按钮操作 */
|
/** 搜索按钮操作 */
|
||||||
function handleQuery() {
|
function handleQuery() {
|
||||||
queryParams.value.pageNum = 1;
|
queryParams.value.pageNum = 1;
|
||||||
|
|
@ -334,7 +434,7 @@ function handleDelete(row) {
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
getList();
|
getList();
|
||||||
proxy.$modal.msgSuccess("删除成功");
|
proxy.$modal.msgSuccess("删除成功");
|
||||||
}).catch(() => {});
|
}).catch(() => { });
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 导出按钮操作 */
|
/** 导出按钮操作 */
|
||||||
|
|
@ -382,14 +482,115 @@ function handleCommand(command, row) {
|
||||||
function handleAuthUser(row) {
|
function handleAuthUser(row) {
|
||||||
router.push("/system/role-auth/user/" + row.roleId);
|
router.push("/system/role-auth/user/" + row.roleId);
|
||||||
}
|
}
|
||||||
|
const countTree = ref(0);
|
||||||
/** 查询菜单树结构 */
|
/** 查询菜单树结构 */
|
||||||
function getMenuTreeselect() {
|
function getMenuTreeselect() {
|
||||||
menuTreeselect().then(response => {
|
menuTreeselect().then(response => {
|
||||||
|
countTree.value = response.count;
|
||||||
menuOptions.value = response.data;
|
menuOptions.value = response.data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
const showLoding = ref(true);
|
||||||
|
/** 获取用户列表 */
|
||||||
|
const getunallocatedUserList = (roleId) => {
|
||||||
|
unallocatedUserList({roleId: roleId }).then(response => {
|
||||||
|
accountOptions.value = response.data.map(item => {
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
label: item.userName,
|
||||||
|
value: item.userId
|
||||||
|
}
|
||||||
|
});
|
||||||
|
showLoding.value = false;
|
||||||
|
nextTick(() => {
|
||||||
|
showLoding.value = true;
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
//添加关联账户
|
||||||
|
const handleAddAccount = () => {
|
||||||
|
if (accountLinking.value.length == 0){
|
||||||
|
proxy.$modal.msgError(proxy.t('请选择要关联的账户'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
proxy.$modal.confirm('请确认此操作,是否继续?').then(function () {
|
||||||
|
let obj = {
|
||||||
|
roleId:form.value.roleId,
|
||||||
|
userIds:accountLinking.value
|
||||||
|
}
|
||||||
|
return authUserSelectAll(obj);
|
||||||
|
}).then(() => {
|
||||||
|
getRole(form.value.roleId).then(response => {
|
||||||
|
form.value = response.data;
|
||||||
|
sysUsersArr.value = response.data.sysUsers;
|
||||||
|
});
|
||||||
|
accountLinking.value = [];
|
||||||
|
getunallocatedUserList(form.value.roleId);
|
||||||
|
handleQuery();
|
||||||
|
proxy.$modal.msgSuccess("关联成功");
|
||||||
|
}).catch(() => { });
|
||||||
|
}
|
||||||
|
const userNameText = ref('');
|
||||||
|
//片段2
|
||||||
|
const handleFilter = () => {
|
||||||
|
if (!userNameText.value.trim()) return form.value.sysUsers = sysUsersArr.value
|
||||||
|
|
||||||
|
const keywords = userNameText.value.trim().split(/\s+/) // 支持空格分隔多个关键词
|
||||||
|
form.value.sysUsers = sysUsersArr.value.filter(user =>
|
||||||
|
keywords.every(k => user.userName.includes(k))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
const userListText = ref('');
|
||||||
|
//
|
||||||
|
const handleUserListFilter = () => {
|
||||||
|
if (!userListText.value.trim()) return formUserList.value.sysUsers = sysUsersArr.value;
|
||||||
|
const keywords = userListText.value.trim().split(/\s+/) // 支持空格分隔多个关键词
|
||||||
|
formUserList.value.sysUsers = sysUsersArr.value.filter(user =>
|
||||||
|
keywords.every(k => user.userName.includes(k))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
//移出关联账户
|
||||||
|
const handleRemoveAccount = () => {
|
||||||
|
if (form.value.sysUsers.length == 0){
|
||||||
|
proxy.$modal.msgError("请选择要移出的账户");
|
||||||
|
return
|
||||||
|
}
|
||||||
|
proxy.$modal.confirm('请确认此操作,是否继续?').then(function () {
|
||||||
|
let userIds = form.value.sysUsers.map(item => item.userId);
|
||||||
|
let obj = {
|
||||||
|
roleId:form.value.roleId,
|
||||||
|
userIds:userIds
|
||||||
|
}
|
||||||
|
return authUserCancelAll(obj);
|
||||||
|
}).then(() => {
|
||||||
|
getRole(form.value.roleId).then(response => {
|
||||||
|
form.value = response.data;
|
||||||
|
sysUsersArr.value = response.data.sysUsers;
|
||||||
|
});
|
||||||
|
handleQuery();
|
||||||
|
getunallocatedUserList(form.value.roleId);
|
||||||
|
proxy.$modal.msgSuccess("移出成功");
|
||||||
|
}).catch(() => { });
|
||||||
|
}
|
||||||
|
//单个移出关联账户
|
||||||
|
const handleClose = (row) => {
|
||||||
|
proxy.$modal.confirm('请确认此操作,是否继续?').then(function () {
|
||||||
|
let userIds = form.value.sysUsers.map(item => item.userId);
|
||||||
|
let obj = {
|
||||||
|
roleId:form.value.roleId,
|
||||||
|
userId:row.userId
|
||||||
|
}
|
||||||
|
return authUserCancel(obj);
|
||||||
|
}).then(() => {
|
||||||
|
getRole(form.value.roleId).then(response => {
|
||||||
|
form.value = response.data;
|
||||||
|
sysUsersArr.value = response.data.sysUsers;
|
||||||
|
});
|
||||||
|
handleQuery();
|
||||||
|
getunallocatedUserList(form.value.roleId);
|
||||||
|
proxy.$modal.msgSuccess("移出成功");
|
||||||
|
}).catch(() => { });
|
||||||
|
}
|
||||||
/** 所有部门节点数据 */
|
/** 所有部门节点数据 */
|
||||||
function getDeptAllCheckedKeys() {
|
function getDeptAllCheckedKeys() {
|
||||||
// 目前被选中的部门节点
|
// 目前被选中的部门节点
|
||||||
|
|
@ -423,15 +624,94 @@ function reset() {
|
||||||
};
|
};
|
||||||
proxy.resetForm("roleRef");
|
proxy.resetForm("roleRef");
|
||||||
}
|
}
|
||||||
|
const roleOptions = ref([]);
|
||||||
/** 添加角色 */
|
/** 添加角色 */
|
||||||
function handleAdd() {
|
function handleAdd() {
|
||||||
reset();
|
reset();
|
||||||
getMenuTreeselect();
|
getMenuTreeselect();
|
||||||
open.value = true;
|
open.value = true;
|
||||||
title.value = "添加角色";
|
title.value = "新增角色";
|
||||||
|
modifyStatus.value = 'add';
|
||||||
|
form.value.dataScope = getLocalStorage('userInfo')?.nickName;
|
||||||
|
optionselect({}).then(response => {
|
||||||
|
roleOptions.value = response.data.map(item => {
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
label: item.roleName,
|
||||||
|
value: item.roleId
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
const handleDetail = (row) => {
|
||||||
|
reset();
|
||||||
|
const roleId = row.roleId || ids.value;
|
||||||
|
const roleMenu = getRoleMenuTreeselect(roleId);
|
||||||
|
getRole(roleId).then(response => {
|
||||||
|
form.value = response.data;
|
||||||
|
form.value.roleSort = Number(form.value.roleSort);
|
||||||
|
open.value = true;
|
||||||
|
nextTick(() => {
|
||||||
|
roleMenu.then((res) => {
|
||||||
|
let checkedKeys = res.checkedKeys;
|
||||||
|
checkedKeys.forEach((v) => {
|
||||||
|
nextTick(() => {
|
||||||
|
menuRef.value.setChecked(v, true, false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
form.value.dataScope = response.data.roleScope;
|
||||||
|
modifyStatus.value = 'detail';
|
||||||
|
title.value = "角色详情";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 角色管理
|
||||||
|
const handleManage = (row) => {
|
||||||
|
reset();
|
||||||
|
const roleId = row.roleId || ids.value;
|
||||||
|
const roleMenu = getRoleMenuTreeselect(roleId);
|
||||||
|
getunallocatedUserList(roleId);
|
||||||
|
getRole(roleId).then(response => {
|
||||||
|
form.value = response.data;
|
||||||
|
sysUsersArr.value = response.data.sysUsers;
|
||||||
|
form.value.roleSort = Number(form.value.roleSort);
|
||||||
|
open.value = true;
|
||||||
|
nextTick(() => {
|
||||||
|
roleMenu.then((res) => {
|
||||||
|
let checkedKeys = res.checkedKeys;
|
||||||
|
checkedKeys.forEach((v) => {
|
||||||
|
nextTick(() => {
|
||||||
|
menuRef.value.setChecked(v, true, false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
form.value.dataScope = response.data.roleScope;
|
||||||
|
modifyStatus.value = 'Manage';
|
||||||
|
title.value = "角色管理";
|
||||||
|
form.value.roleId = row.roleId;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
//复制权限
|
||||||
|
const changeMenu = (roleId) => {
|
||||||
|
if (roleId) {
|
||||||
|
getMenu(roleId).then(response => {
|
||||||
|
let checkedKeys = response.data;
|
||||||
|
checkedKeys.forEach((v) => {
|
||||||
|
nextTick(() => {
|
||||||
|
menuRef.value.setChecked(v, true, false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
menuRef.value.setCheckedKeys([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
/** 修改角色 */
|
/** 修改角色 */
|
||||||
function handleUpdate(row) {
|
function handleUpdate(row) {
|
||||||
reset();
|
reset();
|
||||||
|
|
@ -451,6 +731,13 @@ function handleUpdate(row) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
form.value.menuIds = getMenuAllCheckedKeys();
|
||||||
|
oldForm.value = JSON.stringify(form.value);
|
||||||
|
}, 600);
|
||||||
|
form.value.dataScope = response.data.roleScope;
|
||||||
|
modifyStatus.value = 'edit';
|
||||||
title.value = "修改角色";
|
title.value = "修改角色";
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -470,14 +757,25 @@ function getDeptTree(roleId) {
|
||||||
return response;
|
return response;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
const defaultExpandAll = ref(false);
|
||||||
|
const defaultExpandShow = ref(true);
|
||||||
/** 树权限(展开/折叠)*/
|
/** 树权限(展开/折叠)*/
|
||||||
function handleCheckedTreeExpand(value, type) {
|
function handleCheckedTreeExpand(value, type) {
|
||||||
if (type == "menu") {
|
if (type == "menu") {
|
||||||
let treeList = menuOptions.value;
|
|
||||||
for (let i = 0; i < treeList.length; i++) {
|
// let treeList = menuOptions.value;
|
||||||
menuRef.value.store.nodesMap[treeList[i].id].expanded = value;
|
// for (let i = 0; i < treeList.length; i++) {
|
||||||
|
// menuRef.value.store.nodesMap[treeList[i].id].expanded = value;
|
||||||
|
// }
|
||||||
|
if (!defaultExpandAll.value) {
|
||||||
|
defaultExpandAll.value = true;
|
||||||
|
} else {
|
||||||
|
defaultExpandAll.value = false;
|
||||||
}
|
}
|
||||||
|
defaultExpandShow.value = false;
|
||||||
|
nextTick(() => {
|
||||||
|
defaultExpandShow.value = true;
|
||||||
|
});
|
||||||
} else if (type == "dept") {
|
} else if (type == "dept") {
|
||||||
let treeList = deptOptions.value;
|
let treeList = deptOptions.value;
|
||||||
for (let i = 0; i < treeList.length; i++) {
|
for (let i = 0; i < treeList.length; i++) {
|
||||||
|
|
@ -520,14 +818,32 @@ function submitForm() {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
if (form.value.roleId != undefined) {
|
if (form.value.roleId != undefined) {
|
||||||
form.value.menuIds = getMenuAllCheckedKeys();
|
form.value.menuIds = getMenuAllCheckedKeys();
|
||||||
updateRole(form.value).then(response => {
|
|
||||||
|
if (JSON.stringify(form.value) != oldForm.value) {
|
||||||
|
let params = {
|
||||||
|
menuIds: form.value.menuIds,
|
||||||
|
roleName: form.value.roleName,
|
||||||
|
remark: form.value.remark,
|
||||||
|
roleSort: form.value.roleSort,
|
||||||
|
roleId: form.value.roleId,
|
||||||
|
};
|
||||||
|
updateRole(params).then(response => {
|
||||||
proxy.$modal.msgSuccess("修改成功");
|
proxy.$modal.msgSuccess("修改成功");
|
||||||
open.value = false;
|
open.value = false;
|
||||||
getList();
|
getList();
|
||||||
});
|
});
|
||||||
|
}else{
|
||||||
|
open.value = false;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
form.value.menuIds = getMenuAllCheckedKeys();
|
form.value.menuIds = getMenuAllCheckedKeys();
|
||||||
addRole(form.value).then(response => {
|
let params = {
|
||||||
|
menuIds: form.value.menuIds,
|
||||||
|
roleName: form.value.roleName,
|
||||||
|
remark: form.value.remark,
|
||||||
|
roleSort: form.value.roleSort,
|
||||||
|
};
|
||||||
|
addRole(params).then(response => {
|
||||||
proxy.$modal.msgSuccess("新增成功");
|
proxy.$modal.msgSuccess("新增成功");
|
||||||
open.value = false;
|
open.value = false;
|
||||||
getList();
|
getList();
|
||||||
|
|
@ -587,8 +903,10 @@ function cancelDataScope() {
|
||||||
openDataScope.value = false;
|
openDataScope.value = false;
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
//初始化
|
||||||
getList();
|
onMounted(() => {
|
||||||
|
getList();
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.custom-node-row {
|
.custom-node-row {
|
||||||
|
|
@ -617,6 +935,7 @@ getList();
|
||||||
width: 240px;
|
width: 240px;
|
||||||
color: #aaa;
|
color: #aaa;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table {
|
.table {
|
||||||
// padding: 20px;
|
// padding: 20px;
|
||||||
// min-height: 88vh;
|
// min-height: 88vh;
|
||||||
|
|
@ -624,39 +943,51 @@ getList();
|
||||||
width: 100%;
|
width: 100%;
|
||||||
// margin: 20px;
|
// margin: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu-list {
|
.menu-list {
|
||||||
::v-deep .el-tree {
|
::v-deep .el-tree {
|
||||||
border-top: 1px solid #ebeef5;
|
border-top: 1px solid #ebeef5;
|
||||||
border-left: 1px solid #ebeef5;
|
border-left: 1px solid #ebeef5;
|
||||||
border-right: 1px solid #ebeef5;
|
border-right: 1px solid #ebeef5;
|
||||||
|
|
||||||
.el-tree-node__expand-icon {
|
.el-tree-node__expand-icon {
|
||||||
// display: none !important;
|
// display: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-tree-node {
|
.el-tree-node {
|
||||||
|
|
||||||
&.is-expanded,
|
&.is-expanded,
|
||||||
&.is-current,
|
&.is-current,
|
||||||
&.is-focusable {
|
&.is-focusable {
|
||||||
background-color: transparent !important;
|
background-color: transparent !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-tree-node__content {
|
.el-tree-node__content {
|
||||||
background-color: transparent !important;
|
background-color: transparent !important;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: transparent !important;
|
background-color: transparent !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
> .el-tree-node {
|
|
||||||
|
>.el-tree-node {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
border-bottom: 1px solid #ebeef5;
|
border-bottom: 1px solid #ebeef5;
|
||||||
position: relative;
|
position: relative;
|
||||||
> .el-tree-node__content {
|
padding-top: 10px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
|
||||||
|
>.el-tree-node__content {
|
||||||
width: 300px;
|
width: 300px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
padding-left: 20px !important;
|
padding-left: 20px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-tree-node__children {
|
.el-tree-node__children {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
&::after {
|
&::after {
|
||||||
content: ' ';
|
content: ' ';
|
||||||
display: block;
|
display: block;
|
||||||
|
|
@ -667,6 +998,7 @@ getList();
|
||||||
left: 0px;
|
left: 0px;
|
||||||
top: 0px;
|
top: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-tree-node {
|
.el-tree-node {
|
||||||
// width: 350px;
|
// width: 350px;
|
||||||
padding: 10px 0px;
|
padding: 10px 0px;
|
||||||
|
|
@ -678,4 +1010,16 @@ getList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.accounts-about-scroll-container {
|
||||||
|
align-items: flex-start;
|
||||||
|
content-visibility: auto;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: flex-start;
|
||||||
|
margin-top: 10px;
|
||||||
|
max-height: 100px;
|
||||||
|
overflow: auto;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -1,78 +0,0 @@
|
||||||
<template>
|
|
||||||
<el-dialog
|
|
||||||
v-model="dialogVisible"
|
|
||||||
align-center
|
|
||||||
title="新增权限"
|
|
||||||
width="800px"
|
|
||||||
:before-close="handleClose"
|
|
||||||
>
|
|
||||||
<div class="permission-dialog">
|
|
||||||
<PermissionTreeTable ref="treeTableRef" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<template #footer>
|
|
||||||
<div class="dialog-footer">
|
|
||||||
<el-button @click="handleCancel">取消</el-button>
|
|
||||||
<el-button type="primary" @click="handleConfirm">确认</el-button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-dialog>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref, computed } from 'vue'
|
|
||||||
import PermissionTreeTable from './render.vue'
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
modelValue: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
roleId: {
|
|
||||||
type: [String, Number],
|
|
||||||
default: null
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const emit = defineEmits(['update:modelValue', 'confirm'])
|
|
||||||
|
|
||||||
const treeTableRef = ref()
|
|
||||||
|
|
||||||
const dialogVisible = computed({
|
|
||||||
get: () => props.modelValue,
|
|
||||||
set: (val) => emit('update:modelValue', val)
|
|
||||||
})
|
|
||||||
|
|
||||||
// 获取选中的权限数据
|
|
||||||
const getSelectedPermissions = () => {
|
|
||||||
if (treeTableRef.value) {
|
|
||||||
return treeTableRef.value.getCheckedData()
|
|
||||||
}
|
|
||||||
return { checkedNodes: [], checkedPermissions: {} }
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleClose = () => {
|
|
||||||
dialogVisible.value = false
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleCancel = () => {
|
|
||||||
dialogVisible.value = false
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleConfirm = () => {
|
|
||||||
const selectedData = getSelectedPermissions()
|
|
||||||
emit('confirm', selectedData)
|
|
||||||
dialogVisible.value = false
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.permission-dialog {
|
|
||||||
max-height: 500px;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dialog-footer {
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,195 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="permission-example">
|
|
||||||
<div class="header">
|
|
||||||
<h2>权限树使用示例</h2>
|
|
||||||
<el-button type="primary" @click="showPermissionDialog">
|
|
||||||
新增权限
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 权限对话框 -->
|
|
||||||
<PermissionDialog
|
|
||||||
v-model="dialogVisible"
|
|
||||||
:role-id="currentRoleId"
|
|
||||||
@confirm="handlePermissionConfirm"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!-- 直接展示权限树状表格 -->
|
|
||||||
<div class="tree-container">
|
|
||||||
<h3>权限树状表格展示:</h3>
|
|
||||||
<PermissionTreeTable ref="treeTableRef" />
|
|
||||||
|
|
||||||
<div class="action-buttons">
|
|
||||||
<el-button @click="getSelectedData">获取选中数据</el-button>
|
|
||||||
<el-button type="primary" @click="savePermissions">保存权限</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 已选权限展示 -->
|
|
||||||
<div v-if="selectedData" class="selected-permissions">
|
|
||||||
<h3>已选择的权限:</h3>
|
|
||||||
|
|
||||||
<div class="permission-summary">
|
|
||||||
<div class="section">
|
|
||||||
<h4>选中的节点:</h4>
|
|
||||||
<div class="node-list">
|
|
||||||
<el-tag
|
|
||||||
v-for="node in selectedData.checkedNodes"
|
|
||||||
:key="node.id"
|
|
||||||
size="small"
|
|
||||||
class="node-tag"
|
|
||||||
>
|
|
||||||
{{ node.label }}
|
|
||||||
</el-tag>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="section">
|
|
||||||
<h4>选中的权限:</h4>
|
|
||||||
<div v-for="(perms, nodeId) in selectedData.checkedPermissions" :key="nodeId" class="node-permissions">
|
|
||||||
<strong>节点 {{ nodeId }}:</strong>
|
|
||||||
<el-tag
|
|
||||||
v-for="perm in perms"
|
|
||||||
:key="perm.key"
|
|
||||||
size="small"
|
|
||||||
type="success"
|
|
||||||
class="perm-tag"
|
|
||||||
>
|
|
||||||
{{ perm.label }}
|
|
||||||
</el-tag>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref } from 'vue'
|
|
||||||
import PermissionDialog from './permission-dialog.vue'
|
|
||||||
import PermissionTreeTable from './render.vue'
|
|
||||||
|
|
||||||
const dialogVisible = ref(false)
|
|
||||||
const currentRoleId = ref(1)
|
|
||||||
const selectedData = ref(null)
|
|
||||||
const treeTableRef = ref()
|
|
||||||
|
|
||||||
const showPermissionDialog = () => {
|
|
||||||
dialogVisible.value = true
|
|
||||||
}
|
|
||||||
|
|
||||||
const handlePermissionConfirm = (data) => {
|
|
||||||
console.log('确认选择的权限:', data)
|
|
||||||
selectedData.value = data
|
|
||||||
|
|
||||||
// 这里可以调用API保存权限
|
|
||||||
// await saveRolePermissions(currentRoleId.value, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
const getSelectedData = () => {
|
|
||||||
if (treeTableRef.value) {
|
|
||||||
const data = treeTableRef.value.getCheckedData()
|
|
||||||
selectedData.value = data
|
|
||||||
console.log('当前选中的数据:', data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const savePermissions = async () => {
|
|
||||||
const data = getSelectedData()
|
|
||||||
if (data) {
|
|
||||||
try {
|
|
||||||
// 这里调用保存权限的API
|
|
||||||
// await saveRolePermissions(currentRoleId.value, data)
|
|
||||||
console.log('保存权限成功:', data)
|
|
||||||
// 显示成功消息
|
|
||||||
// ElMessage.success('权限保存成功')
|
|
||||||
} catch (error) {
|
|
||||||
console.error('保存权限失败:', error)
|
|
||||||
// ElMessage.error('权限保存失败')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.permission-example {
|
|
||||||
padding: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tree-container {
|
|
||||||
margin-bottom: 30px;
|
|
||||||
padding: 20px;
|
|
||||||
border: 1px solid #e4e7ed;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-buttons {
|
|
||||||
margin-top: 20px;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-buttons .el-button {
|
|
||||||
margin-left: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.selected-permissions {
|
|
||||||
margin-top: 20px;
|
|
||||||
padding: 20px;
|
|
||||||
background: #f9f9f9;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.permission-summary {
|
|
||||||
margin-top: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section h4 {
|
|
||||||
margin: 0 0 10px 0;
|
|
||||||
color: #303133;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
.node-list {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.node-permissions {
|
|
||||||
margin-bottom: 15px;
|
|
||||||
padding: 10px;
|
|
||||||
background: white;
|
|
||||||
border-radius: 4px;
|
|
||||||
border: 1px solid #e4e7ed;
|
|
||||||
}
|
|
||||||
|
|
||||||
.node-permissions strong {
|
|
||||||
display: block;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
color: #303133;
|
|
||||||
font-size: 13px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.node-tag,
|
|
||||||
.perm-tag {
|
|
||||||
margin-right: 8px;
|
|
||||||
margin-bottom: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.node-tag {
|
|
||||||
background-color: #409eff;
|
|
||||||
border-color: #409eff;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,588 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="table">
|
|
||||||
<!-- default-expand-all 默认展开全部数据 -->
|
|
||||||
<!-- expand-on-click-node 只有点击箭头才会收缩节点 -->
|
|
||||||
<!-- check-on-click-node 点击文本选中 -->
|
|
||||||
<!-- show-checkbox 复选框 -->
|
|
||||||
<div class="menu-list">
|
|
||||||
<el-tree ref="tree" :data="list" default-expand-all :expand-on-click-node='false' check-on-click-node show-checkbox node-key="menuId" :props="defaultProps"></el-tree>
|
|
||||||
</div>
|
|
||||||
<el-button @click="getCheckedKeys">通过 key 获取</el-button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
data () {
|
|
||||||
return {
|
|
||||||
list: [
|
|
||||||
{
|
|
||||||
"menuId": 1,
|
|
||||||
"menuName": "首页(首页)",
|
|
||||||
"menuCode": "首页",
|
|
||||||
"parentId": 0,
|
|
||||||
"orderNum": 0,
|
|
||||||
"path": "/page",
|
|
||||||
"component": null,
|
|
||||||
"query": null,
|
|
||||||
"isFrame": 0,
|
|
||||||
"isCache": 0,
|
|
||||||
"menuType": 0,
|
|
||||||
"visible": 1,
|
|
||||||
"perms": null,
|
|
||||||
"icon": "iconfont icon-shouye",
|
|
||||||
"status": 1,
|
|
||||||
"remark": null,
|
|
||||||
"roleId": null,
|
|
||||||
"selected": true,
|
|
||||||
"level": 1,
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"menuId": 2,
|
|
||||||
"menuName": "首页(首页)",
|
|
||||||
"menuCode": "首页",
|
|
||||||
"parentId": 1,
|
|
||||||
"orderNum": 1,
|
|
||||||
"path": "/welcome",
|
|
||||||
"component": null,
|
|
||||||
"query": null,
|
|
||||||
"isFrame": 0,
|
|
||||||
"isCache": 0,
|
|
||||||
"menuType": 1,
|
|
||||||
"visible": 1,
|
|
||||||
"perms": null,
|
|
||||||
"icon": "",
|
|
||||||
"status": 1,
|
|
||||||
"remark": null,
|
|
||||||
"roleId": null,
|
|
||||||
"selected": true,
|
|
||||||
"level": 2,
|
|
||||||
"children": null
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"menuId": 3,
|
|
||||||
"menuName": "随访数据查询(随访数据查询)",
|
|
||||||
"menuCode": "随访数据查询",
|
|
||||||
"parentId": 0,
|
|
||||||
"orderNum": 1,
|
|
||||||
"path": "/followUpDataQuery",
|
|
||||||
"component": null,
|
|
||||||
"query": null,
|
|
||||||
"isFrame": 0,
|
|
||||||
"isCache": 0,
|
|
||||||
"menuType": 0,
|
|
||||||
"visible": 1,
|
|
||||||
"perms": null,
|
|
||||||
"icon": "iconfont icon-shengwuxuejiance",
|
|
||||||
"status": 1,
|
|
||||||
"remark": null,
|
|
||||||
"roleId": null,
|
|
||||||
"selected": true,
|
|
||||||
"level": 1,
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"menuId": 4,
|
|
||||||
"menuName": "随访数据查询(随访数据查询)",
|
|
||||||
"menuCode": "随访数据查询",
|
|
||||||
"parentId": 3,
|
|
||||||
"orderNum": 1,
|
|
||||||
"path": "index",
|
|
||||||
"component": null,
|
|
||||||
"query": null,
|
|
||||||
"isFrame": 0,
|
|
||||||
"isCache": 0,
|
|
||||||
"menuType": 1,
|
|
||||||
"visible": 1,
|
|
||||||
"perms": null,
|
|
||||||
"icon": "",
|
|
||||||
"status": 1,
|
|
||||||
"remark": null,
|
|
||||||
"roleId": null,
|
|
||||||
"selected": true,
|
|
||||||
"level": 2,
|
|
||||||
"children": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"menuId": 5,
|
|
||||||
"menuName": "随访详情(随访详情)",
|
|
||||||
"menuCode": "随访详情",
|
|
||||||
"parentId": 3,
|
|
||||||
"orderNum": 2,
|
|
||||||
"path": "detail",
|
|
||||||
"component": null,
|
|
||||||
"query": null,
|
|
||||||
"isFrame": 0,
|
|
||||||
"isCache": 0,
|
|
||||||
"menuType": 1,
|
|
||||||
"visible": 1,
|
|
||||||
"perms": null,
|
|
||||||
"icon": "",
|
|
||||||
"status": 1,
|
|
||||||
"remark": null,
|
|
||||||
"roleId": null,
|
|
||||||
"selected": true,
|
|
||||||
"level": 2,
|
|
||||||
"children": null
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"menuId": 21,
|
|
||||||
"menuName": "此单名称(11)",
|
|
||||||
"menuCode": "11",
|
|
||||||
"parentId": 0,
|
|
||||||
"orderNum": 1,
|
|
||||||
"path": "请问请问饿```",
|
|
||||||
"component": null,
|
|
||||||
"query": null,
|
|
||||||
"isFrame": 0,
|
|
||||||
"isCache": 0,
|
|
||||||
"menuType": 0,
|
|
||||||
"visible": 1,
|
|
||||||
"perms": null,
|
|
||||||
"icon": "321",
|
|
||||||
"status": 1,
|
|
||||||
"remark": null,
|
|
||||||
"roleId": null,
|
|
||||||
"selected": true,
|
|
||||||
"level": 1,
|
|
||||||
// "children": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"menuId": 6,
|
|
||||||
"menuName": "调查数据查询(调查数据查询)",
|
|
||||||
"menuCode": "调查数据查询",
|
|
||||||
"parentId": 0,
|
|
||||||
"orderNum": 2,
|
|
||||||
"path": "/surveyDataQuery",
|
|
||||||
"component": null,
|
|
||||||
"query": null,
|
|
||||||
"isFrame": 0,
|
|
||||||
"isCache": 0,
|
|
||||||
"menuType": 0,
|
|
||||||
"visible": 1,
|
|
||||||
"perms": null,
|
|
||||||
"icon": "iconfont icon-shaichaxinxichaxun",
|
|
||||||
"status": 1,
|
|
||||||
"remark": null,
|
|
||||||
"roleId": null,
|
|
||||||
"selected": true,
|
|
||||||
"level": 1,
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"menuId": 7,
|
|
||||||
"menuName": "调查数据查询(调查数据查询)",
|
|
||||||
"menuCode": "调查数据查询",
|
|
||||||
"parentId": 6,
|
|
||||||
"orderNum": 1,
|
|
||||||
"path": "index",
|
|
||||||
"component": null,
|
|
||||||
"query": null,
|
|
||||||
"isFrame": 0,
|
|
||||||
"isCache": 0,
|
|
||||||
"menuType": 1,
|
|
||||||
"visible": 1,
|
|
||||||
"perms": null,
|
|
||||||
"icon": "",
|
|
||||||
"status": 1,
|
|
||||||
"remark": null,
|
|
||||||
"roleId": null,
|
|
||||||
"selected": true,
|
|
||||||
"level": 2,
|
|
||||||
"children": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"menuId": 8,
|
|
||||||
"menuName": "新建问卷(新建问卷)",
|
|
||||||
"menuCode": "新建问卷",
|
|
||||||
"parentId": 6,
|
|
||||||
"orderNum": 2,
|
|
||||||
"path": "evaluationreport",
|
|
||||||
"component": null,
|
|
||||||
"query": null,
|
|
||||||
"isFrame": 0,
|
|
||||||
"isCache": 0,
|
|
||||||
"menuType": 1,
|
|
||||||
"visible": 1,
|
|
||||||
"perms": null,
|
|
||||||
"icon": "",
|
|
||||||
"status": 1,
|
|
||||||
"remark": null,
|
|
||||||
"roleId": null,
|
|
||||||
"selected": true,
|
|
||||||
"level": 2,
|
|
||||||
"children": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"menuId": 9,
|
|
||||||
"menuName": "随访详情(随访详情)",
|
|
||||||
"menuCode": "随访详情",
|
|
||||||
"parentId": 6,
|
|
||||||
"orderNum": 3,
|
|
||||||
"path": "evaluationlook",
|
|
||||||
"component": null,
|
|
||||||
"query": null,
|
|
||||||
"isFrame": 0,
|
|
||||||
"isCache": 0,
|
|
||||||
"menuType": 1,
|
|
||||||
"visible": 1,
|
|
||||||
"perms": null,
|
|
||||||
"icon": "",
|
|
||||||
"status": 1,
|
|
||||||
"remark": null,
|
|
||||||
"roleId": null,
|
|
||||||
"selected": true,
|
|
||||||
"level": 2,
|
|
||||||
"children": null
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"menuId": 10,
|
|
||||||
"menuName": "任务配置(任务配置)",
|
|
||||||
"menuCode": "任务配置",
|
|
||||||
"parentId": 0,
|
|
||||||
"orderNum": 3,
|
|
||||||
"path": "/taskSet",
|
|
||||||
"component": null,
|
|
||||||
"query": null,
|
|
||||||
"isFrame": 0,
|
|
||||||
"isCache": 0,
|
|
||||||
"menuType": 0,
|
|
||||||
"visible": 1,
|
|
||||||
"perms": null,
|
|
||||||
"icon": "iconfont icon-renwuguanli",
|
|
||||||
"status": 1,
|
|
||||||
"remark": null,
|
|
||||||
"roleId": null,
|
|
||||||
"selected": true,
|
|
||||||
"level": 1,
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"menuId": 11,
|
|
||||||
"menuName": "任务配置(任务配置)",
|
|
||||||
"menuCode": "任务配置",
|
|
||||||
"parentId": 10,
|
|
||||||
"orderNum": 1,
|
|
||||||
"path": "index",
|
|
||||||
"component": null,
|
|
||||||
"query": null,
|
|
||||||
"isFrame": 0,
|
|
||||||
"isCache": 0,
|
|
||||||
"menuType": 1,
|
|
||||||
"visible": 1,
|
|
||||||
"perms": null,
|
|
||||||
"icon": "",
|
|
||||||
"status": 1,
|
|
||||||
"remark": null,
|
|
||||||
"roleId": null,
|
|
||||||
"selected": true,
|
|
||||||
"level": 2,
|
|
||||||
"children": null
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"menuId": 12,
|
|
||||||
"menuName": "数据统计(数据统计)",
|
|
||||||
"menuCode": "数据统计",
|
|
||||||
"parentId": 0,
|
|
||||||
"orderNum": 4,
|
|
||||||
"path": "/dataStatistics",
|
|
||||||
"component": null,
|
|
||||||
"query": null,
|
|
||||||
"isFrame": 0,
|
|
||||||
"isCache": 0,
|
|
||||||
"menuType": 0,
|
|
||||||
"visible": 1,
|
|
||||||
"perms": null,
|
|
||||||
"icon": "iconfont icon-shujutongji",
|
|
||||||
"status": 1,
|
|
||||||
"remark": null,
|
|
||||||
"roleId": null,
|
|
||||||
"selected": true,
|
|
||||||
"level": 1,
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"menuId": 13,
|
|
||||||
"menuName": "数据统计(数据统计)",
|
|
||||||
"menuCode": "数据统计",
|
|
||||||
"parentId": 12,
|
|
||||||
"orderNum": 1,
|
|
||||||
"path": "index",
|
|
||||||
"component": null,
|
|
||||||
"query": null,
|
|
||||||
"isFrame": 0,
|
|
||||||
"isCache": 0,
|
|
||||||
"menuType": 1,
|
|
||||||
"visible": 1,
|
|
||||||
"perms": null,
|
|
||||||
"icon": "",
|
|
||||||
"status": 1,
|
|
||||||
"remark": null,
|
|
||||||
"roleId": null,
|
|
||||||
"selected": true,
|
|
||||||
"level": 2,
|
|
||||||
"children": null
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"menuId": 14,
|
|
||||||
"menuName": "数据导出(数据导出)",
|
|
||||||
"menuCode": "数据导出",
|
|
||||||
"parentId": 0,
|
|
||||||
"orderNum": 5,
|
|
||||||
"path": "/dataExport",
|
|
||||||
"component": null,
|
|
||||||
"query": null,
|
|
||||||
"isFrame": 0,
|
|
||||||
"isCache": 0,
|
|
||||||
"menuType": 0,
|
|
||||||
"visible": 1,
|
|
||||||
"perms": null,
|
|
||||||
"icon": "iconfont icon-suifangrenwuguanli",
|
|
||||||
"status": 1,
|
|
||||||
"remark": null,
|
|
||||||
"roleId": null,
|
|
||||||
"selected": true,
|
|
||||||
"level": 1,
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"menuId": 15,
|
|
||||||
"menuName": "数据导出(数据导出)",
|
|
||||||
"menuCode": "数据导出",
|
|
||||||
"parentId": 14,
|
|
||||||
"orderNum": 1,
|
|
||||||
"path": "index",
|
|
||||||
"component": null,
|
|
||||||
"query": null,
|
|
||||||
"isFrame": 0,
|
|
||||||
"isCache": 0,
|
|
||||||
"menuType": 1,
|
|
||||||
"visible": 1,
|
|
||||||
"perms": null,
|
|
||||||
"icon": "",
|
|
||||||
"status": 1,
|
|
||||||
"remark": null,
|
|
||||||
"roleId": null,
|
|
||||||
"selected": true,
|
|
||||||
"level": 2,
|
|
||||||
"children": null
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"menuId": 16,
|
|
||||||
"menuName": "系统管理(系统管理)",
|
|
||||||
"menuCode": "系统管理",
|
|
||||||
"parentId": 0,
|
|
||||||
"orderNum": 6,
|
|
||||||
"path": "/systemManage",
|
|
||||||
"component": null,
|
|
||||||
"query": null,
|
|
||||||
"isFrame": 0,
|
|
||||||
"isCache": 0,
|
|
||||||
"menuType": 0,
|
|
||||||
"visible": 1,
|
|
||||||
"perms": null,
|
|
||||||
"icon": "iconfont icon-xitongguanli",
|
|
||||||
"status": 1,
|
|
||||||
"remark": null,
|
|
||||||
"roleId": null,
|
|
||||||
"selected": true,
|
|
||||||
"level": 1,
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"menuId": 17,
|
|
||||||
"menuName": "用户管理(用户管理)",
|
|
||||||
"menuCode": "用户管理",
|
|
||||||
"parentId": 16,
|
|
||||||
"orderNum": 1,
|
|
||||||
"path": "usersManage",
|
|
||||||
"component": null,
|
|
||||||
"query": null,
|
|
||||||
"isFrame": 0,
|
|
||||||
"isCache": 0,
|
|
||||||
"menuType": 1,
|
|
||||||
"visible": 1,
|
|
||||||
"perms": null,
|
|
||||||
"icon": "",
|
|
||||||
"status": 1,
|
|
||||||
"remark": null,
|
|
||||||
"roleId": null,
|
|
||||||
"selected": true,
|
|
||||||
"level": 2,
|
|
||||||
"children": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"menuId": 18,
|
|
||||||
"menuName": "角色管理(角色管理)",
|
|
||||||
"menuCode": "角色管理",
|
|
||||||
"parentId": 16,
|
|
||||||
"orderNum": 2,
|
|
||||||
"path": "roleManage",
|
|
||||||
"component": null,
|
|
||||||
"query": null,
|
|
||||||
"isFrame": 0,
|
|
||||||
"isCache": 0,
|
|
||||||
"menuType": 1,
|
|
||||||
"visible": 1,
|
|
||||||
"perms": null,
|
|
||||||
"icon": "",
|
|
||||||
"status": 1,
|
|
||||||
"remark": null,
|
|
||||||
"roleId": null,
|
|
||||||
"selected": true,
|
|
||||||
"level": 2,
|
|
||||||
"children": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"menuId": 19,
|
|
||||||
"menuName": "权限配置(权限配置)",
|
|
||||||
"menuCode": "权限配置",
|
|
||||||
"parentId": 16,
|
|
||||||
"orderNum": 3,
|
|
||||||
"path": "permissionSetting",
|
|
||||||
"component": null,
|
|
||||||
"query": null,
|
|
||||||
"isFrame": 0,
|
|
||||||
"isCache": 0,
|
|
||||||
"menuType": 1,
|
|
||||||
"visible": 1,
|
|
||||||
"perms": null,
|
|
||||||
"icon": "",
|
|
||||||
"status": 1,
|
|
||||||
"remark": null,
|
|
||||||
"roleId": null,
|
|
||||||
"selected": true,
|
|
||||||
"level": 2,
|
|
||||||
"children": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"menuId": 20,
|
|
||||||
"menuName": "菜单管理(菜单管理)",
|
|
||||||
"menuCode": "菜单管理",
|
|
||||||
"parentId": 16,
|
|
||||||
"orderNum": 4,
|
|
||||||
"path": "menuManage",
|
|
||||||
"component": null,
|
|
||||||
"query": null,
|
|
||||||
"isFrame": 0,
|
|
||||||
"isCache": 0,
|
|
||||||
"menuType": 1,
|
|
||||||
"visible": 1,
|
|
||||||
"perms": null,
|
|
||||||
"icon": "",
|
|
||||||
"status": 1,
|
|
||||||
"remark": null,
|
|
||||||
"roleId": null,
|
|
||||||
"selected": true,
|
|
||||||
"level": 2,
|
|
||||||
"children": null
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
defaultProps: {
|
|
||||||
children: 'children', // 子级
|
|
||||||
label: 'menuName' // 名称
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted () {
|
|
||||||
// 回显菜单
|
|
||||||
this.setCheckedKeys()
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
// 提交数据
|
|
||||||
getCheckedKeys () {
|
|
||||||
// 获取子级的key
|
|
||||||
const childMenu = this.$refs.tree.getCheckedKeys()
|
|
||||||
// 获取父级的key
|
|
||||||
const partMenu = this.$refs.tree.getHalfCheckedKeys()
|
|
||||||
// 合并数据
|
|
||||||
const menu = partMenu.concat(childMenu)
|
|
||||||
console.log(menu)
|
|
||||||
},
|
|
||||||
|
|
||||||
// 回显菜单
|
|
||||||
setCheckedKeys () {
|
|
||||||
// 一般是调接口,拿到菜单数据和回显的菜单数组
|
|
||||||
|
|
||||||
// 如果default-expand-all没有展开列表时,可以使用下面代码,设置展开所有行,
|
|
||||||
// const nodesMap = this.$refs.tree.store.nodesMap
|
|
||||||
// const keys = Object.keys(nodesMap)
|
|
||||||
// keys.forEach(key => {
|
|
||||||
// nodesMap[key].expanded = true
|
|
||||||
// })
|
|
||||||
|
|
||||||
// 设置回显的菜单
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.$refs.tree.setCheckedKeys([3])
|
|
||||||
})
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style scoped lang="scss">
|
|
||||||
.table {
|
|
||||||
padding: 20px;
|
|
||||||
min-height: 88vh;
|
|
||||||
background: #fff;
|
|
||||||
margin: 20px;
|
|
||||||
}
|
|
||||||
.menu-list {
|
|
||||||
::v-deep .el-tree {
|
|
||||||
border-top: 1px solid #ebeef5;
|
|
||||||
border-left: 1px solid #ebeef5;
|
|
||||||
border-right: 1px solid #ebeef5;
|
|
||||||
.el-tree-node__expand-icon {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
.el-tree-node {
|
|
||||||
&.is-expanded,
|
|
||||||
&.is-current,
|
|
||||||
&.is-focusable {
|
|
||||||
background-color: transparent !important;
|
|
||||||
}
|
|
||||||
.el-tree-node__content {
|
|
||||||
background-color: transparent !important;
|
|
||||||
&:hover {
|
|
||||||
background-color: transparent !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
> .el-tree-node {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
border-bottom: 1px solid #ebeef5;
|
|
||||||
position: relative;
|
|
||||||
> .el-tree-node__content {
|
|
||||||
width: 300px;
|
|
||||||
height: 100%;
|
|
||||||
padding-left: 20px !important;
|
|
||||||
}
|
|
||||||
.el-tree-node__children {
|
|
||||||
position: relative;
|
|
||||||
&::after {
|
|
||||||
content: ' ';
|
|
||||||
display: block;
|
|
||||||
width: 1px;
|
|
||||||
height: 100%;
|
|
||||||
border-left: 1px solid #ebeef5;
|
|
||||||
position: absolute;
|
|
||||||
left: 0px;
|
|
||||||
top: 0px;
|
|
||||||
}
|
|
||||||
.el-tree-node {
|
|
||||||
width: 350px;
|
|
||||||
padding: 10px 0px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<!-- 授权用户 -->
|
<!-- 授权用户 -->
|
||||||
<el-dialog title="选择用户" align-center v-model="visible" width="800px" top="5vh" append-to-body>
|
<el-dialog title="选择用户" v-model="visible" width="800px" top="5vh" append-to-body>
|
||||||
<el-form :model="queryParams" ref="queryRef" :inline="true">
|
<el-form :model="queryParams" ref="queryRef" :inline="true">
|
||||||
<el-form-item label="用户名称" prop="userName">
|
<el-form-item label="用户名称" prop="userName">
|
||||||
<el-input
|
<el-input
|
||||||
|
|
@ -39,7 +39,7 @@
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
<span>{{ formatTime(scope.row.createTime) }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
@ -60,7 +60,7 @@
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="User">
|
<script setup name="SelectUser">
|
||||||
import { authUserSelectAll, unallocatedUserList } from "@/api/system/role";
|
import { authUserSelectAll, unallocatedUserList } from "@/api/system/role";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
|
@ -79,7 +79,7 @@ const userIds = ref([]);
|
||||||
|
|
||||||
const queryParams = reactive({
|
const queryParams = reactive({
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 10,
|
pageSize: 20,
|
||||||
roleId: undefined,
|
roleId: undefined,
|
||||||
userName: undefined,
|
userName: undefined,
|
||||||
phonenumber: undefined
|
phonenumber: undefined
|
||||||
|
|
|
||||||
|
|
@ -1,132 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="test-page">
|
|
||||||
<el-card>
|
|
||||||
<template #header>
|
|
||||||
<div class="card-header">
|
|
||||||
<span>权限树状表格测试页面</span>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<!-- 权限树状表格 -->
|
|
||||||
<PermissionTreeTable ref="treeTableRef" />
|
|
||||||
|
|
||||||
<!-- 操作按钮 -->
|
|
||||||
<div class="actions">
|
|
||||||
<el-button @click="getSelectedData">获取选中数据</el-button>
|
|
||||||
<el-button type="primary" @click="showDialog">打开对话框</el-button>
|
|
||||||
<el-button type="success" @click="setDefaultData">设置默认选中</el-button>
|
|
||||||
<el-button type="warning" @click="clearAll">清空所有</el-button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 结果展示 -->
|
|
||||||
<div v-if="selectedData" class="result">
|
|
||||||
<h3>选中结果:</h3>
|
|
||||||
<el-alert
|
|
||||||
title="数据获取成功"
|
|
||||||
type="success"
|
|
||||||
:closable="false"
|
|
||||||
show-icon
|
|
||||||
/>
|
|
||||||
<pre>{{ JSON.stringify(selectedData, null, 2) }}</pre>
|
|
||||||
</div>
|
|
||||||
</el-card>
|
|
||||||
|
|
||||||
<!-- 对话框测试 -->
|
|
||||||
<PermissionDialog
|
|
||||||
v-model="dialogVisible"
|
|
||||||
@confirm="handleDialogConfirm"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref } from 'vue'
|
|
||||||
import PermissionTreeTable from './render.vue'
|
|
||||||
import PermissionDialog from './permission-dialog.vue'
|
|
||||||
|
|
||||||
const treeTableRef = ref()
|
|
||||||
const dialogVisible = ref(false)
|
|
||||||
const selectedData = ref(null)
|
|
||||||
|
|
||||||
// 获取选中数据
|
|
||||||
const getSelectedData = () => {
|
|
||||||
if (treeTableRef.value) {
|
|
||||||
const data = treeTableRef.value.getCheckedData()
|
|
||||||
selectedData.value = data
|
|
||||||
console.log('选中的数据:', data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 显示对话框
|
|
||||||
const showDialog = () => {
|
|
||||||
dialogVisible.value = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理对话框确认
|
|
||||||
const handleDialogConfirm = (data) => {
|
|
||||||
selectedData.value = data
|
|
||||||
console.log('对话框确认的数据:', data)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置默认选中数据(示例)
|
|
||||||
const setDefaultData = () => {
|
|
||||||
// 这里可以实现设置默认选中状态的逻辑
|
|
||||||
console.log('设置默认选中数据')
|
|
||||||
// 由于当前实现是内部状态管理,这里只是示例
|
|
||||||
// 实际使用时可能需要通过props传入初始状态
|
|
||||||
}
|
|
||||||
|
|
||||||
// 清空所有选中
|
|
||||||
const clearAll = () => {
|
|
||||||
// 这里可以实现清空所有选中状态的逻辑
|
|
||||||
console.log('清空所有选中')
|
|
||||||
selectedData.value = null
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.test-page {
|
|
||||||
padding: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-header {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.actions {
|
|
||||||
margin: 20px 0;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.actions .el-button {
|
|
||||||
margin: 0 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.result {
|
|
||||||
margin-top: 20px;
|
|
||||||
padding: 20px;
|
|
||||||
background: #f9f9f9;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.result h3 {
|
|
||||||
margin-top: 0;
|
|
||||||
color: #303133;
|
|
||||||
}
|
|
||||||
|
|
||||||
.result pre {
|
|
||||||
background: #fff;
|
|
||||||
padding: 15px;
|
|
||||||
border-radius: 4px;
|
|
||||||
border: 1px solid #e4e7ed;
|
|
||||||
overflow-x: auto;
|
|
||||||
font-size: 12px;
|
|
||||||
line-height: 1.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-alert {
|
|
||||||
margin-bottom: 15px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -0,0 +1,121 @@
|
||||||
|
<template>
|
||||||
|
<!-- 账户详情 -->
|
||||||
|
<el-dialog :title="t('账户详情')" align-center v-model="showDialog" width="700px" append-to-body
|
||||||
|
class="el-dialog">
|
||||||
|
<el-scrollbar max-height="700px">
|
||||||
|
<el-descriptions :column="1" border class="c-descriptions">
|
||||||
|
<el-descriptions-item :label="t('所属部门')" label-width="150">
|
||||||
|
{{ modifyDate.dept?.deptName||'--' }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item :label="t('后台账号')" label-width="150" >
|
||||||
|
{{ modifyDate.userName }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item :label="t('后台昵称')" label-width="150">
|
||||||
|
{{ modifyDate.nickName }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item :label="t('权限名称')" label-width="150">
|
||||||
|
{{ modifyDate.roleName }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item :label="t('创建人')" label-width="150">
|
||||||
|
{{ modifyDate.updateBy||modifyDate.createBy }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item :label="t('创建时间')" label-width="150">
|
||||||
|
{{ formatTime(modifyDate.createTime) }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item :label="t('最后登录方式')" label-width="150">
|
||||||
|
{{ t('密码登录') }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item :label="t('最后登录时间')" label-width="150">
|
||||||
|
{{ formatTime(modifyDate.loginDate) || '--' }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item :label="t('最后登出时间')" label-width="150">
|
||||||
|
{{ formatTime(modifyDate.exitDate) || '--' }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item :label="t('最后登入IP')" label-width="150">
|
||||||
|
{{ modifyDate.loginIp || '--' }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
|
||||||
|
|
||||||
|
</el-descriptions>
|
||||||
|
</el-scrollbar>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button @click="closeDialog">{{ t('取 消') }}</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import { nextTick, ref } from "vue";
|
||||||
|
const { proxy } = getCurrentInstance()
|
||||||
|
const emits = defineEmits(['submit', 'update:show']) // 自定义事件
|
||||||
|
const props = defineProps({ // 父组件向子组件传值
|
||||||
|
show: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
modifyDate: {
|
||||||
|
type: Object,
|
||||||
|
default: {}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const showDialog = computed({// 对话框显示隐藏
|
||||||
|
get() {
|
||||||
|
return props.show
|
||||||
|
},
|
||||||
|
set(value) {
|
||||||
|
emits('update:show', value)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const formAll = reactive({ // 表单验证数据
|
||||||
|
id: '',
|
||||||
|
rewardAmount:'',
|
||||||
|
auditRate:'',
|
||||||
|
remark:'',
|
||||||
|
password:''
|
||||||
|
})
|
||||||
|
|
||||||
|
//数据更新区域
|
||||||
|
nextTick(() => {
|
||||||
|
formAll.id = props.modifyDate.id;
|
||||||
|
})
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
onMounted(() => {
|
||||||
|
});
|
||||||
|
// 关闭弹窗
|
||||||
|
const closeDialog = () => {
|
||||||
|
showDialog.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<style scope lang="scss">
|
||||||
|
.icon-box {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
.disable-click {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
.clt-item {
|
||||||
|
.label-box {
|
||||||
|
vertical-align: middle;
|
||||||
|
width: 150px;
|
||||||
|
text-align: right;
|
||||||
|
padding-right: 12px;
|
||||||
|
word-break: break-all;
|
||||||
|
line-height: 20px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-form-item__error) {
|
||||||
|
padding-left: 150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-right {
|
||||||
|
width: calc(100% - 150px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,101 @@
|
||||||
|
<template>
|
||||||
|
<!-- Google验证码 -->
|
||||||
|
<el-dialog v-model="showDialog" align-center width="500px" append-to-body
|
||||||
|
class="el-dialog">
|
||||||
|
<template #title>
|
||||||
|
<div class="title" style="width: 100%;text-align: center;">Google验证码</div>
|
||||||
|
</template>
|
||||||
|
<el-form :model="formGoogle" :rules="rulesGoogle" ref="googleRef" label-width="130px">
|
||||||
|
<el-form-item label="Google验证码" prop="googleCode">
|
||||||
|
<el-input v-model="formGoogle.googleCode" placeholder="请输入您的Google验证码" maxlength="6" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer" style="display: flex;justify-content: center;">
|
||||||
|
<el-button @click="showDialog = false">取消</el-button>
|
||||||
|
<el-button type="primary" @click="submitGoogle">
|
||||||
|
确定
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import { nextTick, ref } from "vue";
|
||||||
|
const { proxy } = getCurrentInstance()
|
||||||
|
const emits = defineEmits(['submit', 'update:show']) // 自定义事件
|
||||||
|
const props = defineProps({ // 父组件向子组件传值
|
||||||
|
show: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
modifyDate: {
|
||||||
|
type: Object,
|
||||||
|
default: {}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const showDialog = computed({// 对话框显示隐藏
|
||||||
|
get() {
|
||||||
|
return props.show
|
||||||
|
},
|
||||||
|
set(value) {
|
||||||
|
emits('update:show', value)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const rulesGoogle = reactive({
|
||||||
|
googleCode: [{ required: true, message: "请输入谷歌验证码", trigger: "change" }]
|
||||||
|
});
|
||||||
|
const formGoogle = reactive({
|
||||||
|
googleCode: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
//数据更新区域
|
||||||
|
nextTick(() => {
|
||||||
|
|
||||||
|
})
|
||||||
|
const submitGoogle = () => {
|
||||||
|
proxy.$refs["googleRef"].validate(valid => {
|
||||||
|
if (valid) {
|
||||||
|
emits('submit', formGoogle.googleCode)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 初始化
|
||||||
|
onMounted(() => {
|
||||||
|
});
|
||||||
|
// 关闭弹窗
|
||||||
|
const closeDialog = () => {
|
||||||
|
showDialog.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<style scope lang="scss">
|
||||||
|
.icon-box {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
.disable-click {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
.clt-item {
|
||||||
|
.label-box {
|
||||||
|
vertical-align: middle;
|
||||||
|
width: 150px;
|
||||||
|
text-align: right;
|
||||||
|
padding-right: 12px;
|
||||||
|
word-break: break-all;
|
||||||
|
line-height: 20px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-form-item__error) {
|
||||||
|
padding-left: 150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-right {
|
||||||
|
width: calc(100% - 150px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div style="margin-bottom: 10px;">
|
||||||
|
<span>批量数量:</span>
|
||||||
|
<b>{{ batchCount }}</b>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-form :model="form">
|
||||||
|
<el-form-item label="操作类型">
|
||||||
|
<el-select v-model="form.actionType" placeholder="请选择操作类型" style="width: 300px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in options"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { reactive } from "vue";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
batchCount: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const form = reactive({
|
||||||
|
actionType: ""
|
||||||
|
});
|
||||||
|
|
||||||
|
// 这里可以暴露给外部取值
|
||||||
|
defineExpose({ form });
|
||||||
|
</script>
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -27,9 +27,9 @@ export default defineConfig(({ mode, command }) => {
|
||||||
proxy: {
|
proxy: {
|
||||||
'/dev-api': {
|
'/dev-api': {
|
||||||
// target: 'http://192.168.50.139:9080',
|
// target: 'http://192.168.50.139:9080',
|
||||||
// target: 'http://192.168.50.233:8081',
|
target: 'http://192.168.50.233:8081',
|
||||||
// target: 'http://192.168.50.178:8080',
|
// target: 'http://192.168.50.178:8080',
|
||||||
target: 'http://192.168.50.11:8081',
|
// target: 'http://192.168.50.11:8081',
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
rewrite: (p) => p.replace(/^\/dev-api/, '')
|
rewrite: (p) => p.replace(/^\/dev-api/, '')
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue