u
This commit is contained in:
1 parent
4aaa93df7d
commit
c330e52fd3
66 files changed
+7386
-4
No files matched your search
@@ -0,0 +1,421 @@
|
||||
<script lang="js" setup>
|
||||
import { loginApi } from "@/request/api";
|
||||
import { useUserStore } from "@/store/user";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { useRouter } from "vue-router";
|
||||
import Vcode from "vue3-puzzle-vcode";
|
||||
import { reset401Flag } from "@/request";
|
||||
|
||||
const router = useRouter();
|
||||
const userStore = useUserStore();
|
||||
|
||||
const form = ref({
|
||||
orgid: userStore.userInfo.orgid,
|
||||
userid: userStore.userInfo.userid,
|
||||
password: "",
|
||||
});
|
||||
|
||||
const showVcode = ref(false);
|
||||
const loginLoading = ref(false);
|
||||
|
||||
const linkList = ref([
|
||||
{
|
||||
title: "新手上路",
|
||||
icon: "solar:key-bold",
|
||||
href: "http://bbs.g3soft.cn/forum.php?mod=viewthread&tid=115&extra=page%3D1",
|
||||
},
|
||||
{
|
||||
title: "会员活动",
|
||||
icon: "mingcute:vip-1-fill",
|
||||
href: "http://www.g3soft.cn/help/guide/promotion.html",
|
||||
},
|
||||
{
|
||||
title: "视频教程",
|
||||
icon: "material-symbols:auto-videocam-rounded",
|
||||
href: "http://bbs.g3soft.cn/forum.php?mod=viewthread&tid=86&extra=page%3D1",
|
||||
},
|
||||
{
|
||||
title: "常见问题",
|
||||
icon: "ic:baseline-help",
|
||||
href: "http://bbs.g3soft.cn/forum.php?mod=forumdisplay&fid=37",
|
||||
},
|
||||
]);
|
||||
|
||||
const endLinkList = ref([
|
||||
{
|
||||
title: "圆通官网",
|
||||
href: "http://www.g3soft.cn",
|
||||
},
|
||||
{
|
||||
title: "申请试用",
|
||||
href: "http://dns.g3soft.cn/demo/jsys/login/login.jsp",
|
||||
},
|
||||
{
|
||||
title: "联系我们",
|
||||
href: "http://www.g3soft.cn/aboutus.html",
|
||||
},
|
||||
{
|
||||
title: "客服热线: 0574-87812201",
|
||||
href: "",
|
||||
},
|
||||
]);
|
||||
|
||||
function toHref(href) {
|
||||
if (href) {
|
||||
window.open(href, "_blank");
|
||||
}
|
||||
}
|
||||
|
||||
function onVcodeShow() {
|
||||
if (form.value.orgid === "") {
|
||||
ElMessage.error("机构码不能为空!");
|
||||
return;
|
||||
}
|
||||
if (form.value.userid === "") {
|
||||
ElMessage.error("用户名不能为空!");
|
||||
return;
|
||||
}
|
||||
showVcode.value = true;
|
||||
}
|
||||
|
||||
function onVcodeClose() {
|
||||
showVcode.value = false;
|
||||
}
|
||||
|
||||
function onVcodeSuccess() {
|
||||
onVcodeClose();
|
||||
|
||||
loginLoading.value = true;
|
||||
|
||||
try {
|
||||
loginApi(form.value.orgid, form.value.userid, form.value.password).then(
|
||||
(res) => {
|
||||
if (res.success) {
|
||||
ElMessage.success("登录成功");
|
||||
|
||||
userStore.setUserInfo(
|
||||
form.value.orgid,
|
||||
form.value.userid,
|
||||
res.data.username,
|
||||
res.data.token,
|
||||
);
|
||||
router.push("/");
|
||||
|
||||
reset401Flag();
|
||||
}
|
||||
},
|
||||
);
|
||||
} finally {
|
||||
loginLoading.value = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="login-container">
|
||||
<div class="login-header">
|
||||
<div class="logo">
|
||||
<img src="@/assets/logo.png" />
|
||||
</div>
|
||||
|
||||
<div class="divider"></div>
|
||||
|
||||
<div class="name">网上服务平台</div>
|
||||
</div>
|
||||
|
||||
<div class="login-body">
|
||||
<div class="login-main">
|
||||
<div class="tip">登录</div>
|
||||
<div class="split"></div>
|
||||
<div class="form">
|
||||
<div class="form-item">
|
||||
<div class="label required">机构码</div>
|
||||
|
||||
<el-input v-model="form.orgid">
|
||||
<template #prefix>
|
||||
<G3Icon icon="lucide:building" size="18" />
|
||||
</template>
|
||||
</el-input>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="label required">账号</div>
|
||||
<el-input v-model="form.userid">
|
||||
<template #prefix>
|
||||
<G3Icon icon="lucide:user-round" size="18" />
|
||||
</template>
|
||||
</el-input>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="label">密码</div>
|
||||
<el-input v-model="form.password" show-password>
|
||||
<template #prefix>
|
||||
<G3Icon icon="lucide:lock-keyhole" size="18" />
|
||||
</template>
|
||||
</el-input>
|
||||
</div>
|
||||
<el-button
|
||||
size="large"
|
||||
long
|
||||
type="primary"
|
||||
style="
|
||||
background-color: #33dcd0;
|
||||
border-color: #00d3c4;
|
||||
font-size: 18px;
|
||||
"
|
||||
@click="onVcodeShow"
|
||||
:loading="loginLoading"
|
||||
>
|
||||
登录
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="service-container">
|
||||
<div class="service-title">
|
||||
<div class="service-left"></div>
|
||||
<div class="service-core">服务中心</div>
|
||||
<div class="service-right"></div>
|
||||
</div>
|
||||
|
||||
<div class="service-link">
|
||||
<template v-for="(item, index) in linkList" :key="index">
|
||||
<div class="link-item" @click="toHref(item.href)">
|
||||
<div class="link-icon">
|
||||
<G3Icon :icon="item.icon" size="38" color="#6cd6b3" />
|
||||
</div>
|
||||
<div class="link-title">{{ item.title }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="end-container">
|
||||
<template v-for="(item, index) in endLinkList" :key="index">
|
||||
<div class="end-li" @click="toHref(item.href)">
|
||||
{{ item.title }}
|
||||
</div>
|
||||
|
||||
<div v-if="index !== endLinkList.length - 1" class="end-line"></div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<Vcode :show="showVcode" @success="onVcodeSuccess" @close="onVcodeClose" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use "@/styles/mixins.scss" as *;
|
||||
|
||||
.login-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.login-header {
|
||||
width: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 81px;
|
||||
margin-left: 25%;
|
||||
|
||||
.logo {
|
||||
img {
|
||||
height: 40px;
|
||||
width: 120px;
|
||||
}
|
||||
}
|
||||
.divider {
|
||||
width: 1px;
|
||||
height: 28px;
|
||||
background-color: #ddd;
|
||||
margin: 0px 24px;
|
||||
}
|
||||
|
||||
.name {
|
||||
color: #595959;
|
||||
}
|
||||
}
|
||||
|
||||
.login-body {
|
||||
background-image: url("@/assets/login-bg.jpg");
|
||||
width: 100%;
|
||||
height: 420px;
|
||||
position: relative;
|
||||
|
||||
.login-main {
|
||||
position: absolute;
|
||||
right: 25%;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
|
||||
background-color: #fdfdfd;
|
||||
padding: 24px 28px;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
width: 320px;
|
||||
}
|
||||
|
||||
.tip {
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
margin: 0 30px;
|
||||
vertical-align: super;
|
||||
}
|
||||
.split {
|
||||
height: 1px;
|
||||
width: 100%;
|
||||
border-bottom: 3px solid #00d3c4;
|
||||
margin: 0 auto;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.form {
|
||||
margin-top: 16px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.form-item {
|
||||
margin-bottom: 12px;
|
||||
.label {
|
||||
font-size: 14px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.required {
|
||||
&::before {
|
||||
content: "*";
|
||||
color: red;
|
||||
margin-right: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-input__wrapper) {
|
||||
height: 38px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.service-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-bottom: 1px solid #e8e8e8;
|
||||
padding-bottom: 56px;
|
||||
flex-shrink: 0;
|
||||
.service-title {
|
||||
width: 100%;
|
||||
max-width: 1200px;
|
||||
margin: 40px 0px;
|
||||
padding: 0 40px;
|
||||
box-sizing: border-box;
|
||||
|
||||
.service-left {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 38%;
|
||||
height: 2px;
|
||||
background-color: #cccccc;
|
||||
vertical-align: middle;
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
right: -6px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
background: #ccc;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.service-core {
|
||||
display: inline-block;
|
||||
width: 24%;
|
||||
font-size: 24px;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
height: 34px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.service-right {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 38%;
|
||||
height: 2px;
|
||||
background-color: #cccccc;
|
||||
vertical-align: middle;
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: -6px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
background: #ccc;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.service-link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@include flexGapWrap(40px, 160px);
|
||||
|
||||
.link-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
|
||||
.link-icon {
|
||||
padding: 12px;
|
||||
border-radius: 999px;
|
||||
border: 2px solid #6cd6b3;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.link-title {
|
||||
margin-top: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.end-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #595959;
|
||||
margin: 24px 0px;
|
||||
|
||||
.end-li {
|
||||
font-size: 12px;
|
||||
line-height: 12px;
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.end-line {
|
||||
margin: 0 22px;
|
||||
width: 1px;
|
||||
height: 14px;
|
||||
border-left: 1px solid #595959;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,11 @@
|
||||
<script lang="js" setup>
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class=""></div>
|
||||
</template>
|
||||
|
||||
<style lang="css" scoped>
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,9 @@
|
||||
<script lang="js" setup></script>
|
||||
|
||||
<template>
|
||||
<div class="">
|
||||
<div></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="css" scoped></style>
|
||||
@@ -0,0 +1,49 @@
|
||||
<script setup lang="js">
|
||||
const value = ref("");
|
||||
|
||||
const options = [
|
||||
{
|
||||
value: "Option1",
|
||||
label: "Option1",
|
||||
},
|
||||
{
|
||||
value: "Option2",
|
||||
label: "Option2",
|
||||
},
|
||||
{
|
||||
value: "Option3",
|
||||
label: "Option3",
|
||||
},
|
||||
{
|
||||
value: "Option4",
|
||||
label: "Option4",
|
||||
},
|
||||
{
|
||||
value: "Option5",
|
||||
label: "Option5",
|
||||
},
|
||||
];
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<G3Grid direction="row">
|
||||
<G3GridGroup :label-width="80" :width="440" :column="2">
|
||||
<G3GridItem label="1222222222222222222222222" content="2" :span="1" required>
|
||||
<el-input type="textarea" v-model="value" />
|
||||
</G3GridItem>
|
||||
|
||||
<G3GridItem label="3" :span="1">
|
||||
<el-input />
|
||||
</G3GridItem>
|
||||
</G3GridGroup>
|
||||
<G3GridGroup :label-width="80" :width="440" :column="2">
|
||||
<G3GridItem label="1222222222222222222222222" content="2" :span="1" required>
|
||||
<el-input type="textarea" v-model="value" />
|
||||
</G3GridItem>
|
||||
|
||||
<G3GridItem label="3" :span="1">
|
||||
<el-input />
|
||||
</G3GridItem>
|
||||
</G3GridGroup>
|
||||
</G3Grid>
|
||||
</template>
|
||||
@@ -0,0 +1,714 @@
|
||||
<script lang="js" setup>
|
||||
import {
|
||||
checkColumnsApi,
|
||||
loadDataApi,
|
||||
loadAllColumnsApi,
|
||||
loadDataBySqlApi,
|
||||
saveObjectApi,
|
||||
} from "@/request/api";
|
||||
import { ElMessage } from "element-plus";
|
||||
import PreviewSql from "./preview-sql.vue";
|
||||
import { diffObject } from "@/utils/diff";
|
||||
|
||||
const tableRef = ref();
|
||||
|
||||
const loading = ref(false);
|
||||
|
||||
const leftSize = ref(200);
|
||||
const isCollapse = ref(false);
|
||||
|
||||
const showSql = ref(false);
|
||||
|
||||
const treeData = [{ b_id: "root", mc_b: "全部分类", isLeaf: false, children: [] }];
|
||||
|
||||
const treeProps = {
|
||||
children: "children",
|
||||
label: "mc_b",
|
||||
};
|
||||
const currentNode = ref(null);
|
||||
const currentModule = ref(null);
|
||||
const isSelectedNode = computed(() => !!currentNode.value);
|
||||
|
||||
const tableData = ref([]);
|
||||
|
||||
const currentRow = ref({});
|
||||
const isSelectedRow = computed(() => !!currentRow.value?.col_FieldName);
|
||||
let oldRowData = {};
|
||||
|
||||
const columns = [
|
||||
{
|
||||
prop: "col_field_name",
|
||||
label: "字段",
|
||||
width: 140,
|
||||
fixed: "left",
|
||||
},
|
||||
{
|
||||
prop: "col_caption",
|
||||
label: "标题",
|
||||
width: 100,
|
||||
fixed: "left",
|
||||
type: "input",
|
||||
},
|
||||
{
|
||||
prop: "col_field_name_v",
|
||||
label: "视图字段",
|
||||
width: 100,
|
||||
type: "input",
|
||||
},
|
||||
{
|
||||
prop: "col_group_index",
|
||||
label: "分组",
|
||||
width: 80,
|
||||
type: "input",
|
||||
},
|
||||
{
|
||||
prop: "col_visible",
|
||||
label: "显示",
|
||||
width: 80,
|
||||
type: "checkbox",
|
||||
},
|
||||
{
|
||||
prop: "col_allow_readonly",
|
||||
label: "只读",
|
||||
width: 80,
|
||||
type: "checkbox",
|
||||
},
|
||||
{
|
||||
prop: "col_allow_null",
|
||||
label: "可不输",
|
||||
width: 80,
|
||||
type: "checkbox",
|
||||
},
|
||||
{
|
||||
prop: "col_allow_repeat",
|
||||
label: "可重复",
|
||||
width: 80,
|
||||
type: "checkbox",
|
||||
},
|
||||
{
|
||||
prop: "col_allow_reserve",
|
||||
label: "可保留",
|
||||
width: 80,
|
||||
type: "checkbox",
|
||||
},
|
||||
{
|
||||
prop: "col_search",
|
||||
label: "可查找",
|
||||
width: 80,
|
||||
type: "checkbox",
|
||||
},
|
||||
{
|
||||
prop: "col_search_order",
|
||||
label: "查找顺序",
|
||||
width: 100,
|
||||
type: "input",
|
||||
},
|
||||
{
|
||||
prop: "col_search_group_index",
|
||||
label: "查找分组",
|
||||
width: 100,
|
||||
type: "input",
|
||||
},
|
||||
{
|
||||
prop: "col_type",
|
||||
label: "字段类型",
|
||||
width: 100,
|
||||
type: "option",
|
||||
},
|
||||
{
|
||||
prop: "col_default_value",
|
||||
label: "默认值",
|
||||
width: 80,
|
||||
type: "input",
|
||||
},
|
||||
{
|
||||
prop: "col_width",
|
||||
label: "宽度",
|
||||
width: 80,
|
||||
type: "input",
|
||||
},
|
||||
{
|
||||
prop: "col_position",
|
||||
label: "位置",
|
||||
width: 80,
|
||||
type: "input",
|
||||
},
|
||||
{
|
||||
prop: "col_show_summary",
|
||||
label: "合计",
|
||||
width: 80,
|
||||
type: "checkbox",
|
||||
},
|
||||
{
|
||||
prop: "col_display_format",
|
||||
label: "显示格式",
|
||||
width: 100,
|
||||
type: "input",
|
||||
},
|
||||
{
|
||||
prop: "col_edit",
|
||||
label: "编辑",
|
||||
width: 80,
|
||||
type: "checkbox",
|
||||
},
|
||||
{
|
||||
prop: "col_edit_position",
|
||||
label: "编辑位置",
|
||||
width: 100,
|
||||
type: "input",
|
||||
},
|
||||
{
|
||||
prop: "col_edit_width",
|
||||
label: "编辑宽度",
|
||||
width: 100,
|
||||
type: "input",
|
||||
},
|
||||
{
|
||||
prop: "col_edit_height",
|
||||
label: "编辑高度",
|
||||
width: 100,
|
||||
type: "input",
|
||||
},
|
||||
{
|
||||
prop: "col_edit_source_data",
|
||||
label: "编辑数据",
|
||||
width: 160,
|
||||
type: "input",
|
||||
},
|
||||
{
|
||||
prop: "col_edit_source_field",
|
||||
label: "下拉表显示字段",
|
||||
width: 100,
|
||||
type: "input",
|
||||
},
|
||||
{
|
||||
prop: "col_edit_group_index",
|
||||
label: "编辑分组",
|
||||
width: 100,
|
||||
type: "input",
|
||||
},
|
||||
{
|
||||
prop: "col_edit_batch",
|
||||
label: "批量编辑",
|
||||
width: 100,
|
||||
type: "checkbox",
|
||||
},
|
||||
{
|
||||
prop: "col_show_property",
|
||||
label: "属性",
|
||||
width: 80,
|
||||
type: "checkbox",
|
||||
},
|
||||
];
|
||||
|
||||
const editTypeOptions = [
|
||||
{
|
||||
value: "input",
|
||||
label: "input",
|
||||
},
|
||||
{
|
||||
value: "textarea",
|
||||
label: "textarea",
|
||||
},
|
||||
{
|
||||
value: "date",
|
||||
label: "date",
|
||||
},
|
||||
{
|
||||
value: "datetime",
|
||||
label: "datetime",
|
||||
},
|
||||
{
|
||||
value: "singleId",
|
||||
label: "singleId",
|
||||
},
|
||||
{
|
||||
value: "singleName",
|
||||
label: "singleName",
|
||||
},
|
||||
{
|
||||
value: "option",
|
||||
label: "option",
|
||||
},
|
||||
{
|
||||
value: "checkbox",
|
||||
label: "checkbox",
|
||||
},
|
||||
{
|
||||
value: "radio",
|
||||
label: "radio",
|
||||
},
|
||||
];
|
||||
|
||||
function getOptions(field) {
|
||||
if (field === "col_type") {
|
||||
return editTypeOptions;
|
||||
}
|
||||
}
|
||||
|
||||
function updateCollapse() {
|
||||
if (isCollapse.value) {
|
||||
isCollapse.value = false;
|
||||
leftSize.value = 200;
|
||||
} else {
|
||||
isCollapse.value = true;
|
||||
leftSize.value = 0;
|
||||
}
|
||||
}
|
||||
|
||||
async function handleTreeLoad(node, resolve) {
|
||||
try {
|
||||
const { level: nodeLevel, data: nodeData } = node;
|
||||
if (nodeLevel === 0) {
|
||||
resolve([
|
||||
{
|
||||
b_id: "root",
|
||||
mc_b: "全部分类",
|
||||
children: [],
|
||||
isLeaf: false,
|
||||
},
|
||||
]);
|
||||
return;
|
||||
}
|
||||
|
||||
const currentLevel = nodeLevel - 1;
|
||||
let sql = "";
|
||||
|
||||
if (currentLevel === 0) {
|
||||
sql = `SELECT * FROM s_module_bmfl WHERE js='1' AND b_canuse='1' ORDER BY b_xh`;
|
||||
} else {
|
||||
if (!nodeData) {
|
||||
resolve([]);
|
||||
return;
|
||||
}
|
||||
|
||||
const parentField = `bm_${currentLevel}_b`;
|
||||
const parentCondition = ` AND ${parentField}='${nodeData.b_id}'`;
|
||||
const childLevel = currentLevel + 1;
|
||||
|
||||
sql = `
|
||||
SELECT s_module_bmfl.*, s_module.b_id AS b_moduleid
|
||||
FROM s_module_bmfl
|
||||
LEFT JOIN s_module ON s_module.b_cate_id = s_module_bmfl.b_id
|
||||
WHERE s_module_bmfl.b_canuse='1'
|
||||
AND js='${childLevel}'
|
||||
${parentCondition}
|
||||
AND s_module_bmfl.b_canuse='1'
|
||||
ORDER BY b_xh
|
||||
`;
|
||||
}
|
||||
|
||||
const res = await loadDataBySqlApi(sql);
|
||||
if (res.success) {
|
||||
resolve(res.data);
|
||||
} else {
|
||||
resolve([]);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
resolve([]);
|
||||
}
|
||||
}
|
||||
|
||||
async function handleTreeNodeClick(nodeData) {
|
||||
if (!nodeData || nodeData.b_id === "root" || !nodeData.b_moduleid) return;
|
||||
|
||||
currentNode.value = nodeData;
|
||||
loading.value = true;
|
||||
|
||||
try {
|
||||
const res = await loadDataApi("s_module", `b_id = '${nodeData.b_moduleid}'`);
|
||||
|
||||
if (res.success) {
|
||||
currentModule.value = res.data[0] || null;
|
||||
|
||||
if (currentModule.value?.b_ViewTable) {
|
||||
const viewTable = currentModule.value?.b_ViewTable;
|
||||
await loadDatas(viewTable);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("加载模块或列失败", err);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
// 加载数据
|
||||
async function loadDatas(viewName) {
|
||||
if (!viewName) {
|
||||
return;
|
||||
}
|
||||
|
||||
const res = await loadAllColumnsApi(viewName);
|
||||
|
||||
if (res.success) {
|
||||
tableData.value = res.data;
|
||||
}
|
||||
}
|
||||
|
||||
// 编辑关闭事件
|
||||
async function handleEditClosed({ row, rowIndex, column, columnIndex }) {
|
||||
const $table = tableRef.value;
|
||||
if ($table) {
|
||||
await handleSaveRow(row);
|
||||
}
|
||||
}
|
||||
|
||||
// 编辑激活事件
|
||||
function handleEditActivated({ row }) {
|
||||
const $table = tableRef.value;
|
||||
if ($table) {
|
||||
oldRowData = JSON.parse(JSON.stringify(row));
|
||||
}
|
||||
}
|
||||
|
||||
// 选中行事件
|
||||
function handleCurrentRowChange({ newValue }) {
|
||||
currentRow.value = newValue;
|
||||
}
|
||||
|
||||
// 保存
|
||||
function handleSaveRow(row) {
|
||||
if (!row?.b_id) return;
|
||||
|
||||
const diffRowResult = diffObject(row, oldRowData, ["b_id"], []);
|
||||
|
||||
if (!diffRowResult.isChanged) {
|
||||
return;
|
||||
}
|
||||
|
||||
const saveData = [
|
||||
{
|
||||
tableName: "s_columnLib",
|
||||
keyField: "b_id",
|
||||
inserts: [],
|
||||
updates: [diffRowResult.result],
|
||||
deletes: [],
|
||||
log: "0",
|
||||
user: "0",
|
||||
},
|
||||
];
|
||||
|
||||
saveObjectApi(saveData).then((res) => {
|
||||
if (res.success) {
|
||||
ElMessage.success("保存成功");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 检查
|
||||
function handleCheckColumns() {
|
||||
if (!currentModule.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
const viewName = currentModule.value.b_ViewTable || "";
|
||||
|
||||
if (!viewName) {
|
||||
return;
|
||||
}
|
||||
|
||||
loading.value = true;
|
||||
|
||||
checkColumnsApi(viewName)
|
||||
.then(async (res) => {
|
||||
if (res.success) {
|
||||
ElMessage.success("检查成功");
|
||||
await loadDatas(viewName);
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="g3-wrapper">
|
||||
<el-splitter>
|
||||
<el-splitter-panel :size="leftSize" :min="0" :max="260">
|
||||
<div class="g3-wrapper-left">
|
||||
<div class="tree-header">
|
||||
<el-text>模块名</el-text>
|
||||
<div class="tree-options"></div>
|
||||
</div>
|
||||
|
||||
<div class="tree-container">
|
||||
<el-scrollbar style="flex: 1">
|
||||
<el-tree
|
||||
lazy
|
||||
highlight-current
|
||||
node-key="b_id"
|
||||
:data="treeData"
|
||||
:props="treeProps"
|
||||
:load="handleTreeLoad"
|
||||
:default-expanded-keys="['root']"
|
||||
@node-click="handleTreeNodeClick"
|
||||
/>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</div>
|
||||
</el-splitter-panel>
|
||||
<el-splitter-panel style="margin-left: 8px">
|
||||
<div class="g3-wrapper-right">
|
||||
<div class="content">
|
||||
<div class="content-head">
|
||||
<div class="content-head-left">
|
||||
<el-button type="primary" :disabled="!isSelectedNode" @click="handleCheckColumns"
|
||||
>检查</el-button
|
||||
>
|
||||
<el-button type="primary" :disabled="!isSelectedNode">浏览栏位预览</el-button>
|
||||
<el-button type="primary" :disabled="!isSelectedNode">编辑栏位预览</el-button>
|
||||
<el-button type="primary" :disabled="!isSelectedNode">属性预览</el-button>
|
||||
<el-button type="primary">修改标签</el-button>
|
||||
<el-button type="primary" :disabled="!isSelectedNode" @click="showSql = !showSql">
|
||||
SQL语句
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<div class="content-head-right">
|
||||
<el-input placeholder="请输入关键词搜索" />
|
||||
<el-button type="primary">搜索</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content-table">
|
||||
<vxe-table
|
||||
ref="tableRef"
|
||||
height="100%"
|
||||
:data="tableData"
|
||||
:loading="loading"
|
||||
:row-config="{
|
||||
useKey: true,
|
||||
keyField: 'col_FieldName',
|
||||
isCurrent: true,
|
||||
}"
|
||||
:column-config="{
|
||||
resizable: true,
|
||||
useKey: true,
|
||||
}"
|
||||
:edit-config="{
|
||||
trigger: 'click',
|
||||
mode: 'row',
|
||||
autoClear: false,
|
||||
showStatus: false,
|
||||
showIcon: false,
|
||||
}"
|
||||
:scroll-x="{
|
||||
gt: 0,
|
||||
enabled: true,
|
||||
}"
|
||||
:scroll-y="{
|
||||
gt: 0,
|
||||
enabled: true,
|
||||
}"
|
||||
show-overflow
|
||||
show-header-overflow
|
||||
@current-row-change="handleCurrentRowChange"
|
||||
@edit-closed="handleEditClosed"
|
||||
@edit-activated="handleEditActivated"
|
||||
>
|
||||
<vxe-column type="seq" width="50" fixed="left" />
|
||||
|
||||
<vxe-column
|
||||
v-for="column in columns"
|
||||
:key="column.prop"
|
||||
:field="column.prop"
|
||||
:title="column.label"
|
||||
:width="column.width"
|
||||
align="center"
|
||||
sortable
|
||||
:edit-render="{ autoFocus: true }"
|
||||
:fixed="column.fixed"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<ElCheckbox
|
||||
v-if="column.type === 'checkbox'"
|
||||
true-value="1"
|
||||
false-value="0"
|
||||
:checked="row[column.prop] === '1'"
|
||||
/>
|
||||
<template v-else>
|
||||
{{ row[column.prop] }}
|
||||
</template>
|
||||
</template>
|
||||
<template #edit="{ row }">
|
||||
<ElCheckbox
|
||||
v-if="column.type === 'checkbox'"
|
||||
v-model="row[column.prop]"
|
||||
true-value="1"
|
||||
false-value="0"
|
||||
/>
|
||||
<el-select
|
||||
v-else-if="column.type === 'option'"
|
||||
v-model="row[column.prop]"
|
||||
size="small"
|
||||
placeholder=" "
|
||||
>
|
||||
<el-option
|
||||
v-for="item in getOptions(column.prop)"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
<ElInput
|
||||
v-else-if="column.type === 'input'"
|
||||
v-model="row[column.prop]"
|
||||
size="small"
|
||||
/>
|
||||
<template v-else>
|
||||
{{ row[column.prop] }}
|
||||
</template>
|
||||
</template>
|
||||
</vxe-column>
|
||||
</vxe-table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-splitter-panel>
|
||||
</el-splitter>
|
||||
|
||||
<PreviewSql v-model="showSql" :data="tableData" :viewtable="currentModule?.b_ViewTable" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use "@/styles/mixins.scss" as *;
|
||||
|
||||
.g3-wrapper {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
:deep(.el-splitter-bar__dragger-horizontal::after),
|
||||
:deep(.el-splitter-bar__dragger-horizontal::before) {
|
||||
width: 1px;
|
||||
}
|
||||
|
||||
:deep(.el-splitter-bar__dragger::after),
|
||||
:deep(.el-splitter-bar__dragger::before) {
|
||||
background-color: #f2f6fc;
|
||||
}
|
||||
}
|
||||
|
||||
.g3-wrapper-left {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
|
||||
.tree-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 40px;
|
||||
padding: 0 10px;
|
||||
border-bottom: 1px solid #f2f6fc;
|
||||
}
|
||||
.tree-options {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.item {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
list-style: none;
|
||||
margin-left: 5px;
|
||||
cursor: pointer;
|
||||
border-radius: 6px;
|
||||
font-size: 16px;
|
||||
height: 26px;
|
||||
width: 26px;
|
||||
color: #333;
|
||||
transition: background-color 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
background-color: #f5f7fa;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tree-container {
|
||||
height: calc(100% - 40px);
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
.g3-wrapper-right {
|
||||
flex: 1;
|
||||
transition: width 0.3s;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #fff;
|
||||
|
||||
.head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 40px;
|
||||
padding: 0 10px;
|
||||
border-bottom: 1px solid #f2f6fc;
|
||||
flex-shrink: 0;
|
||||
.options {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.item {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
list-style: none;
|
||||
margin-left: 5px;
|
||||
border-radius: 6px;
|
||||
font-size: 16px;
|
||||
height: 26px;
|
||||
width: 26px;
|
||||
color: #333;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
|
||||
.item-bg {
|
||||
cursor: pointer;
|
||||
background-color: #f5f7fa;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-width: 0;
|
||||
height: 100%;
|
||||
|
||||
.content-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
.content-head-left {
|
||||
display: flex;
|
||||
@include flexGapWrap(4px, 8px);
|
||||
}
|
||||
|
||||
.content-head-right {
|
||||
display: flex;
|
||||
@include flexGapWrap(4px, 8px);
|
||||
flex-wrap: nowrap;
|
||||
min-width: 200px;
|
||||
}
|
||||
}
|
||||
|
||||
.content-table {
|
||||
margin-top: 8px;
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Whitespace-only changes.
@@ -0,0 +1,71 @@
|
||||
<template>
|
||||
<el-dialog v-bind="$attrs" title="Sql预览" width="1000px" class="dialog" @open="initData">
|
||||
<div class="sql-preview">
|
||||
{{ sqlStr }}
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: null,
|
||||
},
|
||||
viewtable: {
|
||||
type: null,
|
||||
},
|
||||
});
|
||||
|
||||
const sqlStr = ref("");
|
||||
|
||||
function initData() {
|
||||
if (!props.viewtable) return;
|
||||
|
||||
const vrows = props.data || [];
|
||||
|
||||
const sqlArr = [];
|
||||
|
||||
// 删除语句
|
||||
const deleteSql = `DELETE FROM s_columnlib WHERE col_TableName='${props.viewtable}';`;
|
||||
sqlArr.push(deleteSql);
|
||||
|
||||
// 插入语句
|
||||
vrows.forEach((row) => {
|
||||
const insertSql =
|
||||
"INSERT INTO s_columnlib(col_TableName,col_FieldName,col_Caption,col_Width,col_Visible,col_Position," +
|
||||
"col_ShowSummary,col_BandIndex,col_AllowNull,col_AllowRepeat,col_DefaultValue,col_ReadOnly,col_Color," +
|
||||
"col_CanSearch,col_SearchOrder,col_NeedReserve,col_sorted,col_DisplayFormat,col_type,col_datatype,col_foot)";
|
||||
|
||||
const valueSql =
|
||||
`VALUES('${props.viewtable}', '${row.col_FieldName}', '${row.col_Caption}', '${row.col_Width}', '${row.col_Visible}', '${row.col_Position}', ` +
|
||||
`'${row.col_ShowSummary}', '${row.col_BandIndex}', '${row.col_AllowNull}', '${row.col_AllowRepeat}', '${row.col_DefaultValue}', '${row.col_ReadOnly}', '${row.col_Color}', ` +
|
||||
`'${row.col_CanSearch}', '${row.col_SearchOrder}', '${row.col_NeedReserve}', '${row.col_sorted}', '${row.col_DisplayFormat}', '${row.col_type}', '${row.col_datatype}', '${row.col_foot}');`;
|
||||
|
||||
sqlArr.push(insertSql);
|
||||
sqlArr.push(valueSql);
|
||||
});
|
||||
|
||||
// 合并为字符串
|
||||
sqlStr.value = sqlArr.join("\n");
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.dialog-content {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
}
|
||||
.sql-preview {
|
||||
width: 100%;
|
||||
height: 500px;
|
||||
overflow: auto;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
font-family: monospace;
|
||||
padding: 8px;
|
||||
border: 1px solid #e0e0e0;
|
||||
background-color: #fafafa;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,7 @@
|
||||
<script lang="js" setup></script>
|
||||
|
||||
<template>
|
||||
<div class=""></div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -0,0 +1,11 @@
|
||||
<script lang="js" setup>
|
||||
const router = useRouter();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="">
|
||||
test-detail
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -0,0 +1,7 @@
|
||||
<script lang="js" setup></script>
|
||||
|
||||
<template>
|
||||
<div class=""></div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
Reference in new issue
Block a user