FileSqlServerSync/Tool/webtool/src/App.vue

278 lines
6.9 KiB
Vue
Raw Normal View History

2024-06-21 04:32:55 +00:00
<script setup>
2024-09-27 16:14:20 +00:00
import MonacoEditor from 'monaco-editor-vue3';
2024-10-10 01:46:14 +00:00
import HistoryBtn from "./HistoryBtn.vue"
import { ref, onMounted, computed } from 'vue';
import stringifyObject from 'stringify-object';
import ConnectPipe from './connect.js'
2024-10-10 01:46:14 +00:00
const cacheConfig = ref({})
2024-09-27 16:14:20 +00:00
const options = ref({
colorDecorators: true,
lineHeight: 24,
tabSize: 2,
})
let IsSuccess = false
let Pipe = null
const Msgs = ref([])
2024-09-27 16:14:20 +00:00
const code = ref(`
config = {
//发布的名称,每个项目具有唯一的一个名称
Name: "Test",
RemotePwd: "t123",
//远程服务器地址,也就是发布的目的地,它是正式环境
RemoteUrl: "127.0.0.1:6819",
//是否发布数据库 sqlserver
IsDeployDb: true,
//是否发布前重新构建项目
IsDeployProject: true,
//项目地址
2024-10-10 01:46:14 +00:00
LocalProjectAbsolutePath:
"D:/git/HMES-H7-HNFY/HMES-H7-HNFYMF/HMES-H7-HNFYMF.WEB",
//源文件目录地址,是要发布的文件根目录,它是绝对路径,!执行发布时将发布到这个目录!
2024-10-10 01:46:14 +00:00
LocalRootPath: "D:/FileSyncTest/src",
//目标文件目录地址,也就是部署服务的机器上的项目文件根目录,它是绝对路径
RemoteRootPath: "D:/FileSyncTest/dst",
//源数据库配置 SqlServer,将会同步数据库的结构
2024-10-10 01:46:14 +00:00
SrcDb: {
//Host
2024-10-10 01:46:14 +00:00
ServerName: "172.16.12.2",
//数据库名
2024-10-28 09:28:18 +00:00
DatabaseName: "HMES_H7_HNFYMF",
2024-10-10 01:46:14 +00:00
User: "hmes-h7",
Password: "Hmes-h7666",
//是否信任服务器证书
2024-10-10 01:46:14 +00:00
TrustServerCertificate: "True",
//同步的数据,这些数据将会同步
2024-10-10 01:46:14 +00:00
SyncTablesData: [
"dbo.sys_Button",
"dbo.sys_Menu",
"dbo.sys_Module",
"dbo.sys_Page",
],
},
//目标数据库配置 sqlserver
2024-10-10 01:46:14 +00:00
DstDb: {
ServerName: "127.0.0.1",
2024-10-28 09:28:18 +00:00
DatabaseName: "HMES_H7_HNFYMF",
2024-10-10 01:46:14 +00:00
User: "sa",
Password: "0",
2024-10-10 01:46:14 +00:00
TrustServerCertificate: "True",
},
//子目录配置每个子目录都有自己不同的发布策略它是相对路径即相对于LocalRootPath和RemoteRootPath(注意 '/',这将拼成一个完整的路径),文件数据依此进行,
2024-10-10 01:46:14 +00:00
DirFileConfigs: [
{
DirPath: "/bin",
//排除的文件或目录它是相对路径相对于LocalRootPath和RemoteRootPath
2024-10-10 01:46:14 +00:00
Excludes: ["/roslyn", "/Views"],
//只追踪文件或目录它是相对路径相对于LocalRootPath和RemoteRootPath它的优先级最高如果你指定了它的值Excludes将会失效
// CherryPicks:[]
2024-10-10 01:46:14 +00:00
},
],
ExecProcesses: [],
// ExecProcesses:[
// {
// // 参数
// Argumnets:"ls",
// // 执行命令位置
// FileName:"powershell",
// // 相关步骤开始之前B或之后 (A)
// StepBeforeOrAfter:"A",
// // 本地L或远程 (R) 执行
// ExecInLocalOrServer:"L",
// // 步骤 1. 连接远程 2. 发布项目 3. 文件对比 4. 提取sqlserver 5. 打包上传 6. 发布
// Step:1
// }
// ]
2024-10-10 01:46:14 +00:00
};
2024-09-27 16:14:20 +00:00
`)
var CStatus = ref('None')
function getOpEmoj(Op) {
switch (Op) {
case 0:
return "";
case 1:
return "Ⓜ️";
case 2:
return "❌";
default:
2024-11-16 02:54:04 +00:00
return "📁";
}
}
function publishCB(MsgIt) {
console.log(MsgIt)
if (MsgIt.Type == 2) {
Msgs.value[Msgs.value.length - 1] = MsgIt
} else if (MsgIt.Type == 3) {
var it = JSON.parse(MsgIt.Body);
2024-11-16 02:54:04 +00:00
/**
* This function appears to be intended for processing children elements, though the current implementation is incomplete.
*
* @param {Array} children - The array of child elements to be processed.
* @returns {void}
*/
const f = (item) => {
Msgs.value.push({
Step: MsgIt.Step,
Type: MsgIt.Type,
2024-11-16 02:54:04 +00:00
Body: `[${getOpEmoj(item.NextOp)}] ${item.FormatedPath}`
})
2024-11-16 02:54:04 +00:00
if (item.Children) {
item.Children.forEach((e) => {
f(e)
});
2024-11-16 02:54:04 +00:00
}
}
f(it)
}
else {
Msgs.value.push(MsgIt)
}
if (MsgIt.Step == 6) {
if (MsgIt.Body == "发布完成!") {
CStatus.value = 'Success'
IsSuccess = true
Pipe.ClosePipe()
dialogShow("正确:发布完成!")
}
}
if (MsgIt.Step == 8) {
if (CStatus.value != "Success") {
dialogShow("失败:请查看错误信息!")
}
CStatus.value = "None"
}
}
2024-09-27 16:14:20 +00:00
function submit() {
Msgs.value = []
2024-09-27 16:14:20 +00:00
var config = {}
2024-10-10 01:46:14 +00:00
try {
eval(code.value)
if ([undefined, null, ''].includes(config.Name)) {
throw "缺少名称!"
}
cacheConfig.value[config.Name] = config
updateStorage()
Pipe = new ConnectPipe()
Pipe.OpenPipe(config, publishCB)
CStatus.value = "Process"
2024-10-10 01:46:14 +00:00
}
catch (e) {
dialogShow(e)
2024-10-10 01:46:14 +00:00
}
}
function onLoad(name) {
const pretty = stringifyObject(cacheConfig.value[name], {
indent: ' ',
singleQuotes: false
});
code.value = "\nconfig = " + pretty
}
const history = computed(() => {
return Object.keys(cacheConfig.value)
})
function onDel(name) {
delete cacheConfig.value[name]
updateStorage()
2024-09-27 16:14:20 +00:00
}
2024-10-10 01:46:14 +00:00
function updateStorage() {
localStorage.setItem('config', JSON.stringify(cacheConfig.value))
}
2024-10-10 01:46:14 +00:00
onMounted(() => {
var cacheConfigStr = localStorage.getItem('config')
if (cacheConfigStr) {
cacheConfig.value = JSON.parse(cacheConfigStr)
}
})
const dMsg = ref('')
function dialogClose() {
document.getElementById('dialog').close()
}
function dialogShow(msg) {
dMsg.value = msg
document.getElementById('dialog').showModal()
}
function getColor(msg) {
if (msg.Step >= 7) {
if (IsSuccess) {
return "green"
}
return "red"
} else if (msg.Type == 2) {
return "yellow"
} else {
return "green"
}
}
function getTitle(msg) {
var x = getColor(msg)
switch (x) {
case "green":
return "[成功]"
break;
case "red":
return "[失败]"
break;
case "yellow":
return "[上传进度]"
break;
default:
break;
}
}
function getStep(msg) {
if (msg.Step > 6) {
return ""
}
return `(${msg.Step}/6)`
}
function getBody(msg) {
return msg.Body
}
2024-06-21 04:32:55 +00:00
</script>
<template>
2024-09-27 16:14:20 +00:00
<h3>发布工具</h3>
2024-10-10 01:46:14 +00:00
<div>
<HistoryBtn :name="name" @load="onLoad" @del="onDel" v-for="name in history" />
</div>
2024-09-27 16:14:20 +00:00
<div style="display: flex;">
2024-10-10 01:46:14 +00:00
<MonacoEditor theme="vs-dark" :options="options" language="javascript" :width="800" :height="700"
v-model:value="code"></MonacoEditor>
<div style="width: 1200px;height: 700px;background-color: #1e1e1e;overflow:auto;">
2024-09-27 16:14:20 +00:00
发布日志
<p style="text-align: left;border: 1px solid gray;margin: 5px;" v-for="msg in Msgs">
<span :style="{ width: '100px', color: getColor(msg) }">
{{ getTitle(msg) }}
</span>
<span>
{{ getStep(msg) }}
</span>
{{ getBody(msg) }}
</p>
2024-09-27 16:14:20 +00:00
</div>
2024-06-21 04:32:55 +00:00
</div>
<dialog id="dialog">
<p>{{ dMsg }}</p>
<button @click="dialogClose">关闭</button>
</dialog>
2024-09-27 16:14:20 +00:00
<button :disabled="CStatus != 'None'" style="margin-top: 20px;" @click="submit">发布</button>
2024-06-21 04:32:55 +00:00
</template>
2024-09-27 16:14:20 +00:00
<style scoped></style>