feat 孤独数据管理(查看孤独数据、修正孤独数据)

This commit is contained in:
bwcx_jzy 2024-01-09 21:46:06 +08:00
parent 8431cacd3c
commit 3614feb48c
No known key found for this signature in database
GPG Key ID: 5E48E9372088B9E5
16 changed files with 424 additions and 87 deletions

View File

@ -4,6 +4,8 @@
### 🐣 新增功能
1. 【all】新增 孤独数据管理(查看孤独数据、修正孤独数据)(感谢[@陈旭](https://gitee.com/chenxu8989) [Gitee issues I8UNXZ](https://gitee.com/dromara/Jpom/issues/I8UNXZ)
### 🐞 解决BUG、优化功能
1. 【server】优化 上传文件前解析文件信息采用全局 loading

View File

@ -198,6 +198,7 @@ public class ManageEditProjectController extends BaseAgentController {
// 预检查数据
return JsonMessage.success("检查通过");
} else {
exits.setNodeId(projectInfo.getNodeId());
exits.setName(projectInfo.getName());
exits.setGroup(projectInfo.getGroup());
exits.setAutoStart(projectInfo.getAutoStart());

View File

@ -257,4 +257,18 @@ public class ScriptController extends BaseAgentController {
}
return JsonMessage.success("删除成功");
}
@RequestMapping(value = "change-workspace-id", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public IJsonMessage<Object> changeWorkspaceId(@ValidatorItem() String id, String newWorkspaceId, String newNodeId) {
Assert.hasText(newWorkspaceId, "请选择要修改的工作空间");
Assert.hasText(newWorkspaceId, "请选择要修改的节");
NodeScriptModel item = nodeScriptServer.getItem(id);
Assert.notNull(item, "找不到对应的脚本信息");
//
NodeScriptModel update = new NodeScriptModel();
update.setNodeId(newNodeId);
update.setWorkspaceId(newWorkspaceId);
nodeScriptServer.updateById(update, item.getId());
return JsonMessage.success("修改成功");
}
}

View File

@ -145,6 +145,7 @@ public enum NodeUrl {
Script_List("/script/list.json"),
Script_ChangeWorkspaceId("/script/change-workspace-id"),
SCRIPT_PULL_EXEC_LOG("/script/pull_exec_log"),
SCRIPT_DEL_EXEC_LOG("/script/del_exec_log"),
Script_Item("/script/item.json"),

View File

@ -35,10 +35,15 @@ import org.dromara.jpom.func.assets.server.MachineNodeServer;
import org.dromara.jpom.model.PageResultDto;
import org.dromara.jpom.model.data.NodeModel;
import org.dromara.jpom.model.data.WorkspaceModel;
import org.dromara.jpom.model.node.NodeScriptCacheModel;
import org.dromara.jpom.model.node.ProjectInfoCacheModel;
import org.dromara.jpom.permission.ClassFeature;
import org.dromara.jpom.permission.Feature;
import org.dromara.jpom.permission.MethodFeature;
import org.dromara.jpom.permission.SystemPermission;
import org.dromara.jpom.service.node.NodeService;
import org.dromara.jpom.service.node.ProjectInfoCacheService;
import org.dromara.jpom.service.node.script.NodeScriptServer;
import org.dromara.jpom.service.system.WorkspaceService;
import org.springframework.http.MediaType;
import org.springframework.util.Assert;
@ -62,11 +67,20 @@ import java.util.Optional;
public class MachineNodeController extends BaseGroupNameController {
private final WorkspaceService workspaceService;
private final ProjectInfoCacheService projectInfoCacheService;
private final NodeScriptServer nodeScriptServer;
private final NodeService nodeService;
public MachineNodeController(WorkspaceService workspaceService,
MachineNodeServer machineNodeServer) {
MachineNodeServer machineNodeServer,
ProjectInfoCacheService projectInfoCacheService,
NodeScriptServer nodeScriptServer,
NodeService nodeService) {
super(machineNodeServer);
this.workspaceService = workspaceService;
this.projectInfoCacheService = projectInfoCacheService;
this.nodeScriptServer = nodeScriptServer;
this.nodeService = nodeService;
}
@PostMapping(value = "list-data", produces = MediaType.APPLICATION_JSON_VALUE)
@ -188,4 +202,69 @@ public class MachineNodeController extends BaseGroupNameController {
}
return JsonMessage.success("修改成功");
}
/**
* 查询集群孤独的数据
*
* @param id 集群ID
* @return json
*/
@GetMapping(value = "lonely-data", produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.LIST)
public IJsonMessage<Object> lonelyData(@ValidatorItem String id) {
MachineNodeModel machineNodeModel = machineNodeServer.getByKey(id);
Assert.notNull(machineNodeModel, "没有对应的机器");
List<ProjectInfoCacheModel> models = projectInfoCacheService.lonelyDataArray(machineNodeModel);
List<NodeScriptCacheModel> scriptCacheModels = nodeScriptServer.lonelyDataArray(machineNodeModel);
JSONObject jsonObject = new JSONObject();
jsonObject.put("projects", models);
jsonObject.put("scripts", scriptCacheModels);
return JsonMessage.success("", jsonObject);
}
@PostMapping(value = "correct-lonely-data", produces = MediaType.APPLICATION_JSON_VALUE)
@Feature(method = MethodFeature.LIST)
public IJsonMessage<Object> correctLonelyData(@ValidatorItem String id,
@ValidatorItem String type,
@ValidatorItem String dataId,
@ValidatorItem String toNodeId) {
MachineNodeModel machineNodeModel = machineNodeServer.getByKey(id);
Assert.notNull(machineNodeModel, "没有对应的机器");
{
NodeModel nodeModel = nodeService.getByKey(toNodeId);
Assert.notNull(nodeModel, "没有对应的节点");
Assert.hasText(nodeModel.getWorkspaceId(), "节点没有工作空间");
Assert.state(StrUtil.equals(nodeModel.getMachineId(), machineNodeModel.getId()), "资产集群和节点不匹配");
NodeUrl nodeUrl;
if (StrUtil.equalsIgnoreCase(type, "script")) {
nodeUrl = NodeUrl.Script_ChangeWorkspaceId;
} else if (StrUtil.equalsIgnoreCase(type, "project")) {
nodeUrl = NodeUrl.Manage_ChangeWorkspaceId;
} else {
throw new IllegalArgumentException("不支持的类型:" + type);
}
JSONObject jsonObject = new JSONObject();
jsonObject.put("newWorkspaceId", nodeModel.getWorkspaceId());
jsonObject.put("newNodeId", toNodeId);
jsonObject.put("id", dataId);
JsonMessage<String> jsonMessage = NodeForward.request(machineNodeModel, nodeUrl, jsonObject);
if (!jsonMessage.success()) {
return new JsonMessage<>(406, "修正数据失败:" + jsonMessage.getMsg());
}
}
// 重新同步节点数据
{
NodeModel nodeModel = new NodeModel();
nodeModel.setMachineId(id);
List<NodeModel> modelList = nodeService.listByBean(nodeModel);
for (NodeModel model : modelList) {
if (StrUtil.equalsIgnoreCase(type, "script")) {
nodeScriptServer.syncExecuteNode(model);
} else if (StrUtil.equalsIgnoreCase(type, "project")) {
projectInfoCacheService.syncExecuteNode(model);
}
}
}
return JsonMessage.success("修正成功");
}
}

View File

@ -39,6 +39,7 @@ import org.dromara.jpom.common.Const;
import org.dromara.jpom.common.ServerConst;
import org.dromara.jpom.exception.AgentAuthorizeException;
import org.dromara.jpom.exception.AgentException;
import org.dromara.jpom.func.assets.model.MachineNodeModel;
import org.dromara.jpom.model.BaseNodeModel;
import org.dromara.jpom.model.data.NodeModel;
import org.dromara.jpom.model.data.WorkspaceModel;
@ -119,6 +120,54 @@ public abstract class BaseNodeService<T extends BaseNodeModel> extends BaseGloba
ThreadUtil.execute(() -> this.syncExecuteNode(nodeModel));
}
/**
* 检查孤独数据
*
* @param jsonArray 数据
* @param machineId 机器 ID
* @return list
*/
protected List<T> checkLonelyDataArray(JSONArray jsonArray, String machineId) {
if (CollUtil.isEmpty(jsonArray)) {
return null;
}
// 分组
Map<String, List<T>> map = jsonArray.stream().map(o -> {
JSONObject jsonObject = (JSONObject) o;
return jsonObject.to(tClass);
}).collect(Collectors.groupingBy(
t -> StrUtil.emptyToDefault(t.getNodeId(), StrUtil.EMPTY) + StrUtil.COMMA + t.getWorkspaceId(),
Collectors.mapping(t -> t, Collectors.toList())
));
// 查询不存在的节点
return map.entrySet()
.stream()
.filter(entry -> {
String key = entry.getKey();
if (StrUtil.startWith(key, StrUtil.COMMA)) {
// 旧数据没有节点 ID
List<String> list = StrUtil.splitTrim(key, StrUtil.COMMA);
String workspaceId = CollUtil.getLast(list);
NodeModel nodeModel = new NodeModel();
nodeModel.setMachineId(machineId);
nodeModel.setWorkspaceId(workspaceId);
return true;
//return !nodeService.exists(nodeModel);
}
List<String> list = StrUtil.splitTrim(key, StrUtil.COMMA);
if (CollUtil.size(list) != 2) {
return true;
}
NodeModel nodeModel = new NodeModel();
nodeModel.setId(list.get(0));
nodeModel.setWorkspaceId(list.get(1));
return !nodeService.exists(nodeModel);
})
.flatMap(entry -> entry.getValue().stream())
.collect(Collectors.toList());
}
/**
* 同步执行 同步节点信息
*
@ -152,11 +201,13 @@ public abstract class BaseNodeService<T extends BaseNodeModel> extends BaseGloba
.map(BaseNodeModel::dataId)
.collect(Collectors.toSet());
// 转换数据修改时间
List<T> projectInfoModels = jsonArray.stream().map(o -> {
List<T> projectInfoModels = jsonArray.stream()
.map(o -> {
// modifyTime,createTime
JSONObject jsonObject = (JSONObject) o;
T t = jsonObject.to(tClass);
Opt.ofBlankAble(jsonObject.getString("createTime")).map(s -> {
Opt.ofBlankAble(jsonObject.getString("createTime"))
.map(s -> {
try {
return DateUtil.parse(s);
} catch (Exception e) {
@ -165,14 +216,16 @@ public abstract class BaseNodeService<T extends BaseNodeModel> extends BaseGloba
}
}).ifPresent(s -> t.setCreateTimeMillis(s.getTime()));
//
Opt.ofBlankAble(jsonObject.getString("modifyTime")).map(s -> {
Opt.ofBlankAble(jsonObject.getString("modifyTime"))
.map(s -> {
try {
return DateUtil.parse(s);
} catch (Exception e) {
log.warn("数据修改时间格式不正确 {} {}", s, jsonObject);
return null;
}
}).ifPresent(s -> t.setModifyTimeMillis(s.getTime()));
})
.ifPresent(s -> t.setModifyTimeMillis(s.getTime()));
return t;
})
.peek(item -> this.fullData(item, nodeModel))
@ -384,4 +437,12 @@ public abstract class BaseNodeService<T extends BaseNodeModel> extends BaseGloba
* @return json
*/
public abstract JSONArray getLitDataArray(NodeModel nodeModel);
/**
* 查询孤立的数据
*
* @param machineNodeModel 资产
* @return json
*/
public abstract List<T> lonelyDataArray(MachineNodeModel machineNodeModel);
}

