b3d3da60 by lihua

数据服务前端代码

1 parent 4bd6f9b4
# 页面标题
VITE_APP_TITLE = 数据资产管理系统
VITE_APP_TITLE = 可信数据空间
# 接口域名
# VITE_API_BASEURL = https://www.zgsjzc.com/api
# VITE_API_BASEURL = https://swzl-test.csbr.cn/api
# VITE_API_BASEURL = http://localhost:9000
VITE_API_BASEURL = http://192.168.6.20:28052/
VITE_API_BASEURL = http://192.168.9.1:58052/
# VITE_API_BASEURL = http://192.168.6.20:8052/
VITE_IDASS_BASEURL = https://idaas-test.csbr.cn/login
......@@ -96,6 +96,9 @@ VITE_API_CIRCULATION_URL = http://192.168.6.22:29900/circulation
#数据加工交付
VITE_APP_DATA_DELIVERY = http://192.168.6.20:38052/
#数据服务接口地址
VITE_APP_SERVICE_BASEURL = ms-daop-jgjf-data-open-service
# 本地访问地址
# VITE_API_CIRCULATION_URL = http://localhost:9000/circulation
......
# 页面标题
VITE_APP_TITLE = 数据资产管理系统
VITE_APP_TITLE = 可信数据空间
# 接口域名
VITE_API_BASEURL = http://192.168.6.20:28052/
# VITE_API_BASEURL = http://49.4.26.201:31709/
......@@ -122,6 +122,9 @@ VITE_API_MESSAGE = ms-daop-message-service
#企业信息接口
VITE_APP_PERSONAL_URL = ms-daop-personel-service
#数据服务接口地址
VITE_APP_SERVICE_BASEURL = ms-daop-jgjf-data-open-service
#流通平台接口地址
VITE_APP_CIRCULATION = http://192.168.6.20:18052/
#数据加工交付
......
/** 数据服务模块接口 */
import request from "@/utils/request";
/** api类型,有表单类型,自定义sql. */
export const apiTypes: any = [{
value: 1,
label: '单表API'
}, {
value: 2,
label: '自定义sql'
}, {
value: 3,
label: '注册API'
}];
/** 查询域名和文根 */
export const getDomainName = () => request({
url: `${import.meta.env.VITE_APP_SERVICE_BASEURL}/api-base-info/domain-and-service-name`,
method: 'get'
})
// 获取参数类型的接口
export const getDataTypeList = () => request({
url:`${import.meta.env.VITE_APP_API_BASEURL}/data-dict/get-data-list`,
method: 'post',
data: { paramCode: "DATA_TYPE" }
})
/** 获取参数位置 */
// export const getPositionList = () => request({
// url:`${import.meta.env.VITE_APP_CONFIG_URL}/data-dict/get-data-list`,
// method: 'post',
// data: { paramCode: "PARAM_POSITION" }
// })
/** 获取参数操作符 */
export const getOperationList = () => request({
url:`${import.meta.env.VITE_APP_API_BASEURL}/data-dict/get-data-list`,
method: 'post',
data: { paramCode: "PARAM_OPERATOR" }
})
/** 获取主题域分层的主题表树结构 */
export const getSubjectTableTree = (params) => request({
url: `${import.meta.env.VITE_APP_PLAN_BASEURL}/data-catalog-directory/directory-tree-list`,
method: 'post',
data: params
})
/** 获取主题域分层的主题表树结构 */
export const getSubjectTableByDomain = (params) => request({
url: `${import.meta.env.VITE_APP_PLAN_BASEURL}/data-catalog-subject/list-by-domain-guid?domainGuid=${params}`,
method: 'get',
data: params
})
/** 获取主题表详情,用于绑定字段下拉列表。 */
export const getSubjectTableDetail = (params) => request({
url: `${import.meta.env.VITE_APP_PLAN_BASEURL}/data-catalog-subject/detailToSync/${params}`,
method: 'get'
})
/** -------------------------- 管理API ------------------------------------ */
/** 获取标签列表 */
export const getTagsList = (params) => request({
url:`${import.meta.env.VITE_APP_SERVICE_BASEURL}/api-tag-sort/page-list`,
method: 'post',
data: params
})
/** 添加标签接口 */
export const addTagLabel = (params) => request({
url:`${import.meta.env.VITE_APP_SERVICE_BASEURL}/api-tag-sort/save`,
method: 'post',
data: params
})
/** 编辑标签 */
export const editTagLabel = (params) => request({
url:`${import.meta.env.VITE_APP_SERVICE_BASEURL}/api-tag-sort/update`,
method: 'post',
data: params
})
/** 删除标签 */
export const deleteTag = (params) => request({
url:`${import.meta.env.VITE_APP_SERVICE_BASEURL}/api-tag-sort/delete`,
method: 'delete',
data: params
})
/** api信息列表 */
export const getAPIList = (params) => request({
url:`${import.meta.env.VITE_APP_SERVICE_BASEURL}/api-base-info/page-list`,
method: 'post',
data: params
})
/** 启用停用API */
export const updateAPIState = (params) => request({
url:`${import.meta.env.VITE_APP_SERVICE_BASEURL}/api-base-info/start-or-stop?guid=${params.guid}&apiState=${params.apiState}`,
method: 'get'
})
/** 移动API信息 */
export const moveAPI = (params) => request({
url:`${import.meta.env.VITE_APP_SERVICE_BASEURL}/api-base-info/move?sceneGuid=${params.sceneGuid }`,
method: 'post',
data: params.guids
})
/** 新建api时验证api名称是否存在 */
export const checkExistAPIName = (params) => request({
url:`${import.meta.env.VITE_APP_SERVICE_BASEURL}/api-base-info/exist-api-name?apiName=${params}`,
method: 'get'
})
/** 新建api时验证api请求路径是否存在 */
export const checkExistRequestPath = (params) => request({
url:`${import.meta.env.VITE_APP_SERVICE_BASEURL}/api-base-info/exist-request-path?requestName=${params}`,
method: 'get'
})
/** 新增API信息 */
export const addApi = (params) => request({
url:`${import.meta.env.VITE_APP_SERVICE_BASEURL}/api-base-info/save`,
method: 'post',
data: params
})
/** 修改API信息 */
export const updateApi = (params) => request({
url:`${import.meta.env.VITE_APP_SERVICE_BASEURL}/api-base-info/update`,
method: 'post',
data: params
})
/** 提交发起API审批流程 */
export const addApiApprove = (guid) => request({
url:`${import.meta.env.VITE_APP_SERVICE_BASEURL}/api-base-info/add-approve/${guid}`,
method: 'get'
})
/** 删除API信息 */
export const deleteApi = (guid) => request({
url:`${import.meta.env.VITE_APP_SERVICE_BASEURL}/api-base-info/delete?guid=${guid}`,
method: 'delete'
})
/** 复制API */
export const copyApi = (params) => request({
url:`${import.meta.env.VITE_APP_SERVICE_BASEURL}/api-base-info/copy?apiName=${params.apiName}&guid=${params.guid}&requestPath=${params.requestPath}`,
method: 'get'
})
/** 获取api详情信息 */
export const getApiDetail = (guid) => request({
url:`${import.meta.env.VITE_APP_SERVICE_BASEURL}/api-base-info/detail/${guid}`,
method: 'get'
})
/** 获取api流程详情 */
export const getApiApprovalDetail = (guid) => request({
url:`${import.meta.env.VITE_APP_SERVICE_BASEURL}/api-base-info/approve-detail/${guid}`,
method: 'get'
})
/** 验证API */
export const validateApiSql = (params) => request({
url: `${import.meta.env.VITE_APP_SERVICE_BASEURL}/invoke/check-sql`,
method: 'post',
data: params
})
/** 第三步测试调用APi */
export const testEditApi = (params) => request({
url: `${import.meta.env.VITE_APP_SERVICE_BASEURL}/invoke/test`,
method: 'post',
data: params
})
/** --------------------------- API授权设置应用产品 -------------------------------- */
/** 获取api产品列表 */
export const getAppProductList = () => request({
url:`${import.meta.env.VITE_APP_SERVICE_BASEURL}/app-product/list`,
method: 'get'
})
/** 获取api绑定产品列表数据 */
export const getApibindProducts = (params) => request({
url: `${import.meta.env.VITE_APP_SERVICE_BASEURL}/api-product-binding/page-list`,
method: 'post',
data: params
})
/** 保存APi产品绑定关系 */
export const saveApiBindProduct = (params) => request({
url: `${import.meta.env.VITE_APP_SERVICE_BASEURL}/api-product-binding/save`,
method: 'post',
data: params
})
/** --------------------------- 调用,授权API-------------------------------- */
/** 获取product列表数据 */
export const getAppProductData = (params) => request({
url: `${import.meta.env.VITE_APP_SERVICE_BASEURL}/app-product/page-list`,
method: 'post',
data: params
})
/** 判断是否是idaas */
export const isUseIdaas = () => request({
url: `${import.meta.env.VITE_APP_SERVICE_BASEURL}/app-product/isUseIdaas`,
method: 'get'
})
/** 判断应用产品名称是否重复 */
export const isExistProduct = (params) => request({
url: `${import.meta.env.VITE_APP_SERVICE_BASEURL}/app-product/exist?productName=${params}`,
method: 'post'
})
/** 判断appKey是否重复 */
export const isExistAppKey = (params) => request({
url: `${import.meta.env.VITE_APP_SERVICE_BASEURL}/app-product/exist-appKey?appKey=${params}`,
method: 'post'
})
/** 获取应用产品详情 */
export const getProductDetail = (guid) => request({
url: `${import.meta.env.VITE_APP_SERVICE_BASEURL}/app-product/detail?guid=${guid}`,
method: 'get'
})
/** 保存应用产品设置 */
export const saveProduct = (params) => request({
url: `${import.meta.env.VITE_APP_SERVICE_BASEURL}/app-product/save`,
method: 'post',
data: params
})
/** 修改应用产品设置 */
export const updateProduct = (params) => request({
url: `${import.meta.env.VITE_APP_SERVICE_BASEURL}/app-product/update`,
method: 'post',
data: params
})
/** 删除应用产品 */
export const deleteAppProduct = (params) => request({
url: `${import.meta.env.VITE_APP_SERVICE_BASEURL}/app-product/delete`,
method: 'delete',
data: params
});
/** ---------------------------- 测试API ---------------------------------------- */
/** 获取有效的标签列表 */
export const getValidApiLabel = (isApiValid = false) => request({
url: `${import.meta.env.VITE_APP_SERVICE_BASEURL}/api-tag-sort/list-valid${isApiValid ? '?isApiValid=true' : ''}`,
method: 'get'
})
export const getSceneValidApiLabel = (isApiValid = false) => request({
url: `${import.meta.env.VITE_APP_SERVICE_BASEURL}/api-base-info/list-valid-scene${isApiValid ? '?isApiValid=true' : '?isApiValid=false'}`,
method: 'get'
})
/** 根据标签获取有效的api列表 */
export const getValidApi = (sceneGuid) => request({
url: `${import.meta.env.VITE_APP_SERVICE_BASEURL}/api-base-info/list-valid?sceneGuid=${sceneGuid}`,
method: 'get'
})
/** 根据标签获取所有的api列表 */
export const getAllApi = (sceneGuid) => request({
url: `${import.meta.env.VITE_APP_SERVICE_BASEURL}/api-base-info/list-by-scene-guid/${sceneGuid}`,
method: 'get'
})
/** 测试API调用借口 */
export const testApiData = (params) => request({
url: `${import.meta.env.VITE_APP_SERVICE_BASEURL}/invoke/test-by-guid`,
method: 'post',
data: params
})
/** ---------------------------- 首页数据服务看板 ---------------------------------------- */
/** 获取首页指标统计 */
export const getDataStat = (params) => request({
url: `${import.meta.env.VITE_APP_SERVICE_BASEURL}/home-page/data-stat?startTime=${params?.[0]}&endTime=${params?.[1]}`,
method: 'get'
})
/** 调用影响的应用产品统计 */
export const getProductStat = (params) => request({
url: `${import.meta.env.VITE_APP_SERVICE_BASEURL}/home-page/product-stat?endTime=${params?.[1]}`,
method: 'get'
})
/** 调用异常次数的APi统计 */
export const getAPIErrorStat = (params) => request({
url: `${import.meta.env.VITE_APP_SERVICE_BASEURL}/home-page/api-error-stat?appKey=${params.appKey}&startTime=${params.date?.[0]}&endTime=${params.date?.[1]}`,
method: 'get'
})
/** 调用次数的趋势图 */
export const getCallApiCountStat = (params) => request({
url: `${import.meta.env.VITE_APP_SERVICE_BASEURL}/home-page/call-api-number-stat?endTime=${params?.[1]}`,
method: 'get'
})
/** 调用API数的趋势图 */
export const getCallApiNumberStat = (params) => request({
url: `${import.meta.env.VITE_APP_SERVICE_BASEURL}/home-page/call-api-count-stat?endTime=${params?.[1]}`,
method: 'get'
})
/** ---------------------------- ip白名单管理 ---------------------------------------- */
/** 获取ip列表数据 */
export const getIPList = (params) => request({
url: `${import.meta.env.VITE_APP_SERVICE_BASEURL}/white-ip/page-list`,
method: 'post',
data: params
})
/** 添加ip */
export const saveIP = (params) => request({
url: `${import.meta.env.VITE_APP_SERVICE_BASEURL}/white-ip/save`,
method: 'post',
data: params
})
/** 修改Ip */
export const updateIP = (params) => request({
url: `${import.meta.env.VITE_APP_SERVICE_BASEURL}/white-ip/update`,
method: 'post',
data: params
})
/** 删除IP */
export const deleteIP = (params) => request({
url: `${import.meta.env.VITE_APP_SERVICE_BASEURL}/white-ip/delete`,
method: 'delete',
data: params
})
\ No newline at end of file
......@@ -32,10 +32,10 @@ export const getSystemMenu = (params, isAdmin = false) => {
isAdmin
? `${
import.meta.env.VITE_APP_AUTH_URL
}/product-menu-permission/tenant/get-product-menu?tenantGuid=${params.tenantGuid}&platformSystemGuid=32774fcfdf5e43e8b866660374d8bced`
}/product-menu-permission/tenant/get-product-menu?tenantGuid=${params.tenantGuid}&platformSystemGuid=4149c763d70948b195eb3d4b997c1722`
: `${
import.meta.env.VITE_APP_AUTH_URL
}/product-menu-permission/staff/get-product-menu-template?platformSystemGuid=32774fcfdf5e43e8b866660374d8bced`,
}/product-menu-permission/staff/get-product-menu-template?platformSystemGuid=4149c763d70948b195eb3d4b997c1722`,
method: "get",
});
};
......@@ -247,6 +247,21 @@ export const getDataSource = (params) => request({
method: "post",
data: params,
});
/** 获取数据源列表 */
export const getSchemaTableList = (params) => request({
url:`${import.meta.env.VITE_APP_DATA_SOURCE_URL}/data-source/schema-table-page-list`,
method: 'post',
data: params
})
// 获取表结构
export const tableColumnList = (params)=> request({
url:`${import.meta.env.VITE_APP_DATA_SOURCE_URL}/data-source/table-column-list`,
method: 'post',
data: params
})
// 新增
export const addDataSource = (params) => request({
url: `${import.meta.env.VITE_APP_DATA_SOURCE_URL}/data-source/save`,
......@@ -289,6 +304,12 @@ export const getAllFlowData = (params) => request({
method: 'get',
params
})
export const getParamsDictList = (dictType) => request({
url: `${import.meta.env.VITE_APP_CONFIG_URL}/dict/data/get-by-dictType?dictType=${dictType}`,
method: 'get',
})
// 获取资产/价值评估机构数据
export const getSingleList = (params) => request({
url: `${import.meta.env.VITE_APP_PERSONAL_URL}/tenant/singlePage`,
......@@ -316,4 +337,11 @@ export const getParamsList = (params) => request({
url: `${import.meta.env.VITE_APP_CONFIG_URL}/dict/data/get-by-dictType`,
method: 'get',
params
})
\ No newline at end of file
})
// sql验证
export const checkSql = (params) => request({
url:`${import.meta.env.VITE_APP_DATA_SOURCE_URL }/sql-operate/check-sql`,
method: 'post',
data:params
})
......
......@@ -3,25 +3,6 @@ function Layout() {
return import('@/layouts/index.vue')
}
const routes: RouteRecordRaw[] = [
// {
// path: '/data-asset/register-guide',
// component: Layout,
// meta: {
// title: '登记服务指南',
// icon: 'sidebar-videos',
// },
// children: [{
// path: '',
// name: 'registerGuide',
// component: () => import('@/views/data_asset/registerGuide.vue'),
// meta: {
// title: '登记服务指南',
// sidebar: false,
// breadcrumb: false,
// cache: true
// },
// }]
// },
{
path: '/data-asset/register-catalog',
component: Layout,
......
......@@ -253,47 +253,5 @@ const routes: RouteRecordRaw[] = [
},
],
},
{
path: '/data-asset-register/register-progress',
component: Layout,
meta: {
title: '登记进度一览',
icon: 'ep:grid',
},
children: [
{
path: '',
name: 'registerProgress',
component: () => import('@/views/data_asset/registerProgress.vue'),
meta: {
title: '登记进度一览',
sidebar: false,
cache: true,
breadcrumb: false,
},
},
]
},
{
path: '/data-asset-register/contract-progress',
component: Layout,
meta: {
title: '合同进度一览',
icon: 'ep:grid',
},
children: [
{
path: '',
name: 'contractProgress',
component: () => import('@/views/data_asset/contractProgress.vue'),
meta: {
title: '合同进度一览',
sidebar: false,
cache: true,
breadcrumb: false,
},
},
]
}
]
export default routes
......
import type { RouteRecordRaw } from 'vue-router'
function Layout() {
return import('@/layouts/index.vue')
}
const routes: RouteRecordRaw[] = [
{
path: '/data-service/api-management',
component: Layout,
meta: {
title: '管理API',
icon: 'sidebar-videos',
},
children: [
{
path: '',
name: 'apiManagement',
component: () => import('@/views/data_service/apiManagement.vue'),
meta: {
title: '管理API',
sidebar: false,
breadcrumb: false,
cache: true
}
},
{
path: 'api-create',
name: 'apiCreate',
component: () => import('@/views/data_service/apiCreate.vue'),
meta: {
title: '新建API',
sidebar: false,
breadcrumb: false,
cache: true,
reuse: true,
editPage: true
},
beforeEnter: (to, from) => {
if (to.query.type) {
to.meta.title = `新建(${to.query.type == '1' ? '单表API' : (to.query.type == '2' ? '自定义sql' : '注册API')})`;
to.meta.editPage = true;
} else if (to.query.detail) {
to.meta.title = `详情-${to.query.apiName}`;
to.meta.editPage = false;
} else if (to.query.guid) {
to.meta.title = `编辑-${to.query.apiName}`;
to.meta.editPage = true;
}
}
},
{
// path: 'processDetail',
// name: 'APIProcessDetail',
path: 'api-detail',
name: 'apiDetail',
component: () => import('@/views/data_service/detail_serviceApi.vue'),
meta: {
title: '流程详情',
sidebar: false,
breadcrumb: false,
cache: true,
reuse: true
}
},
{
path: 'processDetail',
name: 'APIProcessDetail',
component: () => import('@/views/detail.vue'),
meta: {
title: '流程详情',
sidebar: false,
breadcrumb: false,
cache: true,
reuse: true
}
},
],
},
{
path: '/data-service/api-test',
component: Layout,
meta: {
title: '测试API',
icon: 'sidebar-videos',
},
children: [
{
path: '',
name: 'apiTest',
component: () => import('@/views/data_service/apiTest.vue'),
meta: {
title: '测试API',
sidebar: false,
breadcrumb: false,
cache: true
},
},
],
},
]
export default routes
......@@ -3,6 +3,7 @@ import generatedRoutes from 'virtual:generated-pages'
import type { RouteRecordRaw } from 'vue-router'
import DataAssess from './modules/dataAsset';
import DataAssetRegistry from './modules/dataAssetRegistry';
import DataService from './modules/dataService';
import useSettingsStore from '@/store/modules/settings'
......@@ -90,7 +91,8 @@ const systemRoutes: RouteRecordRaw[] = [
// 动态路由(异步路由、导航栏路由)
const asyncRoutes: RouteRecordRaw[] = [
...DataAssess,
...DataAssetRegistry,
...DataService,
// ...DataAssetRegistry,
]
const constantRoutesByFilesystem = generatedRoutes.filter((item) => {
......
......@@ -40,7 +40,7 @@ const globalSettings: Settings.all = {
},
"home": {
"enable": false,
"title": "数据资产管理系统"
"title": "可信数据空间"
},
"breadcrumb": {
"enable": true
......
const useDataAnonymizationStore = defineStore(
// 资产目录guid
'isRefresh',
() => {
const isRefresh = ref<boolean>(false);
function setIsRefresh(v: boolean) {
isRefresh.value = v;
}
const isAnonPageRefresh = ref<boolean>(false);
function setIsAnonPageRefresh(v: boolean) {
isAnonPageRefresh.value = v;
}
return {
isRefresh,
isAnonPageRefresh,
setIsRefresh,
setIsAnonPageRefresh,
};
}
);
export default useDataAnonymizationStore;
const useDataCatalogStore = defineStore(
// 主题域guid
'domainGuid',
() => {
const domainGuid = ref<string>("")
function set(guid: any) {
domainGuid.value = guid;
}
return {
domainGuid,
set
}
},
)
export default useDataCatalogStore
\ No newline at end of file
const useEntryStore = defineStore(
// api标签分类guid
'isRefresh',
() => {
const isRefresh = ref(false);
function setIsRefresh(update: boolean) {
isRefresh.value = update;
}
return {
isRefresh,
setIsRefresh,
}
},
)
export default useEntryStore
\ No newline at end of file
const useDataMetaStore = defineStore("dataMeta", () => {
const guid: Ref<string> = ref("")
const databaseName = ref("")
const tableName = ref("")
const databaseChName = ref("");
const databaseGuid = ref('');
const fieldGuid = ref("");
const fieldEnName = ref('');
const isFieldLineage = ref(false);
const set = (prop?: {
tableGuid: string;
table: string;
databas: string;
databaseCh: string;
dsGuid: string;
fGuid?: string;
fEnName?: string;
isFieldLine?: boolean;
}) => {
guid.value = prop?.tableGuid || "";
databaseName.value = prop?.databas || "";
tableName.value = prop?.table || "";
databaseChName.value = prop?.databaseCh || "";
databaseGuid.value = prop?.dsGuid || "";
fieldGuid.value = prop?.fGuid || "";
fieldEnName.value = prop?.fEnName || "";
isFieldLineage.value = prop?.isFieldLine ?? false;
}
return {
guid,
databaseName,
tableName,
databaseChName,
databaseGuid,
fieldGuid,
fieldEnName,
isFieldLineage,
set
}
})
export default useDataMetaStore
\ No newline at end of file
const useDataQualityStore = defineStore(
// 质检表分组guid
'modelGroupGuid',
() => {
const modelGroupGuid = ref<string>("")
function set(guid: any) {
modelGroupGuid.value = guid;
}
const modelGuid = ref<string>("")
function setModelGuid(guid: any) {
modelGuid.value = guid;
}
const planType = ref<number>(0);
function setPlanType(type: any) {
planType.value = type;
}
const defaultPlanType = ref<number>(1);
function setDefaultPlanType(type: any) {
defaultPlanType.value = type;
}
const isUpdate = ref(false);
function setIsUpdate(update: boolean) {
isUpdate.value = update;
}
return {
modelGroupGuid,
set,
setModelGuid,
modelGuid,
planType,
isUpdate,
setIsUpdate,
setPlanType,
setDefaultPlanType,
defaultPlanType
}
},
)
export default useDataQualityStore
\ No newline at end of file
const useDataAsyncStore = defineStore("asyncGuid",()=>{
const taskGuid = ref("")
const set = (guid:string)=>{
taskGuid.value = guid
}
return {
taskGuid,
set
}
})
export default useDataAsyncStore
\ No newline at end of file
const useDataStandardsStore = defineStore(
// 主题域guid
'domainGuid',
() => {
const isAdd = ref(false)
const standardSetGuid = ref("")
const guid = ref("")
function set(guid: any) {
isAdd.value = guid;
}
function setGuid(sGuid,stanGuid){
guid.value = sGuid
standardSetGuid.value = stanGuid
}
return {
isAdd,
set,
guid,
setGuid,
standardSetGuid,
}
},
)
export default useDataStandardsStore
\ No newline at end of file
......@@ -46,4 +46,4 @@ export const commonPageConfig = {
}
/** 通用的系统guid */
export const SystemGuid = '32774fcfdf5e43e8b866660374d8bced';
\ No newline at end of file
export const SystemGuid = '4149c763d70948b195eb3d4b997c1722';
\ No newline at end of file
......
<route lang="yaml">
name: notFound
meta:
title: 数据资产管理
title: 可信数据空间
constant: true
layout: false
</route>
......
<route lang="yaml">
name: contractProgress
</route>
<script lang="ts" setup name="contractProgress">
import { ref } from 'vue';
import { TableColumnWidth, commonPageConfig } from '@/utils/enum';
import {
saveDamContract,
updateDamContract,
delDamContract,
getContractList,
getParamsList,
getTenantList
} from "@/api/modules/dataAsset";
import { Plus } from "@element-plus/icons-vue";
import TableTools from "@/components/Tools/table_tools.vue";
import { useValidator } from '@/hooks/useValidator';
import useUserStore from "@/store/modules/user";
import { cloneDeep } from 'lodash-es';
import { onUploadFileDownload } from '@/api/modules/common';
const { proxy } = getCurrentInstance() as any;
const userStore = useUserStore();
const userData = JSON.parse(userStore.userData)
const { required } = useValidator();
const contractTypes: any = ref([]);
/** 交易合同节点 */
const tradeContractNodesList: any = ref([]);
/** 资产合同节点 */
const registerContractNodesList: any = ref([]);
/** 甲方乙方的下拉会员列表 */
const partyAList: any = ref([]);
const searchItemList = ref([
{
type: "input",
label: "",
field: "contractName",
default: "",
maxlength: 50,
placeholder: "合同名称",
clearable: true,
},
{
label: "",
type: "select",
placeholder: "合同类型",
field: "contractTypeCode",
options: contractTypes.value,
default: '',
filterable: true,
clearable: true,
},
{
type: 'select',
label: '',
field: 'contractNodeCode',
default: '',
placeholder: '进展阶段',
options: [],
clearable: true
},
{
type: "date-range",
field: "dateRange",
default: null,
startPlaceholder: '签约开始日期',
endPlaceholder: '签约结束日期',
clearable: true,
required: true
}
]);
const page = ref({
...commonPageConfig,
contractName: '',
contractTypeCode: '',
contractNodeCode: '',
dateRange: []
});
const toSearch = (val: any, clear: boolean = false) => {
page.value.curr = 1;
if (clear) {
searchItemList.value.map((item) => (item.default = ""));
page.value.contractName = '';
page.value.contractTypeCode = "";
page.value.contractNodeCode = "";
page.value.dateRange = [];
searchItemList.value[2].options = [];
} else {
page.value.contractName = val.contractName;
page.value.contractTypeCode = val.contractTypeCode;
page.value.contractNodeCode = val.contractNodeCode;
page.value.dateRange = val.dateRange;
}
getTableData();
};
const tableTools = ref();
const handleSearchChange = (val, row, info) => {
if (row.field == 'contractTypeCode') {
tableTools.value.toolSearch.formInline.contractNodeCode = '';
searchItemList.value[2].options = val == '1' ? registerContractNodesList.value : (!val ? [] : tradeContractNodesList.value);
}
}
const getTableData = () => {
tableInfo.value.loading = true;
getContractList({
pageSize: page.value.limit,
pageIndex: page.value.curr,
contractName: page.value.contractName,
contractTypeCode: page.value.contractTypeCode,
contractNodeCode: page.value.contractNodeCode,
startDate: page.value.dateRange?.[0] || '',
endDate: page.value.dateRange?.[1] || '',
}).then((res: any) => {
tableInfo.value.loading = false
if (res.code == proxy.$passCode) {
const data = res.data || {}
tableInfo.value.data = data.records || [];
tableInfo.value.page.curr = data.pageIndex;
tableInfo.value.page.rows = data.totalRows || 0;
} else {
proxy.$ElMessage.error(res.msg);
}
})
}
const currTableData: any = ref({});
const tableInfo = ref({
id: 'contract-data-table',
rowKey: 'guid',
loading: false,
fields: [
{ label: "合同名称", field: "contractName", width: 160, align: "left" },
{ label: "合同类型", field: "contractTypeName", width: 110 },
{ label: "甲方名称", field: "partyAName", width: 180 },
{ label: "乙方名称", field: "partyBName", width: 180 },
{ label: "签约日期", field: "signContractDate", width: 110 },
],
childFields: [
{ label: "进展节点", field: "contractNodeName", width: 140, align: "left" },
{ label: "开始日期", field: "startDate", width: TableColumnWidth.DATE },
{ label: "结束日期", field: "endDate", width: TableColumnWidth.DATE },
{ label: "工作内容描述", field: "contentDescribe", width: 280 },
],
data: [],
page: {
type: "normal",
rows: 0,
...page.value,
}
});
const getNodeSteps = (scope) => {
let contractNodeCodes = scope.row.contractNodeCodes || [];
return {
list: contractNodeCodes.map((n, index) => {
return {
// tooltip: {
// placement: 'top',
// content: n.name,
// className: 'step_title_tooltip',
// effect: 'light',
// },
title: n.name,
value: index + 1
}
}),
step: !scope.row.contractNodes?.length ? null : (scope.row.contractNodes.length - 1)
}
}
const contractEditFormItems = ref([
{
label: "合同类型",
type: "select",
placeholder: "请选择",
field: "contractTypeCode",
options: contractTypes.value,
default: '',
filterable: true,
clearable: true,
required: true,
},
{
type: "input",
label: "合同名称",
field: "contractName",
default: "",
maxlength: 50,
placeholder: "请输入",
clearable: true,
required: true,
},
{
label: "甲方名称",
type: "select",
placeholder: "请选择",
field: "partyAGuid",
options: partyAList.value,
props: {
value: 'guid',
label: 'tenantName'
},
default: '',
filterable: true,
clearable: true,
required: true,
},
{
label: "乙方名称",
type: "select",
placeholder: "请选择",
field: "partyBGuid",
options: partyAList.value,
props: {
value: 'guid',
label: 'tenantName'
},
default: '',
filterable: true,
clearable: true,
required: true,
},
{
label: "跟进节点",
type: "select",
placeholder: "请选择",
field: "contractNodeCodes",
options: [],
multiple: true,
default: [],
filterable: true,
collapse: true,
tagsTooltip: true,
clearable: true,
required: true,
},
{
label: '签约日期',
type: 'date',
placeholder: '请输入',
field: 'signContractDate',
default: "",
unlink: true,
disabled: false,
clearable: true,
required: true
},
]);
const contractEditFormRules = ref({
contractTypeCode: [required('请选择合同类型')],
contractName: [required('请填写合同名称')],
partyAGuid: [required('请选择甲方名称')],
partyBGuid: [required('请选择乙方名称')],
contractNodeCodes: [required('请选择跟进节点')],
signContractDate: [required('请选择签约日期')],
});
/** 新增分类的form */
const contractEditFormInfo = ref({
type: "form",
title: "",
col: "span",
formInfo: {
id: "add-class-form",
readonly: false,
items: contractEditFormItems.value,
rules: contractEditFormRules.value,
},
});
const drawerRef = ref();
/** 新增编辑分类。 */
const drawerInfo = ref({
visible: false,
direction: 'rtl',
size: 550,
header: {
title: '新增合同',
},
type: '',
container: {
contents: [contractEditFormInfo.value],
},
footer: {
visible: true,
btns: [
{ type: 'default', label: '取消', value: 'cancel' },
{ type: 'primary', label: '确定', value: 'save', loading: false },
]
}
})
const validate = async () => {
if (!nodesInfo.value?.length) {
return true;
}
let taskIndex = 0;
for (const task of nodesInfo.value) {
let res = await depFormRef.value['ref-' + task.contractNodeCode]?.ruleFormRef?.validate((valid, errorItem) => {
if (!valid) {
var obj = Object.keys(errorItem);
depFormRef.value['ref-' + task.contractNodeCode]?.ruleFormRef?.scrollToField(obj[0]);
return false;
}
})
if (!res) {
return res;
}
taskIndex++;
}
return true;
}
const drawerBtnClick = async (btn, info) => {
if (btn.value == 'cancel') {
drawerInfo.value.visible = false;
} else {
if (info.partyAGuid == info.partyBGuid) {
proxy.$ElMessage.error(`甲方名称跟乙方名称不能选择同一个`);
drawerRef.value?.getDrawerConRef('drawerFormRef')?.ruleFormRef?.scrollToField('partyAGuid');
return;
}
let res = await validate();
if (!res) {
return
}
info.contractNodes = [];
let index = 0;
for (const n of nodesInfo.value) {
let formInline = depFormRef.value['ref-' + n.contractNodeCode].formInline;
if (index != 0) {
if (formInline.dateRange[0] < info.contractNodes[index - 1].endDate) {
proxy.$ElMessage.error(`【${n.contractNodeName}】的开始日期应大于等于上一个节点的结束日期`);
depFormRef.value['ref-' + n.contractNodeCode]?.ruleFormRef?.scrollToField('dateRange');
return;
}
}
info.contractNodes.push(Object.assign({}, formInline, {
contractNodeCode: n.contractNodeCode,
contractGuid: currTableData.value.guid,
contractTypeCode: info.contractTypeCode,
startDate: formInline.dateRange[0],
endDate: formInline.dateRange[1],
nodeAchievement: formInline.nodeAchievement?.map(n => {
return {
name: n.name,
url: n.url
}
}) || []
}))
index++;
}
drawerInfo.value.footer.btns[1].loading = true;
if (drawerInfo.value.type == 'add') {
saveDamContract(info).then((res: any) => {
drawerInfo.value.footer.btns[1].loading = false;
if (res.code == proxy.$passCode) {
page.value.curr = 1;
getTableData();
proxy.$ElMessage.success('新增合同成功');
drawerInfo.value.visible = false;
} else {
proxy.$ElMessage.error(res.msg);
}
})
} else {
const params = { ...info };
params.guid = currTableData.value.guid;
updateDamContract(params).then((res: any) => {
drawerInfo.value.footer.btns[1].loading = false;
if (res.code == proxy.$passCode) {
getTableData();
proxy.$ElMessage.success('修改合同成功');
drawerInfo.value.visible = false;
} else {
proxy.$ElMessage.error(res.msg);
}
})
}
}
}
const drawerSelectChange = (val, row, info) => {
if (row.field == 'contractTypeCode') {
contractEditFormItems.value.forEach(item => {
item.default = info[item.field];
if (item.field == 'contractNodeCodes') {
item.default = '';
nodesInfo.value = [];
item.options = val == '1' ? registerContractNodesList.value : (!val ? [] : tradeContractNodesList.value);
}
});
} else if (row.field == 'contractNodeCodes') {
info.contractNodeCodes = val?.sort((a, b) => parseInt(a) - parseInt(b));
let oldNodesInfo = nodesInfo.value;
let nodeInfo: any[] = [];
info.contractNodeCodes?.forEach(code => {
let node = oldNodesInfo.find(on => on.contractNodeCode == code);
if (node) {
let formInline = depFormRef.value['ref-' + node.contractNodeCode]?.formInline || {};
node.nodeFormItems.forEach(item => {
item.default = formInline[item.field];
})
nodeInfo.push(node);
} else {
if (oldNodesInfo.length > 0 && parseInt(code) < parseInt(oldNodesInfo[oldNodesInfo.length - 1].contractNodeCode)) {
nodeInfo.push({
contractNodeCode: code,
contractNodeName: registerContractNodesList.value.find(r => r.value == code)?.label || tradeContractNodesList.value.find(r => r.value == code)?.label,
nodeFormItems: cloneDeep(nodeFormItems.value),
nodeFormRules: nodeFormRules.value
});
}
}
}) || [];
nodesInfo.value = nodeInfo;
}
}
const contractNodeCodes = computed(() => {
return drawerRef.value?.getDrawerConRef('drawerFormRef')?.formInline?.contractNodeCodes;
})
const handleNodeFileView = (scope) => {
let file = scope.row?.nodeAchievement?.[0];
onUploadFileDownload(file);
}
const handleTableEdit = (scope) => {
drawerInfo.value.visible = true;
drawerInfo.value.type = 'edit';
drawerInfo.value.header.title = '编辑合同';
drawerInfo.value.footer.visible = true;
currTableData.value = scope.row;
contractEditFormItems.value.forEach(item => {
item.default = scope.row[item.field];
item.disabled = false;
if (item.field == 'contractNodeCodes') {
item.default = scope.row.contractNodeCodes?.map(c => c.code) || [];
item.options = scope.row.contractTypeCode == '1' ? registerContractNodesList.value : (!scope.row.contractTypeCode ? [] : tradeContractNodesList.value);
}
})
nodesInfo.value = scope.row.contractNodes?.map(node => {
let items = cloneDeep(nodeFormItems.value);
items.forEach(item => {
item.disabled = false;
item.default = node[item.field];
if (item.field == 'dateRange') {
item.default = [node.startDate, node.endDate];
}
})
return Object.assign({}, node, {
nodeFormItems: items,
nodeFormRules: nodeFormRules.value
})
}) || [];
}
const handleTableDel = (scope) => {
proxy.$openMessageBox("确定要删除该登记合同吗?", () => {
delDamContract([scope.row.guid]).then((res: any) => {
if (res.code == proxy.$passCode) {
page.value.curr = 1;
getTableData();
proxy.$ElMessage.success('删除登记合同成功');
} else {
proxy.$ElMessage.error(res.msg);
}
});
}, () => {
proxy.$ElMessage.info("已取消删除");
})
}
const handleTableView = (scope) => {
drawerInfo.value.visible = true;
drawerInfo.value.type = 'view';
drawerInfo.value.header.title = '查看合同';
currTableData.value = scope.row;
contractEditFormItems.value.forEach(item => {
item.default = scope.row[item.field];
item.disabled = true;
if (item.field == 'contractNodeCodes') {
item.default = scope.row.contractNodeCodes?.map(c => c.code) || [];
item.options = scope.row.contractTypeCode == '1' ? registerContractNodesList.value : (!scope.row.contractTypeCode ? [] : tradeContractNodesList.value);
}
})
nodesInfo.value = scope.row.contractNodes?.map(node => {
let items = cloneDeep(nodeFormItems.value);
items.forEach(item => {
item.default = node[item.field];
item.disabled = true;
if (item.field == 'dateRange') {
item.default = [node.startDate, node.endDate];
}
})
return Object.assign({}, node, {
nodeFormItems: items,
nodeFormRules: nodeFormRules.value
})
}) || [];
drawerInfo.value.footer.visible = false;
}
const handleCreate = () => {
drawerInfo.value.visible = true;
drawerInfo.value.type = 'add';
drawerInfo.value.header.title = '新增合同';
drawerInfo.value.footer.visible = true;
contractEditFormItems.value.forEach(item => {
item.default = '';
item.disabled = false;
if (item.field == 'partyBGuid') {
item.default = userData.tenantGuid;
}
})
}
const nodesInfo: any = ref([]);
const depFormRef = ref({});
const setDepItemRef = (el: any, index: string) => {
if (el) {
depFormRef.value['ref-' + index] = el;
}
}
const nodeFormItems = ref([{
label: "开始日期~结束日期",
type: "date-picker",
field: "dateRange",
default: [],
placeholder: "开始日期~结束日期",
clearable: true,
format: 'YYYY-MM-DD',
valueFormat: 'YYYY-MM-DD',
block: true,
required: true,
},
// {
// label: '开始日期',
// type: 'date',
// placeholder: '请选择',
// field: 'startDate',
// default: "",
// unlink: true,
// disabled: false,
// clearable: true,
// required: true
// }, {
// label: '结束日期',
// type: 'date',
// placeholder: '请选择',
// field: 'endDate',
// default: "",
// unlink: true,
// disabled: false,
// clearable: true,
// required: true
// },
{
label: '节点成果上传',
tip: '支持格式:xls .xlsx .doc .docx .rar .zip',
type: 'upload-file',
accept: '.xls, .xlsx, .doc, .docx, .rar, .zip',
required: true,
block: true,
visible: true,
default: [],
field: 'nodeAchievement',
limit: 1,
}, {
label: '工作内容描述',
type: 'textarea',
placeholder: '请输入',
field: 'contentDescribe',
default: '',
maxlength: 200,
block: true,
clearable: true,
},]);
const nodeFormRules = ref({
dateRange: [{
type: 'array', required: true, message: '请填写开始日期~结束日期', trigger: 'change',
}],
// startDate: [required('请填写开始日期')],
// endDate: [required('请填写结束日期')],
nodeAchievement: [{
validator: (rule: any, value: any, callback: any) => {
if (!value?.length) {
callback(new Error('请上传节点成果附件'))
} else {
callback();
}
}, trigger: 'change'
}],
});
const addNode = () => {
let len = nodesInfo.value.length;
let code = contractNodeCodes.value[len];
let nodeList = drawerRef.value?.getDrawerConRef('drawerFormRef')?.formInline?.contractTypeCode == '2' ? tradeContractNodesList.value : registerContractNodesList.value;
nodesInfo.value.push({
contractNodeCode: code,
contractNodeName: nodeList.find(r => r.value == code)?.label,
nodeFormItems: cloneDeep(nodeFormItems.value),
nodeFormRules: nodeFormRules.value
})
}
const handleDelNode = (index) => {
proxy.$openMessageBox("确定要删除该进展阶段节点信息录入吗?", () => {
nodesInfo.value.splice(index, 1);
}, () => {
proxy.$ElMessage.info("已取消删除");
})
}
onBeforeMount(() => {
getParamsList({
dictType: "资产合同类型"
}).then((res: any) => {
contractTypes.value = [];
if (res.code == proxy.$passCode) {
contractTypes.value = res.data || [];
searchItemList.value[1].options = contractTypes.value;
contractEditFormItems.value[0].options = contractTypes.value;
} else {
proxy.$ElMessage.error(res.msg);
}
})
getParamsList({
dictType: "交易合同节点"
}).then((res: any) => {
tradeContractNodesList.value = [];
if (res.code == proxy.$passCode) {
tradeContractNodesList.value = res.data || [];
} else {
proxy.$ElMessage.error(res.msg);
}
})
getParamsList({
dictType: "登记合同节点"
}).then((res: any) => {
registerContractNodesList.value = [];
if (res.code == proxy.$passCode) {
registerContractNodesList.value = res.data || [];
} else {
proxy.$ElMessage.error(res.msg);
}
})
getTenantList({
bizState: 'Y',
pageSize: -1
}).then((res: any) => {
partyAList.value = [];
if (res.code == proxy.$passCode) {
partyAList.value = res.data?.records || [];
contractEditFormItems.value[2].options = partyAList.value;
contractEditFormItems.value[3].options = partyAList.value;
} else {
proxy.$ElMessage.error(res.msg);
}
})
})
</script>
<template>
<div class="container_wrap">
<div class="table_tool_wrap">
<TableTools ref="tableTools" :searchItems="searchItemList" :searchId="'contract-data-search'" @search="toSearch"
:init="true" @select-change="handleSearchChange" />
</div>
<div class="tools_btns">
<el-button type="primary" @click="handleCreate">新增</el-button>
</div>
<div class="table_panel_wrap">
<el-table v-loading="tableInfo.loading" ref="tableRef" :data="tableInfo.data" :highlight-current-row="true" stripe
border height="100%" tooltip-effect="light" row-key="guid" class="expand-table"
:style="{ width: '100%', height: 'calc(100% - 8px)', margin: '8px 0px', display: 'inline-block', }">
<el-table-column type="expand">
<template #default="scope">
<el-table ref="fieldsTableRef" :data="scope.row.contractNodes" :highlight-current-row="true" stripe border
height="100%" tooltip-effect="light" :style="{
width: '100%',
'max-height': '100%',
display: 'inline-block',
}">
<el-table-column label="序号" type="index" width="56px" align="center" show-overflow-tooltip>
</el-table-column>
<el-table-column v-for="field in tableInfo.childFields" :prop="field.field" :label="field.label"
:width="field.width" :align="field.align" show-overflow-tooltip>
<template #default="scope">
<span>{{ scope.row[field.field || ''] || '--' }}</span>
</template>
</el-table-column>
<el-table-column label="附件信息" width="120px" align="left" fixed="right" show-overflow-tooltip>
<template #default="scope">
<span class="text_btn" @click="handleNodeFileView(scope)">查看</span>
</template>
</el-table-column>
</el-table>
</template>
</el-table-column>
<el-table-column label="序号" type="index" width="56px" align="center" show-overflow-tooltip>
</el-table-column>
<el-table-column v-for="field in tableInfo.fields" :prop="field.field" :label="field.label" :width="field.width"
:align="field.align" show-overflow-tooltip>
<template #default="scope">
<span>{{ scope.row[field.field || ''] || '--' }}</span>
</template>
</el-table-column>
<el-table-column label="进展阶段" width="450px" align="center">
<template #default="scope">
<div class="custom-steps" v-if="scope.row.contractNodeCodes?.length">
<StepBar :steps-info="getNodeSteps(scope)" />
</div>
<span v-else>--</span>
</template>
</el-table-column>
<el-table-column label="操作" width="100px" align="left" fixed="right" show-overflow-tooltip>
<template #default="scope">
<span v-if="!scope.row.createUserId || scope.row.createUserId == userData.userGuid" class="text_btn" @click="handleTableEdit(scope)">编辑</span>
<span v-if="!scope.row.createUserId || scope.row.createUserId == userData.userGuid" class="text_btn ml4" @click="handleTableDel(scope)">删除</span>
<span v-if="scope.row.createUserId && scope.row.createUserId != userData.userGuid" class="text_btn ml4" @click="handleTableView(scope)">查看</span>
</template>
</el-table-column>
</el-table>
</div>
<Drawer :drawerInfo="drawerInfo" @drawerBtnClick="drawerBtnClick" ref="drawerRef"
@drawerSelectChange='drawerSelectChange'>
<!-- 传递到 Form 组件中的默认插槽 -->
<template v-slot:default>
<template v-if="contractNodeCodes?.length > 0">
<div v-show="!(!nodesInfo?.length && drawerInfo.type == 'view')" class="title-label">进展阶段录入</div>
<!-- 渲染行 -->
<div v-for="(row, index) in nodesInfo" :key="index" class="match-content-wrapper">
<div class="title-row"><span class="title">{{ row.contractNodeName }}</span><span class="btns"
v-show="index == nodesInfo.length - 1" @click="handleDelNode(index)">删除</span></div>
<Form :ref="(el: any) => { setDepItemRef(el, row.contractNodeCode) }" :itemList="row.nodeFormItems"
:formId="'node-form' + index" :rules="row.nodeFormRules" col="col2" />
</div>
<!-- 新增按钮 -->
<div class="bottm_tools" v-show="nodesInfo.length < contractNodeCodes?.length && drawerInfo.type != 'view'" @click="addNode">
<el-icon>
<Plus />
</el-icon>
<span>新增进展</span>
</div>
</template>
</template>
</Drawer>
</div>
</template>
<style lang="scss" scoped>
.container_wrap {
padding: 0 16px;
}
.table_panel_wrap {
height: calc(100% - 94px);
}
.ml4 {
margin-left: 4px;
}
:deep(.custom-steps) {
width: 100%;
height: 64px;
display: flex;
.el-steps {
width: 100%;
}
}
.title-label {
margin-bottom: 4px;
font-size: 18px;
color: #212121;
}
.title-row {
height: 48px;
display: flex;
justify-content: space-between;
align-items: center;
.title {
color: #212121;
font-size: 16px;
font-weight: 600;
}
.btns {
cursor: pointer;
color: var(--el-color-primary);
font-size: 14px;
}
}
.bottm_tools {
width: 100%;
height: 40px;
display: flex;
justify-content: center;
align-items: center;
background: #fafafa;
color: #999;
font-size: 14px;
border: 1px dashed var(--el-border-color-regular);
margin-bottom: 12px;
>span {
margin-left: 8px;
}
&:hover {
background: #EBF6F7;
border: 1px dashed var(--el-color-primary);
}
}
:deep(.el-table.expand-table) {
.el-table__expanded-cell.el-table__cell {
background: #fff !important;
padding-left: 48px;
padding-right: 8px;
}
}
:deep(.el-steps) {
.el-step__head.is-finish .el-step__icon.is-icon {
background-color: transparent;
}
}
</style>
\ No newline at end of file
<route lang="yaml">
name: apiCalls
</route>
<script lang="ts" setup name="apiCalls">
import { ref } from 'vue';
import { TableColumnWidth } from '@/utils/enum';
import { commonPageConfig } from '@/components/PageNav/index';
import TableTools from '@/components/Tools/table_tools.vue';
import { useRouter, useRoute } from "vue-router";
import {
getAppProductData,
deleteAppProduct
} from "@/api/modules/dataService";
import useDataServiceStore from "@/store/modules/dataService";
const { proxy } = getCurrentInstance() as any;
const router = useRouter();
const dataServiceStore = useDataServiceStore();
/** 分页及搜索传参信息配置。 */
const page = ref({
...commonPageConfig,
productName: ''
});
const searchItemList = ref([
{
type: "input",
label: "",
field: "productName",
default: "",
placeholder: "应用名称",
clearable: true,
}
]);
const tableInfo = ref({
id: 'data-app-table',
fields: [
{ label: "序号", type: "index", width: TableColumnWidth.INDEX, align: "center" },
{ label: "应用名称", field: "productName", width: 140 },
{ label: "appKey", field: "appKey", width: 140 },
{ label: "appSecret", field: "appSecret", width: 120 },
{
label: "绑定API数", field: "apiBingingNum", width: 100, align: 'right', type: 'chnum'
},
{
label: "调用次数", field: "invokeNum", width: 100, align: 'right', type: 'chnum'
},
{
label: "调用异常数", field: "invokeErrorNum", width: 105, align: 'right', type: 'chnum'
},
{ label: "应用负责人", field: "directorName", width: TableColumnWidth.USERNAME },
{ label: "修改人", field: "updateUserName", width: TableColumnWidth.USERNAME },
{ label: "修改时间", field: "updateTime", width: TableColumnWidth.DATETIME },
],
data: [],
page: {
type: "normal",
rows: 0,
...page.value,
},
actionInfo: {
label: "操作",
type: "btn",
width: 120,
fixed: 'right',
btns: (scope) => {
const row = scope.row
let btnsArr: any = [];
btnsArr.push({
label: "编辑", value: "edit", click: (scope) => {
router.push({
name: 'apiBind',
query: {
guid: scope.row.guid,
productName: scope.row.productName
}
});
}
});
btnsArr.push({
label: "删除", value: "delete", click: (scope) => {
if (scope.row.apiBingingNum > 0) {
proxy.$ElMessage.warning('该应用有绑定的API,无法删除');
return;
}
proxy.$openMessageBox('确定要删除该应用吗?', () => {
deleteAppProduct([scope.row.guid]).then((res: any) => {
if (res.code == proxy.$passCode) {
page.value.curr = 1;
getTableData();
proxy.$ElMessage.success("删除成功");
} else {
proxy.$ElMessage.error(res.msg);
}
});
}, () => {
proxy.$ElMessage.info("已取消");
})
}
});
return btnsArr
},
},
loading: false
})
const toSearch = (val: any, clear: boolean = false) => {
page.value.curr = 1;
if (clear) {
searchItemList.value.map((item) => (item.default = ""));
page.value.productName = '';
} else {
page.value.productName = val.productName;
}
getTableData();
};
const tablePageChange = (info) => {
page.value.curr = Number(info.curr);
page.value.limit = Number(info.limit);
getTableData();
};
const getTableDataPromise: any = ref(null);
const getTableData = () => {
tableInfo.value.loading = true
getTableDataPromise.value = getAppProductData({
pageIndex: page.value.curr,
pageSize: page.value.limit,
productName: page.value.productName
}).then((res: any) => {
getTableDataPromise.value = null;
if (res.code == proxy.$passCode) {
const data = res.data || {}
tableInfo.value.data = data.records || []
tableInfo.value.page.limit = data.pageSize
tableInfo.value.page.curr = data.pageIndex
tableInfo.value.page.rows = data.totalRows
} else {
proxy.$ElMessage({
type: 'error',
message: res.msg,
})
}
tableInfo.value.loading = false
})
};
const addAppProduct = () => {
router.push({
name: 'apiBind',
});
}
onBeforeMount(() => {
toSearch({})
})
onActivated(() => {
if (dataServiceStore.isUpdate) {
if (getTableDataPromise.value) {
getTableDataPromise.value.then(() => {
getTableData();
dataServiceStore.setIsUpdate(false);
});
} else {
getTableData();
dataServiceStore.setIsUpdate(false);
}
}
});
</script>
<template>
<div class="container_wrap">
<div class="table_tool_wrap">
<TableTools :searchItems="searchItemList" :searchId="'data-source-search'" @search="toSearch" :init="false" />
<div class="tools_btns">
<el-button type="primary" @click="addAppProduct" v-preReClick>添加</el-button>
</div>
</div>
<div class="table_panel_wrap">
<Table :tableInfo="tableInfo" @tablePageChange="tablePageChange" />
</div>
</div>
</template>
<style lang="scss" scoped>
.table_tool_wrap {
width: 100%;
height: 84px !important;
padding: 0 8px;
.tools_btns {
padding: 0px 0 0;
}
}
.table_panel_wrap {
width: 100%;
height: calc(100% - 84px);
padding: 0px 8px 0;
}
</style>
\ No newline at end of file
<route lang="yaml">
name: apiCreate
</route>
<script lang="ts" setup name="apiCreate">
import { ref } from 'vue';
import { useValidator } from '@/hooks/useValidator';
import { CirclePlus } from '@element-plus/icons-vue';
import { TableColumnWidth } from '@/utils/enum';
import { handleContentWrapView, scrollLastRowToView } from '@/utils/common';
import { enableRowDrop, destroySort } from '@/utils/sortable';
import {
apiTypes,
// getDataTypeList,
// getPositionList,
// getOperationList,
getSubjectTableTree,
getSubjectTableByDomain,
getSubjectTableDetail,
checkExistAPIName,
checkExistRequestPath,
addApi,
updateApi,
getApiDetail,
testEditApi,
validateApiSql,
getDomainName
} from "@/api/modules/dataService";
import {
getDataSource,
getSchemaTableList,
tableColumnList,
checkSql,
getParamsDictList,
} from "@/api/modules/queryService";
import { getCamundaDeploymentId, isNeedApprove } from "@/api/modules/workFlowService"
import useUserStore from "@/store/modules/user";
import useDataServiceStore from "@/store/modules/dataService";
import { useDefault } from "@/hooks/useDefault"
const route = useRoute();
const router = useRouter();
const { proxy } = getCurrentInstance() as any;
const { required, description, chOrEnPreffix, regexpValidate, checkExistName } = useValidator();
const { checkValidValue } = useDefault()
const userStore = useUserStore();
const userData = JSON.parse(userStore.userData)
const dataServiceStore = useDataServiceStore();
const scrollContainer = ref(null);
const flowExpand = ref(true);
const bizApproveVO = ref()
const deploymentId = ref('');
const fullPath = route.fullPath;
const apiType: any = ref(route.query.type);
// const sceneName = ref(route.query.tagName);
const apiGuid = ref(route.query.guid);
/** 是否是详情页面。 */
const isDetail = ref(route.query.isDetail);
/** 域名 */
const domainName = ref('');
/** 整个页面的加载状态,获取详情或提交时显示。 */
const fullscreenLoading = ref(false);
/** 编辑时的详情信息。 */
const detailInfo: any = ref({});
/** 默认显示步骤 */
const step = ref(0);
/** 步骤条配置信息 */
const stepsInfo = ref({
step: step.value,
list: [
{ title: '填写API基本信息', value: 1 },
{ title: '配置取数逻辑', value: 2 },
{ title: '测试API', value: 3 },
]
})
/** 验证表格入参是否符合条件 */
const validInputParams = (data, paramTypeName: string = "参数", isConst = false) => {
let paramNames: string[] = [];
let dataIndex = 1;
for (const d of data) {
if (!d.paramName) {
proxy.$ElMessage.error(`第 ${dataIndex}${paramTypeName}名称不能为空`);
return false;
}
// 确保第一个字符是字母
if (!/^[A-Za-z]/.test(d.paramName)) {
proxy.$ElMessage.error(`第 ${dataIndex}${paramTypeName}名称输入必须以字母开头`);
return false;
}
if (paramNames.some(p => p == d.paramName)) {
proxy.$ElMessage.error(`${paramTypeName}名称不能重复`);
return false;
}
if (!d.paramPosition) {
proxy.$ElMessage.error(`第 ${dataIndex}${paramTypeName}位置不能为空`);
return false;
}
if (!d.dataType) {
proxy.$ElMessage.error(`第 ${dataIndex}${paramTypeName}类型不能为空`);
return false;
}
if (checkValidValue[d.dataType]) {
let v = checkValidValue[d.dataType](d.defaultValue, d.isManyValue == 'Y');
if (v !== true) {
proxy.$ElMessage.error(`第 ${dataIndex}${paramTypeName}类型为${v},请输入合法的值`);
return false;
}
}
if (isConst && !d.defaultValue) {
proxy.$ElMessage.error(`第 ${dataIndex}${paramTypeName}的常量值不能为空`);
return;
}
// if (d.isRequired == 'Y' && !d.defaultValue) {
// proxy.$ElMessage.error(`第 ${dataIndex} 个参数为必填则默认值不能为空`);
// return;
// }
paramNames.push(d.paramName);
dataIndex++;
}
return true;
}
/** 步骤条的上一步,下一步。 */
const nextStep = (val) => {
if (val == 1) {
baseInfoFormRef.value?.ruleFormRef?.validate((valid, errorItem) => {
if (valid) {
// if (row.field == 'processOrderGuids') {//场景名称
// }
//验证入参定义表格输入, 入参参数名不能有重复的。
// if (!inputParamsData.value.length) { //请求参数都来自入参定义。
// proxy.$ElMessage.error('入参定义不能为空');
// return;
// }
if (!validInputParams(inputParamsData.value)) {
handleContentWrapView('inputParams');
return;
}
step.value = val;
stepsInfo.value.step = val;
/** 处理数据源表单下拉列表数据获取 */
if (apiType.value == '1') {
if (apiGuid.value && !targetDsFields.value.length) {
getTargetDatabaseList().then(() => {
if (detailInfo.value.dataSourceType == 1) {
getSchemaTableData(detailInfo.value.dataSourceGuid).then(() => {
getBingFieldList(1, detailInfo.value.dataSourceGuid, detailInfo.value.tableName, false);
});
} else {
currDsInfo.value.subjectDomainGuid = detailInfo.value.subjectDomainGuid;
currDsInfo.value.subjectDomainName = detailInfo.value.subjectDomainName;
currDsInfo.value.directoryGuid = detailInfo.value.directoryGuid;
getSubjectDomainData(detailInfo.value.subjectDomainGuid).then(() => {
getBingFieldList(2, detailInfo.value.dataSourceGuid, detailInfo.value.tableGuid, false);
});
}
});
} else {
getTargetDatabaseList();
}
getMatchTableList();
} else if (apiType.value == '2') {
getTargetDatabaseList();
}
} else {
var obj = Object.keys(errorItem);
baseInfoFormRef.value.ruleFormRef.scrollToField(obj[0])
}
if (scrollContainer.value) {
scrollContainer.value.scrollTo({
top: 0,
behavior: 'smooth' // 平滑滚动
});
}
});
} else if (val == 2) {
if (apiType.value != '3') {
//先验证再下一步。
tableInfoFormRef.value?.ruleFormRef?.validate((valid, errorItem) => {
if (valid) {
if (apiType.value == '1') {
/** 请求参数可以不填写,TODO,滚动到可见范围内 */
let requestParamsData: any = requestParamsTableInfo.value.data;
let dataIndex = 1;
for (const d of requestParamsData) {
if (!d.paramName) {
handleContentWrapView('requestParams');
proxy.$ElMessage.error(`第 ${dataIndex} 个请求参数的参数名称不能为空`);
return;
}
if (!d.boundField) {
handleContentWrapView('requestParams');
proxy.$ElMessage.error(`第 ${dataIndex} 个请求参数的绑定字段不能为空`);
return;
}
if (!d.operator) {
handleContentWrapView('requestParams');
proxy.$ElMessage.error(`第 ${dataIndex} 个请求参数的操作符不能为空`);
return;
}
if (d.operator == '2' || d.operator == '11') {
let inputParam = inputParamsData.value.find(param => param.paramName == d.paramName);
if (inputParam && inputParam.isRequired != 'Y') {
handleContentWrapView('requestParams');
proxy.$ElMessage.error(`参数名称:${d.paramName}需必填,请返回上一步修改`);
return;
}
}
dataIndex++;
}
let responseParamsData: any[] = responseParamsTableInfo.value.data;
if (!responseParamsData.length) {
handleContentWrapView('responseParams');
proxy.$ElMessage.error(`返回参数不能为空`);
return;
}
dataIndex = 1;
let resParamNames: string[] = [];
for (const d of responseParamsData) {
if (!d.paramName) {
handleContentWrapView('responseParams');
proxy.$ElMessage.error(`第 ${dataIndex} 个返回参数的参数名不能为空`);
return;
}
if (resParamNames.some(p => p == d.paramName)) {
handleContentWrapView('responseParams');
proxy.$ElMessage.error(`返回参数的参数名称不能重复`);
return;
}
if (!d.boundField) {
handleContentWrapView('responseParams');
proxy.$ElMessage.error(`第 ${dataIndex} 个返回参数的绑定字段不能为空`);
return;
}
if (!d.dataType) {
handleContentWrapView('responseParams');
proxy.$ElMessage.error(`第 ${dataIndex} 个返回参数的参数类型不能为空`);
return;
}
resParamNames.push(d.paramName);
dataIndex++;
}
let sortParamsData: any[] = sortParamsTableInfo.value.data;
dataIndex = 1;
let sortParamNames: string[] = [];
let boundFields: string[] = [];
for (const d of sortParamsData) {
if (!d.paramName) {
handleContentWrapView('sortParams');
proxy.$ElMessage.error(`第 ${dataIndex} 个排序参数的参数名不能为空`);
return;
}
if (sortParamNames.some(p => p == d.paramName)) {
handleContentWrapView('sortParams');
proxy.$ElMessage.error(`排序参数的参数名称不能重复`);
return;
}
if (!d.boundField) {
handleContentWrapView('sortParams');
proxy.$ElMessage.error(`第 ${dataIndex} 个排序参数的绑定字段不能为空`);
return;
}
if (boundFields.some(b => b == d.boundField)) {
handleContentWrapView('sortParams');
proxy.$ElMessage.error(`排序参数的绑定字段不能重复`);
return;
}
if (!d.sortMode) {
handleContentWrapView('sortParams');
proxy.$ElMessage.error(`第 ${dataIndex} 个排序参数的排序方式不能为空`);
return;
}
sortParamNames.push(d.paramName);
boundFields.push(d.boundField);
dataIndex++;
}
/** query参数数据来自于请求参数以及入参定义的结合 */
let queryParamData: any[] = queryParamsTableInfo.value.data;
queryParamsTableInfo.value.data = requestParamsData.map(r => {
let inputParam = inputParamsData.value.find(i => r.paramName == i.paramName);
let introductionValue = queryParamData.find((q: any) => q.paramName == r.paramName)?.introductionValue;
return { ...r, ...inputParam, introductionValue: introductionValue != null ? introductionValue : inputParam.defaultValue };
});
} else if (apiType.value == '2') {
if (!sqlIsChecked.value) {
proxy.$ElMessage.error(`请先验证通过Sql`);
return;
}
/** query参数数据来自于请求参数 */
let queryParamData: any[] = queryParamsTableInfo.value.data;
queryParamsTableInfo.value.data = inputParamsData.value.map(r => {
let introductionValue = queryParamData.find((q: any) => q.paramName == r.paramName)?.introductionValue;
return { ...r, introductionValue: introductionValue != null ? introductionValue : r.defaultValue };
});
}
apiFormItems.value.forEach(item => {
item.default = baseInfoFormRef.value.formInline[item.field];
if (item.field == 'requestMode') {
item.default = item.default == 'G' ? 'get' : 'post';
} else if (item.field == 'requestPath') {
item.default = `https${domainName.value}${item.default}`
}
})
if (baseInfoFormRef.value.formInline.authenticationType == 'N') {
defaultParamsTableInfo.value.data = defaultParamsData.value.concat([{
paramName: 'appKey',
dataType: '字符型',
isRequired: '是',
value: ''
}]);
} else {
defaultParamsTableInfo.value.data = defaultParamsData.value;
}
step.value = val;
stepsInfo.value.step = val;
/** 每次到这一步都清除请求结果。 */
// resultFormItems.value[0].default = '';
// resultFormItems.value[1].default = '';
} else {
//将表单滚动到可见范围内。
var obj = Object.keys(errorItem);
tableInfoFormRef.value.ruleFormRef.scrollToField(obj[0])
}
});
} else {
backApiInfoFormRef.value?.ruleFormRef?.validate((valid, errorItem) => {
if (valid) {
if (!validInputParams(registRequestParamsTableInfo.value.data, '请求参数')) {
handleContentWrapView('registRequestParams');
return;
}
if (!validInputParams(constParamsTableInfo.value.data, '常量参数', true)) {
handleContentWrapView('constParams');
return;
}
/** query参数数据来自于请求参数 */
let queryParamData: any[] = queryParamsTableInfo.value.data;
queryParamsTableInfo.value.data = registRequestParamsTableInfo.value.data.map((r: any) => {
let introductionValue = queryParamData.find((q: any) => q.paramName == r.paramName)?.introductionValue;
return { ...r, introductionValue: introductionValue != null ? introductionValue : r.defaultValue };
});
constParamsTableInfo.value.data.map((r: any) => {
let introductionValue = queryParamData.find((q: any) => q.paramName == r.paramName)?.introductionValue;
queryParamsTableInfo.value.data.push({ ...r, introductionValue: introductionValue != null ? introductionValue : r.defaultValue, isConst: true });
});
apiFormItems.value.forEach(item => {
item.default = baseInfoFormRef.value.formInline[item.field];
if (item.field == 'requestMode') {
item.default = item.default == 'G' ? 'get' : 'post';
} else if (item.field == 'requestPath') {
item.default = `https${domainName.value}${item.default}`
}
})
if (baseInfoFormRef.value.formInline.authenticationType == 'N') {
defaultParamsTableInfo.value.data = defaultParamsData.value.concat([{
paramName: 'appKey',
dataType: '字符型',
isRequired: '是',
value: ''
}]);
} else {
defaultParamsTableInfo.value.data = defaultParamsData.value;
}
step.value = val;
stepsInfo.value.step = val;
/** 每次到这一步都清除请求结果。 */
// resultFormItems.value[0].default = '';
// resultFormItems.value[1].default = '';
} else {
var obj = Object.keys(errorItem);
backApiInfoFormRef.value.ruleFormRef.scrollToField(obj[0])
}
})
}
if (scrollContainer.value) {
scrollContainer.value.scrollTo({
top: 0,
behavior: 'smooth' // 平滑滚动
});
}
}
};
const previousStep = (val) => {
step.value = val - 1;
stepsInfo.value.step = val - 1;
if (scrollContainer.value) {
scrollContainer.value.scrollTo({
top: 0,
behavior: 'smooth' // 平滑滚动
});
}
}
/** ---------------------------- 获取参数字典 -------------------------- */
const dataTypeList: any = ref([]);
/** 获取参数类型下拉选项 */
const getParamDataTypeList = () => {
getParamsDictList('字段类型').then((res: any) => {
dataTypeList.value = [];
if (res.code == proxy.$passCode) {
dataTypeList.value = res.data || [];
inputParamsTableInfo.value.editInfo.dataType.options = dataTypeList.value;
responseParamsTableInfo.value.editInfo.dataType.options = dataTypeList.value;
registRequestParamsTableInfo.value.editInfo.dataType.options = dataTypeList.value;
constParamsTableInfo.value.editInfo.dataType.options = dataTypeList.value;
} else {
proxy.$ElMessage.error(res.msg);
}
})
}
const paramPositionList: any = ref([]);
/** 获取参数类型下拉选项 */
const getParamPositionList = () => {
getParamsDictList('API参数位置').then((res: any) => {
paramPositionList.value = [];
if (res.code == proxy.$passCode) {
paramPositionList.value = res.data || [];
inputParamsTableInfo.value.editInfo.paramPosition.options = paramPositionList.value;
registRequestParamsTableInfo.value.editInfo.paramPosition.options = paramPositionList.value;
constParamsTableInfo.value.editInfo.paramPosition.options = paramPositionList.value;
} else {
proxy.$ElMessage.error(res.msg);
}
})
}
const paramOperatorList: any = ref([])
/** 获取参数操作符下拉选项 */
const getParamOperatorList = () => {
getParamsDictList('参数操作符').then((res: any) => {
paramOperatorList.value = [];
if (res.code == proxy.$passCode) {
paramOperatorList.value = res.data || [];
requestParamsTableInfo.value.editInfo.operator.options = paramOperatorList.value;
} else {
proxy.$ElMessage.error(res.msg);
}
})
}
const sceneList: any = ref([]);//场景列表
/** 获取参数类型下拉选项 */
// const getParamSceneList = () => {
// let query={
// pageIndex: 1,
// pageSize: -1,
// tenantGuid: userData.tenantGuid
// }
// getSceneList(query).then((res: any) => {
// sceneList.value = [];
// if (res.code == proxy.$passCode) {
// sceneList.value = res.data.records || [];
// baseFormItems.value[3].options = sceneList.value
// } else {
// proxy.$ElMessage.error(res.msg);
// }
// })
// }
// const processSheetList: any = ref([]);//场景列表
// /** 获取参数类型下拉选项 */
// const getParamProcessSheetList = () => {
// getProcessSheetListByUser(userData.staffGuid).then((res: any) => {
// processSheetList.value = [];
// if (res.code == proxy.$passCode) {
// processSheetList.value = res.data || [];
// baseFormItems.value[5].options = processSheetList.value
// } else {
// proxy.$ElMessage.error(res.msg);
// }
// })
// }
/** ----------------------------第一步填写基本信息 -------------------------- */
/** 基本信息表单组件引用 */
const baseInfoFormRef = ref();
/** 基本信息表单配置。 */
const baseFormItems = ref([{
label: 'API名称',
type: 'input',
placeholder: '只能以中文或英文开头',
field: 'apiName',
maxlength: 50,
regexp: /[^a-zA-Z0-9_\u4e00-\u9fa5-]/g,
default: '',
required: true
}, {
label: '返回类型',
type: 'select',
options: [{
label: 'json',
value: 'json'
}, {
label: 'xml',
value: 'xml'
}],
placeholder: '请选择',
field: 'responseType',
default: 'json',
clearable: true,
filterable: true,
required: true
}, {
label: 'API类型',
type: 'select',
options: apiTypes,
placeholder: '请选择',
field: 'apiType',
default: parseInt(apiType.value),
disabled: true,
required: true
},
// {
// label: '场景名称',
// type: 'select',
// options: sceneList.value,
// placeholder: '请选择',
// field: 'sceneGuid',
// default: '',
// props: {
// value: 'guid',
// label: 'sceneName'
// },
// required: true,
// visible: false
// },
{
type: "select-group",
field: "httpInfo",
col: ' select-input-long',
children: [
{
label: "请求路径",
type: "input",
placeholder: "请选择",
default: "https",
field: "httpType",
required: true,
disabled: true,
visible: true,
},
{
label: " ",
type: "input",
placeholder: "请输入",
default: '/',
field: "requestPath",
maxlength: 50,
required: true,
visible: true,
},
],
visible: true
},
// {
// label: '场景名称',
// type: 'input',
// placeholder: '请选择',
// field: 'sceneName',
// default: '',
// disabled: true,
// },
// {
// label: '加工单号',
// type: 'select',
// options: processSheetList.value,
// placeholder: '请选择',
// field: 'processOrderGuids',
// default: '',
// props: {
// value: 'guid',
// label: 'requirementOrderName'
// },
// required: true,
// filterable: true,
// clearable: true,
// // multiple: true,
// // tagsTooltip: true,
// // collapse: true,
// // maxTags: 1,
// },
// {
// label: '加工单号',
// type: 'input',
// placeholder: '请选择',
// field: 'processOrderNo',
// default: null,
// visible: false
// },
{
label: '请求方式',
type: 'select',
options: [{
value: 'P',
label: 'post'
}, {
value: 'G',
label: 'get'
}],
placeholder: '请选择',
field: 'requestMode',
default: 'P',
clearable: true,
filterable: true,
// disabled: true,
required: true
}, {
label: '安全认证',
type: 'select',
options: [{
value: 'T',
label: 'TOKEN认证'
},
// {
// value: 'N',
// label: '无认证'
// }
],
placeholder: '请选择',
field: 'authenticationType',
default: 'T',
clearable: true,
filterable: true,
disabled: true,
required: true
},
// {
// label: "IP白名单",
// type: "select",
// placeholder: "请选择",
// default: [],
// field: "whiteIPs", //只有无安全认证时显示。
// options: whiteIPsList.value,
// props: {
// value: 'guid',
// label: 'ip'
// },
// filterable: true,
// clearable: true,
// multiple: true,
// tagsTooltip: true,
// collapse: true,
// maxTags: 1,
// required: true,
// visible: false,
// },
{
label: 'API描述',
type: 'textarea',
placeholder: '请输入',
field: 'apiDescription',
default: '',
maxlength: 200,
block: true,
clearable: true,
required: true,
},
// {
// label: "加工单对象",
// type: "select",
// placeholder: "请选择",
// default: [],
// field: "processDTOS",
// options: whiteIPsList.value,
// props: {
// value: 'guid',
// label: 'ip'
// },
// filterable: true,
// clearable: true,
// multiple: true,
// tagsTooltip: true,
// collapse: true,
// maxTags: 1,
// required: true,
// visible: false,
// },
])
/** 记录已检验过的APIName */
const checkedInfo = ref({});
/** 记录已检验过的API路径 */
const checkedPathInfo = ref({});
/** 基本信息表单配置规则。 */
const baseFormRules = ref({
apiName: [required("请填写API名称"), chOrEnPreffix(), checkExistName(checkedInfo.value, checkExistAPIName, detailInfo.value, 'apiName')],
responseType: [required("请选择返回类型")],
// sceneGuid: [required("请选择场景名称")],
// processOrderGuids: [required("请选择加工单号")],
/** 此处请求路径后端说只能输入一级。 */
requestPath: [required("请填写请求路径"), regexpValidate(/^\/[^\/][\w\u4e00-\u9fa5_-]*$/, '请填写合法的请求路径'), checkExistName(checkedPathInfo.value, checkExistRequestPath, detailInfo.value, 'requestPath', '该请求路径已存在,请填写其他路径')],
requestMode: [required("请选择请求方式")],
authenticationType: [required("请选择安全认证")],
apiDescription: [required('请填写API描述'), description(200)],
// whiteIPs: [required('请选择IP白名单')],
});
const inputParamsTableRef = ref();
const inputParamsData: any = ref([]);
/** 基本信息的入参定义表格配置 */
const inputParamsTableInfo = ref({
id: "input-params-table",
height: '214px',
fields: [
{ label: "序号", type: "index", width: TableColumnWidth.INDEX, align: "center" },
{ label: "参数名", field: "paramName", width: 140, required: true, columClass: 'edit-colum', type: 'edit' },
{ label: "参数位置", field: "paramPosition", width: 120, required: true, columClass: 'edit-colum', type: 'edit' },
{ label: "参数类型", field: "dataType", width: 120, required: true, columClass: 'edit-colum', type: 'edit', impactValue: "defaultValue" },
{ label: "是否必填", field: "isRequired", width: 100, required: true, columClass: 'edit-colum', type: 'edit' },
{ label: "是否多值", field: "isManyValue", width: 100, required: true, columClass: 'edit-colum', type: 'edit' },
{ label: "默认值", field: "defaultValue", width: 160, columClass: 'edit-colum', type: 'edit', dataTypeName: 'dataType' },
{ label: "描述", field: "description", width: 160, columClass: 'edit-colum', type: 'edit' },
],
editInfo: {
paramName: {
needCacheOldValue: true,
label: '',
type: 'input',
field: 'paramName',
default: '',
maxlength: 50,
regexp: /[^A-Za-z0-9_]/g,
placeholder: '请输入',
clearable: true,
},
paramPosition: {
label: '',
type: 'select',
field: 'paramPosition',
default: '',
options: paramPositionList.value,
props: {
label: 'label',
value: 'value'
},
placeholder: '请选择',
clearable: true,
filterable: true
},
dataType: {
label: '',
type: 'select',
field: 'dataType',
default: '',
options: dataTypeList.value,
props: {
label: 'label',
value: 'value'
},
placeholder: '请选择',
clearable: true,
filterable: true
},
isRequired: {
label: '',
type: 'select',
field: 'isRequired',
default: 'N',
options: [
{
label: "是",
value: "Y",
},
{
label: "否",
value: "N",
},
],
placeholder: '请选择',
},
isManyValue: {
label: '',
type: 'select',
field: 'isManyValue',
default: 'N',
options: [
{
label: "是",
value: "Y",
},
{
label: "否",
value: "N",
},
],
placeholder: '请选择',
},
defaultValue: {
label: '',
type: 'input',
field: 'defaultValue',
default: '',
maxlength: 100,
placeholder: '请输入',
clearable: true,
},
description: {
label: '',
type: 'input',
field: 'description',
default: '',
maxlength: 100,
placeholder: '请输入',
clearable: true,
}
},
STATUS: 'edit',
data: inputParamsData.value,
showPage: false,
actionInfo: {
show: true,
label: "操作",
type: "btn",
width: 60,
fixed: 'right',
btns: [
{
label: "删除", value: "remove", click: (scope) => {
//点击上一步,删除入参定义时,需要判断下一步的参数有没有引用,若引用了,需要同步删除的。
let requestParamsData = requestParamsTableInfo.value.data || [];
let rIndex = requestParamsData.findIndex((r: any) => r.paramName == scope.row.paramName);
let index = scope.$index;
if (rIndex > -1) {
proxy.$openMessageBox("该参数被请求参数引用,确定同步删除吗?", () => {
inputParamsData.value.splice(index, 1);
inputParamsTableInfo.value.data = inputParamsData.value;
requestParamsTableInfo.value.data.splice(rIndex, 1);
proxy.$ElMessage.success('参数删除成功');
}, () => {
proxy.$ElMessage.info("已取消");
});
} else {
inputParamsData.value.splice(index, 1);
inputParamsTableInfo.value.data = inputParamsData.value;
}
}
},
]
},
loading: false
});
/** 给表格添加一行入参定义。 */
const addInputParams = () => {
inputParamsData.value.push({ paramName: '', isRequired: 'N', isManyValue: 'N', paramPosition: 'B', dataType: 'varchar', defaultValue: '', description: '' });
inputParamsTableInfo.value.data = inputParamsData.value;
nextTick(() => {
scrollLastRowToView(inputParamsTableRef.value?.tableRef, inputParamsData.value.length);
})
}
const inputParamsTableInputChange = (val, scope, item) => {
if (item.field == 'paramName') {
let oldV = scope.row[`old-${item.field}`];
if (oldV != val) {
let param: any = requestParamsTableInfo.value.data.find((r: any) => r.paramName == oldV);
param && (param.paramName = val);
}
}
}
/** 记录当前输入的白名单值,用于切换隐藏后再显示时显示之前的输入值 */
const whiteIPsValue = ref([]);
const processDTOSValue = ref([]);
const handleBaseInfoSelectChange = (val, row, info) => {
// if (row.field == 'authenticationType') {
// baseFormItems.value.forEach(item => {
// item.default = info[item.field];
// if (item.field == 'httpInfo') {
// item.children && (item.children[1].default = info['requestPath']);
// }
// // if (item.field == 'whiteIPs') {
// // item.visible = info.authenticationType == 'N';
// // if (item.visible) {
// // item.default = whiteIPsValue.value || [];
// // }
// // }
// });
// whiteIPsValue.value = info.whiteIPs;
// }
// if (row.field == 'processOrderGuids'){
// // if(val&&val.length>0){
// // let obj=processSheetList.value.filter(item => val.includes(item.guid))||[]
// // let processDTOS=obj.map(item=>({
// // processOrderNo:item.processOrderNo,
// // guid:item.guid,
// // requirementOrderName:item.requirementOrderName,
// // }))
// // if(processDTOS?.length>0){
// // processDTOS.forEach(obj=>{
// // obj.noName=obj.processOrderNo + '' + obj.requirementOrderName
// // })
// // }
// // processDTOSValue.value = processDTOS || [];
// // }
// if(val){
// let obj=processSheetList.value.filter(item => val==item.guid)||[]
// let processDTOS=obj.map(item=>({
// processOrderNo:item.processOrderNo,
// guid:item.guid,
// requirementOrderName:item.requirementOrderName,
// }))
// if(processDTOS?.length>0){
// processDTOS.forEach(obj=>{
// obj.noName=obj.processOrderNo + '' + obj.requirementOrderName
// })
// }
// processDTOSValue.value = processDTOS || [];
// }
// }
// console.log('ooo',baseInfoFormRef?.value.formInline);
// if (row.field == 'sceneGuid') {//场景名称
// let obj=sceneList.value.filter(item => item.guid == val)||[]
// console.log('obj',sceneList.value,obj,val);
// baseFormItems.value.forEach(item => {
// item.default = info[item.field];
// if (item.field == 'sceneName') {
// item.default = obj[0].sceneName||''
// }
// });
// }
}
/** ----------------------------第二步配置取数逻辑(单表API类型) -------------------------- */
/** 数据源列表 */
const databaseList: any = ref([]);
/** 选择的数据源对应的表列表 */
const dsTableList: any = ref([]);
/** 获取数据源列表 */
const getTargetDatabaseList = () => {
return getDataSource({ connectStatus: 1, }).then((res: any) => {
if (res.code == proxy.$passCode) {
databaseList.value = res.data || [];
tableFormItems.value[1].options = databaseList.value;
} else {
proxy.$ElMessage.error(res.msg);
}
})
}
/** 获取 数据目录主题域列表 */
const matchtableList: any = ref([]);
const getMatchTableList = () => {
getSubjectTableTree({}).then((res: any) => {
if (res.code === proxy.$passCode) {
matchtableList.value = res.data || []
tableFormItems.value[2].options = matchtableList.value;
} else {
proxy.$ElMessage.error(res.msg);
}
})
}
/** 数据源选择表单组件 */
const tableInfoFormRef = ref();
/** 数据源选择表单配置。 */
const tableFormItems = ref([{
label: "数据类型",
type: "select",
placeholder: "请选择",
field: "dataSourceType",
options: [
{ label: "数据源", value: 1 },
{ label: "数据目录", value: 2 }
],
default: 1,
required: true,
}, {
label: "数据源",
type: "select",
placeholder: "请选择",
field: "dataSourceGuid",
options: databaseList.value,
props: {
value: 'guid',
label: 'databaseNameZh'
},
default: '',
filterable: true,
clearable: true,
visible: true,
required: true,
},
{
label: "数据源",
type: "tree-select",
placeholder: "请选择",
field: "subjectDomainGuid",
options: matchtableList.value,
lazy: false,
expandKeys: [],
props: {
label: 'name',
value: 'guid',
children: 'children',
isLeaf: 'isLeaf'
},
filterable: true,
clearable: true,
default: '',
visible: false,
required: true,
},
{
label: "数据表",
type: "select",
placeholder: "请选择",
field: "tableName",
options: dsTableList.value,
props: {
label: 'label',
value: 'value'
},
default: '',
filterable: true,
clearable: true,
required: true,
}, {
label: "数据表",
type: "select",
placeholder: "请选择",
field: "tableGuid",
options: dsTableList.value,
props: {
label: 'label',
value: 'value'
},
default: '',
filterable: true,
clearable: true,
visible: false,
required: true,
}]);
/** 数据源选择表单配置规则。 */
const tableFormRules = ref({
dataSourceGuid: [required("请选择数据源")],
subjectDomainGuid: [required("请选择数据源")],
tableName: [required("请选择数据表")],
tableGuid: [required("请选择数据表")],
});
/** 单表API当前选择的数据源信息 */
const currDsInfo: any = ref({});
/** 根据选择的数据源和表显示绑定字段列表。 */
const targetDsFields: any = ref([]);
const handleTableFormSelectChange = (val, row, formInfo) => {
if (row.field == 'dataSourceType') {
tableFormItems.value[0].default = val;
tableFormItems.value[1].visible = val == 1;
tableFormItems.value[2].visible = val == 2;
tableFormItems.value[3].visible = val == 1;
tableFormItems.value[4].visible = val == 2;
currDsInfo.value = {};
if (val == 1) {
tableFormItems.value[1].default = '';
} else {
tableFormItems.value[2].default = '';
/** 只有单表API有切换数据源请求表的需求。 */
apiType.value == '1' && handleTableFormSelectChange('', { field: 'dataSourceGuid' }, formInfo);
}
} else if (row.field == 'dataSourceGuid') {
tableFormItems.value[3].default = '';//清空数据表。重新显示下拉框表数据。
tableFormItems.value[1].default = val;
if (!val) {
currDsInfo.value = {};
dsTableList.value = [];
tableFormItems.value[3].options = dsTableList.value;
} else {
getSchemaTableData(val);
}
handleTableFormSelectChange('', { field: 'tableName' }, formInfo);
sqlIsChecked.value = false;
} else if (row.field == 'subjectDomainGuid') {
tableFormItems.value[4].default = '';//清空数据表。重新显示下拉框表数据。
tableFormItems.value[2].default = val;
getSubjectDomainData(val);
} else if (row.field == 'tableName' || row.field == 'tableGuid') {
if (!val) {
targetDsFields.value = [];
requestParamsTableInfo.value.editInfo.boundField.options = targetDsFields.value;
responseParamsTableInfo.value.editInfo.boundField.options = targetDsFields.value;
sortParamsTableInfo.value.editInfo.boundField.options = targetDsFields.value;
requestParamsTableInfo.value.data.forEach((d: any) => {
if (d.boundField) {
d.boundField = "";
}
})
responseParamsTableInfo.value.data.forEach((d: any) => {
if (d.boundField) {
d.boundField = "";
}
})
sortParamsTableInfo.value.data.forEach((d: any) => {
if (d.boundField) {
d.boundField = "";
}
})
} else {
getBingFieldList(formInfo.dataSourceType, formInfo.dataSourceGuid, formInfo[row.field]);
}
}
}
const handleTableTreeNodeChange = (node) => {
if (!node.children) {
currDsInfo.value = node;
currDsInfo.value.subjectDomainGuid = node.guid;
currDsInfo.value.subjectDomainName = node.name;
currDsInfo.value.directoryGuid = node.parentGuid;
}
}
/** 根据数据源获取对应的表列表。 */
const getSchemaTableData = (dsGuid) => {
const option = databaseList.value.find((item) => item.guid === dsGuid)
currDsInfo.value = option;
const obj = { curr: -1, limit: -1, ...option }
return getSchemaTableList({
pageSize: obj.limit,
pageIndex: obj.curr,
dataSourceGuid: obj.guid,
database: obj.databaseNameEn,
databaseType: obj.databaseType,
tableName: obj.value,
hadFlag: false,
subjectDomainGuid: obj.subjectDomainGuid
}).then((res: any) => {
if (res.code == proxy.$passCode) {
dsTableList.value = res.data.records?.map(r => {
r.label = r.tableComment ? (r.tableComment + `(${r.tableName})`) : r.tableName;
r.value = r.tableName;
return r;
}) || [];
tableFormItems.value[3].options = dsTableList.value;
} else {
proxy.$ElMessage.error(res.msg);
}
})
}
/** 获取数据目录列表 */
const getSubjectDomainData = (val) => {
return getSubjectTableByDomain(val).then((res: any) => {
if (res.code == proxy.$passCode) {
dsTableList.value = res.data?.map(r => {
r.label = r.chName ? (r.chName + `(${r.enName})`) : r.enName;
r.value = r.guid;
return r;
}) || [];
tableFormItems.value[4].options = dsTableList.value
} else {
proxy.$ElMessage.error(res.msg);
}
})
}
/** 获取绑定字段列表 */
const getBingFieldList = (dataSourceType, dataSourceGuid, tableName, isSelectChange = true) => {
/** 表选择变化,对应的绑定字段列表会变化,那么请求参数,返回参数,排序参数,需要判断,不在当前字段列表中就清除。 */
if (dataSourceType == 1) {//数据源的表
// 此处跟数据同步那里不同,因为用户可以不使用数据目录模块。
tableColumnList({
dataSourceGuid: dataSourceGuid,
database: currDsInfo.value.databaseNameEn,
databaseType: currDsInfo.value.databaseType,
pageIndex: 1,
pageSize: -1,
tableName: tableName,
}).then((res: any) => {
if (res.code == proxy.$passCode) {
targetDsFields.value = res.data?.map(r => {
r.value = r.columnName,
r.label = r.columnName + (r.columnComment ? `(${r.columnComment})` : '');
return r
}) || [];
console.log('targetDsFields.value', targetDsFields.value)
requestParamsTableInfo.value.editInfo.boundField.options = targetDsFields.value;
isSelectChange && requestParamsTableInfo.value.data.forEach((d: any) => {
if (d.boundField && !targetDsFields.value.some(f => f.value == d.boundField)) {
d.boundField = "";
}
})
responseParamsTableInfo.value.editInfo.boundField.options = targetDsFields.value;
isSelectChange && responseParamsTableInfo.value.data.forEach((d: any) => {
if (d.boundField && !targetDsFields.value.some(f => f.value == d.boundField)) {
d.boundField = "";
}
})
sortParamsTableInfo.value.editInfo.boundField.options = targetDsFields.value;
isSelectChange && sortParamsTableInfo.value.data.forEach((d: any) => {
if (d.boundField && !targetDsFields.value.some(f => f.value == d.boundField)) {
d.boundField = "";
}
})
} else {
proxy.$ElMessage.error(res.msg);
}
})
} else { //数据目录的表
getSubjectTableDetail(tableName).then((res: any) => {
if (res.code == proxy.$passCode) {
targetDsFields.value = res.data.subjectFieldVOS?.map(r => {
r.value = r.enName,
r.label = r.enName + (r.chName ? `(${r.chName})` : '');
return r
}) || [];
requestParamsTableInfo.value.editInfo.boundField.options = targetDsFields.value;
responseParamsTableInfo.value.editInfo.boundField.options = targetDsFields.value;
sortParamsTableInfo.value.editInfo.boundField.options = targetDsFields.value;
} else {
proxy.$ElMessage.error(res.msg);
}
})
}
}
const requestParamsTableInfoRef = ref();
/**
* 请求参数表格配置
* 注意:绑定字段需要自动匹配,第一步点进来时默认将入参定义,全部变为请求参数的默认值设置。
*/
const requestParamsTableInfo = ref({
id: "request-params-table",
height: '214px',
fields: [
{ label: "序号", type: "index", width: TableColumnWidth.INDEX, align: "center" },
{ label: "绑定参数", field: "paramName", width: 140, required: true, columClass: 'edit-colum', type: 'edit' },
{ label: "绑定字段", field: "boundField", width: 140, required: true, columClass: 'edit-colum', type: 'edit' },
{ label: "操作符", field: "operator", width: 100, required: true, columClass: 'edit-colum', type: 'edit' },
],
editInfo: {
paramName: {
label: '',
type: 'select',
field: 'paramName',
default: '',
getOptions: (scope) => {
return inputParamsData.value;
},
props: {
label: 'paramName',
value: 'paramName'
},
placeholder: '请选择',
clearable: true,
},
boundField: {
label: '',
type: 'select',
field: 'boundField',
default: '',
options: targetDsFields.value,
placeholder: '请选择',
clearable: true,
},
operator: {
label: '',
type: 'select',
field: 'operator',
default: '1',
options: paramOperatorList.value,
props: {
label: 'label',
value: 'value'
},
filterable: true,
placeholder: '请选择',
clearable: true,
}
},
STATUS: 'edit',
data: <Array<Object>>[],
showPage: false,
actionInfo: {
show: true,
label: "操作",
type: "btn",
width: apiType.value != '3' ? 180 : 80,
fixed: 'right',
btns: (scope) => {
let row = scope.row;
return [
{
label: "复制", visible: apiType.value != '3', value: "copy", disabled: requestParamsTableInfo.value.data.length == inputParamsData.value.length, click: (scope) => {
let index = scope.$index;
let data = requestParamsTableInfo.value.data;
data.push({ ...scope.row });
}
},
{
label: "添加至排序", visible: apiType.value != '3', disabled: !row.paramName || !row.boundField || sortParamsTableInfo.value.data.some(d => d.paramName == row.paramName), value: "addSort", click: (scope) => { //必填参数完成后再启用添加至排序按钮
sortParamsTableInfo.value.data.push({ paramName: row.paramName, boundField: row.boundField, sortMode: 'ASC', index: sortParamsTableInfo.value.data.length + 1 });
}
},
{
label: "删除", value: "remove", click: (scope) => {
let index = scope.$index;
requestParamsTableInfo.value.data.splice(index, 1);
}
},
]
}
},
loading: false
});
/** 给表格添加一行请求参数。 */
const addRequestParams = () => {
requestParamsTableInfo.value.data.push({ operator: '1' });
nextTick(() => {
scrollLastRowToView(requestParamsTableInfoRef.value?.tableRef, requestParamsTableInfo.value.data.length);
})
}
const getRequestParamOptions = () => {
let requestData: any = requestParamsTableInfo.value.data;
requestParamsTableInfo.value.editInfo.paramName.getOptions = (scope) => {
let val = inputParamsData.value.filter(p => !requestData.some(r => r.paramName == p.paramName));
return scope.row.paramName ? val.concat({
paramName: scope.row.paramName
}) : val;
};
}
const seeDetail = (row) => {
console.log('row', row);
router.push({
name: 'processSheetDetail',
query: {
guid: row.guid,
}
});
}
watch(() => inputParamsData.value, (v, oldV) => {
if (isEditNoChange.value) {
isEditNoChange.value = false;
return;
}
if (checkedSqlScript.value.params.some(item1 => v.find(vv => vv.paramName == item1)) && checkedSqlScript.value.sql) {
return;
}
/** 修改了请求参数,需要重新检验sql. */
sqlIsChecked.value = false;
getRequestParamOptions();
}, {
deep: true
});
watch(() => requestParamsTableInfo.value.data, (v) => {
getRequestParamOptions();
}, {
deep: true
});
const handleRequestSelectChange = (val, scope, item) => {
if (item.field == 'paramName') {
let inputParam = inputParamsData.value.find(p => p.paramName == val);
if (!inputParam) {
return;
}
if (inputParam.isManyValue == 'Y' && scope.row.isManyValue != 'Y') {
scope.row.operator = '10';//多值时默认是in。非多值时不设置,避免出现,已经设置了like操作符,但是切换了参数值之后就被改变了。
} else if (inputParam.isManyValue == 'N' && scope.row.isManyValue != 'N') {
scope.row.operator = '1';
}
scope.row.isManyValue = inputParam.isManyValue;
if (inputParam.isRequired != 'Y' && (scope.row.operator == '2' || scope.row.operator == '11')) {
proxy.$ElMessage.error(`参数名称:${scope.row.paramName}需必填,请返回上一步修改`);
}
} else if (item.field == 'operator') {
let inputParam = inputParamsData.value.find(p => p.paramName == scope.row.paramName);
if (!inputParam) {
return;
}
if (inputParam.isRequired != 'Y' && (scope.row.operator == '2' || scope.row.operator == '11')) {
proxy.$ElMessage.error(`参数名称:${scope.row.paramName}需必填,请返回上一步修改`);
}
}
}
const responseParamsTableRef = ref();
/**
* 返回参数表格配置
* 注意:绑定字段需要自动匹配,第一步点进来时默认将入参定义,全部变为返回参数的默认值设置。
*/
const responseParamsTableInfo = ref({
id: "reponse-params-table",
height: '214px',
fields: [
{ label: "序号", type: "index", width: TableColumnWidth.INDEX, align: "center" },
{ label: "参数名", field: "paramName", width: 140, required: true, columClass: 'edit-colum', type: 'edit' },
{ label: "绑定字段", field: "boundField", width: 140, required: true, columClass: 'edit-colum', type: 'edit' },
{ label: "参数类型", field: "dataType", width: 120, required: true, columClass: 'edit-colum', type: 'edit' },
{ label: "示例值", field: "exampleValue", width: 160, columClass: 'edit-colum', type: 'edit' },
{ label: "描述", field: "description", width: 160, columClass: 'edit-colum', type: 'edit' },
],
editInfo: {
paramName: {
label: '',
type: 'input',
field: 'paramName',
maxlength: 50,
regexp: /[^A-Za-z0-9_]/g,
default: '',
placeholder: '请选择',
clearable: true,
},
boundField: {
label: '',
type: 'select',
field: 'boundField',
default: '',
options: targetDsFields.value,
placeholder: '请选择',
clearable: true,
},
dataType: {
label: '',
type: 'select',
field: 'dataType',
default: '',
options: dataTypeList.value,
props: {
label: 'label',
value: 'value'
},
placeholder: '请选择',
clearable: true,
filterable: true
},
exampleValue: {
label: '',
type: 'input',
field: 'exampleValue',
default: '',
maxlength: 100,
placeholder: '请输入',
clearable: true,
},
description: {
label: '',
type: 'input',
field: 'description',
default: '',
maxlength: 100,
placeholder: '请输入',
clearable: true,
}
},
STATUS: 'edit',
data: <Array<Object>>[],
showPage: false,
actionInfo: {
show: true,
label: "操作",
type: "btn",
width: 150,
fixed: 'right',
btns: (scope) => {
let row = scope.row;
return [
{
label: "添加至排序", value: "addSort", disabled: !row.paramName || !row.boundField || sortParamsTableInfo.value.data.some(d => d.paramName == row.paramName), click: (scope) => {
sortParamsTableInfo.value.data.push({ paramName: row.paramName, boundField: row.boundField, sortMode: 'ASC', index: sortParamsTableInfo.value.data.length + 1 });
}
},
{
label: "删除", value: "remove", click: (scope) => {
let index = scope.$index;
responseParamsTableInfo.value.data.splice(index, 1);
}
},
]
}
},
loading: false
});
/** 给表格添加一行返回参数。 */
const addresponseParams = () => {
responseParamsTableInfo.value.data.push({});
nextTick(() => {
scrollLastRowToView(responseParamsTableRef.value?.tableRef, responseParamsTableInfo.value.data.length);
});
}
/** 处理返回参数编辑表格中的下拉框事件 */
const handleresponseParamselectChange = (val, scope, item) => {
if (item.field == 'boundField') {
scope.row.paramName = val;
if (tableInfoFormRef.value.formInline.dataSourceType == 1) {
scope.row.dataType = targetDsFields.value.find(t => t.columnName == val)?.dataType;
} else {
scope.row.dataType = targetDsFields.value.find(t => t.enName == val)?.dataType;
}
}
}
const sortParamsTableRef = ref();
/**
* 排序参数表格配置
* 注意:绑定字段需要自动匹配,第一步点进来时默认将入参定义,全部变为返回参数的默认值设置。
*/
const sortParamsTableInfo = ref({
id: "sort-params-table",
sortable: true,
rowKey: 'index',
height: '214px',
fields: [
{ label: "序号", type: "index", width: TableColumnWidth.INDEX, align: "center" },
{ label: "参数名", field: "paramName", width: 140, required: true, columClass: 'edit-colum', type: 'edit' },
{ label: "绑定字段", field: "boundField", width: 140, required: true, columClass: 'edit-colum', type: 'edit' },
{ label: "排序方式", field: "sortMode", width: 120, required: true, columClass: 'edit-colum', type: 'edit' },
{ label: "描述", field: "description", width: 160, columClass: 'edit-colum', type: 'edit' },
],
editInfo: {
paramName: {
label: '',
type: 'input',
field: 'paramName',
default: '',
maxlength: 50,
regexp: /[^A-Za-z0-9_]/g,
placeholder: '请输入',
clearable: true,
},
boundField: {
label: '',
type: 'select',
field: 'boundField',
default: '',
options: targetDsFields.value,
placeholder: '请选择',
clearable: true,
},
sortMode: {
label: '',
type: 'select',
field: 'sortMode',
default: 'ASC',
options: [{
value: 'ASC',
label: '升序'
}, {
value: 'DESC',
label: '降序'
}],
placeholder: '请选择',
clearable: false,
},
description: {
label: '',
type: 'input',
field: 'description',
default: '',
maxlength: 100,
placeholder: '请输入',
clearable: true,
}
},
STATUS: 'edit',
data: <Array<{
paramName: string,
boundField: string,
description?: string,
sortMode?: string,
index?: number
}>>[],
showPage: false,
actionInfo: {
show: true,
label: "操作",
type: "btn",
width: 120,
fixed: 'right',
btns: [
{ value: 'sort' },
{
label: "删除", value: "remove", click: (scope) => {
let index = scope.$index;
sortParamsTableInfo.value.data.splice(index, 1);
}
},
]
},
loading: false
});
/** 给表格添加一行排序参数。 */
const addSortParams = () => {
sortParamsTableInfo.value.data.push({ paramName: '', boundField: '', description: '', sortMode: 'ASC', index: sortParamsTableInfo.value.data.length + 1 });
nextTick(() => {
scrollLastRowToView(sortParamsTableRef.value?.tableRef, sortParamsTableInfo.value.data.length);
});
}
/** 处理排序参数编辑表格中的下拉框事件 */
const handleSortParamSelectChange = (val, scope, item) => {
if (item.field == 'boundField') {
scope.row.paramName = val;
}
}
/** ----------------------------第二步配置取数逻辑(自定义sql类型) -------------------------- */
/** 数据源选择表单组件 */
const sqlInfoFormRef = ref();
/** sql是否验证通过,只有通过才可以继续进行下一步 */
const sqlIsChecked = ref(false);
const isEditNoChange = ref(false);
watch(() => sqlIsChecked.value, (val) => {
if (val === false) {
checkedSqlScript.value = {
sql: '',
params: []
};
}
})
const checkedSqlScript = ref({
sql: '',
params: []
});
/** 数据源选择表单配置。 */
const sqlFormItems = ref([{
label: "",
type: "textarea-panel",
title: '编写查询sql',
placeholder: "select * from mf_staff where tenant_name=@{id1} and organisaiton=@{id2} and age between @{id3} and @{id4} order by (mf_staff.tenant_name, mf_staff.staff_name)",
trim: false,
rows: 12,
field: "sqlScript",
default: '',
btns: [
{
label: '验证', value: 'sqlyz', click: () => {
let dataSourceGuid = tableInfoFormRef.value.formInline.dataSourceGuid;
if (!dataSourceGuid) {
proxy.$ElMessage.error('请选择数据源');
return;
}
let sqlScript = sqlInfoFormRef.value.formInline.sqlScript?.trim();
if (!sqlScript) {
proxy.$ElMessage.error('请先编写查询sql');
return;
}
checkSql({
dataSourceGuid: dataSourceGuid,
sqlScript: sqlScript,
}).then((res: any) => {
if (res.code == proxy.$passCode) {
sqlIsChecked.value = true;
checkedSqlScript.value = {
sql: sqlScript,
params: inputParamsData.value?.map(p => p.paramName)
};
proxy.$ElMessage.success('Sql验证通过');
} else {
sqlIsChecked.value = false;
proxy.$ElMessage.error(res.msg);
}
});
}
}
],
clearable: true,
required: true,
block: true,
},]);
/** 数据源选择表单配置规则。 */
const sqlFormRules = ref({
sqlScript: [required('请编写查询sql')]
});
const sqlFormInputChange = (val, row) => {
if (row.field == 'sqlScript') {
if (checkedSqlScript.value.sql != val.trim()) {
sqlIsChecked.value = false
}
}
}
/** ----------------------------第二步配置取数逻辑(注册API类型) -------------------------- */
/** 基本信息表单组件引用 */
const backApiInfoFormRef = ref();
/** 基本信息表单配置。 */
const backApiFormItems = ref([{
type: "select-group",
field: "backHttpInfo",
col: ' select-input-long',
children: [
{
label: "后台服务HOST",
type: "select",
placeholder: "请选择",
options: [
{
value: "https",
label: "https",
},
{
value: "http",
label: "http",
}
],
default: "https",
field: "backstageAgreement",
required: true,
visible: true,
},
{
label: " ",
type: "input",
placeholder: "请输入",
default: '',
field: "backstageHost",
required: true,
maxlength: 50,
visible: true,
},
],
visible: true
}, {
label: "后台服务PATH",
type: "input",
placeholder: "请输入",
default: '/',
field: "backstagePath",
required: true,
maxlength: 200,
visible: true,
}, {
label: '请求方式',
type: 'select',
options: [{
value: 'P',
label: 'post'
}, {
value: 'G',
label: 'get'
}],
placeholder: '请选择',
field: 'backstageRequestMode',
default: 'P',
clearable: true,
filterable: true,
required: true
}, {
label: "后端超时(ms)",
type: "input",
placeholder: "请输入",
default: '',
field: "backstageOvertime",
required: false,
maxlength: 50,
regexp: /\D/g,
visible: true,
}])
/** 基本信息表单配置规则。 */
const backApiFormRules = ref({
backstageAgreement: [required("请选择后台服务协议")],
backstageHost: [required("请填写后台服务HOST")],
backstageRequestMode: [required("请选择请求方式")],
backstagePath: [required("请填写后台服务PATH"), regexpValidate(/^\/(?!\/)[\u4e00-\u9fa5a-zA-Z_-]+(\/[\u4e00-\u9fa5a-zA-Z_-]+)*$/, '请输入合法的请求路径')],
});
const registRequestParamsTableRef = ref();
/**
* 注册APi的请求参数表格配置
* 注意:绑定字段需要自动匹配,第一步点进来时默认将入参定义,全部变为注册API请求参数的默认值设置。
*/
const registRequestParamsTableInfo = ref({
id: "regist-request-params-table",
height: '214px',
fields: [
{ label: "序号", type: "index", width: TableColumnWidth.INDEX, align: "center" },
{ label: "参数名", field: "paramName", width: 140, required: true, columClass: 'edit-colum', type: 'edit' },
{ label: "参数位置", field: "paramPosition", width: 120, required: true, columClass: 'edit-colum', type: 'edit' },
{ label: "参数类型", field: "dataType", width: 120, required: true, columClass: 'edit-colum', type: 'edit', impactValue: "defaultValue" },
{ label: "是否必填", field: "isRequired", width: 100, required: true, columClass: 'edit-colum', type: 'edit' },
{ label: "是否多值", field: "isManyValue", width: 100, required: true, columClass: 'edit-colum', type: 'edit' },
{ label: "默认值", field: "defaultValue", width: 160, columClass: 'edit-colum', type: 'edit', dataTypeName: 'dataType' },
{ label: "描述", field: "description", width: 160, columClass: 'edit-colum', type: 'edit' },
],
editInfo: {
paramName: {
label: '',
type: 'input',
field: 'paramName',
maxlength: 50,
regexp: /[^A-Za-z0-9_]/g,
default: '',
placeholder: '请输入',
clearable: true,
},
paramPosition: {
label: '',
type: 'select',
field: 'paramPosition',
default: '',
options: paramPositionList.value,
props: {
label: 'label',
value: 'value'
},
placeholder: '请选择',
clearable: true,
filterable: true
},
dataType: {
label: '',
type: 'select',
field: 'dataType',
default: '',
options: dataTypeList.value,
props: {
label: 'label',
value: 'value'
},
placeholder: '请选择',
clearable: true,
filterable: true
},
isRequired: {
label: '',
type: 'select',
field: 'isRequired',
default: 'N',
options: [
{
label: "是",
value: "Y",
},
{
label: "否",
value: "N",
},
],
placeholder: '请选择',
},
isManyValue: {
label: '',
type: 'select',
field: 'isManyValue',
default: 'N',
options: [
{
label: "是",
value: "Y",
},
{
label: "否",
value: "N",
},
],
placeholder: '请选择',
},
defaultValue: {
label: '',
type: 'input',
field: 'defaultValue',
default: '',
maxlength: 100,
placeholder: '请输入',
clearable: true,
},
description: {
label: '',
type: 'input',
field: 'description',
default: '',
maxlength: 100,
placeholder: '请输入',
clearable: true,
}
},
STATUS: 'edit',
data: <Array<Object>>[],
showPage: false,
actionInfo: {
show: true,
label: "操作",
type: "btn",
width: 80,
fixed: 'right',
btns: (scope) => {
let row = scope.row;
return [
{
label: "删除", value: "remove", click: (scope) => {
let index = scope.$index;
registRequestParamsTableInfo.value.data.splice(index, 1);
}
}
]
}
},
loading: false
});
/** 给表格添加一行请求参数。 */
const addRegistRequestParams = () => {
registRequestParamsTableInfo.value.data.push({ paramName: '', isRequired: 'N', isManyValue: 'N', paramPosition: 'B', dataType: 'varchar', defaultValue: '' });
nextTick(() => {
scrollLastRowToView(registRequestParamsTableRef.value?.tableRef, registRequestParamsTableInfo.value.data.length);
});
}
const constParamsTableRef = ref();
/**
* 常量参数表格配置
* 注意:绑定字段需要自动匹配,第一步点进来时默认将入参定义,全部变为常量参数的默认值设置。
*/
const constParamsTableInfo = ref({
id: "const-params-table",
height: '214px',
minHeight: '100px',
minPanelHeight: '100px',
fields: [
{ label: "序号", type: "index", width: TableColumnWidth.INDEX, align: "center" },
{ label: "参数名", field: "paramName", width: 140, required: true, columClass: 'edit-colum', type: 'edit' },
{ label: "参数位置", field: "paramPosition", width: 120, required: true, columClass: 'edit-colum', type: 'edit' },
{ label: "参数类型", field: "dataType", width: 120, required: true, columClass: 'edit-colum', type: 'edit', impactValue: "defaultValue" },
{ label: "是否必填", field: "isRequired", width: 100, required: true },
{ label: "常量值", field: "defaultValue", width: 160, required: true, columClass: 'edit-colum', type: 'edit', dataTypeName: 'dataType' },
{ label: "描述", field: "description", width: 160, columClass: 'edit-colum', type: 'edit' },
],
editInfo: {
paramName: {
label: '',
type: 'input',
field: 'paramName',
maxlength: 50,
default: '',
regexp: /[^A-Za-z0-9_]/g,
placeholder: '请输入',
clearable: true,
},
paramPosition: {
label: '',
type: 'select',
field: 'paramPosition',
default: '',
options: paramPositionList.value,
props: {
label: 'label',
value: 'value'
},
placeholder: '请选择',
clearable: true,
filterable: true
},
dataType: {
label: '',
type: 'select',
field: 'dataType',
default: '',
options: dataTypeList.value,
props: {
label: 'label',
value: 'value'
},
placeholder: '请选择',
clearable: true,
filterable: true
},
isRequired: {
label: '',
type: 'select',
field: 'isRequired',
default: 'Y',
options: [
{
label: "是",
value: "Y",
},
{
label: "否",
value: "N",
},
],
placeholder: '请选择',
},
isManyValue: {
label: '',
type: 'select',
field: 'isManyValue',
default: 'N',
options: [
{
label: "是",
value: "Y",
},
{
label: "否",
value: "N",
},
],
placeholder: '请选择',
},
defaultValue: {
label: '',
type: 'input',
field: 'defaultValue',
default: '',
maxlength: 100,
placeholder: '请输入',
clearable: true,
},
description: {
label: '',
type: 'input',
field: 'description',
default: '',
maxlength: 100,
placeholder: '请输入',
clearable: true,
}
},
STATUS: 'edit',
data: <Array<Object>>[],
showPage: false,
actionInfo: {
show: true,
label: "操作",
type: "btn",
width: 80,
fixed: 'right',
btns: (scope) => {
let row = scope.row;
return [
{
label: "删除", value: "remove", click: (scope) => {
let index = scope.$index;
constParamsTableInfo.value.data.splice(index, 1);
}
}
]
}
},
loading: false
});
/** 给表格添加一行常量参数。 */
const addConstParams = () => {
constParamsTableInfo.value.data.push({ paramName: '', isRequired: 'Y', isManyValue: 'N', paramPosition: 'B', dataType: 'varchar', defaultValue: '' });
nextTick(() => {
scrollLastRowToView(constParamsTableRef.value?.tableRef, constParamsTableInfo.value.data.length);
});
}
/** ---------------------------- 测试API -------------------------- */
/** api基本信息表单配置 */
const apiFormItems = ref([{
label: 'API名称',
type: 'input',
disabled: true,
field: 'apiName',
maxlength: 50,
default: '',
required: true
}, {
label: '请求方式',
type: 'input',
disabled: true,
field: 'requestMode',
maxlength: 50,
default: 'post',
required: true
}, {
label: '请求路径',
type: 'input',
disabled: true,
field: 'requestPath',
maxlength: 50,
default: '',
block: true,
required: true,
},]);
/**
* query参数表格配置。
*/
const queryParamsTableInfo = ref({
id: "query-params-table",
height: '214px',
fields: [
{ label: "序号", type: "index", width: TableColumnWidth.INDEX, align: "center" },
{ label: "参数名", field: "paramName", width: 140 },
{
label: "参数类型", field: "dataType", width: 100, getName: (scope) => {
return dataTypeList.value.find(d => d.value == scope.row.dataType)?.label;
}
},
{
label: "是否必填", field: "isRequired", width: 100, getName: (scope) => {
return scope.row.isRequired == 'Y' ? '是' : '否'
}
},
{
label: "是否多值", field: "isManyValue", width: 100, getName: (scope) => {
return scope.row.isManyValue == 'Y' ? '是' : '否'
}
},
{
label: "值", field: "introductionValue", width: 240, columClass: 'edit-colum', type: 'edit', dataTypeName: 'dataType', getVisible: (scope) => {
return !scope.row.isConst;
}
},
{ label: "描述", field: "description", width: 140 },
],
editInfo: {
introductionValue: {
label: '',
type: 'input',
field: 'introductionValue',
default: '',
placeholder: '请输入',
clearable: true,
}
},
STATUS: 'edit',
data: <Array<Object>>[],
showPage: false,
actionInfo: {
show: false
},
loading: false
});
const defaultParamsData: any = ref([{
paramName: 'pageSize',
dataType: '整型',
isRequired: '是',
value: 50
}, {
paramName: 'pageIndex',
dataType: '整型',
isRequired: '是',
value: 1
}]);
/** default参数表格配置 */
const defaultParamsTableInfo = ref({
id: "default-params-table",
height: 'auto',
minHeight: '50px',
minPanelHeight: '50px',
fields: [
{ label: "序号", type: "index", width: TableColumnWidth.INDEX, align: "center" },
{ label: "参数名", field: "paramName", width: 140 },
{ label: "参数类型", field: "dataType", width: 100 },
{ label: "是否必填", field: "isRequired", width: 100 },
{ label: "值", field: "value", width: 240, columClass: 'edit-colum', type: 'edit' },
],
editInfo: {
value: { //只能输入大于0的整数。
label: '',
type: 'input',
field: 'value',
default: '',
maxlength: 50,
min: 1,
regexp: /\D/g,
placeholder: '请输入',
clearable: false,
}
},
STATUS: 'edit',
data: defaultParamsData.value,
showPage: false,
actionInfo: {
show: false
},
loading: false
});
/** api测试结果详情表单 */
const resultFormItems = ref([{
label: '请求详情',
type: 'textarea',
placeholder: '输出请求详情',
field: 'requestUrlDetail',
default: '',
rows: 10,
readonly: true,
maxlength: "",
clearable: true,
required: false,
}, {
label: '返回内容',
type: 'textarea',
placeholder: '输出返回内容',
field: 'resultInfo',
default: '',
rows: 10,
readonly: true,
maxlength: "",
clearable: true,
required: false,
}]);
onActivated(() => {
// getIPList({
// pageSize: -1
// }).then((res: any) => {
// if (res.code == proxy.$passCode) {
// whiteIPsList.value = res.data.records || [];
// let formItem: any = baseFormItems.value.find(i => i.field == 'whiteIPs');
// formItem && (formItem.options = whiteIPsList.value);
// } else {
// proxy.$ElMessage.error(res.msg);
// }
// });
})
const getDetailPromise = ref();
const needApprove = ref(false);
onBeforeMount(() => {
getDomainName().then((res: any) => {
if (res.code == proxy.$passCode) {
domainName.value = res.data;
} else {
proxy.$ElMessage.error(res.msg);
}
});
getParamDataTypeList();
getParamPositionList();
//TODO,需要取消注释
// isNeedApprove({ funcCode: 'ZCZLPJ' }).then((res1: any) => {
// if (res1.code == proxy.$passCode) {
// needApprove.value = !!res1.data;
// } else {
// proxy.$ElMessage.error(res1.msg);
// }
// });
// getParamSceneList();
//getParamProcessSheetList()
if (apiGuid.value) {//编辑页面。
fullscreenLoading.value = true;
getDetailPromise.value = getApiDetail(apiGuid.value).then((res: any) => {
getDetailPromise.value = null;
fullscreenLoading.value = false;
if (res.code == proxy.$passCode) {
let data = detailInfo.value = res.data;
apiType.value = data.apiType;
baseFormItems.value.forEach(item => {
item.default = data[item.field];
if (item.field == 'httpInfo') {
item.children && (item.children[1].default = data['requestPath']);
}
// if (item.field == 'processOrderGuids'){
// if(data.processDTOS&&data.processDTOS.length>0){
// // item.default=data.processDTOS.map(item=>item.guid)
// item.default=data.processDTOS[0].guid
// let processDTOS=data.processDTOS || [];
// if(processDTOS?.length>0){
// processDTOS.forEach(obj=>{
// obj.noName=obj.processOrderNo + '' + obj.requirementOrderName
// })
// }
// processDTOSValue.value = processDTOS || [];
// }
// }
// if (item.field == 'processOrderNo') {
// if (data.processOrderNo?.length) {
// item.default = data.processOrderNo || [];
// }
// }
// if (item.field == 'whiteIPs') {
// item.visible = data.authenticationType == 'N';
// if (data.whiteIPs?.length) {
// item.default = data.whiteIPs || [];
// }
// // }
// if (item.field == 'authenticationType') {
// // item.disabled = apiType.value == '3';
// }
});
/** 需要重新设置,否则detailInfo.value无法为最新。 */
nextTick().then(() => {
baseFormRules.value.apiName = [required("请填写API名称"), chOrEnPreffix(), checkExistName(checkedInfo.value, checkExistAPIName, detailInfo.value, 'apiName')];
baseFormRules.value.requestPath = [required("请填写请求路径"), regexpValidate(/^\/[^\/][\w\u4e00-\u9fa5_-]*$/, '请输入合法的请求路径'), checkExistName(checkedPathInfo.value, checkExistRequestPath, detailInfo.value, 'requestPath', '该请求路径已存在,请填写其他路径')];
});
let apiConfigAccessRSVOS = data.apiConfigAccessRSVOS || [];
inputParamsData.value = [];
let requestData: any[] = [];
let responseData: any[] = [];
let registRequestData: any[] = [];
let constData: any[] = [];
let sortData: any[] = [];
apiConfigAccessRSVOS.forEach(vo => {
if (vo.paramType == 'DEFIN') {
inputParamsData.value.push(vo);
} else if (vo.paramType == 'REQ') {
if (apiType.value == '3') {
registRequestData.push(vo);
} else if (apiType.value == '2') {
inputParamsData.value.push(vo);
} else {
requestData.push(vo);
}
} else if (vo.paramType == 'RESP') {
responseData.push(vo);
} else if (vo.paramType == 'ORDER') {
sortData.push({ ...vo, index: sortData.length + 1 });
} else if (vo.paramType == 'SQL') {
sqlFormItems.value.forEach(item => {
item.default = vo.selectSqlStatement;
});
} else if (vo.paramType == 'CONSTANT') {
constData.push(vo);
}
});
inputParamsTableInfo.value.data = inputParamsData.value;
requestParamsTableInfo.value.data = requestData;
responseParamsTableInfo.value.data = responseData;
sortParamsTableInfo.value.data = sortData;
registRequestParamsTableInfo.value.data = registRequestData;
constParamsTableInfo.value.data = constData;
tableFormItems.value.forEach(item => {
item.default = data[item.field];
});
if (apiType.value == '1') {
getParamOperatorList();
tableFormItems.value[1].visible = data.dataSourceType == 1;
tableFormItems.value[3].visible = data.dataSourceType == 1;
tableFormItems.value[2].visible = data.dataSourceType == 2;
tableFormItems.value[4].visible = data.dataSourceType == 2;
} else if (apiType.value == '3') {
backApiFormItems.value.forEach(item => {
item.default = data[item.field];
if (item.children) {
item.children.forEach(c => {
c.default = data[c.field];
});
}
});
}
sqlIsChecked.value = true;
isEditNoChange.value = true;
checkedSqlScript.value = {
sql: sqlFormItems.value[0].default,
params: inputParamsData.value.map(i => i.paramName)
};
let { approveVO } = data;
bizApproveVO.value = data.approveVO;
if (approveVO && (approveVO.approveState == 'N' || approveVO.approveState == 'C' || approveVO.approveState == 'R')) {
getCamundaDeploymentId('10023').then((res: any) => {
if (res.code == proxy.$passCode) {
deploymentId.value = res.data;
} else {
proxy.$ElMessage.error(res.msg);
}
})
}
} else {
apiType.value = '1';
proxy.$ElMessage.error(res.msg);
}
});
} else {
// baseFormItems.value[4].default = sceneName.value
getCamundaDeploymentId('10023').then((res: any) => {
if (res.code == proxy.$passCode) {
deploymentId.value = res.data;
} else {
proxy.$ElMessage.error(res.msg);
}
})
if (apiType.value == '1') {
getParamOperatorList();
}
let item = baseFormItems.value.find(b => b.field == 'authenticationType');
// item && (item.disabled = apiType.value == '3');
}
})
onMounted(() => {
if (getDetailPromise.value) {
getDetailPromise.value.then(() => {
enableRowDrop((evt) => {
let tableData = sortParamsTableInfo.value.data;
const movedItem = tableData.splice(evt.oldIndex, 1)[0];
tableData.splice(evt.newIndex, 0, movedItem);
nextTick(() => {
sortParamsTableInfo.value.data = JSON.parse(JSON.stringify(tableData)).map((t: any, index) => {
t.index = index + 1;
return t;
})
})
});
});
} else {
enableRowDrop((evt) => {
let tableData = sortParamsTableInfo.value.data;
const movedItem = tableData.splice(evt.oldIndex, 1)[0];
tableData.splice(evt.newIndex, 0, movedItem);
nextTick(() => {
sortParamsTableInfo.value.data = JSON.parse(JSON.stringify(tableData)).map((t: any, index) => {
t.index = index + 1;
return t;
})
})
});
}
});
onUnmounted(() => {
destroySort();
})
const startTestApiBtnLoading = ref(false);
/** 调用测试API接口,并返回详情。 */
const startTestApi = () => {
let queryParamData: any[] = queryParamsTableInfo.value.data;
let dataIndex = 1;
for (const d of queryParamData) {
if (d.isRequired == 'Y' && d.introductionValue !== 0 && !d.introductionValue) {
proxy.$ElMessage.error(`第 ${dataIndex} 个参数为必填则值不能为空`);
handleContentWrapView('queryParams');
return;
}
if (checkValidValue[d.dataType]) {
let v = checkValidValue[d.dataType](d.introductionValue, d.isManyValue == 'Y');
if (v !== true) {
proxy.$ElMessage.error(`第 ${dataIndex} 个参数类型为${v},请输入合法的值`);
handleContentWrapView('queryParams');
return;
}
}
dataIndex++;
}
let params = { ...baseInfoFormRef.value?.formInline, ...tableInfoFormRef.value?.formInline, dataSourceName: currDsInfo.value.databaseNameZh, requestAgreement: 'https' };
if (params.apiType == '1') {
if (params.dataSourceType == 2) {
params.directoryGuid = currDsInfo.value.directoryGuid;
params.subjectDomainName = currDsInfo.value.subjectDomainName;
let dsTable = dsTableList.value.find(d => d.value == params.tableGuid);
params.dataSourceGuid = dsTable.dataSourceGuid;
params.tableName = dsTable.enName;
}
}
let defaultParamsDataInfo = defaultParamsTableInfo.value.data;
if (defaultParamsDataInfo.length == 3 && !defaultParamsDataInfo[2].value) {
proxy.$ElMessage.error(`请填写参数appKey`);
handleContentWrapView('defaultParams');
return;
}
let apiConfigAccessDTOS: any[] = [];
if (apiType.value != '2') { //单表API,注册API
inputParamsData.value.forEach(i => {
apiConfigAccessDTOS.push({ ...i, paramType: 'DEFIN' });
});
requestParamsTableInfo.value.data.forEach((r: any, index) => {
let obj = { ...r, paramType: 'REQ' };
if (apiType.value == 1) {
let p = inputParamsData.value.find(i => i.paramName == r.paramName);
let queryData = queryParamData[index];
obj = Object.assign({}, p, obj, { paramPosition: p.paramPosition, dataType: p.dataType, isRequired: queryData.isRequired, isManyValue: queryData.isManyValue, introductionValue: queryData.introductionValue });
}
apiConfigAccessDTOS.push(obj);
});
let responseParamsData = responseParamsTableInfo.value.data;
responseParamsData.forEach(r => {
apiConfigAccessDTOS.push({ ...r, paramType: 'RESP' });
});
sortParamsTableInfo.value.data.forEach(s => {
apiConfigAccessDTOS.push({ ...s, paramType: 'ORDER' });
});
if (apiType.value == '3') {
registRequestParamsTableInfo.value.data.forEach((r, index) => {
let queryData = queryParamData[index];
apiConfigAccessDTOS.push({ ...r, paramType: 'REQ', isRequired: queryData.isRequired, isManyValue: queryData.isManyValue, introductionValue: queryData.introductionValue });
});
constParamsTableInfo.value.data.forEach(c => {
apiConfigAccessDTOS.push({ ...c, paramType: 'CONSTANT' });
});
params = { ...params, ...backApiInfoFormRef.value.formInline };
}
} else {//自定义sql
inputParamsData.value.forEach((i, index) => {
apiConfigAccessDTOS.push({ ...i, paramType: 'REQ', introductionValue: queryParamData[index].introductionValue });
});
apiConfigAccessDTOS.push({
paramType: 'SQL',
selectSqlStatement: sqlInfoFormRef.value.formInline.sqlScript?.trim()
});
}
params.apiConfigAccessDTOS = apiConfigAccessDTOS;
params.pageSize = defaultParamsDataInfo[0].value;
params.pageIndex = defaultParamsDataInfo[1].value;
defaultParamsDataInfo.length == 3 && (params.appKey = defaultParamsDataInfo[2].value);
startTestApiBtnLoading.value = true;
resultFormItems.value[0].default = '';
resultFormItems.value[1].default = '';
testEditApi(params).then((res: any) => {
startTestApiBtnLoading.value = false;
if (res.code == proxy.$passCode) {
proxy.$ElMessage.success('测试API调用成功');
let info = res.data;
resultFormItems.value[0].default = JSON.stringify(info.apiInvokeReqVO, null, 4);
resultFormItems.value[1].default = JSON.stringify(info.apiInvokeRespVO, null, 4);
} else {
proxy.$ElMessage.error(res.msg);
}
}).catch(() => {
startTestApiBtnLoading.value = false;
});
}
/** 提交新增API. */
const save = (isSubmit: boolean = false) => {
let params = { isSubmit: isSubmit ? 'Y' : 'N', ...baseInfoFormRef.value?.formInline, ...tableInfoFormRef.value?.formInline, dataSourceName: currDsInfo.value.databaseNameZh, requestAgreement: 'https' };
params.immediateApprove = isSubmit
if (params.apiType == '1') {
if (params.dataSourceType == 2) {
params.directoryGuid = currDsInfo.value.directoryGuid;
params.subjectDomainName = currDsInfo.value.subjectDomainName;
let dsTable = dsTableList.value.find(d => d.value == params.tableGuid);
params.dataSourceGuid = dsTable.dataSourceGuid;
params.tableName = dsTable.enName;
}
}
/** 验证输入的query值, query参数的值应该不用存储 */
// let queryParamData: any[] = queryParamsTableInfo.value.data;
// let dataIndex = 1;
// for (const d of queryParamData) {
// if (d.introductionValue && checkValidValue[d.dataType]) {
// let v = checkValidValue[d.dataType](d.introductionValue, d.isManyValue == 'Y');
// if (v !== true) {
// proxy.$ElMessage.error(`第 ${dataIndex} 个参数类型为${v},请输入合法的值`);
// return;
// }
// }
// dataIndex++;
// }
let apiConfigAccessDTOS: any[] = [];
if (apiType.value != '2') { //单表API
inputParamsData.value.forEach(i => {
apiConfigAccessDTOS.push({ ...i, paramType: 'DEFIN' });
});
requestParamsTableInfo.value.data.forEach((r: any, index) => {
let obj = { ...r, paramType: 'REQ', /*introductionValue: queryParamData[index].introductionValue*/ };
if (apiType.value == 1) {
let p = inputParamsData.value.find(i => i.paramName == r.paramName);
obj = Object.assign({}, p, obj, { paramPosition: p.paramPosition, dataType: p.dataType, description: p.description, isRequired: p.isRequired, isManyValue: p.isManyValue, defaultValue: p.defaultValue });
}
apiConfigAccessDTOS.push(obj);
});
let responseParamsData = responseParamsTableInfo.value.data;
responseParamsData.forEach(r => {
apiConfigAccessDTOS.push({ ...r, paramType: 'RESP' });
});
sortParamsTableInfo.value.data.forEach(s => {
apiConfigAccessDTOS.push({ ...s, paramType: 'ORDER' });
});
if (apiType.value == '3') {
registRequestParamsTableInfo.value.data.forEach((r, index) => {
apiConfigAccessDTOS.push({ ...r, paramType: 'REQ', /*introductionValue: queryParamData[index].introductionValue*/ });
});
constParamsTableInfo.value.data.forEach(c => {
apiConfigAccessDTOS.push({ ...c, paramType: 'CONSTANT' });
});
params = { ...params, ...backApiInfoFormRef.value.formInline };
}
} else {//自定义sql
inputParamsData.value.forEach(i => {
apiConfigAccessDTOS.push({ ...i, paramType: 'REQ' });
});
apiConfigAccessDTOS.push({
paramType: 'SQL',
selectSqlStatement: sqlInfoFormRef.value.formInline.sqlScript?.trim()
});
}
fullscreenLoading.value = true;
params.apiConfigAccessDTOS = apiConfigAccessDTOS;
let defaultParamsDataInfo = defaultParamsTableInfo.value.data;
params.pageSize = defaultParamsDataInfo[0].value;
params.pageIndex = defaultParamsDataInfo[1].value;
if (!apiGuid.value) {
addApi(params).then((res: any) => {
fullscreenLoading.value = false;
if (res.code == proxy.$passCode) {
proxy.$ElMessage.success(!isSubmit ? '新建API保存成功' : '新建API保存并提交成功');
router.push({
name: 'apiManagement'
});
userStore.setTabbar(userStore.tabbar.filter((tab: any) => tab.fullPath !== fullPath));
dataServiceStore.setIsUpdate(true);//改成存场景guid
} else {
proxy.$ElMessage.error(res.msg);
}
});
} else {
params.guid = apiGuid.value;
updateApi(params).then((res: any) => {
fullscreenLoading.value = false;
if (res.code == proxy.$passCode) {
proxy.$ElMessage.success(!isSubmit ? 'API编辑保存成功' : 'API编辑保存并提交成功');
router.push({
name: 'apiManagement'
});
userStore.setTabbar(userStore.tabbar.filter((tab: any) => tab.fullPath !== fullPath));
dataServiceStore.setIsUpdate(true);
} else {
proxy.$ElMessage.error(res.msg);
}
});
}
}
/** 取消关闭当前新建或编辑页面。 */
const cancel = () => {
if (isDetail.value) {
userStore.setTabbar(userStore.tabbar.filter((tab: any) => tab.fullPath !== fullPath));
router.push({
path: '/data-service/api-management'
});
return;
}
proxy.$openMessageBox("当前页面尚未保存,确定放弃修改吗?", () => {
userStore.setTabbar(userStore.tabbar.filter((tab: any) => tab.fullPath !== fullPath));
router.push({
path: '/data-service/api-management'
});
}, () => {
proxy.$ElMessage.info("已取消");
});
}
</script>
<template>
<div class="container_wrap full" v-loading="fullscreenLoading">
<div class="content_main" ref="scrollContainer">
<div class="top_tool_wrap">
<StepBar :steps-info="stepsInfo" />
</div>
<div class="operator_panel_wrap" v-show="step == 0">
<ContentWrap id="id-baseInfo" title="基本信息" description="">
<Form ref="baseInfoFormRef" :itemList="baseFormItems" formId="register-base-form" :rules="baseFormRules"
@select-change="handleBaseInfoSelectChange" col="col3" />
</ContentWrap>
<ContentWrap id="id-inputParams" v-if="apiType != '3'" :title="apiType == '2' ? '请求参数' : '入参定义'" description=""
class="mt16">
<Table ref="inputParamsTableRef" :tableInfo="inputParamsTableInfo" class="fiveRow-table"
@tableInputChange="inputParamsTableInputChange" />
<div class="row-add-btn">
<el-button link @click="addInputParams" :icon="CirclePlus" v-preReClick>添加</el-button>
</div>
</ContentWrap>
</div>
<div class="operator_panel_wrap" v-show="step == 1">
<template v-if="apiType == '1'">
<ContentWrap id="id-tableInfo" title="数据源" description="">
<Form ref="tableInfoFormRef" :itemList="tableFormItems" formId="table-base-form" :rules="tableFormRules"
col="col3" @select-change="handleTableFormSelectChange"
@treeSelectNodeChange="handleTableTreeNodeChange" />
</ContentWrap>
<ContentWrap id="id-requestParams" title="请求参数" description="" class="mt16">
<Table ref="requestParamsTableRef" :tableInfo="requestParamsTableInfo" class="fiveRow-table"
@tableSelectChange="handleRequestSelectChange" />
<div class="row-add-btn">
<el-button link @click="addRequestParams" :icon="CirclePlus"
:disabled="requestParamsTableInfo.data.length == inputParamsData.length" v-preReClick>添加</el-button>
</div>
</ContentWrap>
<ContentWrap id="id-responseParams" title="返回参数" description="" class="mt16">
<Table ref="responseParamsTableRef" :tableInfo="responseParamsTableInfo"
@tableSelectChange="handleresponseParamselectChange" class="fiveRow-table" />
<div class="row-add-btn">
<el-button link @click="addresponseParams" :icon="CirclePlus" v-preReClick>添加</el-button>
</div>
</ContentWrap>
<ContentWrap id="id-sortParams" title="排序参数" description="" class="mt16">
<Table ref="sortParamsTableRef" :tableInfo="sortParamsTableInfo"
@tableSelectChange="handleSortParamSelectChange" class="fiveRow-table" />
<div class="row-add-btn">
<el-button link @click="addSortParams" :icon="CirclePlus" v-preReClick>添加</el-button>
</div>
</ContentWrap>
</template>
<template v-else-if="apiType == '2'">
<ContentWrap id="id-dsInfo" title="数据源" description="">
<Form ref="tableInfoFormRef" :itemList="[tableFormItems[1]]" formId="table-base-form"
:rules="tableFormRules" col="col3" @select-change="handleTableFormSelectChange" />
</ContentWrap>
<ContentWrap id="id-sqlInfo" title="sql" description="" class="mt16">
<Form ref="sqlInfoFormRef" :itemList="sqlFormItems" formId="table-base-form" :rules="sqlFormRules"
@inputChange="sqlFormInputChange" />
</ContentWrap>
</template>
<template v-else-if="apiType == '3'">
<ContentWrap id="id-backApiInfo" title="注册API信息" description="">
<Form ref="backApiInfoFormRef" :itemList="backApiFormItems" formId="table-base-form"
:rules="backApiFormRules" col="col3" />
</ContentWrap>
<ContentWrap id="id-registRequestParams" title="请求参数" description="" class="mt16">
<Table ref="registRequestParamsTableRef" :tableInfo="registRequestParamsTableInfo" class="fiveRow-table" />
<div class="row-add-btn">
<el-button link @click="addRegistRequestParams" :icon="CirclePlus" v-preReClick>添加</el-button>
</div>
</ContentWrap>
<ContentWrap id="id-constParams" title="常量参数" description="" class="mt16">
<Table ref="constParamsTableRef" :tableInfo="constParamsTableInfo" class="fiveRow-table" />
<div class="row-add-btn">
<el-button link @click="addConstParams" :icon="CirclePlus" v-preReClick>添加</el-button>
</div>
</ContentWrap>
</template>
</div>
<div class="operator_panel_wrap" v-show="step == 2">
<ContentWrap id="id-api" title="API" description="">
<Form ref="apiInfoFormRef" style="width: 70%" :itemList="apiFormItems" formId="api-base-form" col="col2" />
</ContentWrap>
<ContentWrap id="id-queryParams" title="QUERY" description="" class="mt16">
<Table :tableInfo="queryParamsTableInfo" class="mb10" />
</ContentWrap>
<ContentWrap id="id-defaultParams" title="DEFAULT" description="" class="mt16">
<Table :tableInfo="defaultParamsTableInfo" class="mb10" />
</ContentWrap>
<ContentWrap id="id-test" title="测试API" description="" class="mt16">
<el-button :loading="startTestApiBtnLoading" @click="startTestApi" class="mb10">开始测试</el-button>
<Form ref="resultInfoFormRef" :itemList="resultFormItems" formId="result-base-form" col="col2" />
</ContentWrap>
</div>
<ContentWrap title="流程审批" v-show="needApprove" description="" :isExpand="flowExpand" :expand-swicth="true" class="mt16"
@expand="(v) => flowExpand = v">
<ApprovalProcess v-if="deploymentId" :deploymentId="deploymentId" :definitionId="''">
</ApprovalProcess>
</ContentWrap>
</div>
<!-- <FlowBtnGroup v-show="step == 2" pageType="add" :approveVO="bizApproveVO" @save="save"></FlowBtnGroup> -->
<div class="bottom_tool_wrap">
<template v-if="step == 0">
<el-button @click="cancel">取消</el-button>
<el-button type="primary" @click="nextStep(1)">下一步</el-button>
</template>
<template v-else-if="step == 1">
<el-button @click="cancel">取消</el-button>
<el-button type="primary" @click="previousStep(1)">上一步</el-button>
<el-button type="primary" @click="nextStep(2)">下一步</el-button>
</template>
<template v-else>
<el-button @click="cancel">取消</el-button>
<el-button type="primary" @click="previousStep(2)">上一步</el-button>
<el-button v-if="!isDetail" type="primary" @click="save()">保存</el-button>
<el-button v-if="!isDetail" type="primary" @click="save(true)">保存并提交</el-button>
</template>
<!-- <template v-if="pageType == 'add'">
<template v-if="approveVO && approveVO.approveState == 'N'">
<el-button type="" @click="save(false)">保存草稿</el-button>
</template>
<template v-if="!approveVO">
<el-button type="" @click="save(false)">保存草稿</el-button>
</template>
<el-button type="primary" @click="save(true)">提交流程</el-button>
</template> -->
</div>
</div>
</template>
<style lang="scss" scoped>
.top_tool_wrap {
width: 100%;
height: 72px;
margin: 8px 0 0px;
display: flex;
justify-content: center;
align-items: center;
:deep(.el-steps) {
width: 50%;
justify-content: center;
}
}
.content_main {
height: calc(100% - 40px);
padding: 0 16px 16px;
overflow: hidden auto;
.operator_panel_wrap {
height: auto;
.row-add-btn {
.el-button--default {
padding: 4px 0px;
margin: 8px 0px;
}
:deep(.el-icon) {
width: 16px;
height: 16px;
svg {
width: 16px;
height: 16px;
}
}
}
}
}
:deep(.el-form) {
.select-input-long {
.el-form-item:first-child {
width: 100px;
margin-right: 0px;
}
.el-form-item:last-child {
width: calc(100% - 100px);
margin-right: 0px;
.item-label {
white-space: pre;
.required_mark::after {
content: '';
}
}
}
}
}
.bottom_tool_wrap {
height: 40px;
padding: 0 16px;
border-top: 1px solid #d9d9d9;
display: flex;
justify-content: flex-end;
align-items: center;
}
.mb10 {
margin-bottom: 10px;
}
.mt16 {
margin-top: 16px;
}
.fiveRow-table {
:deep(.el-table) {
.el-table__empty-block {
height: 182px !important;
}
}
}
#id-test {
:deep(.el-form) {
.el-textarea .el-textarea__inner {
overflow-wrap: break-word;
white-space: pre-wrap;
word-break: break-all;
}
}
}
</style>
\ No newline at end of file
<route lang="yaml">
name: processDetail
</route>
<script lang="ts" setup name="processDetail">
import { ref } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import { CircleCloseFilled } from '@element-plus/icons-vue'
import useUserStore from "@/store/modules/user";
import { useRoute } from "vue-router";
import detail_serviceApi from './detail_serviceApi.vue';
import Dialog from "@/components/Dialog/index.vue";
import { getCamundaDeploymentId,getDetailDataPromise,getProcessFlowDetail, passFlowData, rejectFlowData, revokeFlowData } from "@/api/modules/workFlowService";
const route = useRoute();
const fullPath = route.fullPath;
const deploymentId = ref('');
const guid = route.query.guid as string;
const detailType = <string>route.query.type || '';
const reason = ref('')
const toolBtns: any = ref([])
const emits = defineEmits([
"tableSelectChange",
"tableBtnClick",
]);
const { proxy } = getCurrentInstance() as any
const userStore = useUserStore()
const userData = JSON.parse(userStore.userData)
const srcs = ref('')
const flowDetail: any = ref({});
const flowDetailLoading = ref(false);
const bizGuid = ref('');
const contents = ref({
pass: [
{
type: 'form',
title: '',
formInfo: {
id: 'batch-pass-form',
items: [
{
label: '',
type: "textarea",
placeholder: "请填写通过备注(选填)",
field: "approveSuggest",
clearable: true,
block: true,
col: 'margin_b_0',
}
]
}
}
],
reject: [
{
type: 'form',
title: '',
formInfo: {
id: 'batch-reject-form',
items: [
{
label: '',
type: "textarea",
placeholder: "请填写驳回理由(必填)",
field: "approveSuggest",
clearable: true,
block: true,
col: 'margin_b_0',
}
]
}
}
],
});
const dialogInfo = ref({
visible: false,
size: 460,
direction: "column",
header: {
title: "",
},
type: '',
contents: [],
footer: {
btns: [
{ type: "default", label: "取消", value: "cancel" },
{ type: "primary", label: "确定", value: "submit" },
],
},
});
const getProcessDetail = () => {
if (!flowDetailLoading.value) {
flowDetailLoading.value = true
}
getCamundaDeploymentId('10023').then((res: any) => {
flowDetailLoading.value = false
if (res.code == proxy.$passCode) {
if (res.code == proxy.$passCode) {
deploymentId.value = res.data;
} else {
proxy.$ElMessage.error(res.msg);
}
} else {
proxy.$ElMessage.error(res.msg);
}
})
// getProcessFlowDetail(guid).then((res: any) => {
// flowDetailLoading.value = false;
// if (res.code == proxy.$passCode) {
// let detail = res.data || {};
// if(Object.keys(detail).length == 0){
// ElMessage({
// type: 'error',
// message: '流程不存在'
// })
// return
// }
// flowDetail.value = detail;
// srcs.value = `${import.meta.env.VITE_BPMN_URL}/daopIframeBpmn?token=${userStore.token}&processInstanceId=${detail.camundaInstanceId}&camundaDeploymentId=${detail.camundaDeploymentId}`
// bizGuid.value = detail.bizGuid || '';
// let tab: any = userStore.tabbar.find((tab: any) => tab.fullPath === fullPath);
// if (tab) {
// tab.meta.title = `流程详情-${detail.functionName}`;
// }
// if (detailType !== 'detail') {
// const btnsArr: any = []
// if (detail.approveState == 'A') {
// if (detail.approveStaffGuids && detail.approveStaffGuids.indexOf(userData.staffGuid) > -1) {
// btnsArr.splice(0, 1, { label: "驳回", value: "reject", type: 'danger', plain: true }, { label: "通过", value: "pass", type: 'primary' })
// }
// if (detail.staffGuid && detail.staffGuid == userData.staffGuid) {
// btnsArr.push({ label: "撤销", value: "revoke" })
// }
// }
// toolBtns.value = btnsArr
// }
// } else {
// ElMessage.error(res.msg);
// }
// }).catch(() => {
// flowDetailLoading.value = false;
// })
}
const btnClick = (btn) => {
const type = btn.value
if (type == 'pass' || type == 'reject') {
dialogInfo.value.type = type
dialogInfo.value.header.title = type == 'pass' ? '通过备注' : '驳回理由'
dialogInfo.value.contents = contents.value[type]
dialogInfo.value.visible = true
} else if (type == 'revoke') {
ElMessageBox.confirm('确定撤销吗?', "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: type,
}).then(() => {
flowDetailLoading.value = true;
let params = {
guid: flowDetail.value.guid,
flowType: flowDetail.value.flowType,
approveSuggest: '',
approveStaffGuid: userData.staffGuid
}
revokeFlowData(params).then((res: any) => {
if (res.code == proxy.$passCode) {
getProcessDetail()
ElMessage({
type: 'success',
message: '撤销成功'
})
} else {
ElMessage({
type: 'error',
message: res.msg
})
flowDetailLoading.value = false;
}
}).catch(() => {
flowDetailLoading.value = false;
})
})
}
}
const dialogBtnClick = (btn, info) => {
if (btn.value == 'submit') {
let params = { ...info }
params.guid = flowDetail.value.guid
params.flowType = flowDetail.value.flowType
params.approveStaffGuid = userData.staffGuid
if (dialogInfo.value.type == 'pass') {
dialogInfo.value.visible = false;
flowDetailLoading.value = true;
passFlowData(params).then((res: any) => {
if (res.code == proxy.$passCode) {
getProcessDetail();
ElMessage({
type: 'success',
message: '审批成功'
})
} else {
ElMessage({
type: 'error',
message: res.msg,
})
flowDetailLoading.value = false;
}
}).catch(() => {
flowDetailLoading.value = false;
})
} else if (dialogInfo.value.type == 'reject') {
if (info.approveSuggest == '') {
ElMessage.error('请填写驳回理由')
return
}
dialogInfo.value.visible = false;
flowDetailLoading.value = true;
rejectFlowData(params).then((res: any) => {
if (res.code == proxy.$passCode) {
getProcessDetail();
ElMessage({
type: 'success',
message: '驳回成功'
})
dialogInfo.value.visible = false;
} else {
ElMessage({
type: 'error',
message: res.msg,
})
flowDetailLoading.value = false;
}
}).catch(() => {
flowDetailLoading.value = false;
})
}
} else if (btn.value == 'cancel') {
dialogInfo.value.visible = false;
}
};
onBeforeMount(() => {
getProcessDetail();
})
</script>
<template>
<div class="container_wrap" v-loading="flowDetailLoading">
<div class="content_main" :class="{ full: toolBtns.length == 0 }">
<div class="panel_wrap">
<div class="panel_header">
<div class="header_title">
<span class="title_text">申请内容</span>
</div>
</div>
<div class="panel_body">
<div class="list_panel">
<detail_serviceApi :apiGuid="guid"></detail_serviceApi>
</div>
</div>
</div>
<div class="panel_wrap">
<div class="panel_header">
<div class="header_title">
<span class="title_text">审批操作</span>
</div>
</div>
<div class="panel_body">
<div class="process_panel" v-if="!flowDetailLoading">
<ApprovalProcess v-if="deploymentId" :deploymentId="deploymentId" :definitionId="''">
</ApprovalProcess>
</div>
</div>
</div>
</div>
<div class="tool_btns" v-if="toolBtns.length">
<div class="btns">
<el-button v-for="btn in toolBtns" :type="btn.type" :plain="btn.plain" @click="btnClick(btn)">{{ btn.label
}}</el-button>
</div>
</div>
<Dialog :dialogInfo="dialogInfo" @btnClick="dialogBtnClick" />
</div>
</template>
<style lang="scss" scoped>
.container_wrap {
padding: 0;
height: 100%;
overflow: hidden;
&>.content_main {
padding: 16px;
height: calc(100% - 44px);
overflow: hidden auto;
&.full {
height: 100%;
}
}
}
.panel_wrap {
.panel_header {
.header_title {
height: 40px;
padding: 0 16px;
background-color: #fafafa;
box-shadow: 0 0 0 1px rgba(229, 229, 229, 1);
display: flex;
align-items: center;
}
.title_text {
line-height: 22px;
font-size: 14px;
color: var(--el-color-regular);
font-weight: 600;
}
}
.panel_body {
padding: 8px 16px;
box-shadow: 0 0 0 1px rgba(229, 229, 229, 1);
border-top: none;
margin-top: 1px;
.list_panel {
display: flex;
flex-wrap: wrap;
.list_item {
width: 33.33%;
line-height: 32px;
font-size: 14px;
color: #666666;
display: flex;
justify-content: space-between;
.item_label {
width: 100px;
text-align: right;
}
.item_value {
color: var(--el-color-regular);
padding: 0 16px;
flex: 1;
text-align: justify;
}
&.is_block {
width: 100%;
}
}
:deep(.panel_body) {
box-shadow: none;
}
}
.table_panel_wrap {
.table_panel {
padding: 0;
min-height: unset;
}
}
.process_panel {
height: 500px;
.iframe-sty {
width: 100%;
height: 100%;
border: none;
}
:deep(.property-panel) {
height: calc(100% - 50px) !important;
}
}
}
+.panel_wrap {
margin-top: 16px;
}
&.results_panel {
box-shadow: 0 0 0 1px #d9d9d9;
.panel_header {
.header_title {
background-color: transparent;
box-shadow: none;
.el-icon {
margin-right: 8px;
width: 20px;
height: 20px;
svg {
width: 100%;
height: 100%;
}
}
}
}
.panel_body {
padding-top: 0;
margin-top: 0;
box-shadow: none;
.results_list {
display: flex;
.list_item {
display: flex;
margin-bottom: 8px;
margin-right: 60px;
color: #666;
.item_value {
padding: 0 8px;
color: var(--el-color-regular);
}
}
}
}
&.success {
background-color: #F4FEF6;
box-shadow: 0 0 0 1px #4FA55D;
.panel_header {
.header_title {
.el-icon {
color: #4FA55D;
}
}
}
}
&.reject {
background-color: #FDF2F4;
box-shadow: 0 0 0 1px #E63E33;
.panel_header {
.header_title {
.el-icon {
color: #E63E33;
}
}
}
}
&.audit {
background-color: #FEFBF3;
box-shadow: 0 0 0 1px #F19E40;
.panel_header {
.header_title {
.el-icon {
color: #F19E40;
}
}
}
}
&.revoke {
background-color: #F5F5F5;
box-shadow: 0 0 0 1px #CCCCCC;
.panel_header {
.header_title {
.el-icon {
color: #666666;
}
}
}
}
}
}
.tool_btns {
display: flex;
justify-content: center;
align-items: center;
height: 44px;
padding: 0 16px;
box-shadow: 0 -1px 0 0 #d9d9d9;
}
</style>
\ No newline at end of file
<route lang="yaml">
name: apiManagement
</route>
<script lang="ts" setup name="apiManagement">
import { ref } from 'vue';
import { TableColumnWidth } from '@/utils/enum';
import { commonPageConfig } from '@/components/PageNav/index';
import TableTools from '@/components/Tools/table_tools.vue'
import { useValidator } from '@/hooks/useValidator';
import { useRouter, useRoute } from "vue-router";
import { isNeedApprove, passFlowData, rejectFlowData, revokeFlowData } from "@/api/modules/workFlowService";
import {
apiTypes,
getAPIList,
updateAPIState,
addApiApprove,
deleteApi,
copyApi,
checkExistAPIName,
} from "@/api/modules/dataService";
import useDataServiceStore from "@/store/modules/dataService";
import useUserStore from "@/store/modules/user";
const router = useRouter();
const dataServiceStore = useDataServiceStore();
const { required, chOrEnPreffix, regexpValidate, checkExistName } = useValidator();
const userStore = useUserStore()
const userData = JSON.parse(userStore.userData)
const { proxy } = getCurrentInstance() as any;
onBeforeMount(() => {
//TODO,需要调用isNeedApprove接口判断是否需要审批,判断是否显示审批列
getTableData();
});
onActivated(() => {
/** 若是新建则默认选中对应的标签展示列表。 */
if (dataServiceStore.isUpdate) {
getTableData();
dataServiceStore.setIsUpdate(false);
}
})
const APIDataPage: any = ref({
...commonPageConfig, apiType: '',
apiName: '',//API标签名称搜索。
approveState: ''
});
/** api管理列表表格数据上方搜索区域 */
const tableSearchItemList: any = ref([
{
type: 'input',
label: '',
field: 'apiName',
default: '',
placeholder: 'API名称',
maxlength: 50,
clearable: true
}, {
type: 'select',
label: '',
field: 'apiType',
default: '',
placeholder: 'API类型',
options: apiTypes,
clearable: true
}, {
type: 'select',
label: '',
field: 'approveState',
default: '',
placeholder: '全部状态',
options: [
{ label: '草稿中', value: 'N' },
{ label: '审批中', value: 'A' },
{ label: '已通过', value: 'Y' },
{ label: '已驳回', value: 'R' },
{ label: '已撤销', value: 'C' },
],
clearable: true
}
]);
const getTableData = () => {
tableInfo.value.loading = true;
getAPIList({
// tagGuid: lastClickNode.value.guid,
pageSize: APIDataPage.value.limit,
pageIndex: APIDataPage.value.curr,
apiName: APIDataPage.value.apiName,
apiType: APIDataPage.value.apiType,
approveState: APIDataPage.value.approveState
}).then((res: any) => {
tableInfo.value.loading = false;
if (res.code == proxy.$passCode) {
const data = res.data || {};
tableInfo.value.data = data.records || []
tableInfo.value.page.limit = data.pageSize
tableInfo.value.page.curr = data.pageIndex
tableInfo.value.page.rows = data.totalRows
} else {
proxy.$ElMessage.error(res.msg);
}
})
}
const toTableSearch = (val, clear) => {
APIDataPage.value.curr = 1;
if (clear) {
APIDataPage.value.apiType = '';
APIDataPage.value.apiName = '';
APIDataPage.value.dataState = null;
APIDataPage.value.approveState = '';
getTableData();
return;
}
APIDataPage.value.apiType = val.apiType;
APIDataPage.value.apiName = val.apiName;
if (!val.approveState) {
APIDataPage.value.approveState = '';
} else {
APIDataPage.value.approveState = val.approveState;
}
getTableData();
}
const handleAPICreateCommand = (command: string) => {
router.push({
name: 'apiCreate',
query: {
type: command,
}
});
}
/** 记录正在提交审批流程的api,防止重复提交 */
const addApprovePromise = ref({});
const selectRowData: any = ref([])
const currTableData: any = ref({});
const tableInfo = ref({
id: 'api-data-table',
rowKey: 'guid',
loading: false,
multiple: false,
fields: [
{ label: "序号", type: "index", width: TableColumnWidth.INDEX, align: "center" },
{ label: "API名称", field: "apiName", width: 140, align: "left" },
{
label: "API类型", field: "apiType", width: 100, align: "left", getName: (scope) => {
return apiTypes.find(a => a.value == scope.row.apiType)?.label;
}
},
{
label: "调用次数", field: "invokeCount", width: 100, align: 'right', type: 'chnum'
},
{
label: "调用异常数", field: "invokeErrorCount", width: 105, align: 'right', type: 'chnum'
},
{
label: "平均响应时间(s)", field: "averageRespTime", width: 130, align: 'right', type: 'chnum'
},
{ label: "API请求路径", field: "requestUrl", width: TableColumnWidth.DESCRIPTION },
{
label: '状态', field: 'apiState', type: 'switch', activeText: '启用', inactiveText: '停用', activeValue: 1, inactiveValue: 0, switchWidth: 56, width: 96, align: 'center', isDisabled: (scope) => {
if (scope.row.apiState == 1 && scope.row.bindingCount > 0) {//被授权的不能禁用。
return true;
}
return scope.row.approveState != 'Y';//正在审批中的不能停用。草稿中的不能启用。
}
},
{ label: "审批状态", field: "approveState", type: "tag", width: TableColumnWidth.STATE, align: 'center' },
{ label: "API描述", field: "apiDescription", width: TableColumnWidth.DESCRIPTION },
{ label: "修改人", field: "updateUserName", width: TableColumnWidth.USERNAME },
{ label: "修改时间", field: "updateTime", width: 170 },
],
data: [],
page: {
type: "normal",
rows: 0,
...APIDataPage.value,
},
actionInfo: {
label: "操作",
type: "btn",
isMore: false,
width: 200,
btns: (scope) => {
const { row } = scope;
let list: any = [];
const approveVO = row.approveVO || {};
if (!approveVO && row.isApprove == 'N') {
list.push({ label: "编辑", value: "edit", click: apiManageTableBtnMap.EDIT });
list.push({ label: "删除", value: "del", click: apiManageTableBtnMap.DELETE });
list.push({ label: "详情", value: "detail", click: apiManageTableBtnMap.DETAIL });
list.push({ label: "复制", value: "copy", click: apiManageTableBtnMap.COPY })
return list;
}
const currentStaffGuid = userData.staffGuid
const bizApproveState = row.bizApproveState;
const approveState = approveVO.approveState || null;
const approveStaffGuids = approveVO.approveStaffGuids || [];
const staffGuid = approveVO.staffGuid || '';
let isShowCancel = false;
let flowState;
if (approveState == 'N') {
flowState = 1;
}
if (approveState == 'A' && approveStaffGuids.indexOf(currentStaffGuid) > -1) {
flowState = 2;
}
if ((approveState == 'C' || approveState == 'R') && staffGuid == currentStaffGuid) {
flowState = 3;
}
if (approveVO && approveVO.approveState == 'A' && staffGuid == currentStaffGuid) {
isShowCancel = true;
}
if (flowState === 1) {
list = [{ label: "编辑", value: "edit", click: apiManageTableBtnMap.EDIT }]
}
if (flowState === 2) {
list = [{ label: "通过", value: "pass", click: apiManageTableBtnMap.PASS }, { label: "驳回", value: "reject", click: apiManageTableBtnMap.REJECT }]
}
if (approveState == 'Y' && row.apiState != 1 && staffGuid == currentStaffGuid) {
list = [{ label: "编辑", value: "edit", click: apiManageTableBtnMap.EDIT }]
}
if (flowState === 3 || (row.apiState != 1 && approveState !== 'A')) {
list.push({ label: "删除", value: "del", click: apiManageTableBtnMap.DELETE })
}
if (flowState === 3 && bizApproveState != 'D') {
list.push({ label: "重新提交", value: "redit", click: apiManageTableBtnMap.EDIT })
}
if (isShowCancel) {
list.push({ label: "撤销", value: "revoke", click: apiManageTableBtnMap.REVOKE })
}
if (flowState !== 1) {
list.push({ label: "详情", value: "detail", click: apiManageTableBtnMap.DETAIL })
}
list.push({ label: "复制", value: "copy", click: apiManageTableBtnMap.COPY })
return list
},
}
});
/** api管理表格的操作按钮事件。 */
const apiManageTableBtnMap = {
/** 编辑 */
EDIT: (scope) => {
router.push({
name: 'apiCreate',
query: {
guid: scope.row.guid,
apiName: scope.row.apiName,
// tagGuid: lastClickNode.value.guid
}
});
},
/** 详情 */
DETAIL: (scope) => {
let row = scope.row;
if (!row.approveGuid) {
proxy.$ElMessage.error(`【${row.apiName}】关联流程已删除!`);
return;
}
router.push({
name: 'APIProcessDetail',
query: { guid: row.approveGuid, type: 'detail' }
});
},
/** 撤回 */
REVOKE: (scope) => {
proxy.$openMessageBox('确定撤销该API审批吗?', () => {
let params = {
guid: scope.row.approveGuid,
approveStaffGuid: userData.staffGuid
}
revokeFlowData(params).then((res: any) => {
if (res.code == proxy.$passCode) {
getTableData();
proxy.$ElMessage.success('撤销成功');
} else {
proxy.$ElMessage.error(res.msg);
}
})
}, () => {
proxy.$ElMessage({
type: 'info',
message: '已取消撤销'
});
});
},
SUBMIT: (scope) => {
if (addApprovePromise.value[scope.row.guid]) {
return;
}
addApprovePromise.value[scope.row.guid] = addApiApprove(scope.row.guid).then((res: any) => {
delete addApprovePromise.value[scope.row.guid];
if (res.code == proxy.$passCode) {
getTableData();
proxy.$ElMessage({
type: 'success',
message: '该API提交成功'
})
} else {
proxy.$ElMessage.error(res.msg);
}
})
},
PASS: (scope) => {
approveSuggest.value = '';
approveType.value = 'pass';
dialogTitle.value = '通过理由'
dialogVisible.value = true;
},
REJECT: (scope) => {
approveSuggest.value = '';
approveType.value = 'reject';
dialogTitle.value = '驳回理由'
dialogVisible.value = true;
},
DELETE: (scope) => {
proxy.$openMessageBox("确定要删除该API吗?", () => {
deleteApi(scope.row.guid).then((res: any) => {
if (res.code == proxy.$passCode) {
APIDataPage.value.curr = 1;
getTableData();
proxy.$ElMessage.success('删除该API提交成功');
} else {
proxy.$ElMessage.error(res.msg);
}
});
})
},
COPY: (scope) => {
currTableData.value = scope.row;
copyApiFormItems.value[0].default = scope.row.apiName + '_copy';
copyApiFormItems.value[1].children && (copyApiFormItems.value[1].children[1].default = scope.row.requestPath + '-copy');
copyApiDialogInfo.value.formInfo.items = copyApiFormItems.value;
copyApiDialogInfo.value.visible = true;
}
}
const approveSuggest = ref();
const dialogTitle = ref('通过理由');
const dialogVisible = ref(false);
//弹窗类型
const approveType = ref();
const passSubmit = () => {
let row = currTableData.value
dialogVisible.value = false;
tableInfo.value.loading = true;
passFlowData({
guid: row.approveVO.approveGuid,
flowType: row.approveVO.flowType,
approveSuggest: approveSuggest.value,
approveStaffGuid: userData.staffGuid,
}).then((res: any) => {
tableInfo.value.loading = false;
if (res.code == '00000') {
proxy.$ElMessage.success('审批通过!')
getTableData();
} else {
proxy.$ElMessage.error(res.msg)
}
})
}
const rejectSubmit = () => {
if (!approveSuggest.value) return proxy.$ElMessage.error('请填写驳回理由!')
let row = currTableData.value
dialogVisible.value = false;
tableInfo.value.loading = true;
rejectFlowData({
guid: row.approveVO.approveGuid,
flowType: row.approveVO.flowType,
approveSuggest: approveSuggest.value,
approveStaffGuid: userData.staffGuid,
}).then((res: any) => {
if (res.code == '00000') {
tableInfo.value.loading = false;
proxy.$ElMessage.success('驳回成功!')
getTableData();
} else {
proxy.$ElMessage.error(res.msg)
}
})
}
const apiTablePageChange = (info) => {
APIDataPage.value.curr = Number(info.curr);
APIDataPage.value.limit = Number(info.limit);
tableInfo.value.page.limit = APIDataPage.value.limit;
tableInfo.value.page.curr = APIDataPage.value.curr;
getTableData();
};
const tableSwitchBeforeChange = (scope, field, callback) => {
const msg = `确定【${scope.row[field] == 1 ? '停用' : '启用'}】该API吗?`;
proxy.$openMessageBox(msg, () => {
const state = scope.row[field] == 1 ? 0 : 1
const result = tableSwitchChange(state, scope, field)
callback(result)
}, () => {
callback(false)
});
}
const tableSwitchChange = (val, scope, field) => {
return new Promise((resolve, reject) => {
let params = {
guid: scope.row.guid,
apiState: val
}
updateAPIState(params).then((res: any) => {
if (res.code == proxy.$passCode && res.data) {
getTableData();
proxy.$ElMessage({
type: "success",
message: `该API${val == 1 ? '启用' : '停用'}成功`,
});
resolve(true)
} else {
proxy.$ElMessage({
type: "error",
message: res.msg,
});
getTableData();
reject(false)
}
}).catch(() => {
getTableData();
reject(false)
})
})
}
const tableSelectionChange = (val) => {
selectRowData.value = val;
};
/** -------------- 复制功能 ------------------- */
const copyApiFormItems = ref([{
type: 'input',
label: 'API名称',
field: 'apiName',
default: '',
regexp: /[^a-zA-Z0-9_\u4e00-\u9fa5-]/g,
block: true,
placeholder: '请输入',
maxlength: 50,
clearable: true,
required: true
}, {
type: "select-group",
field: "httpInfo",
col: ' select-input-long-reverse',
block: true,
children: [
{
label: "API请求路径",
type: "input",
placeholder: "请选择",
default: "https",
field: "httpType",
required: true,
disabled: true,
visible: true,
},
{
label: " ",
type: "input",
placeholder: "请输入",
default: '/',
field: "requestPath",
maxlength: 50,
required: true,
visible: true,
},
],
visible: true
}]);
/** 记录已检验过的APIName */
const checkedInfo = ref({});
const copyApiFormRules = ref({
apiName: [required("请填写API名称"), chOrEnPreffix(), checkExistName(checkedInfo.value, checkExistAPIName, '')],
requestPath: [required("请填写请求路径"), regexpValidate(/^\/[^\/][\w\u4e00-\u9fa5_-]*$/, '请输入合法的请求路径')],
});
const copyApiDialogInfo = ref({
visible: false,
size: 480,
title: "复制API",
type: 'add',
formInfo: {
id: 'add-authorize-form',
items: copyApiFormItems.value,
rules: copyApiFormRules.value
},
btns: {
submit: (btn, info) => {
info.guid = currTableData.value.guid;
copyApiDialogInfo.value.submitBtnLoading = true;
copyApi(info).then((res: any) => {
copyApiDialogInfo.value.submitBtnLoading = false;
if (res.code == proxy.$passCode) {
APIDataPage.value.curr = 1;
getTableData();
proxy.$ElMessage({
type: 'success',
message: `【${info.apiName}】API复制成功`
})
copyApiDialogInfo.value.visible = false;
} else {
proxy.$ElMessage.error(res.msg);
}
})
},
cancel: () => {
copyApiDialogInfo.value.visible = false;
}
},
submitBtnLoading: false
});
</script>
<template>
<div class="container_wrap full flex">
<div class="main_wrap">
<div class="table_tool_wrap">
<TableTools ref="tableTools" :searchItems="tableSearchItemList" :init="false" :searchId="'api-table-search'"
@search="toTableSearch" />
<div class="tools_btns">
<el-dropdown popper-class="table-create-menu" @command="handleAPICreateCommand" placement="bottom-start"
trigger="click">
<span class="el-dropdown-link">
<el-button type="primary">新建API</el-button>
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="1">
<el-icon style="width: 24px;height: 24px;">
<svg-icon style="width: 24px;height: 24px;" name="api-single-table" />
</el-icon>
<div class="item-content">
<span class="item-content-title">单表API</span>
<span class="item-content-desc">选单表中的字段进行对外输出</span>
</div>
</el-dropdown-item>
<el-dropdown-item command="2">
<el-icon style="width: 24px;height: 24px;">
<svg-icon style="width: 24px;height: 24px;" name="api-sql" />
</el-icon>
<div class="item-content">
<span class="item-content-title">自定义sql</span>
<span class="item-content-desc">对复杂接口的配置</span>
</div>
</el-dropdown-item>
<el-dropdown-item command="3">
<el-icon style="width: 24px;height: 24px;">
<svg-icon style="width: 24px;height: 24px;" name="api-regist" />
</el-icon>
<div class="item-content">
<span class="item-content-title">注册API</span>
<span class="item-content-desc">已有的API接口,通过注册进行线上监控和维护</span>
</div>
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</div>
<div class="table_panel_wrap">
<Table :tableInfo="tableInfo" @tablePageChange="apiTablePageChange"
@tableSwitchBeforeChange="tableSwitchBeforeChange" @tableSelectionChange="tableSelectionChange" />
</div>
</div>
<!-- 复制对话框 -->
<Dialog_form :dialogConfigInfo="copyApiDialogInfo" />
<el-dialog v-model="dialogVisible" width="40%">
<template #title>
<div v-if="dialogTitle == '驳回理由'">{{ dialogTitle }}<span style="color:red;">*</span></div>
<div v-else>{{ dialogTitle }}</div>
</template>
<el-input type="textarea" :rows="4" maxlength="100" v-model="approveSuggest" show-word-limit resize="none">
</el-input>
<template #footer>
<div class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button v-if="approveType == 'pass'" type="primary" @click="passSubmit">通过</el-button>
<el-button v-if="approveType == 'reject'" type="primary" @click="rejectSubmit">驳回</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<style lang="scss" scoped>
.container_wrap {
padding: 0;
display: flex;
justify-content: space-between;
.aside_wrap {
width: 199px;
border-right: 1px solid #d9d9d9;
box-shadow: none;
.aside_title {
width: calc(100% - 32px);
display: inline-block;
}
.icon-add.el-icon {
width: 24px;
height: 24px;
vertical-align: middle;
cursor: pointer;
svg {
width: 24px;
height: 24px;
}
}
:deep(.tree_panel) {
height: 100%;
padding-top: 0;
.el-tree {
margin: 0;
height: calc(100% - 68px);
overflow: hidden auto;
}
}
}
.main_wrap {
padding: 0 16px;
height: auto;
flex: 1;
.table_panel_wrap {
height: calc(100% - 92px);
}
}
}
:deep(.el-form) {
.select-input-long {
.el-form-item:first-child {
width: 67%;
margin-right: 0px;
}
.el-form-item:last-child {
width: 33%;
margin-right: 0px;
.item-label {
white-space: pre;
.required_mark::after {
content: '';
}
}
}
}
.select-input-long-reverse {
.el-form-item:first-child {
width: 100px;
margin-right: 0px;
}
.el-form-item:last-child {
width: calc(100% - 100px);
margin-right: 0px;
.item-label {
white-space: pre;
.required_mark::after {
content: '';
}
}
}
}
}
</style>
\ No newline at end of file
<route lang="yaml">
name: apiTest
</route>
<script lang="ts" setup name="apiTest">
import { ref } from 'vue';
import {
getValidApiLabel,
getSceneValidApiLabel,
getAllApi,
testApiData,
getApiDetail
} from "@/api/modules/dataService";
import { TableColumnWidth } from '@/utils/enum';
import { useValidator } from '@/hooks/useValidator';
import { progressProps } from 'element-plus';
import { useRouter } from "vue-router";
const { required } = useValidator();
const router = useRouter();
const { proxy } = getCurrentInstance() as any;
/** API下拉列表。已发布的启用的API名称,选择后自动带出路径和请求参数。 */
const apiLabelList = ref([]);
const processDTOSValue = ref([]);
const apiFormRef = ref();
/** 选择要测试的API. */
const apiFormItems = ref([
{
type: 'tree-select',
label: 'API名称',
field: 'apiGuid',
default: '',
placeholder: '请选择',
options: [],
col: 'path-w30',
props: {
label: "sceneName",
children: "children",
value: 'guid',
isLeaf: 'isLeaf'
},
filterable: true,
clearable: true,
required: true
},
// {
// type: 'input',
// label: 'API路径',
// field: 'path',
// default: '',
// maxlength: 50,
// col: 'path-w30',
// disabled: true,
// required: false
// },
// {
// type: 'input',
// label: '场景名称',
// field: 'sceneName',
// default: '',
// maxlength: 50,
// col: 'path-w20',
// disabled: true,
// required: false,
// },{
// type: 'input',
// label: '场景名称',
// field: 'sceneGuid',
// default: '',
// maxlength: 50,
// col: 'path-w20',
// disabled: true,
// required: false,
// visible: false,
// },{
// type: 'input',
// label: '加工单号',
// field: 'processOrderNo',
// default: '',
// maxlength: 50,
// col: 'path-w20',
// disabled: true,
// required: false,
// },
]);
const apiFormRules = ref({
apiGuid: [required('请选择数据产品')]
});
const requestParamsTableInfo = ref({
id: "query-params-table",
height: '214px',
fields: [
{ label: "序号", type: "index", width: TableColumnWidth.INDEX, align: "center" },
{ label: "参数名", field: "paramName", width: 140 },
{ label: "参数位置", field: "paramPositionName", width: 100 },
{ label: "参数类型", field: "dataTypeName", width: 120 },
{
label: "是否必填", field: "isRequired", width: 100, getName: (scope) => {
return scope.row.isRequired == 'Y' ? '是' : '否'
}
},
{
label: "是否多值", field: "isManyValue", width: 100, getName: (scope) => {
return scope.row.isManyValue == 'Y' ? '是' : '否'
}
},
{
label: "值", field: "introductionValue", width: 240, columClass: 'edit-colum', type: 'edit', dataTypeName: 'paramType', getVisible: (scope) => {
return !scope.row.isConst;
}
},
{ label: "描述", field: "description", width: 120 },
],
editInfo: {
introductionValue: {
label: '',
type: 'input',
field: 'introductionValue',
default: '',
placeholder: '请输入',
clearable: true,
}
},
STATUS: 'edit',
data: <Array<Object>>[],
showPage: false,
actionInfo: {
show: false
},
loading: false
});
const defaultParamsData: any = ref([{
paramName: 'pageSize',
dataType: '整型',
isRequired: '是',
value: 50
}, {
paramName: 'pageIndex',
dataType: '整型',
isRequired: '是',
value: 1
}]);
/** default参数表格配置 */
const defaultParamsTableInfo = ref({
id: "default-params-table",
height: 'auto',
minHeight: '50px',
minPanelHeight: '50px',
fields: [
{ label: "序号", type: "index", width: TableColumnWidth.INDEX, align: "center" },
{ label: "参数名", field: "paramName", width: 140 },
{ label: "参数类型", field: "dataType", width: 100 },
{ label: "是否必填", field: "isRequired", width: 100 },
{ label: "值", field: "value", width: 240, columClass: 'edit-colum', type: 'edit' },
],
editInfo: {
value: { //只能输入大于0的整数。
label: '',
type: 'input',
field: 'value',
default: '',
maxlength: 50,
min: 1,
regexp: /\D/g,
placeholder: '请输入',
clearable: false,
}
},
STATUS: 'edit',
data: defaultParamsData.value,
showPage: false,
actionInfo: {
show: false
},
loading: false
});
/** api测试结果详情表单 */
const resultFormItems = ref([{
label: '请求详情',
type: 'textarea',
placeholder: '输出请求详情',
field: 'requestUrlDetail',
default: '',
rows: 10,
readonly: true,
maxlength: "",
clearable: true,
required: false,
}, {
label: '返回内容',
type: 'textarea',
placeholder: '输出返回内容',
field: 'resultInfo',
default: '',
rows: 10,
readonly: true,
maxlength: "",
clearable: true,
required: false,
}]);
const getValidLabelPromise: any = ref(null);
onBeforeMount(() => {
getValidLabelPromise.value = getSceneValidApiLabel().then((res: any) => {
getValidLabelPromise.value = null;
if (res.code == proxy.$passCode) {
apiLabelList.value = res.data || [];
} else {
proxy.$ElMessage.error(res.msg);
}
})
// selectApiDetailInfo.value = {
// requestUrl: 'baidu.com',
// sceneName: '场景A',
// sceneGuid: 'A',
// processOrderNo: [
// {
// processOrderNo:1111,
// guid:'02e799002ad64cd3b1bc5aa31b592eca',
// requirementOrderName:'需求名称1',
// },
// {
// processOrderNo:2222,
// guid:'02e799002ad64cd3b1bc5aa31b592eca',
// requirementOrderName:'需求名称2',
// }
// ]
// };
if(selectApiDetailInfo.value?.processOrderNo?.length>0){
selectApiDetailInfo.value.processOrderNo.forEach(item=>{
item.noName=item.processOrderNo + '' + item.requirementOrderName
})
}
console.log('selectApiDetailInfo',selectApiDetailInfo.value);
})
const apiNodeLoad = (node, resolve, item) => {
if (node.level === 0) {
if (getValidLabelPromise.value) {
getValidLabelPromise.value.then(() => {
resolve(apiLabelList.value);
});
return;
}
resolve(apiLabelList.value)
} else if (node.level === 1) {
getAllApi(node.data.guid).then((res: any) => {
if (res.code == proxy.$passCode) {
const apiData = res.data?.map(d => {
d.sceneName = d.apiName;
d.isLeaf = true;
return d;
}) ?? [];
resolve(apiData);
} else {
proxy.$ElMessage.error(res.msg);
}
});
}
}
const getApiDetailPromise: any = ref(null);
const selectApiDetailInfo: any = ref({});////选择数据产品后带出来的信息
const apiSelectNodeChange = (node, item) => {
if (!node.isLeaf) {
return true;
}
requestParamsTableInfo.value.loading = true;
getApiDetailPromise.value = getApiDetail(node.guid).then((res: any) => {
getApiDetailPromise.value = null;
requestParamsTableInfo.value.loading = false;
requestParamsTableInfo.value.data = [];
if (res.code == proxy.$passCode) {
let data = res.data;
selectApiDetailInfo.value = res.data || {};
if(data.processDTOS&&data.processDTOS.length>0){
let processDTOS=data.processDTOS || [];
if(processDTOS?.length>0){
processDTOS.forEach(obj=>{
obj.noName=obj.processOrderNo + '' + obj.requirementOrderName
})
}
processDTOSValue.value = processDTOS || [];
}
}
else {
proxy.$ElMessage.error(res.msg);
}
})
}
const apiSelectChange = (val) => {
if (!val) {//清空值
apiFormItems.value[0].default = val;
// apiFormItems.value[1].default = '';
requestParamsTableInfo.value.data = [];
resultFormItems.value[0].default = '';
resultFormItems.value[1].default = '';
} else {
resultFormItems.value[0].default = '';
resultFormItems.value[1].default = '';
if (getApiDetailPromise.value) {
getApiDetailPromise.value.then(() => {
apiFormItems.value[0].default = val;
// apiFormItems.value[1].default = selectApiDetailInfo.value.requestUrl;
// apiFormItems.value[2].default = selectApiDetailInfo.value.sceneName;
// apiFormItems.value[3].default = selectApiDetailInfo.value.sceneGuid;
// apiFormItems.value[4].default = selectApiDetailInfo.value.processOrderNo;
let apiConfigAccessRSVOS = selectApiDetailInfo.value.apiConfigAccessRSVOS || [];
apiConfigAccessRSVOS.forEach(vo => {
if (vo.paramType == 'REQ') {
requestParamsTableInfo.value.data.push({ ...vo, introductionValue: vo.defaultValue });
} else if (vo.paramType == 'CONSTANT') {
requestParamsTableInfo.value.data.push({ ...vo, isConst: true, introductionValue: vo.defaultValue });
}
})
if (selectApiDetailInfo.value.authenticationType == 'N') {
defaultParamsTableInfo.value.data = defaultParamsData.value.concat([{
paramName: 'appKey',
dataType: '字符型',
isRequired: '是',
value: ''
}]);
} else {
defaultParamsTableInfo.value.data = defaultParamsData.value;
}
});
} else {
apiFormItems.value[0].default = val;
// apiFormItems.value[1].default = selectApiDetailInfo.value.requestUrl;
let apiConfigAccessRSVOS = selectApiDetailInfo.value.apiConfigAccessRSVOS || [];
apiConfigAccessRSVOS.forEach(vo => {
if (vo.paramType == 'REQ') {
requestParamsTableInfo.value.data.push({ ...vo, introductionValue: vo.defaultValue });
} else if (vo.paramType == 'CONSTANT') {
requestParamsTableInfo.value.data.push({ ...vo, isConst: true, introductionValue: vo.defaultValue });
}
})
}
}
}
const startTestApiBtnLoading = ref(false);
const startTestApi = () => {
apiFormRef.value?.ruleFormRef?.validate((valid, errorItem) => {
if (valid) {
let requestParamsData: any[] = requestParamsTableInfo.value.data;
if (requestParamsData.length) {
let dataIndex = 1;
for (const d of requestParamsData) {
if (d.isRequired == 'Y' && d.introductionValue !== 0 && !d.introductionValue) {
proxy.$ElMessage.error(`第 ${dataIndex} 个请求参数为必填则值不能为空`);
return;
}
dataIndex++;
}
}
let defaultParamsDataInfo = defaultParamsTableInfo.value.data;
if (defaultParamsDataInfo.length == 3 && !defaultParamsDataInfo[2].value) {
proxy.$ElMessage.error(`请填写参数appKey`);
return;
}
resultFormItems.value[0].default = '';
resultFormItems.value[1].default = '';
startTestApiBtnLoading.value = true;
testApiData({
pageSize: defaultParamsDataInfo[0].value,
pageIndex: defaultParamsDataInfo[1].value,
appKey: defaultParamsDataInfo.length == 3 ? defaultParamsDataInfo[2].value : '',
guid: apiFormRef.value.formInline.apiGuid,
apiConfigAccessDTOS: requestParamsData
}).then((res: any) => {
startTestApiBtnLoading.value = false;
if (res.code == proxy.$passCode) {
proxy.$ElMessage.success('测试API调用成功');
let info = res.data;
resultFormItems.value[0].default = JSON.stringify(info.apiInvokeReqVO, null, 4);
resultFormItems.value[1].default = JSON.stringify(info.apiInvokeRespVO, null, 4);
} else {
proxy.$ElMessage.error(res.msg);
}
}).catch(() => {
startTestApiBtnLoading.value = false;
});
} else {
var obj = Object.keys(errorItem);
apiFormRef.value.ruleFormRef.scrollToField(obj[0])
}
});
}
const seeDetail = (row) => {
console.log('row',row);
router.push({
name: 'processSheetDetail',
query: {
guid: row.guid,
}
});
}
</script>
<template>
<div class="container_wrap full">
<ContentWrap id="id-requestParams" title="请求参数" description="">
<div>
<Form ref="apiFormRef" :itemList="apiFormItems" formId="table-base-form" :rules="apiFormRules" col="col3"
@treeSelectLoad="apiNodeLoad" @treeSelectNodeChange="apiSelectNodeChange" @select-change="apiSelectChange" />
<el-row :gutter="24" class="mb10" v-if="selectApiDetailInfo?.sceneName">
<el-col :span="24">
<span class="label">API路径:</span>
<!-- -->
<span class="value">{{ selectApiDetailInfo?.requestUrl||'-' }}</span>
</el-col>
<!-- <el-col :span="12">
<span class="label">场景名称:</span>
<span class="value">{{ selectApiDetailInfo?.sceneName }}</span>
</el-col>
-->
</el-row>
<!-- <el-row :gutter="24" class="mb10" v-if="selectApiDetailInfo?.sceneName">
<el-col :span="24">
<span class="label">加工单号:</span>
<span v-for="(obj,idx) in processDTOSValue" @click="seeDetail(obj)" class="value cursor" style="color:#4fa1a4;padding-right:8px">{{ obj.noName }}{{ idx<processDTOSValue.length-1?'、':'' }}</span>
</el-col>
</el-row> -->
</div>
<Table :tableInfo="requestParamsTableInfo" class="mb10 mt8" />
</ContentWrap>
<ContentWrap id="id-defaultParams" title="DEFAULT" description="" class="mt16">
<Table :tableInfo="defaultParamsTableInfo" class="mb10" />
</ContentWrap>
<ContentWrap id="id-test" title="测试API" description="" class="mt16">
<el-button :disabled="requestParamsTableInfo.loading" :loading="startTestApiBtnLoading" @click="startTestApi"
class="mb10">开始测试</el-button>
<Form ref="resultInfoFormRef" :itemList="resultFormItems" formId="result-base-form" col="col2" />
</ContentWrap>
</div>
</template>
<style lang="scss" scoped>
.container_wrap.full {
overflow-y: auto;
padding: 16px;
}
:deep(.el-form) {
.el-form-item.path-w50 {
width: calc(60% - 6px) !important;
max-width: 720px;
}
.el-form-item.path-w30 {
width: calc(30% - 6px) !important;
max-width: 540px;
}
.el-form-item.path-w20 {
width: calc(18% - 6px) !important;
max-width: 540px;
margin-right: 8px !important;
}
.el-textarea .el-textarea__inner {
overflow-wrap: break-word;
white-space: pre-wrap;
word-break: break-all;
}
}
.mt8 {
margin-top: 8px;
}
.mt16 {
margin-top: 16px;
}
.mb10 {
margin-bottom: 10px;
}
.value {
color: #212121;
}
</style>
\ No newline at end of file
<script lang="ts" setup name="detail_serviceApi">
import { ref } from "vue";
import { TableColumnWidth } from '@/utils/enum';
import { getCamundaDeploymentId } from "@/api/modules/workFlowService"
import {
getApiApprovalDetail,
getApiDetail,
apiTypes,
} from "@/api/modules/dataService";
const route = useRoute();
const { proxy } = getCurrentInstance() as any;
const router = useRouter();
const props = defineProps({
apiGuid: {
type: String,
default: ''
}
});
const detailLoading = ref(false);
const baseInfoExpand = ref(true);
const deploymentId = ref('');
const processInstanceId = ref('');
const pageDetail = ref({});
const bizApproveVO = ref();
const process = ref();
const flowExpand = ref(true);
const detailInfo: any = ref({});
const apiType = ref('1');// 单表API.
const sql = ref('');
const processDTOSValue = ref([]);
onBeforeMount(() => {
if (route.query.guid) {
getDetail();
} else {
getCamundaDeploymentId('10023').then((res: any) => {
if (res.code == proxy.$passCode) {
deploymentId.value = res.data;
} else {
proxy.$ElMessage.error(res.msg);
}
})
}
});
onActivated(() => {
// if (route.query.guid) {
// getDetail();
// } else {
// getCamundaDeploymentId('10023').then((res: any) => {
// if (res.code == proxy.$passCode) {
// deploymentId.value = res.data;
// } else {
// proxy.$ElMessage.error(res.msg);
// }
// })
// }
})
const getDetail = () => {
detailLoading.value = true;
// getApiDetail
return getApiDetail(route.query.guid).then((res: any) => {
detailLoading.value = false;
if (res?.code == proxy.$passCode) {
let data = res.data;
let { approveVO } = data
pageDetail.value = res.data;
bizApproveVO.value = data.approveVO;
deploymentId.value = approveVO.camundaDeploymentId
processInstanceId.value = approveVO.camundaInstanceId
process.value?.renderProcessNodes();
detailInfo.value = data;
apiType.value = data.apiType;
let apiConfigAccessRSVOS = data.apiConfigAccessRSVOS || [];
let inputParamData: any[] = [];
let requestData: any[] = [];
let responseData: any[] = [];
let registRequestData: any[] = [];
let constData: any[] = [];
let sortData: any[] = [];
apiConfigAccessRSVOS.forEach(vo => {
if (vo.paramType == 'DEFIN') {
inputParamData.push(vo);
} else if (vo.paramType == 'REQ') {
if (apiType.value == '3') {
registRequestData.push(vo);
} else if (apiType.value == '2') {
inputParamData.push(vo);
} else {
requestData.push(vo);
}
} else if (vo.paramType == 'RESP') {
responseData.push(vo);
} else if (vo.paramType == 'ORDER') {
sortData.push({ ...vo, index: sortData.length + 1 });
} else if (vo.paramType == 'SQL') {
sql.value = vo.selectSqlStatement;
// sqlFormItems.value.forEach(item => {
// item.default = vo.selectSqlStatement;
// });
} else if (vo.paramType == 'CONSTANT') {
constData.push(vo);
}
});
if(data.processDTOS&&data.processDTOS.length>0){
let processDTOS=data.processDTOS || [];
if(processDTOS?.length>0){
processDTOS.forEach(obj=>{
obj.noName=obj.processOrderNo + '' + obj.requirementOrderName
})
}
processDTOSValue.value = processDTOS || [];
}
inputParamsTableInfo.value.data = inputParamData;
inputParamsTableInfo.value.height = inputParamData.length > 10 ? '390px' : 'auto';
requestParamsTableInfo.value.data = requestData;
requestParamsTableInfo.value.height = requestData.length > 10 ? '390px' : 'auto';
responseParamsTableInfo.value.data = responseData;
responseParamsTableInfo.value.height = responseData.length > 10 ? '390px' : 'auto';
sortParamsTableInfo.value.data = sortData;
sortParamsTableInfo.value.height = sortData.length > 10 ? '390px' : 'auto';
registRequestParamsTableInfo.value.data = registRequestData;
registRequestParamsTableInfo.value.height = registRequestData.length > 10 ? '390px' : 'auto';
constParamsTableInfo.value.data = constData;
constParamsTableInfo.value.height = constData.length > 10 ? '390px' : 'auto';
} else {
proxy.$ElMessage.error(res?.msg);
}
});
}
const seeDetail = (row) => {
router.push({
name: 'processSheetDetail',
query: {
guid: row.guid,
}
});
}
/** 基本信息的入参定义表格配置 */
const inputParamsTableInfo = ref({
id: "input-params-table",
height: 'auto',
minHeight: '50px',
minPanelHeight: '50px',
fields: [
{ label: "序号", type: "index", width: TableColumnWidth.INDEX, align: "center" },
{ label: "参数名", field: "paramName", width: 160 },
{ label: "参数位置", field: "paramPositionName", width: 100 },
{ label: "参数类型", field: "dataTypeName", width: 120 },
{
label: "是否必填", field: "isRequired", width: 100, getName: (scope) => {
return scope.row.isRequired == 'Y' ? '是' : '否'
}
},
{
label: "是否多值", field: "isManyValue", width: 100, getName: (scope) => {
return scope.row.isManyValue == 'Y' ? '是' : '否'
}
},
{ label: "默认值", field: "defaultValue", width: 200 },
{ label: "描述", field: "description", width: 160 }
],
data: <Array<Object>>[],
showPage: false,
actionInfo: {
show: false,
},
loading: false
});
const requestParamsTableInfo = ref({
id: "request-params-table",
height: 'auto',
minHeight: '50px',
minPanelHeight: '50px',
fields: [
{ label: "序号", type: "index", width: TableColumnWidth.INDEX, align: "center" },
{ label: "绑定参数", field: "paramName", width: 160 },
{ label: "绑定字段", field: "boundField", width: 160 },
{ label: "操作符", field: "operatorName", width: 100 },
],
data: <Array<Object>>[],
showPage: false,
actionInfo: {
show: false,
},
loading: false
});
/** 注册API的请求参数 */
const registRequestParamsTableInfo = ref({
id: "request-params-table",
height: 'auto',
minHeight: '50px',
minPanelHeight: '50px',
fields: [
{ label: "序号", type: "index", width: TableColumnWidth.INDEX, align: "center" },
{ label: "参数名", field: "paramName", width: 160 },
{ label: "参数位置", field: "paramPositionName", width: 100 },
{ label: "参数类型", field: "dataTypeName", width: 120 },
{
label: "是否必填", field: "isRequired", width: 100, getName: (scope) => {
return scope.row.isRequired == 'Y' ? '是' : '否'
}
},
{
label: "是否多值", field: "isManyValue", width: 100, getName: (scope) => {
return scope.row.isManyValue == 'Y' ? '是' : '否'
}
},
{ label: "默认值", field: "defaultValue", width: 200 },
{ label: "描述", field: "description", width: 160 }
],
data: <Array<Object>>[],
showPage: false,
actionInfo: {
show: false,
},
loading: false
});
/** 注册API的常量参数 */
const constParamsTableInfo = ref({
id: "const-params-table",
height: 'auto',
minHeight: '50px',
minPanelHeight: '50px',
fields: [
{ label: "序号", type: "index", width: TableColumnWidth.INDEX, align: "center" },
{ label: "参数名", field: "paramName", width: 160 },
{ label: "参数位置", field: "paramPositionName", width: 100 },
{ label: "参数类型", field: "dataTypeName", width: 120 },
{
label: "是否必填", field: "isRequired", width: 100, getName: (scope) => {
return scope.row.isRequired == 'Y' ? '是' : '否'
}
},
{ label: "常量值", field: "defaultValue", width: 200 },
{ label: "描述", field: "description", width: 160 }
],
data: <Array<Object>>[],
showPage: false,
actionInfo: {
show: false,
},
loading: false
});
const responseParamsTableInfo = ref({
id: "response-params-table",
height: 'auto',
minHeight: '50px',
minPanelHeight: '50px',
fields: [
{ label: "序号", type: "index", width: TableColumnWidth.INDEX, align: "center" },
{ label: "参数名", field: "paramName", width: 160 },
{ label: "绑定字段", field: "boundField", width: 140 },
{ label: "参数类型", field: "dataTypeName", width: 120 },
{ label: "示例值", field: "exampleValue", width: 160 },
{ label: "描述", field: "description", width: 160 },
],
data: <Array<Object>>[],
showPage: false,
actionInfo: {
show: false,
},
loading: false
});
/** 排序参数配置 */
const sortParamsTableInfo = ref({
id: "sort-params-table",
height: 'auto',
minHeight: '100px',
minPanelHeight: '100px',
fields: [
{ label: "序号", type: "index", width: TableColumnWidth.INDEX, align: "center" },
{ label: "参数名", field: "paramName", width: 160 },
{ label: "绑定字段", field: "boundField", width: 140 },
{
label: "排序方式", field: "sortMode", width: 100, getName: (scope) => {
return scope.row.sortMode == 'ASC' ? '升序' : '降序';
}
},
{ label: "描述", field: "description", width: 160 },
],
data: <Array<Object>>[],
showPage: false,
actionInfo: {
show: false,
},
loading: false
});
</script>
<template>
<div class="content_main" v-loading="detailLoading">
<ContentWrap title="基础信息" description="" :isExpand="baseInfoExpand" :expand-swicth="true"
class="mb16" @expand="(v) => baseInfoExpand = v">
<div class="list_panel">
<div class="list_item">
<span class="item_label">API类型:</span>
<span class="item_value">{{ apiTypes.find(a => a.value == apiType)?.label || '-' }}</span>
</div>
<div class="list_item">
<span class="item_label">API名称:</span>
<span class="item_value">{{ detailInfo.apiName || '-' }}</span>
</div>
<!-- <div class="list_item">
<span class="item_label">场景名称:</span>
<span class="item_value">{{ detailInfo.sceneName || '-' }}</span>
</div> -->
<div class="list_item">
<span class="item_label">返回类型:</span>
<span class="item_value">{{ detailInfo.responseType || '-' }}</span>
</div>
<div class="list_item">
<span class="item_label">请求方式:</span>
<span class="item_value">{{ detailInfo.requestMode == 'G' ? 'get' : 'post' }}</span>
</div>
<div class="list_item">
<span class="item_label">安全认证:</span>
<span class="item_value">{{ detailInfo.authenticationType == 'T' ? 'token认证' : '无认证' }}</span>
</div>
<div class="list_item" v-if="detailInfo.authenticationType == 'N'">
<span class="item_label">IP白名单:</span>
<span class="item_value">
<ellipsis-tooltip :content="detailInfo.whiteIPAddrs?.length ? detailInfo.whiteIPAddrs.join(',') : '-'" class-name="w100f mr8-i"
:refName="'tooltipOver' + 'WhiteIPs'"></ellipsis-tooltip>
</span>
</div>
<!-- 空白占位符 -->
<!-- <div class="list_item" v-if="apiType == '1'">
<span class="item_label"></span>
<span class="item_value"></span>
</div> -->
<div class="list_item" v-if="apiType == '1'">
<span class="item_label">数据类型:</span>
<span class="item_value">{{ detailInfo.dataSourceType == 1 ? '数据源' : '数据目录' }}</span>
</div>
<div class="list_item" v-if="apiType != '3'">
<span class="item_label">数据源:</span>
<span class="item_value">{{ detailInfo.dataSourceName || '-' }}</span>
</div>
<div class="list_item" v-if="apiType == '1'">
<span class="item_label">数据表:</span>
<span class="item_value">{{ detailInfo.tableName || '-' }}</span>
</div>
<div class="list_item" v-if="apiType == '1'">
<span class="item_label">数据表中文名:</span>
<span class="item_value">{{ detailInfo.tableNameCh || '-' }}</span>
</div>
<div class="list_item is_block">
<span class="item_label">请求路径:</span>
<span class="item_value">
<ellipsis-tooltip :content="detailInfo.requestUrl || '-'" class-name="w100f mr8-i"
:refName="'tooltipOver' + 'requestUrl'"></ellipsis-tooltip></span>
</div>
<div class="list_item is_block">
<span class="item_label">API描述:</span>
<span class="item_value">
<ellipsis-tooltip :content="detailInfo.apiDescription || '-'" class-name="w100f mr8-i"
:refName="'tooltipOver' + route.query.guid"></ellipsis-tooltip></span>
</div>
<template v-if="apiType == '3'">
<div class="list_item">
<span class="item_label">后台服务HOST:</span>
<span class="item_value">{{ `${detailInfo.backstageAgreement}://${detailInfo.backstageHost}` }}</span>
</div>
<div class="list_item">
<span class="item_label">请求方式:</span>
<span class="item_value">{{ detailInfo.backstageRequestMode == 'G' ? 'get' : 'post' }}</span>
</div>
<div class="list_item">
<span class="item_label">后端超时:</span>
<span class="item_value">{{ detailInfo.backstageOvertime == null ? '-' : (detailInfo.backstageOvertime + 'ms') }}</span>
</div>
<div class="list_item is_block">
<span class="item_label">后台服务PATH:</span>
<span class="item_value">
<ellipsis-tooltip :content="detailInfo.backstagePath || '-'" class-name="w100f mr8-i"
:refName="'tooltipOver' + 'path'"></ellipsis-tooltip></span>
</div>
</template>
</div>
</ContentWrap>
<template v-if="inputParamsTableInfo.data.length">
<div class="list_item" style="font-weight: 500;color: var(--el-color-regular);margin: 8px 0px;">{{ apiType == '3' ? '请求参数' : '入参定义' }}</div>
<Table :tableInfo="inputParamsTableInfo" />
</template>
<template v-if="requestParamsTableInfo.data.length">
<div class="list_item" style="font-weight: 500;color: var(--el-color-regular);margin: 8px 0px;">请求参数</div>
<Table :tableInfo="requestParamsTableInfo" />
</template>
<template v-if="responseParamsTableInfo.data.length">
<div class="list_item" style="font-weight: 500;color: var(--el-color-regular);margin: 8px 0px;">返回参数</div>
<Table :tableInfo="responseParamsTableInfo" />
</template>
<template v-if="sortParamsTableInfo.data.length">
<div class="list_item" style="font-weight: 500;color: var(--el-color-regular);margin: 8px 0px;">排序参数</div>
<Table :tableInfo="sortParamsTableInfo" />
</template>
<template v-if="apiType == '3'">
<template v-if="registRequestParamsTableInfo.data.length">
<div class="list_item" style="font-weight: 500;color: var(--el-color-regular);margin: 8px 0px;">请求参数</div>
<Table :tableInfo="registRequestParamsTableInfo" />
</template>
<template v-if="constParamsTableInfo.data.length">
<div class="list_item" style="font-weight: 500;color: var(--el-color-regular);margin: 8px 0px;">常量参数</div>
<Table :tableInfo="constParamsTableInfo" />
</template>
</template>
<template v-if="apiType == '2'">
<div class="list_item" style="font-weight: 500;color: var(--el-color-regular);margin: 8px 0px;">查询sql</div>
<el-input v-model.trim="sql" :rows="10" type="textarea" :readonly="true" />
</template>
<ContentWrap title="流程审批" v-if="detailInfo.approveVO && detailInfo.isApprove != 'N'" description="" :isExpand="flowExpand" :expand-swicth="true"
class="mb16" @expand="(v) => flowExpand = v">
<ApprovalProcess ref="process" v-if="deploymentId" :deploymentId="deploymentId" :processInstanceId="processInstanceId">
</ApprovalProcess>
</ContentWrap>
<FlowBtnGroup pageType="detail" :approveVO="bizApproveVO" @refreshPage="getDetail"></FlowBtnGroup>
</div>
</template>
<style scoped lang="scss">
.content_main {
height: calc(100% - 40px);
padding: 16px;
overflow: hidden auto;
position: sticky;
.list_panel {
display: flex;
flex-wrap: wrap;
.list_item {
width: 33.33%;
line-height: 21px;
margin-bottom: 12px;
font-size: 14px;
color: var(--el-text-color-regular);
display: flex;
justify-content: space-between;
min-width: 120px;
.item_label {
width: 100px;
text-align: right;
}
.item_value {
color: var(--el-color-regular);
padding: 0 8px;
flex: 1;
text-align: justify;
max-width: calc(100% - 100px);
}
&.is_block {
width: 100%;
}
.file-operate {
display: flex;
align-items: center;
position: relative;
.file-img {
width: 24px;
height: 24px;
}
&:hover {
background-color: #f5f5f5;
}
.file-name {
color: var(--el-color-regular);
margin-left: 4px;
}
.file-preview {
position: absolute;
cursor: pointer;
color: var(--el-color-primary);
margin-right: 8px;
}
}
}
}
.table_panel {
height: 200px;
min-height: 200px;
}
}
</style>
\ No newline at end of file
<route lang="yaml">
name: ipWhitelist
</route>
<script lang="ts" setup name="ipWhitelist">
import { ref } from 'vue';
import { TableColumnWidth } from '@/utils/enum';
import TableTools from '@/components/Tools/table_tools.vue';
import { commonPageConfig } from '@/components/PageNav/index';
import { useRouter, useRoute } from "vue-router";
import {
getIPList,
deleteIP,
saveIP,
updateIP
} from "@/api/modules/dataService";
import { useValidator } from '@/hooks/useValidator';
const { proxy } = getCurrentInstance() as any;
const router = useRouter();
const { required, regexpValidate } = useValidator();
/** 分页及搜索传参信息配置。 */
const page = ref({
...commonPageConfig,
ip: ''
});
const searchItemList = ref([{
type: "input",
label: "",
field: "ip",
default: "",
placeholder: "IP",
clearable: true,
}]);
const currTableData: any = ref({});
const tableInfo = ref({
id: 'data-app-table',
fields: [
{ label: "序号", type: "index", width: TableColumnWidth.INDEX, align: "center" },
{ label: "IP", field: "ip", width: 140 },
{ label: "描述", field: "description", width: TableColumnWidth.DESCRIPTION },
{ label: "修改人", field: "updateUserName", width: TableColumnWidth.USERNAME },
{ label: "修改时间", field: "updateTime", width: TableColumnWidth.DATETIME },
],
data: [],
page: {
type: "normal",
rows: 0,
...page.value,
},
actionInfo: {
label: "操作",
type: "btn",
width: 120,
fixed: 'right',
btns: (scope) => {
let btnsArr: any = [];
btnsArr.push({
label: "编辑", value: "edit", click: (scope) => {
currTableData.value = scope.row;
IPDialogInfo.value.header.title = '编辑IP';
IPDialogInfo.value.type = 'edit';
IPFormItems.value[0].default = scope.row.ip;
IPFormItems.value[1].default = scope.row.description;
IPDialogInfo.value.visible = true;
}
});
btnsArr.push({
label: "删除", value: "delete", click: (scope) => {
proxy.$openMessageBox('确定要删除该IP吗?', () => {
deleteIP([scope.row.guid]).then((res: any) => {
if (res.code == proxy.$passCode) {
page.value.curr = 1;
getTableData();
proxy.$ElMessage.success("删除成功");
} else {
proxy.$ElMessage.error(res.msg);
}
});
}, () => {
proxy.$ElMessage.info("已取消");
})
}
});
return btnsArr
},
},
loading: false
})
const IPFormItems = ref([{
type: 'input',
label: 'IP',
field: 'ip',
default: '',
block: true,
placeholder: '请输入',
maxlength: 50,
clearable: true,
required: true
}, {
label: '描述',
type: 'textarea',
placeholder: '请输入',
field: 'description',
default: '',
maxlength: 200,
block: true,
clearable: true,
required: false
}]);
const IPFormRules = ref({
ip: [required("请填写IP"), regexpValidate(/^(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])$/, '请输入合法的IP地址')],
});
const IPDialogInfo = ref({
visible: false,
size: 480,
direction: "column",
header: {
title: "添加IP",
},
type: 'add',
contents: [
{
type: 'form',
title: '',
formInfo: {
id: 'add-authorize-form',
items: IPFormItems.value,
rules: IPFormRules.value
}
}
],
footer: {
btns: [
{ type: "default", label: "取消", value: "cancel" },
{ type: "primary", label: "确定", value: "submit", loading: false },
],
},
});
const IPDialogBtnClick = (btn, info) => {
if (btn.value == 'submit') {
IPDialogInfo.value.footer.btns[1].loading = true;
if (IPDialogInfo.value.type == 'add') {
saveIP(info).then((res: any) => {
IPDialogInfo.value.footer.btns[1].loading = false;
if (res.code == proxy.$passCode) {
page.value.curr = 1;
getTableData();
proxy.$ElMessage({
type: 'success',
message: `添加IP成功`
})
IPDialogInfo.value.visible = false;
} else {
proxy.$ElMessage.error(res.msg);
}
})
} else {
info.guid = currTableData.value.guid;
updateIP(info).then((res: any) => {
IPDialogInfo.value.footer.btns[1].loading = false;
if (res.code == proxy.$passCode) {
page.value.curr = 1;
getTableData();
proxy.$ElMessage({
type: 'success',
message: `编辑IP成功`
})
IPDialogInfo.value.visible = false;
} else {
proxy.$ElMessage.error(res.msg);
}
})
}
} else if (btn.value == 'cancel') {
IPDialogInfo.value.visible = false;
}
};
const toSearch = (val: any, clear: boolean = false) => {
page.value.curr = 1;
if (clear) {
searchItemList.value.map((item) => (item.default = ""));
page.value.ip = '';
} else {
page.value.ip = val.ip;
}
getTableData();
};
const tablePageChange = (info) => {
page.value.curr = Number(info.curr);
page.value.limit = Number(info.limit);
getTableData();
};
const getTableData = () => {
tableInfo.value.loading = true
getIPList({
pageIndex: page.value.curr,
pageSize: page.value.limit,
ip: page.value.ip
}).then((res: any) => {
if (res.code == proxy.$passCode) {
const data = res.data || {}
tableInfo.value.data = data.records || []
tableInfo.value.page.limit = data.pageSize
tableInfo.value.page.curr = data.pageIndex
tableInfo.value.page.rows = data.totalRows
} else {
proxy.$ElMessage({
type: 'error',
message: res.msg,
})
}
tableInfo.value.loading = false
})
};
const addIPWhite = () => {
IPDialogInfo.value.visible = true;
IPDialogInfo.value.header.title = '添加IP';
IPDialogInfo.value.type = 'add';
IPFormItems.value[0].default = '';
IPFormItems.value[1].default = ''
}
onBeforeMount(() => {
toSearch({})
})
</script>
<template>
<div class="container_wrap">
<div class="table_tool_wrap">
<TableTools :searchItems="searchItemList" :searchId="'data-source-search'" @search="toSearch" :init="false" />
<div class="tools_btns">
<el-button type="primary" @click="addIPWhite" v-preReClick>添加</el-button>
</div>
</div>
<div class="table_panel_wrap">
<Table :tableInfo="tableInfo" @tablePageChange="tablePageChange" />
</div>
<!-- 添加编辑IP对话框 -->
<Dialog :dialogInfo="IPDialogInfo" @btnClick="IPDialogBtnClick" />
</div>
</template>
<style lang="scss" scoped>
.table_tool_wrap {
width: 100%;
height: 84px !important;
padding: 0 8px;
.tools_btns {
padding: 0px 0 0;
}
}
.table_panel_wrap {
width: 100%;
height: calc(100% - 84px);
padding: 0px 8px 0;
}
</style>
\ No newline at end of file
......@@ -154,7 +154,7 @@ function testAccount(logonUser: string) {
<div>
<img :src="banner" class="banner">
<div class="banner_desc">
<h4>数据资产管理系统</h4>
<h4>可信数据空间</h4>
<span>激活数据流通体系,释放数据要素新质生产力</span>
</div>
</div>
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!