View File

@ -27,6 +27,7 @@ import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import org.dromara.jpom.common.forward.NodeForward;
import org.dromara.jpom.common.forward.NodeUrl;
import org.dromara.jpom.func.assets.model.MachineNodeModel;
import org.dromara.jpom.model.data.NodeModel;
import org.dromara.jpom.model.node.ProjectInfoCacheModel;
import org.dromara.jpom.service.ITriggerToken;
@ -34,6 +35,8 @@ import org.dromara.jpom.service.h2db.BaseNodeService;
import org.dromara.jpom.service.system.WorkspaceService;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @author bwcx_jzy
* @since 2021/12/5
@ -108,6 +111,14 @@ public class ProjectInfoCacheService extends BaseNodeService<ProjectInfoCacheMod
return tJsonMessage.getData();
}
@Override
public List<ProjectInfoCacheModel> lonelyDataArray(MachineNodeModel machineNodeModel) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("notStatus", true);
JsonMessage<JSONArray> tJsonMessage = NodeForward.request(machineNodeModel, NodeUrl.Manage_GetProjectInfo, jsonObject);
return this.checkLonelyDataArray(tJsonMessage.getData(), machineNodeModel.getId());
}
@Override
public String typeName() {
return getTableName();

View File

@ -34,6 +34,7 @@ import org.dromara.jpom.common.ServerConst;
import org.dromara.jpom.common.forward.NodeForward;
import org.dromara.jpom.common.forward.NodeUrl;
import org.dromara.jpom.exception.AgentException;
import org.dromara.jpom.func.assets.model.MachineNodeModel;
import org.dromara.jpom.model.BaseDbModel;
import org.dromara.jpom.model.data.NodeModel;
import org.dromara.jpom.model.data.WorkspaceModel;
@ -91,7 +92,11 @@ public class NodeScriptExecuteLogServer extends BaseNodeService<NodeScriptExecut
}
}
return jsonArray;
}
@Override
public List<NodeScriptExecuteLogCacheModel> lonelyDataArray(MachineNodeModel machineNodeModel) {
throw new IllegalStateException("不支持的模式script log");
}
@Override

View File

@ -27,6 +27,7 @@ import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import org.dromara.jpom.common.forward.NodeForward;
import org.dromara.jpom.common.forward.NodeUrl;
import org.dromara.jpom.func.assets.model.MachineNodeModel;
import org.dromara.jpom.model.data.NodeModel;
import org.dromara.jpom.model.node.NodeScriptCacheModel;
import org.dromara.jpom.service.ITriggerToken;
@ -75,6 +76,12 @@ public class NodeScriptServer extends BaseNodeService<NodeScriptCacheModel> impl
return NodeForward.requestData(nodeModel, NodeUrl.Script_List, null, JSONArray.class);
}
@Override
public List<NodeScriptCacheModel> lonelyDataArray(MachineNodeModel machineNodeModel) {
JSONArray jsonArray = NodeForward.requestData(machineNodeModel, NodeUrl.Script_List, null, JSONArray.class);
return this.checkLonelyDataArray(jsonArray, machineNodeModel.getId());
}
@Override
public String typeName() {
return getTableName();

View File

@ -1,71 +1,71 @@
import axios from "@/api/config";
import axios from '@/api/config'
// 机器 列表
export function machineListData(params) {
return axios({
url: "/system/assets/machine/list-data",
method: "post",
data: params,
});
url: '/system/assets/machine/list-data',
method: 'post',
data: params
})
}
export function machineListGroup(params) {
return axios({
url: "/system/assets/machine/list-group",
method: "get",
params: params,
});
url: '/system/assets/machine/list-group',
method: 'get',
params: params
})
}
// 编辑机器
export function machineEdit(params) {
return axios({
url: "/system/assets/machine/edit",
method: "post",
data: params,
});
url: '/system/assets/machine/edit',
method: 'post',
data: params
})
}
// 删除机器
export function machineDelete(params) {
return axios({
url: "/system/assets/machine/delete",
method: "post",
data: params,
});
url: '/system/assets/machine/delete',
method: 'post',
data: params
})
}
// 分配机器
export function machineDistribute(params) {
return axios({
url: "/system/assets/machine/distribute",
method: "post",
data: params,
});
url: '/system/assets/machine/distribute',
method: 'post',
data: params
})
}
export const statusMap = {
0: "无法连接",
1: "正常",
2: "授权信息错误",
3: "状态码错误",
};
0: '无法连接',
1: '正常',
2: '授权信息错误',
3: '状态码错误'
}
// 查看机器关联节点
export function machineListNode(params) {
return axios({
url: "/system/assets/machine/list-node",
method: "get",
params: params,
});
url: '/system/assets/machine/list-node',
method: 'get',
params: params
})
}
export function machineListTemplateNode(params) {
return axios({
url: "/system/assets/machine/list-template-node",
method: "get",
params: params,
});
url: '/system/assets/machine/list-template-node',
method: 'get',
params: params
})
}
/**
@ -73,10 +73,10 @@ export function machineListTemplateNode(params) {
*/
export function saveWhitelist(data) {
return axios({
url: "/system/assets/machine/save-whitelist",
method: "post",
data: data,
});
url: '/system/assets/machine/save-whitelist',
method: 'post',
data: data
})
}
/**
@ -84,8 +84,24 @@ export function saveWhitelist(data) {
*/
export function saveNodeConfig(data) {
return axios({
url: "/system/assets/machine/save-node-config",
method: "post",
data: data,
});
url: '/system/assets/machine/save-node-config',
method: 'post',
data: data
})
}
export function machineLonelyData(data) {
return axios({
url: '/system/assets/machine/lonely-data',
method: 'get',
params: data
})
}
export function machineCorrectLonelyData(data) {
return axios({
url: '/system/assets/machine/correct-lonely-data',
method: 'post',
data: data
})
}

View File

@ -61,7 +61,82 @@
</a-timeline>
</a-tab-pane>
<a-tab-pane key="2" tab="定时任务"> <task-stat :taskList="taskList" @refresh="loadData" /></a-tab-pane>
<a-tab-pane key="3" tab="孤独数据">
<a-space direction="vertical" style="width: 100%">
<a-alert message="何为孤独数据" type="warning" show-icon>
<template #description>
<ul>
<li>
孤独数据是值机器几点里面存在数据但是无非和当前系统绑定上关系关闭绑定节点ID+工作空间ID对应才行一般情况下不会出现这样的数据
</li>
<li>通常情况为项目迁移工作空间迁移物理机器等一些操作可能产生孤独数据</li>
<li>如果孤独数据被工作空间下的其他功能关联修正后关联的数据将失效对应功能无非查询到关联数据</li>
</ul>
</template>
</a-alert>
<a-list size="small" bordered :data-source="machineLonelyData.projects">
<template #renderItem="{ item }">
<a-list-item>
<a-space>
<span>项目名称{{ item.name }}</span>
<span>项目ID{{ item.id }}</span>
<span>工作空间ID{{ item.workspaceId }}</span>
<span>节点ID{{ item.nodeId }}</span>
<a-button type="primary" size="small" danger @click="openCorrectLonely(item.id, 'project')"
>修正</a-button
>
</a-space>
</a-list-item>
</template>
<template #header>
<div>项目孤独数据</div>
</template>
</a-list>
<a-list size="small" bordered :data-source="machineLonelyData.scripts">
<template #renderItem="{ item }">
<a-list-item
><a-space>
<span>脚本名称{{ item.name }}</span>
<span>脚本ID{{ item.id }}</span>
<span>工作空间ID{{ item.workspaceId }}</span>
<span>节点ID{{ item.nodeId }}</span>
<a-button type="primary" size="small" danger @click="openCorrectLonely(item.id, 'script')"
>修正</a-button
>
</a-space>
</a-list-item>
</template>
<template #header>
<div>脚本孤独数据</div>
</template>
</a-list></a-space
>
</a-tab-pane>
</a-tabs>
<!-- 分配到其他工作空间 -->
<a-modal
destroyOnClose
:confirmLoading="confirmLoading"
v-model:open="correctLonelyOpen"
title="修正孤独数据"
@ok="handleCorrectLonely"
:maskClosable="false"
>
<a-space direction="vertical" style="width: 100%">
<a-alert message="温馨提示" type="warning">
<template #description>修改后如果有原始关联数据将失效需要重新配置关联 </template>
</a-alert>
<a-form :model="temp" :label-col="{ span: 6 }" :wrapper-col="{ span: 14 }">
<a-form-item label="选择节点" name="nodeId">
<a-select show-search option-filter-prop="children" v-model:value="temp.toNodeId" placeholder="请选择节点">
<a-select-option v-for="item in nodeList" :key="item.id">
{{ item.workspace && item.workspace.name }}{{ item.name }}
</a-select-option>
</a-select>
</a-form-item>
</a-form>
</a-space>
</a-modal>
</div>
</template>
@ -69,6 +144,7 @@
import { getNodeCache, clearCache } from '@/api/system'
import TaskStat from '@/pages/system/taskStat'
import { renderSize } from '@/utils/const'
import { machineLonelyData, machineCorrectLonelyData, machineListNode } from '@/api/system/assets-machine'
export default {
components: {
TaskStat
@ -81,11 +157,18 @@ export default {
data() {
return {
temp: {},
taskList: []
taskList: [],
machineLonelyDataLoading: true,
machineLonelyData: {},
correctLonelyOpen: false,
confirmLoading: false,
nodeList: [],
temp: {}
}
},
mounted() {
this.loadData()
this.listMachineLonelyData()
},
methods: {
// parseTime,
@ -116,6 +199,60 @@ export default {
this.loadData()
}
})
},
//
listMachineLonelyData() {
this.machineLonelyDataLoading = true
machineLonelyData({
id: this.machineId
})
.then((res) => {
if (res.code === 200 && res.data) {
this.machineLonelyData = res.data
}
})
.finally(() => {
this.machineLonelyDataLoading = false
})
},
//
listMachineNode() {
machineListNode({
id: this.machineId
}).then((res) => {
if (res.code === 200) {
this.nodeList = res.data
}
})
},
//
openCorrectLonely(dataId, type) {
this.temp = { type: type, id: this.machineId, dataId: dataId }
this.correctLonelyOpen = true
this.listMachineNode()
},
//
handleCorrectLonely() {
if (!this.temp.toNodeId) {
$notification.warn({
message: '请选择节点'
})
return false
}
this.confirmLoading = true
machineCorrectLonelyData(this.temp)
.then((res) => {
if (res.code == 200) {
$notification.success({
message: res.msg
})
this.correctLonelyOpen = false
this.listMachineLonelyData()
}
})
.finally(() => {
this.confirmLoading = false
})
}
}
}

View File

@ -8,7 +8,7 @@
</a-layout-sider>
<!-- 单个文件内容 -->
<a-layout-content class="log-content">
<log-view2 :ref="`logView`" height="calc(100vh - 165px)">
<log-view2 :ref="`logView`" height="calc(100vh - 160px - 30px)">
<template v-slot:before>
<a-space>
<a-button type="primary" size="small" @click="loadData">刷新</a-button>
@ -215,13 +215,14 @@ export default {
.log-sider {
border: 1px solid #e2e2e2;
overflow-x: auto;
height: calc(100vh - 110px);
/* width: max-content; */
}
.log-content {
margin: 0;
padding-left: 15px;
/* margin: 0; */
padding: 15px;
/* background: #fff; */
height: calc(100vh - 130px);
/* height: calc(100vh - 130px); */
overflow-y: auto;
}
</style>

View File

@ -1341,7 +1341,8 @@ export default {
:deep(.ant-statistic div) {
display: inline-block;
}
:deep(.ant-statistic-content-value .ant-statistic-content) {
:deep(.ant-statistic-content-value, .ant-statistic-content) {
font-size: 16px;
}
</style>

View File

@ -1,14 +1,14 @@
<template>
<a-layout class="log-layout">
<!-- 侧边栏 文件树 -->
<a-layout-sider theme="light" class="" width="20%">
<a-layout-sider theme="light" class="sider" width="20%">
<a-empty :image="Empty.PRESENTED_IMAGE_SIMPLE" v-if="list.length === 0" />
<a-directory-tree :treeData="list" :fieldNames="replaceFields" @select="select" default-expand-all>
</a-directory-tree>
</a-layout-sider>
<!-- 单个文件内容 -->
<a-layout-content class="log-content">
<log-view2 :ref="`logView`" height="calc(100vh - 165px)">
<log-view2 :ref="`logView`" height="calc(100vh - 140px)">
<template #before>
<a-space>
<a-button type="primary" size="small" @click="loadData">刷新</a-button>
@ -197,14 +197,14 @@ export default {
}
.sider {
border: 1px solid #e2e2e2;
height: calc(100vh - 110px);
height: calc(100vh - 80px);
overflow-y: auto;
}
.log-content {
margin: 0;
padding-left: 15px;
/* background: #fff; */
height: calc(100vh - 110px);
/* height: calc(100vh - 80px); */
overflow-y: auto;
}
</style>

View File

@ -140,7 +140,7 @@ import { CHANGE_PAGE, COMPUTED_PAGINATION, PAGE_DEFAULT_LIST_QUERY, parseTime }
export default {
components: {
JsonViewer
// JsonViewer
},
data() {
return {

View File

@ -48,19 +48,19 @@ export default defineConfig(({ mode }: ConfigEnv) => {
alias: {
'@/': `${path.resolve(__dirname, 'src')}/`
},
dedupe: ['vue'],
preserveSymlinks: false,
// dedupe: ['vue'],
// preserveSymlinks: false,
// 忽略后缀名的配置选项
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue']
},
rollupOptions: {
external: ['vue'],
output: {
globals: {
vue: 'Vue'
}
}
},
// rollupOptions: {
// external: ['vue'],
// output: {
// globals: {
// vue: 'Vue'
// }
// }
// },
build: {
sourcemap: mode !== 'production', // 非生产环境都生成sourcemap
outDir: '../modules/server/src/main/resources/dist'
@ -101,6 +101,7 @@ export default defineConfig(({ mode }: ConfigEnv) => {
createHtmlPlugin({
minify: true,
viteNext: true,
inject: {
data: {
title: env.JPOM_APP_TITLE,