20260808172946
This commit is contained in:
1 parent
4fbfea82f2
commit
d72ca4193d
293 files changed
+37523
-73467
No files matched your search
@@ -0,0 +1,66 @@
|
||||
<template>
|
||||
<!-- UPDATE -->
|
||||
<el-table
|
||||
v-if="data.action === 'UPDATE'"
|
||||
:data="data.diffs"
|
||||
size="small"
|
||||
border
|
||||
show-header
|
||||
class="diff-table"
|
||||
>
|
||||
<el-table-column prop="field" label="字段" width="200" />
|
||||
<el-table-column label="旧值">
|
||||
<template #default="{ row }">
|
||||
<span class="old-value">
|
||||
{{ row.old == null ? "" : row.old }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="新值">
|
||||
<template #default="{ row }">
|
||||
<span class="new-value">
|
||||
{{ row.new == null ? "" : row.new }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- INSERT / DELETE -->
|
||||
<el-descriptions v-else :column="2" border size="small" class="snapshot">
|
||||
<el-descriptions-item
|
||||
v-for="(val, key) in data.values"
|
||||
:key="key"
|
||||
:label="key"
|
||||
>
|
||||
{{ val == null ? "" : val }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.diff-table {
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
.old-value {
|
||||
color: #f56c6c;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.new-value {
|
||||
color: #67c23a;
|
||||
}
|
||||
|
||||
.snapshot {
|
||||
margin-top: 6px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,256 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
v-model="visible"
|
||||
title="变更详情"
|
||||
width="920px"
|
||||
@close="onClose"
|
||||
>
|
||||
<div class="timeline" v-loading="loading">
|
||||
<div
|
||||
v-for="(item, index) in logList"
|
||||
:key="index"
|
||||
class="timeline-item"
|
||||
>
|
||||
<!-- 左侧圆点 + 竖线 -->
|
||||
<div class="timeline-left">
|
||||
<div class="dot" :class="dotClass(item.action)"></div>
|
||||
<div
|
||||
class="line"
|
||||
v-if="index < logList.length - 1"
|
||||
></div>
|
||||
</div>
|
||||
|
||||
<!-- 右侧内容 -->
|
||||
<div class="timeline-right">
|
||||
<!-- 摘要行 -->
|
||||
<div class="summary">
|
||||
<span class="time">{{ formatTime(item.operateTime) }}</span>
|
||||
<el-tag :type="tagType(item.action)" size="small">
|
||||
{{ item.action }}
|
||||
</el-tag>
|
||||
<span class="operator">{{ item.operator }}</span>
|
||||
<span class="table">{{ item.table }}</span>
|
||||
<span class="row-id">ID: {{ item.rowId }}</span>
|
||||
</div>
|
||||
|
||||
<!-- 展开/折叠 diff -->
|
||||
<div class="diff-wrapper">
|
||||
<AuditLogDetail :data="item" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-empty
|
||||
v-if="!loading && logList.length === 0"
|
||||
description="暂无变更记录"
|
||||
/>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch } from "vue";
|
||||
import { ElMessage } from "element-plus";
|
||||
import axios from "@/utils/axios";
|
||||
import AuditLogDetail from "./AuditLogDetail.vue";
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: Boolean,
|
||||
bizNo: String, // ✅ 业务单据号(loggroupid)
|
||||
});
|
||||
|
||||
const emit = defineEmits(["update:modelValue"]);
|
||||
|
||||
const visible = ref(false);
|
||||
const loading = ref(false);
|
||||
const logList = ref([]);
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(val) => {
|
||||
visible.value = val;
|
||||
if (val) {
|
||||
loadLog();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
watch(visible, (val) => {
|
||||
emit("update:modelValue", val);
|
||||
});
|
||||
|
||||
const loadLog = async () => {
|
||||
if (!props.bizNo) {
|
||||
ElMessage.warning("bizNo 不能为空");
|
||||
return;
|
||||
}
|
||||
|
||||
loading.value = true;
|
||||
try {
|
||||
const response = await axios.get("/logdetail", {
|
||||
params: {
|
||||
bizNo: props.bizNo,
|
||||
},
|
||||
});
|
||||
|
||||
const result = response.data;
|
||||
if (!result?.data || result.data.length === 0) {
|
||||
logList.value = [];
|
||||
return;
|
||||
}
|
||||
|
||||
const parsedList = [];
|
||||
|
||||
for (const raw of result.data) {
|
||||
try {
|
||||
const changeData =
|
||||
typeof raw.changeData === "string"
|
||||
? JSON.parse(raw.changeData)
|
||||
: raw.changeData;
|
||||
|
||||
changeData.table = changeData.table || raw.tableName;
|
||||
changeData.operator = changeData.operator || raw.operator;
|
||||
changeData.operateTime =
|
||||
changeData.operateTime || raw.operateTime;
|
||||
|
||||
parsedList.push(changeData);
|
||||
} catch (e) {
|
||||
console.error("changeData 解析失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
logList.value = parsedList;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
ElMessage.error("加载变更日志失败");
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const onClose = () => {
|
||||
logList.value = [];
|
||||
};
|
||||
|
||||
const tagType = (action) => {
|
||||
switch (action) {
|
||||
case "INSERT":
|
||||
return "success";
|
||||
case "UPDATE":
|
||||
return "primary";
|
||||
case "DELETE":
|
||||
return "danger";
|
||||
default:
|
||||
return "info";
|
||||
}
|
||||
};
|
||||
|
||||
const dotClass = (action) => {
|
||||
switch (action) {
|
||||
case "INSERT":
|
||||
return "dot-green";
|
||||
case "UPDATE":
|
||||
return "dot-blue";
|
||||
case "DELETE":
|
||||
return "dot-red";
|
||||
default:
|
||||
return "dot-gray";
|
||||
}
|
||||
};
|
||||
|
||||
const formatTime = (time) => {
|
||||
if (!time) return "";
|
||||
if (typeof time === "string" && time.includes("T")) {
|
||||
return time.replace("T", " ").split(".")[0];
|
||||
}
|
||||
return time;
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.timeline {
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
.timeline-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.timeline-left {
|
||||
width: 24px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
.dot {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 50%;
|
||||
margin-top: 6px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.dot-green {
|
||||
background-color: #67c23a;
|
||||
}
|
||||
|
||||
.dot-blue {
|
||||
background-color: #409eff;
|
||||
}
|
||||
|
||||
.dot-red {
|
||||
background-color: #f56c6c;
|
||||
}
|
||||
|
||||
.dot-gray {
|
||||
background-color: #909399;
|
||||
}
|
||||
|
||||
.line {
|
||||
width: 2px;
|
||||
flex: 1;
|
||||
background-color: #e4e7ed;
|
||||
margin-top: 4px;
|
||||
min-height: 24px;
|
||||
}
|
||||
|
||||
.timeline-right {
|
||||
flex: 1;
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
|
||||
.summary {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
font-size: 13px;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.summary .time {
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.summary .operator {
|
||||
color: #409eff;
|
||||
}
|
||||
|
||||
.summary .table {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.summary .row-id {
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.diff-wrapper {
|
||||
background-color: #fafafa;
|
||||
border-radius: 4px;
|
||||
padding: 8px 12px;
|
||||
margin-top: 6px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,184 +0,0 @@
|
||||
<script lang="js" setup>
|
||||
import dayjs from "dayjs";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { computed, ref } from "vue";
|
||||
import { useUserStore } from "@/store/user.js";
|
||||
import axios from "@/utils/axios";
|
||||
import { getTableBatchEditColumns } from "@/utils/dodata";
|
||||
import G3EditField from "../table/G3EditField.vue";
|
||||
|
||||
const props = defineProps({
|
||||
viewname: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
tablename: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
keyField: {
|
||||
type: String,
|
||||
default: "b_id",
|
||||
},
|
||||
selectedValue: {
|
||||
type: Array,
|
||||
required: false,
|
||||
default: () => [],
|
||||
},
|
||||
// 选中全部,该属性留着备用修改表中的全部数据(不用单指选中的数据)
|
||||
checkedAll: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
const userStore = useUserStore();
|
||||
|
||||
const _visible = defineModel(false);
|
||||
const disabledConfirm = computed(() => !(props.checkedAll || props.selectedValue.length > 0));
|
||||
|
||||
const loading = ref(true);
|
||||
const tablename = ref("");
|
||||
|
||||
const columns = ref([]);
|
||||
|
||||
const selectedField = ref(null);
|
||||
const selectedFieldName = ref(null);
|
||||
|
||||
const inputValue = ref("");
|
||||
|
||||
async function onOpened() {
|
||||
loading.value = true;
|
||||
|
||||
if (props.viewname === "" || props.tablename === "") {
|
||||
ElMessage.warning("必传参数不能为空");
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await getTableBatchEditColumns(props.viewname);
|
||||
if (result.success) {
|
||||
columns.value = result.data;
|
||||
if (columns.value.length > 0) {
|
||||
selectedFieldName.value = columns.value[0].col_FieldName;
|
||||
selectedField.value = columns.value[0];
|
||||
}
|
||||
loading.value = false;
|
||||
} else {
|
||||
ElMessage.error(`加载失败: ${result.error}`);
|
||||
}
|
||||
}
|
||||
|
||||
async function onClosed() {
|
||||
loading.value = true;
|
||||
tablename.value = "";
|
||||
columns.value = [];
|
||||
selectedField.value = null;
|
||||
selectedFieldName.value = null;
|
||||
inputValue.value = "";
|
||||
}
|
||||
|
||||
function onFieldChange() {
|
||||
inputValue.value = "";
|
||||
selectedField.value = columns.value.find(
|
||||
(item) => item.col_FieldName === selectedFieldName.value,
|
||||
);
|
||||
}
|
||||
|
||||
async function handleConfirm() {
|
||||
if (selectedField.value.col_AllowNull !== "1" && inputValue.value === "") {
|
||||
ElMessage.warning("请输入更新值");
|
||||
return;
|
||||
}
|
||||
|
||||
const updateRows = props.selectedValue.map((item) => {
|
||||
return item[props.keyField];
|
||||
});
|
||||
|
||||
const columnsData = {
|
||||
[selectedFieldName.value]: inputValue.value,
|
||||
b_updateuser_id: userStore.userInfo.userid,
|
||||
b_updatedatetime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
|
||||
};
|
||||
|
||||
const requestData = {
|
||||
tableName: props.tablename,
|
||||
keyField: props.keyField,
|
||||
updateRows,
|
||||
columns: columnsData,
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await axios.post("/batchUpdate", requestData, {
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
|
||||
if (response.data?.success) {
|
||||
ElMessage.success("保存成功");
|
||||
maintableorigina.value = { ...maintable.value };
|
||||
} else {
|
||||
throw new Error(response.data?.message || "保存失败");
|
||||
}
|
||||
} catch (error) {
|
||||
// Catch network or server errors
|
||||
console.error("Request failed:", error);
|
||||
ElMessage.error(error.message || "请求失败,请稍后再试");
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-dialog
|
||||
v-model="_visible"
|
||||
title="批量更新"
|
||||
width="500"
|
||||
v-bind="$attrs"
|
||||
@opened="onOpened"
|
||||
@closed="onClosed"
|
||||
>
|
||||
<div v-loading="loading" class="g3-container">
|
||||
<el-select
|
||||
v-model="selectedFieldName"
|
||||
placeholder="请选择需要修改的列"
|
||||
style="width: 100px"
|
||||
@change="onFieldChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in columns"
|
||||
:key="item.col_FieldName"
|
||||
:label="item.col_Caption"
|
||||
:value="item.col_FieldName"
|
||||
/>
|
||||
</el-select>
|
||||
|
||||
<el-divider direction="vertical" />
|
||||
|
||||
<G3EditField
|
||||
v-model="inputValue"
|
||||
:field="selectedField"
|
||||
placeholder="请输入需要修改的值"
|
||||
style="flex: 1"
|
||||
/>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="_visible = false"> 取消 </el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
:disabled="disabledConfirm"
|
||||
:loading="loading"
|
||||
@click="handleConfirm"
|
||||
>
|
||||
确认
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<style lang="css" scoped>
|
||||
.g3-container {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
align-items: center;
|
||||
height: 60px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,43 @@
|
||||
import { app } from "@/main";
|
||||
import { createVNode, render, ref } from "vue";
|
||||
import BatchUpdate from './index.vue'
|
||||
import { ElMessage } from "element-plus";
|
||||
|
||||
export function showbatchupdate(viewname, tablename, keyfield, rows) {
|
||||
if (!rows || rows.length === 0) {
|
||||
ElMessage.warning("请选择操作行");
|
||||
return;
|
||||
}
|
||||
|
||||
const container = document.createElement("div");
|
||||
document.body.appendChild(container);
|
||||
|
||||
const visible = ref(true);
|
||||
|
||||
const vnode = createVNode(BatchUpdate, {
|
||||
viewname,
|
||||
tablename,
|
||||
keyfield,
|
||||
rows,
|
||||
|
||||
modelValue: visible.value,
|
||||
|
||||
"onUpdate:modelValue": (val) => {
|
||||
visible.value = val;
|
||||
|
||||
if (!val) {
|
||||
render(null, container);
|
||||
container.remove();
|
||||
}
|
||||
},
|
||||
|
||||
onClose() {
|
||||
render(null, container);
|
||||
container.remove();
|
||||
},
|
||||
});
|
||||
|
||||
vnode.appContext = app._context;
|
||||
|
||||
render(vnode, container);
|
||||
}
|
||||
@@ -0,0 +1,257 @@
|
||||
<script setup>
|
||||
import { ElMessage } from "element-plus";
|
||||
import { computed, ref } from "vue";
|
||||
import { getTableBatchEditColumns } from "@/utils/dodata";
|
||||
import G3DatePicker from "@/components/g3-date-picker/G3DatePicker.vue";
|
||||
import G3DateTimePicker from "@/components/g3-date-picker/G3DateTimePicker.vue";
|
||||
import g3Select from "@/components/g3Select.vue";
|
||||
import G3Memo from "@/components/g3Memo.vue";
|
||||
import G3Number from "@/components/g3Number.vue";
|
||||
import { saveobjtApi } from "@/utils/doSql";
|
||||
|
||||
const props = defineProps({
|
||||
viewname: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
tablename: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
keyfield: {
|
||||
type: String,
|
||||
default: "b_id",
|
||||
},
|
||||
rows: {
|
||||
type: Array,
|
||||
required: false,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
|
||||
const _visible = defineModel(false);
|
||||
const disabledConfirm = computed(() => !(props.rows.length > 0));
|
||||
|
||||
const loading = ref(true);
|
||||
const tablename = ref("");
|
||||
|
||||
const columns = ref([]);
|
||||
|
||||
const selectedField = ref(null);
|
||||
const selectedFieldName = ref(null);
|
||||
|
||||
const inputId = ref("");
|
||||
const inputValue = ref("");
|
||||
|
||||
async function onOpened() {
|
||||
loading.value = true;
|
||||
|
||||
if (props.viewname === "" || props.tablename === "") {
|
||||
ElMessage.warning("必传参数不能为空");
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await getTableBatchEditColumns(props.viewname);
|
||||
if (result.success) {
|
||||
columns.value = result.data;
|
||||
if (columns.value.length > 0) {
|
||||
selectedFieldName.value = columns.value[0].col_FieldName;
|
||||
selectedField.value = columns.value[0];
|
||||
|
||||
console.log(selectedField.value);
|
||||
}
|
||||
loading.value = false;
|
||||
} else {
|
||||
ElMessage.error(`加载失败: ${result.error}`);
|
||||
}
|
||||
}
|
||||
|
||||
async function onClosed() {
|
||||
loading.value = true;
|
||||
tablename.value = "";
|
||||
columns.value = [];
|
||||
selectedField.value = null;
|
||||
selectedFieldName.value = null;
|
||||
inputValue.value = "";
|
||||
inputId.value = "";
|
||||
}
|
||||
|
||||
function onFieldChange() {
|
||||
inputValue.value = "";
|
||||
selectedField.value = columns.value.find(
|
||||
(item) => item.col_FieldName === selectedFieldName.value
|
||||
);
|
||||
}
|
||||
|
||||
async function handleConfirm() {
|
||||
try {
|
||||
if (selectedField.value.col_AllowNull !== "1" && inputValue.value === "") {
|
||||
ElMessage.warning("请输入更新值");
|
||||
return;
|
||||
}
|
||||
|
||||
let columnsData = {
|
||||
[selectedFieldName.value]: inputValue.value,
|
||||
};
|
||||
|
||||
if (selectedField.value.col_edit_type === "selectid") {
|
||||
columnsData = {
|
||||
...columnsData,
|
||||
[selectedField.value.col_Field_id]: inputId.value,
|
||||
};
|
||||
}
|
||||
|
||||
let updaterows = [];
|
||||
|
||||
props.rows.forEach((row) => {
|
||||
let columnsData = {
|
||||
[props.keyfield]: row[props.keyfield],
|
||||
[selectedFieldName.value]: inputValue.value,
|
||||
};
|
||||
|
||||
if (selectedField.value.col_edit_type === "selectid") {
|
||||
columnsData = {
|
||||
...columnsData,
|
||||
[selectedField.value.col_Field_id]: inputId.value,
|
||||
};
|
||||
}
|
||||
|
||||
updaterows.push(columnsData);
|
||||
});
|
||||
|
||||
if (updaterows.length === 0) {
|
||||
ElMessage.warning("无有效数据可更新");
|
||||
return;
|
||||
}
|
||||
|
||||
let requestData = [
|
||||
{
|
||||
tableName: props.tablename,
|
||||
keyField: props.keyfield,
|
||||
inserts: [],
|
||||
updates: updaterows,
|
||||
deletes: [],
|
||||
},
|
||||
];
|
||||
|
||||
saveobjtApi(requestData);
|
||||
ElMessage.success("更新成功");
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
ElMessage.error(`更新失败:${error.message || "未知错误"}`);
|
||||
}
|
||||
}
|
||||
|
||||
function handleCancel() {
|
||||
_visible.value = false;
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-dialog
|
||||
v-model="_visible"
|
||||
title="批量更新"
|
||||
width="500"
|
||||
v-bind="$attrs"
|
||||
@opened="onOpened"
|
||||
@closed="onClosed"
|
||||
>
|
||||
<div v-loading="loading" class="g3-container">
|
||||
<el-select
|
||||
v-model="selectedFieldName"
|
||||
placeholder="请选择需要修改的列"
|
||||
style="width: 100px"
|
||||
@change="onFieldChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in columns"
|
||||
:key="item.col_FieldName"
|
||||
:label="item.col_Caption"
|
||||
:value="item.col_FieldName"
|
||||
/>
|
||||
</el-select>
|
||||
|
||||
<el-divider direction="vertical" />
|
||||
|
||||
<!-- <G3EditField
|
||||
v-model="inputValue"
|
||||
:field="selectedField"
|
||||
placeholder="请输入需要修改的值"
|
||||
style="flex: 1"
|
||||
/> -->
|
||||
<div v-if="selectedField" style="flex: 1; min-height: 0">
|
||||
<template v-if="selectedField.col_edit_type === 'selectid'">
|
||||
<g3Select
|
||||
v-model="inputValue"
|
||||
v-model:model-id="inputId"
|
||||
:query-params="{ dataset: selectedField.col_edit_source_table }"
|
||||
:mustmatch="true"
|
||||
:pycode="selectedField.pycode"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<template v-else-if="selectedField.col_edit_type === 'selectname'">
|
||||
<g3Select
|
||||
v-model="inputValue"
|
||||
:query-params="{ dataset: selectedField.col_edit_source_table }"
|
||||
:in-table="true"
|
||||
:mustmatch="true"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<template v-else-if="selectedField.col_edit_type === 'checkbox'">
|
||||
<el-checkbox
|
||||
v-model="inputValue"
|
||||
true-value="1"
|
||||
false-value="0"
|
||||
size="large"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<template v-else-if="selectedField.col_edit_type === 'datetime'">
|
||||
<G3DateTimePicker v-model="inputValue" />
|
||||
</template>
|
||||
|
||||
<template v-else-if="selectedField.col_edit_type === 'date'">
|
||||
<G3DatePicker v-model="inputValue" />
|
||||
</template>
|
||||
<template v-else-if="selectedField.col_edit_type === 'g3memo'">
|
||||
<G3Memo v-model="inputValue" />
|
||||
</template>
|
||||
|
||||
<template v-else-if="selectedField.col_edit_type === 'g3Number'">
|
||||
<G3Number v-model="inputValue" size="small" />
|
||||
</template>
|
||||
|
||||
<template v-else>
|
||||
<el-input v-model="inputValue" size="small" />
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="handleCancel"> 取消 </el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
:disabled="disabledConfirm"
|
||||
:loading="loading"
|
||||
@click="handleConfirm"
|
||||
>
|
||||
确认
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.g3-container {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
align-items: center;
|
||||
height: 60px;
|
||||
::deep(.g3-input) {
|
||||
height: 32px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -35,7 +35,7 @@ import {
|
||||
import { computed, nextTick, ref, watch } from "vue";
|
||||
import { useUserStore } from "@/store/user";
|
||||
import axios from "@/utils/axios";
|
||||
import { compareAndClassifyData } from "@/utils/dataDiffUtils";
|
||||
import { compareAndClassifyData, diffData } from "@/utils/dataDiffUtils";
|
||||
import {
|
||||
compressImage,
|
||||
deleteFileApi,
|
||||
@@ -45,6 +45,7 @@ import {
|
||||
getFileExtension,
|
||||
uploadFile,
|
||||
} from "@/utils/file";
|
||||
import { loaddataApi } from "@/utils/doSql";
|
||||
import G3Icon from "@/components/g3-icon/index.vue";
|
||||
import { VxeTable, VxeColumn } from "vxe-table";
|
||||
|
||||
@@ -81,6 +82,34 @@ const displayMode = ref(0);
|
||||
|
||||
const userStore = useUserStore();
|
||||
|
||||
// 根据 moduleid 查询主表状态,自动判断是否可编辑
|
||||
const editable = ref(true);
|
||||
const isReadonly = computed(() => props.readonly || !editable.value);
|
||||
|
||||
async function loadEditableStatus() {
|
||||
try {
|
||||
const modules = await loaddataApi("s_module", `b_id = '${props.moduleid}'`);
|
||||
if (!modules?.length) {
|
||||
editable.value = true;
|
||||
return;
|
||||
}
|
||||
const saveTable = modules[0].b_SaveTable;
|
||||
if (!saveTable) {
|
||||
editable.value = true;
|
||||
return;
|
||||
}
|
||||
const records = await loaddataApi(saveTable, `b_id = '${props.father}'`);
|
||||
if (!records?.length) {
|
||||
editable.value = true;
|
||||
return;
|
||||
}
|
||||
const state = records[0].b_state;
|
||||
editable.value = ["草拟", "审核驳回"].includes(state) || !state;
|
||||
} catch {
|
||||
editable.value = true;
|
||||
}
|
||||
}
|
||||
|
||||
const containerRef = ref(null);
|
||||
const fileInputRef = ref(null);
|
||||
|
||||
@@ -234,6 +263,7 @@ watch(
|
||||
|
||||
function onOpened() {
|
||||
loadFiles();
|
||||
loadEditableStatus();
|
||||
}
|
||||
|
||||
async function loadFiles() {
|
||||
@@ -291,7 +321,7 @@ function formatTime(date) {
|
||||
}
|
||||
// 手动上传
|
||||
function handleClickUpload() {
|
||||
if (props.readonly) {
|
||||
if (isReadonly.value) {
|
||||
return;
|
||||
}
|
||||
fileInputRef.value.click();
|
||||
@@ -306,7 +336,7 @@ function handleFileInputChange(event) {
|
||||
}
|
||||
|
||||
function handlePaste(e) {
|
||||
if (props.readonly) {
|
||||
if (isReadonly.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -335,10 +365,9 @@ function handleDrop(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
if (props.readonly) {
|
||||
if (isReadonly.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
const files = e.dataTransfer.files;
|
||||
|
||||
// 过滤掉文件夹,只处理文件
|
||||
@@ -570,6 +599,13 @@ function handleBatchDelete() {
|
||||
}
|
||||
|
||||
async function deleteFiles(files) {
|
||||
await loadEditableStatus();
|
||||
if (isReadonly.value) {
|
||||
ElMessage.warning("当前单据已审核,不允许删除附件");
|
||||
loadFiles();
|
||||
return;
|
||||
}
|
||||
|
||||
// 收集文件的 mx_filename
|
||||
const filenames = files.map((file) => file.mx_filename).join(", ");
|
||||
|
||||
@@ -608,24 +644,31 @@ async function deleteFiles(files) {
|
||||
}).then((action) => {
|
||||
if (action === "confirm") {
|
||||
loadFiles();
|
||||
loadEditableStatus();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 保存
|
||||
async function handleSave() {
|
||||
await loadEditableStatus();
|
||||
if (isReadonly.value) {
|
||||
ElMessage.warning("当前单据已审核,不允许上传附件");
|
||||
loadFiles();
|
||||
return;
|
||||
}
|
||||
|
||||
loading.value = true;
|
||||
loadingTip.value = "正在保存中 . . .";
|
||||
|
||||
const { insertdata, updatedata, deletedata, hasChanges } = compareAndClassifyData(
|
||||
fileList.value,
|
||||
oldFileList.value,
|
||||
"subid",
|
||||
["_content", "_status", "checked"],
|
||||
);
|
||||
const data = compareAndClassifyData(fileList.value, oldFileList.value, "subid", [
|
||||
"_content",
|
||||
"_status",
|
||||
"checked",
|
||||
]);
|
||||
|
||||
// 处理新增的文件
|
||||
for (const item of insertdata) {
|
||||
for (const item of data.inserts) {
|
||||
try {
|
||||
await uploadFile(
|
||||
item._content,
|
||||
@@ -649,6 +692,7 @@ async function handleSave() {
|
||||
loading.value = false;
|
||||
|
||||
loadFiles();
|
||||
loadEditableStatus();
|
||||
}
|
||||
|
||||
async function handleDownloadZip() {
|
||||
@@ -709,7 +753,7 @@ function handleTreeNodeClick(data) {
|
||||
<div class="g3-title">
|
||||
附件管理({{ fileList.length }})
|
||||
|
||||
<template v-if="!props.readonly"> 未上传 ({{ pendingFileList.length }}) </template>
|
||||
<template v-if="!isReadonly"> 未上传 ({{ pendingFileList.length }}) </template>
|
||||
</div>
|
||||
</template>
|
||||
<input
|
||||
@@ -753,7 +797,7 @@ function handleTreeNodeClick(data) {
|
||||
</el-button>
|
||||
|
||||
<el-button
|
||||
v-if="!props.readonly"
|
||||
v-if="!isReadonly"
|
||||
size="small"
|
||||
type="danger"
|
||||
:disabled="checkedFiles.length === 0 || loading"
|
||||
@@ -840,7 +884,7 @@ function handleTreeNodeClick(data) {
|
||||
</div>
|
||||
<div class="g3-file-actions">
|
||||
<el-button
|
||||
v-if="!props.readonly"
|
||||
v-if="!isReadonly"
|
||||
type="danger"
|
||||
:icon="Delete"
|
||||
size="small"
|
||||
@@ -854,7 +898,7 @@ function handleTreeNodeClick(data) {
|
||||
circle
|
||||
@click.stop="handleDownloadFile(file)"
|
||||
/>
|
||||
<el-dropdown v-if="!props.readonly" placement="top" trigger="click">
|
||||
<el-dropdown v-if="!isReadonly" placement="top" trigger="click">
|
||||
<el-button
|
||||
type="info"
|
||||
:icon="More"
|
||||
@@ -936,7 +980,7 @@ function handleTreeNodeClick(data) {
|
||||
<template #default="{ row }">
|
||||
<div style="display: flex; align-items: center; justify-content: center">
|
||||
<el-button
|
||||
v-if="!props.readonly"
|
||||
v-if="!isReadonly"
|
||||
type="danger"
|
||||
link
|
||||
@click.stop="handleDeleteOne(row)"
|
||||
@@ -946,7 +990,7 @@ function handleTreeNodeClick(data) {
|
||||
<el-button type="primary" link @click.stop="handleDownloadFile(row)">
|
||||
下载
|
||||
</el-button>
|
||||
<el-dropdown v-if="!props.readonly" placement="top" trigger="click">
|
||||
<el-dropdown v-if="!isReadonly" placement="top" trigger="click">
|
||||
<el-button type="info" link style="margin-left: 12px"> 更多 </el-button>
|
||||
<el-icon class="el-icon--right">
|
||||
<ArrowDown />
|
||||
@@ -969,7 +1013,7 @@ function handleTreeNodeClick(data) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template v-if="!props.readonly" #footer>
|
||||
<template v-if="!isReadonly" #footer>
|
||||
<el-button type="primary" :icon="HelpFilled" :disabled="loading" @click="handleClickUpload">
|
||||
选择
|
||||
</el-button>
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
import { createVNode, render } from "vue";
|
||||
import { app } from "@/main";
|
||||
import G3SelectDlg from "../g3SelectDlg.vue";
|
||||
|
||||
export function showselectdlg(options = {}) {
|
||||
const container = document.createElement("div");
|
||||
document.body.appendChild(container);
|
||||
|
||||
const vnode = createVNode(G3SelectDlg, {
|
||||
...options,
|
||||
|
||||
visible: true,
|
||||
|
||||
"onUpdate:visible"(val) {
|
||||
if (!val) {
|
||||
render(null, container);
|
||||
container.remove();
|
||||
}
|
||||
},
|
||||
|
||||
onConfirm(data) {
|
||||
options.onConfirm?.(data);
|
||||
|
||||
render(null, container);
|
||||
container.remove();
|
||||
},
|
||||
|
||||
onClose() {
|
||||
render(null, container);
|
||||
container.remove();
|
||||
},
|
||||
});
|
||||
|
||||
vnode.appContext = app._context;
|
||||
|
||||
render(vnode, container);
|
||||
|
||||
return {
|
||||
close() {
|
||||
render(null, container);
|
||||
container.remove();
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import G3DatePicker from "@/components/g3-date-picker/G3DatePicker.vue";
|
||||
import G3DateTimePicker from "@/components/g3-date-picker/G3DateTimePicker.vue";
|
||||
import G3Select from "@/components/g3Select.vue";
|
||||
import G3Memo from "@/components/g3Memo.vue";
|
||||
import G3Number from "@/components/g3Number.vue";
|
||||
|
||||
const props = defineProps({
|
||||
label: { type: String, required: true },
|
||||
@@ -17,6 +18,7 @@ const props = defineProps({
|
||||
required: { type: Boolean, default: false },
|
||||
readonly: { type: Boolean, default: false },
|
||||
maxlength: { type: Number, default: 1000 },
|
||||
field: { type: String, default: "" },
|
||||
});
|
||||
|
||||
const emit = defineEmits(["update:modelValue", "update:modelId", "select"]);
|
||||
@@ -27,7 +29,7 @@ function onInput(val) {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="g3field">
|
||||
<div class="g3field" :field="props.field">
|
||||
<!-- 标签 -->
|
||||
<div class="label">
|
||||
<span v-if="required" class="req">*</span>
|
||||
@@ -81,11 +83,19 @@ function onInput(val) {
|
||||
v-else-if="type === 'checkbox'"
|
||||
class="g3checkbox"
|
||||
type="checkbox"
|
||||
:checked="modelValue == 1"
|
||||
:checked="String(modelValue) === '1'"
|
||||
:disabled="disabled"
|
||||
:readonly="readonly"
|
||||
@change="onInput($event.target.checked ? 1 : 0)"
|
||||
@change="onInput($event.target.checked ? '1' : '0')"
|
||||
/>
|
||||
<G3Number
|
||||
v-else-if="type === 'g3Number'"
|
||||
:model-value="modelValue"
|
||||
:disabled="disabled"
|
||||
:readonly="readonly"
|
||||
@update:model-value="emit('update:modelValue', $event)"
|
||||
/>
|
||||
|
||||
<G3Memo
|
||||
v-else-if="type === 'g3memo'"
|
||||
:model-value="modelValue"
|
||||
|
||||
@@ -0,0 +1,256 @@
|
||||
<script setup>
|
||||
import { nextTick, ref, watch } from "vue";
|
||||
import G3Field from "@/components/g3Field.vue";
|
||||
import g3OtherCompanyType from "@/components/other/g3OtherCompanyType.vue";
|
||||
import { getDataBySql } from "@/utils/doSql";
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
viewtable: { type: String, required: true },
|
||||
groupName: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
showGroupTitle: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
leftBgColor: {
|
||||
type: String,
|
||||
default: "#f1b408",
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(["update:modelValue", "select", "field-input"]);
|
||||
|
||||
// 更新字段
|
||||
function updateFields(fields) {
|
||||
// console.log(fields);
|
||||
|
||||
emit("update:modelValue", {
|
||||
...props.modelValue,
|
||||
...fields,
|
||||
});
|
||||
console.log("===1===");
|
||||
}
|
||||
// function updateField(prop, value) {
|
||||
// emit("update:modelValue", {
|
||||
// ...props.modelValue,
|
||||
// [prop]: value,
|
||||
// });
|
||||
// }
|
||||
|
||||
function getFieldType(column) {
|
||||
if (column.edit_type === "selectid") {
|
||||
return "select";
|
||||
}
|
||||
|
||||
if (column.edit_type === "selectname") {
|
||||
return "select";
|
||||
}
|
||||
|
||||
if (column.edit_type === "calculate") {
|
||||
return "input";
|
||||
}
|
||||
|
||||
return column.edit_type || "input";
|
||||
}
|
||||
function getFieldProps(column) {
|
||||
return {
|
||||
field: column.prop,
|
||||
disabled: String(column.readOnly) === "1",
|
||||
required: String(column.allowNull) !== "1",
|
||||
class: column.edit_type === "textarea" ? "fieldremark" : "",
|
||||
};
|
||||
}
|
||||
|
||||
const handleSelect = (column, val) => {
|
||||
if (column.edit_type === "selectid") {
|
||||
updateFields({
|
||||
[column.prop]: val?.b_name || "",
|
||||
[column.field_id]: val?.b_id || "",
|
||||
});
|
||||
}
|
||||
|
||||
console.log(column);
|
||||
console.log(val);
|
||||
|
||||
emit("select", {
|
||||
column,
|
||||
value: val,
|
||||
});
|
||||
};
|
||||
|
||||
const columns = ref([]);
|
||||
|
||||
watch(
|
||||
() => [props.viewtable, props.groupName],
|
||||
async ([table, group]) => {
|
||||
if (!table) return;
|
||||
|
||||
columns.value = [];
|
||||
|
||||
await addColumns(table, group);
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
|
||||
async function addColumns(viwetable, groupName) {
|
||||
try {
|
||||
let sql = `SELECT col_FieldName as prop,col_Field_id as field_id, col_Caption as label, col_Width as width, col_edit_type as edit_type,col_edit_width as edit_width,col_ReadOnly as readOnly,col_AllowNull as allowNull,col_edit_source_table as edit_source_table,col_edit_height as edit_height,col_DisplayFormat as displayFormat,col_edit_pycode as pycode FROM s_columnLib WHERE col_TableName = '${viwetable}' and col_edit= '1' `;
|
||||
|
||||
if (groupName !== null && groupName !== undefined && groupName !== "") {
|
||||
sql += ` AND col_edit_grouping='${groupName}'`;
|
||||
}
|
||||
sql += ` ORDER BY col_edit_position`;
|
||||
let datas = await getDataBySql(sql);
|
||||
if (!datas.records || datas.records.length === 0) {
|
||||
ElMessage.warning("返回数据格式异常");
|
||||
return;
|
||||
}
|
||||
columns.value = datas.records;
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
ElMessage.warning(err.message || "加载列配置失败");
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div :class="props.showGroupTitle ? 'g3group' : ''">
|
||||
<div
|
||||
v-if="props.showGroupTitle"
|
||||
class="g3grouptitle"
|
||||
:style="{ backgroundColor: props.leftBgColor }"
|
||||
>
|
||||
<span v-for="(char, index) in props.groupName" :key="index">
|
||||
{{ char }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="g3panel" :class="{ g3marginleft15: props.showGroupTitle }">
|
||||
<template v-for="column in columns" :key="column.prop">
|
||||
<template v-if="column.edit_type === 'selectid'">
|
||||
<G3Field
|
||||
:model-value="modelValue[column.prop]"
|
||||
:model-id="modelValue[column.field_id]"
|
||||
@update:model-value="
|
||||
updateFields({
|
||||
[column.prop]: $event,
|
||||
})
|
||||
"
|
||||
@update:model-id="
|
||||
updateFields({
|
||||
[column.field_id]: $event,
|
||||
})
|
||||
"
|
||||
:label="column.label"
|
||||
:type="getFieldType(column)"
|
||||
:pycode="column.pycode == 'true'"
|
||||
:mustmatch="true"
|
||||
:query-params="{ dataset: column.edit_source_table }"
|
||||
v-bind="getFieldProps(column)"
|
||||
@select="handleSelect(column, $event)"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="column.edit_type === 'selectname'">
|
||||
<G3Field
|
||||
:model-value="modelValue[column.prop]"
|
||||
@update:model-value="
|
||||
updateFields({
|
||||
[column.prop]: $event,
|
||||
})
|
||||
"
|
||||
:label="column.label"
|
||||
:type="getFieldType(column)"
|
||||
:query-params="{ dataset: column.edit_source_table }"
|
||||
v-bind="getFieldProps(column)"
|
||||
@select="handleSelect(column, $event)"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="column.edit_type === 'othercompanytype'">
|
||||
<g3OtherCompanyType
|
||||
:model-value="modelValue[column.prop]"
|
||||
:label="column.label"
|
||||
@update:model-value="
|
||||
updateFields({
|
||||
[column.prop]: $event,
|
||||
})
|
||||
"
|
||||
v-bind="getFieldProps(column)"
|
||||
/>
|
||||
</template>
|
||||
<template v-else>
|
||||
<G3Field
|
||||
:model-value="modelValue[column.prop]"
|
||||
@update:model-value="
|
||||
updateFields({
|
||||
[column.prop]: $event,
|
||||
})
|
||||
"
|
||||
:label="column.label"
|
||||
:type="getFieldType(column)"
|
||||
v-bind="getFieldProps(column)"
|
||||
@input="
|
||||
emit('field-input', {
|
||||
column,
|
||||
value: $event,
|
||||
})
|
||||
"
|
||||
/>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
.g3group {
|
||||
background: #fff;
|
||||
padding: 4px 4px;
|
||||
display: flex;
|
||||
}
|
||||
.g3grouptitle {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-evenly;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
padding: 0px 5px;
|
||||
background-color: #f1b408;
|
||||
width: 30px;
|
||||
white-space: normal;
|
||||
word-break: break-all;
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
.g3panel {
|
||||
width: 620px;
|
||||
height: auto;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 2px;
|
||||
align-content: start;
|
||||
}
|
||||
|
||||
.g3panel .fieldremark {
|
||||
grid-column: span 2;
|
||||
height: 72px;
|
||||
}
|
||||
|
||||
.g3panel .fieldremark :deep(textarea) {
|
||||
height: 100%;
|
||||
min-height: 100%;
|
||||
resize: none;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.g3panel .fieldremark :deep(.g3content) {
|
||||
width: 100%;
|
||||
}
|
||||
.g3marginleft15 {
|
||||
margin-left: 15px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,234 @@
|
||||
<script setup>
|
||||
import { nextTick, ref, watch } from "vue";
|
||||
import G3Field from "@/components/g3Field.vue";
|
||||
import g3OtherCompanyType from "@/components/other/g3OtherCompanyType.vue";
|
||||
import { getDataBySql } from "@/utils/doSql";
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
viewtable: { type: String, required: true },
|
||||
groupName: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
showGroupTitle: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(["update:modelValue", "select", "field-input"]);
|
||||
|
||||
// 更新字段
|
||||
function updateFields(fields) {
|
||||
console.log(fields);
|
||||
|
||||
emit("update:modelValue", fields);
|
||||
console.log("===1===");
|
||||
}
|
||||
// function updateField(prop, value) {
|
||||
// emit("update:modelValue", {
|
||||
// ...props.modelValue,
|
||||
// [prop]: value,
|
||||
// });
|
||||
// }
|
||||
|
||||
function getFieldType(column) {
|
||||
if (column.edit_type === "selectid") {
|
||||
return "select";
|
||||
}
|
||||
|
||||
if (column.edit_type === "selectname") {
|
||||
return "select";
|
||||
}
|
||||
|
||||
if (column.edit_type === "calculate") {
|
||||
return "input";
|
||||
}
|
||||
|
||||
return column.edit_type || "input";
|
||||
}
|
||||
function getFieldProps(column) {
|
||||
return {
|
||||
field: column.prop,
|
||||
disabled: String(column.readOnly) === "1",
|
||||
required: String(column.allowNull) !== "1",
|
||||
class: column.edit_type === "textarea" ? "fieldremark" : "",
|
||||
};
|
||||
}
|
||||
|
||||
const handleSelect = (column, val) => {
|
||||
emit("select", {
|
||||
column,
|
||||
value: val,
|
||||
});
|
||||
};
|
||||
|
||||
const columns = ref([]);
|
||||
|
||||
watch(
|
||||
() => [props.viewtable, props.groupName],
|
||||
async ([table, group]) => {
|
||||
if (!table) return;
|
||||
|
||||
columns.value = [];
|
||||
|
||||
await addColumns(table, group);
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
|
||||
async function addColumns(viwetable, groupName) {
|
||||
try {
|
||||
let sql = `SELECT col_FieldName as prop,col_Field_id as field_id, col_Caption as label, col_Width as width, col_edit_type as edit_type,col_edit_width as edit_width,col_ReadOnly as readOnly,col_AllowNull as allowNull,col_edit_source_table as edit_source_table,col_edit_height as edit_height,col_DisplayFormat as displayFormat,col_edit_pycode as pycode FROM s_columnLib WHERE col_TableName = '${viwetable}' and col_edit= '1' `;
|
||||
|
||||
if (groupName !== null && groupName !== undefined && groupName !== "") {
|
||||
sql += ` AND col_edit_grouping='${groupName}'`;
|
||||
}
|
||||
sql += ` ORDER BY col_edit_position`;
|
||||
let datas = await getDataBySql(sql);
|
||||
if (!datas.records || datas.records.length === 0) {
|
||||
ElMessage.warning("返回数据格式异常");
|
||||
return;
|
||||
}
|
||||
columns.value = datas.records;
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
ElMessage.warning(err.message || "加载列配置失败");
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<div :class="props.showGroupTitle ? 'g3group' : ''">
|
||||
<div v-if="props.showGroupTitle" class="g3grouptitle">
|
||||
<span v-for="(char, index) in props.groupName" :key="index">
|
||||
{{ char }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="g3panel" :class="{ g3marginleft15: props.showGroupTitle }">
|
||||
<template v-for="column in columns" :key="column.prop">
|
||||
<template v-if="column.edit_type === 'selectid'">
|
||||
<G3Field
|
||||
:model-value="modelValue[column.prop]"
|
||||
:model-id="modelValue[column.field_id]"
|
||||
@update:model-value="
|
||||
updateFields({
|
||||
[column.prop]: $event,
|
||||
})
|
||||
"
|
||||
@update:model-id="
|
||||
updateFields({
|
||||
[column.field_id]: $event,
|
||||
})
|
||||
"
|
||||
:label="column.label"
|
||||
:type="getFieldType(column)"
|
||||
:pycode="column.pycode == 'true'"
|
||||
:mustmatch="true"
|
||||
:query-params="{ dataset: column.edit_source_table }"
|
||||
v-bind="getFieldProps(column)"
|
||||
@select="handleSelect(column, $event)"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="column.edit_type === 'selectname'">
|
||||
<G3Field
|
||||
:model-value="modelValue[column.prop]"
|
||||
@update:model-value="
|
||||
updateFields({
|
||||
[column.prop]: $event,
|
||||
})
|
||||
"
|
||||
:label="column.label"
|
||||
:type="getFieldType(column)"
|
||||
:query-params="{ dataset: column.edit_source_table }"
|
||||
v-bind="getFieldProps(column)"
|
||||
@select="handleSelect(column, $event)"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="column.edit_type === 'othercompanytype'">
|
||||
<g3OtherCompanyType
|
||||
:model-value="modelValue[column.prop]"
|
||||
:label="column.label"
|
||||
@update:model-value="
|
||||
updateFields({
|
||||
[column.prop]: $event,
|
||||
})
|
||||
"
|
||||
v-bind="getFieldProps(column)"
|
||||
/>
|
||||
</template>
|
||||
<template v-else>
|
||||
<G3Field
|
||||
:model-value="modelValue[column.prop]"
|
||||
@update:model-value="
|
||||
updateFields({
|
||||
[column.prop]: $event,
|
||||
})
|
||||
"
|
||||
:label="column.label"
|
||||
:type="getFieldType(column)"
|
||||
v-bind="getFieldProps(column)"
|
||||
@input="
|
||||
emit('field-input', {
|
||||
column,
|
||||
value: $event,
|
||||
})
|
||||
"
|
||||
/>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
.g3group {
|
||||
background: #fff;
|
||||
padding: 4px 4px;
|
||||
display: flex;
|
||||
}
|
||||
.g3grouptitle {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-evenly;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
padding: 0px 5px;
|
||||
background-color: #f1b408;
|
||||
width: 30px;
|
||||
white-space: normal;
|
||||
word-break: break-all;
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
.g3panel {
|
||||
width: 620px;
|
||||
height: auto;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 2px;
|
||||
align-content: start;
|
||||
}
|
||||
|
||||
.g3panel .fieldremark {
|
||||
grid-column: span 2;
|
||||
height: 72px;
|
||||
}
|
||||
|
||||
.g3panel .fieldremark :deep(textarea) {
|
||||
height: 100%;
|
||||
min-height: 100%;
|
||||
resize: none;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.g3panel .fieldremark :deep(.g3content) {
|
||||
width: 100%;
|
||||
}
|
||||
.g3marginleft15 {
|
||||
margin-left: 15px;
|
||||
}
|
||||
</style>
|
||||
@@ -3,7 +3,7 @@ import { ref, nextTick, onMounted, onBeforeUnmount } from "vue";
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: String,
|
||||
type: [String, Number],
|
||||
default: "",
|
||||
},
|
||||
|
||||
|
||||
@@ -29,17 +29,17 @@ const props = defineProps({
|
||||
|
||||
precision: {
|
||||
type: Number,
|
||||
default: 2,
|
||||
default: -1,
|
||||
},
|
||||
|
||||
allowNegative: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
default: true,
|
||||
},
|
||||
|
||||
thousand: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
default: true,
|
||||
},
|
||||
|
||||
min: {
|
||||
@@ -66,9 +66,13 @@ const props = defineProps({
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
align: {
|
||||
type: String,
|
||||
default: "right",
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(["update:modelValue", "change", "blur", "focus"]);
|
||||
const emit = defineEmits(["update:modelValue", "input", "change", "blur", "focus"]);
|
||||
|
||||
const inputRef = ref();
|
||||
|
||||
@@ -164,6 +168,7 @@ function onInput(e) {
|
||||
text.value = value;
|
||||
|
||||
emit("update:modelValue", value);
|
||||
emit("input", value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -179,6 +184,7 @@ function onPaste(e) {
|
||||
text.value = value;
|
||||
|
||||
emit("update:modelValue", value);
|
||||
emit("input", value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -307,6 +313,7 @@ const showSuffix = computed(() => {
|
||||
:placeholder="placeholder"
|
||||
:disabled="disabled"
|
||||
:readonly="readonly"
|
||||
:style="{ textAlign: align }"
|
||||
autocomplete="off"
|
||||
spellcheck="false"
|
||||
@input="onInput"
|
||||
@@ -410,6 +417,8 @@ const showSuffix = computed(() => {
|
||||
line-height: 22px;
|
||||
|
||||
box-sizing: border-box;
|
||||
|
||||
text-align: right; /* 默认右对齐 */
|
||||
}
|
||||
|
||||
/* ============================
|
||||
@@ -461,13 +470,13 @@ const showSuffix = computed(() => {
|
||||
.g3-number.disabled .g3-number-input {
|
||||
background: #f5f7fa;
|
||||
|
||||
cursor: not-allowed;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.g3-number.disabled input {
|
||||
color: #a8abb2;
|
||||
|
||||
cursor: not-allowed;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
/* ============================
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -18,6 +18,14 @@ const props = defineProps({
|
||||
type: Function,
|
||||
default: null,
|
||||
},
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
disabledSum: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
});
|
||||
const emit = defineEmits(["update:visible", "confirm"]);
|
||||
const loading = ref(false);
|
||||
@@ -58,9 +66,12 @@ function handleClose() {
|
||||
}
|
||||
|
||||
const tableRef = ref();
|
||||
// 点击确认
|
||||
async function handleConfirm() {
|
||||
const rows = tableRef.value?.getCheckboxRecords?.() || [];
|
||||
const rows = props.multiple
|
||||
? tableRef.value?.getCheckboxRecords?.() || []
|
||||
: tableRef.value?.getRadioRecord()
|
||||
? [tableRef.value.getRadioRecord()]
|
||||
: [];
|
||||
|
||||
if (!rows.length) {
|
||||
ElMessage.warning("请选择数据!");
|
||||
@@ -76,16 +87,24 @@ async function handleConfirm() {
|
||||
}
|
||||
}
|
||||
|
||||
const subidCondition = `AND subid IN (${rows.map((r) => `'${r.subid}'`).join(",")})`;
|
||||
// 判断条件字段
|
||||
const field = rows[0].hasOwnProperty("b_id") ? "b_id" : "subid";
|
||||
|
||||
tableData.value = tableData.value.filter(
|
||||
(item) => !rows.some((r) => r.subid === item.subid),
|
||||
);
|
||||
const condition = `AND ${field} IN (${rows.map((r) => `'${r[field]}'`).join(",")})`;
|
||||
|
||||
// 移除已选择数据
|
||||
tableData.value = tableData.value.filter((item) => !rows.some((r) => r[field] === item[field]));
|
||||
|
||||
// 清除选择
|
||||
if (props.multiple) {
|
||||
tableRef.value.clearCheckboxRow();
|
||||
} else {
|
||||
tableRef.value.clearRadioRow();
|
||||
}
|
||||
|
||||
tableRef.value.clearCheckboxRow();
|
||||
handleTableFooterData();
|
||||
|
||||
emit("confirm", subidCondition);
|
||||
emit("confirm", condition);
|
||||
}
|
||||
|
||||
let filterSql = ref("");
|
||||
@@ -107,6 +126,7 @@ function buildSql() {
|
||||
async function loadData() {
|
||||
loading.value = true;
|
||||
try {
|
||||
|
||||
const result = await getDataBySqlPageMapping(
|
||||
buildSql(),
|
||||
props.moduleId,
|
||||
@@ -172,7 +192,7 @@ function computeFooter() {
|
||||
}
|
||||
|
||||
const selectSql = ref("");
|
||||
const selectOrder = ref("");
|
||||
const selectOrder = ref("");
|
||||
async function getselectSQLbyid(selectid) {
|
||||
let data_selectsql = await getDataBySql(
|
||||
`select * from s_selectsql where selectid='${selectid}' `,
|
||||
@@ -183,12 +203,11 @@ async function getselectSQLbyid(selectid) {
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化加载数据
|
||||
onMounted(async () => {
|
||||
async function handleOpened(){
|
||||
await getselectSQLbyid(props.selectid);
|
||||
await getSelectColumns(props.selectid, columns);
|
||||
await handleSearch();
|
||||
});
|
||||
// await handleSearch();
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -200,95 +219,92 @@ onMounted(async () => {
|
||||
align-center
|
||||
class="g3-dialog"
|
||||
draggable
|
||||
@opened="handleOpened"
|
||||
>
|
||||
<div class="g3pagecontainer">
|
||||
<div class="g3main">
|
||||
<div class="g3container">
|
||||
<div class="g3toolbar">
|
||||
<g3filter :module-id="props.selectid" @update:search="handlefilter" />
|
||||
<el-button @click="handleConfirm"> 选取 </el-button>
|
||||
<!-- <el-button @click="handleClose">取消</el-button> -->
|
||||
</div>
|
||||
<!-- 表格 -->
|
||||
<div class="g3container">
|
||||
<div>
|
||||
<div class="g3subgrid">
|
||||
<vxe-table
|
||||
ref="tableRef"
|
||||
border
|
||||
stripe
|
||||
header-align="center"
|
||||
:data="tableData"
|
||||
:show-footer="true"
|
||||
:footer-data="tableFooterData"
|
||||
:loading="loading"
|
||||
:sort-config="{
|
||||
// showIcon: false,
|
||||
trigger: 'cell',
|
||||
}"
|
||||
:filter-config="{
|
||||
showIcon: false,
|
||||
}"
|
||||
:column-drag-config="{
|
||||
showIcon: false,
|
||||
trigger: 'cell',
|
||||
}"
|
||||
:row-config="{
|
||||
keyField: 'subid',
|
||||
useKey: true,
|
||||
isCurrent: true,
|
||||
isHover: true,
|
||||
}"
|
||||
size="small"
|
||||
:cell-config="{
|
||||
height: 26,
|
||||
}"
|
||||
:column-config="{
|
||||
resizable: true,
|
||||
drag: true,
|
||||
}"
|
||||
show-overflow
|
||||
show-header-overflow
|
||||
show-footer-overflow
|
||||
height="100%"
|
||||
@checkbox-change="computeFooter"
|
||||
@checkbox-all="computeFooter"
|
||||
<div class="g3main">
|
||||
<div class="g3grid">
|
||||
<vxe-table
|
||||
ref="tableRef"
|
||||
border
|
||||
stripe
|
||||
header-align="center"
|
||||
:data="tableData"
|
||||
:show-footer="true"
|
||||
:footer-data="tableFooterData"
|
||||
:loading="loading"
|
||||
:sort-config="{
|
||||
// showIcon: false,
|
||||
trigger: 'cell',
|
||||
}"
|
||||
:filter-config="{
|
||||
showIcon: false,
|
||||
}"
|
||||
:column-drag-config="{
|
||||
showIcon: false,
|
||||
trigger: 'cell',
|
||||
}"
|
||||
:row-config="{
|
||||
isCurrent: true,
|
||||
isHover: true,
|
||||
}"
|
||||
size="small"
|
||||
:cell-config="{
|
||||
height: 26,
|
||||
}"
|
||||
:column-config="{
|
||||
resizable: true,
|
||||
drag: true,
|
||||
}"
|
||||
show-overflow
|
||||
show-header-overflow
|
||||
show-footer-overflow
|
||||
height="100%"
|
||||
@checkbox-change="computeFooter"
|
||||
@checkbox-all="computeFooter"
|
||||
>
|
||||
<vxe-column field="seq" type="seq" width="38" align="center" title=" " fixed="left" />
|
||||
<vxe-column
|
||||
:type="props.multiple ? 'checkbox' : 'radio'"
|
||||
width="38"
|
||||
align="center"
|
||||
fixed="left"
|
||||
/>
|
||||
|
||||
<vxe-column
|
||||
v-for="column in columns"
|
||||
:key="column.prop"
|
||||
:field="column.prop"
|
||||
:title="column.label"
|
||||
:width="column.width"
|
||||
:align="getAlignByFormat(column.displayFormat)"
|
||||
:params="column"
|
||||
sortable
|
||||
>
|
||||
<vxe-column
|
||||
field="seq"
|
||||
type="seq"
|
||||
width="38"
|
||||
align="center"
|
||||
title=" "
|
||||
fixed="left"
|
||||
/>
|
||||
<vxe-column type="checkbox" width="30" align="center" fixed="left" />
|
||||
<vxe-column
|
||||
v-for="column in columns"
|
||||
:key="column.prop"
|
||||
:field="column.prop"
|
||||
:title="column.label"
|
||||
:width="column.width"
|
||||
:align="getAlignByFormat(column.displayFormat)"
|
||||
:params="column"
|
||||
sortable
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<template v-if="column.displayFormat === 'checkbox'">
|
||||
<el-checkbox :checked="row[column.prop] === '1'" />
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ formatValueByFormat(row[column.prop], column.displayFormat) }}
|
||||
</template>
|
||||
<template #default="{ row }">
|
||||
<template v-if="column.displayFormat === 'checkbox'">
|
||||
<el-checkbox :checked="row[column.prop] === '1'" />
|
||||
</template>
|
||||
<template v-if="column.showSummary === '1'" #footer="{ row }">
|
||||
<template v-else>
|
||||
{{ formatValueByFormat(row[column.prop], column.displayFormat) }}
|
||||
</template>
|
||||
</vxe-column>
|
||||
</vxe-table>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="column.showSummary === '1'" #footer="{ row }">
|
||||
{{ formatValueByFormat(row[column.prop], column.displayFormat) }}
|
||||
</template>
|
||||
</vxe-column>
|
||||
</vxe-table>
|
||||
</div>
|
||||
<div class="g3footer">
|
||||
<div>
|
||||
|
||||
<div class="g3footer" :style="{ justifyContent: props.disabledSum ? 'right' : '' }">
|
||||
<div v-if="!props.disabledSum">
|
||||
{{ footerText }}
|
||||
</div>
|
||||
<div>
|
||||
@@ -321,7 +337,7 @@ onMounted(async () => {
|
||||
padding: 2px 2px;
|
||||
}
|
||||
|
||||
.g3main {
|
||||
.g3container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-width: 0;
|
||||
@@ -343,7 +359,7 @@ onMounted(async () => {
|
||||
height: 34px;
|
||||
}
|
||||
|
||||
.g3container {
|
||||
.g3main {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
@@ -356,15 +372,12 @@ onMounted(async () => {
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.g3subgrid {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.g3container > div:first-child {
|
||||
display: flex;
|
||||
.g3grid {
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.g3footer {
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
<script setup>
|
||||
import { ref, computed, onMounted } from "vue";
|
||||
import axios from "@/utils/axios";
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: { type: [String, Number], default: "" },
|
||||
label: String,
|
||||
disabled: { type: Boolean, default: false },
|
||||
required: { type: Boolean, default: false },
|
||||
field: { type: String, default: "" },
|
||||
});
|
||||
|
||||
const emit = defineEmits(["update:modelValue"]);
|
||||
|
||||
const options = ref([]);
|
||||
|
||||
const typeArray = computed({
|
||||
get: () => (props.modelValue ? props.modelValue.split(",") : []),
|
||||
set: (val) => emit("update:modelValue", val.join(",")),
|
||||
});
|
||||
|
||||
async function loadData() {
|
||||
if (options.value.length) return;
|
||||
|
||||
const res = await axios.get("/pagtable", {
|
||||
params: {
|
||||
tableName: "b_othercompany_partner_type",
|
||||
pkColumn: "b_id",
|
||||
page: 1,
|
||||
size: 100,
|
||||
whereClause: "2>1",
|
||||
},
|
||||
});
|
||||
|
||||
options.value =
|
||||
res.data?.data?.records?.map((item) => ({
|
||||
b_id: item.b_id,
|
||||
b_name: item.b_name,
|
||||
})) || [];
|
||||
}
|
||||
|
||||
onMounted(loadData);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="g3cell" :field="props.field">
|
||||
<div class="g3label">
|
||||
<span v-if="required" class="req">*</span>
|
||||
{{ label }}
|
||||
</div>
|
||||
|
||||
<el-select
|
||||
v-model="typeArray"
|
||||
multiple
|
||||
filterable
|
||||
size="small"
|
||||
:disabled="disabled"
|
||||
class="g3elselect"
|
||||
>
|
||||
<el-option v-for="item in options" :key="item.b_id" :label="item.b_name" :value="item.b_id" />
|
||||
</el-select>
|
||||
</div>
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
.g3cell {
|
||||
display: flex;
|
||||
grid-column: span 2;
|
||||
height: 52px;
|
||||
}
|
||||
|
||||
.g3label {
|
||||
width: 104px;
|
||||
padding-right: 8px;
|
||||
font-size: 14px;
|
||||
text-align: right;
|
||||
}
|
||||
.req {
|
||||
color: #d32f2f;
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
.g3elselect {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.g3elselect :deep(.el-select__wrapper) {
|
||||
height: 100%;
|
||||
align-items: flex-start;
|
||||
}
|
||||
:deep(.el-select__wrapper.is-disabled) {
|
||||
cursor: unset;
|
||||
}
|
||||
</style>
|
||||
@@ -3,6 +3,7 @@ import { ElMessage } from "element-plus";
|
||||
import { onMounted, ref, watch } from "vue";
|
||||
import axios from "@/utils/axios";
|
||||
import { isNotEmpty } from "@/utils/g3Funlib.js";
|
||||
import { getDataBySql } from "@/utils/doSql";
|
||||
|
||||
const props = defineProps({
|
||||
moduleId: { type: String },
|
||||
@@ -16,14 +17,12 @@ const sqlvalue = ref("");
|
||||
|
||||
// 列配置
|
||||
async function addQuery(moduleId) {
|
||||
let searchsql = `select ROW_NUMBER() OVER (ORDER BY col_SearchOrder) AS b_id,col_caption as lable, col_fieldname from s_columnlib where col_TableName='${moduleId}' and col_CanSearch ='1' and isnull(col_type,'') <> 'date' order by col_SearchOrder`;
|
||||
const response = await axios.get("/selectlistbysql", { params: { sql: searchsql } });
|
||||
if (response.data?.success) {
|
||||
const records = response.data.data.records || [];
|
||||
if (records.length > 0) {
|
||||
querys.value = records;
|
||||
sqllable.value = records[0].lable;
|
||||
} else {
|
||||
try {
|
||||
let searchsql = `select ROW_NUMBER() OVER (ORDER BY col_SearchOrder) AS b_id,col_caption as lable, col_fieldname from s_columnlib where col_TableName='${moduleId}' and col_CanSearch ='1' and isnull(col_type,'') <> 'date' order by col_SearchOrder`;
|
||||
|
||||
let datas = await getDataBySql(searchsql);
|
||||
|
||||
if (!datas.records || datas.records.length === 0) {
|
||||
const columnsDefault = [
|
||||
{ b_id: 1, col_fieldname: "b_id", lable: "代码" },
|
||||
{ b_id: 2, col_fieldname: "b_name", lable: "名称" },
|
||||
@@ -31,7 +30,13 @@ async function addQuery(moduleId) {
|
||||
querys.value = columnsDefault;
|
||||
sqllable.value = columnsDefault[0].lable;
|
||||
ElMessage.warning("没有查询条件,默认条件");
|
||||
return;
|
||||
}
|
||||
querys.value = datas.records;
|
||||
sqllable.value = datas.records[0].lable;
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
ElMessage.warning(error || "没有查询条件,默认条件");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
import dayjs from "dayjs";
|
||||
|
||||
import { ElMessage } from "element-plus";
|
||||
import { onMounted, ref } from "vue";
|
||||
import { watch, ref } from "vue";
|
||||
import g3Select from "@/components/g3Select.vue";
|
||||
import axios from "@/utils/axios";
|
||||
import { Search } from "@element-plus/icons-vue";
|
||||
import { getDataBySql } from "@/utils/doSql";
|
||||
|
||||
const props = defineProps({
|
||||
moduleId: { type: String },
|
||||
@@ -27,7 +27,7 @@ const colNum = ref(4);
|
||||
// 列配置
|
||||
async function addQuery(moduleId) {
|
||||
let searchsql = `select ROW_NUMBER() OVER (ORDER BY col_position) AS b_id,subid,col_caption as lable,col_fieldname,col_operator,col_option,col_type,col_pycode,col_source_field,col_source_table,col_defaultvalue_end,col_defaultvalue_start from s_search_sub where mx_module_id='${moduleId}' and col_visible ='1' order by col_position`;
|
||||
const response = await axios.get("/selectlistbysql", { params: { sql: searchsql } });
|
||||
const response = await axios.post("/selectlistbysql", { sql: searchsql });
|
||||
if (response.data?.success) {
|
||||
const records = response.data.data.records || [];
|
||||
// console.log('records=-=-=-=-=-')
|
||||
@@ -144,6 +144,7 @@ function handleSearch() {
|
||||
}
|
||||
});
|
||||
let sql = whereList.length > 0 ? " " + whereList.join(" AND ") : "";
|
||||
|
||||
emit("update:search", sql, querys.value);
|
||||
}
|
||||
function handleReset() {
|
||||
@@ -230,15 +231,19 @@ function parseDateConfig(configStr) {
|
||||
}
|
||||
|
||||
async function addSQL(moduleId) {
|
||||
let searchsql = `select * from s_search where b_module_id='${moduleId}'`;
|
||||
const response = await axios.get("/selectlistbysql", { params: { sql: searchsql } });
|
||||
if (response.data?.success) {
|
||||
const records = response.data.data.records || [];
|
||||
if (records.length > 0) {
|
||||
colNum.value = records[0].b_col_num;
|
||||
} else {
|
||||
try {
|
||||
let searchsql = `select * from s_search where b_module_id='${moduleId}'`;
|
||||
|
||||
let datas = await getDataBySql(searchsql);
|
||||
|
||||
if (!datas.records || datas.records.length === 0) {
|
||||
ElMessage.warning("没有查询语句");
|
||||
return;
|
||||
}
|
||||
colNum.value = datas.records[0].b_col_num;
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
ElMessage.warning(err.message || "没有查询语句");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,10 +255,18 @@ const handleSetdata = (val, col_fieldname) => {
|
||||
query._value = val;
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
await addSQL(props.moduleId);
|
||||
await addQuery(props.moduleId);
|
||||
});
|
||||
watch(
|
||||
() => props.moduleId,
|
||||
async (newVal) => {
|
||||
if (!newVal) return;
|
||||
|
||||
await addSQL(newVal);
|
||||
await addQuery(newVal);
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
},
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -529,4 +542,8 @@ onMounted(async () => {
|
||||
border-radius: 8px;
|
||||
}
|
||||
/* -------------------------- */
|
||||
/* 查询日期图标 */
|
||||
:deep(.g3-prefix .el-input__prefix) {
|
||||
display: none !important;
|
||||
}
|
||||
</style>
|
||||
@@ -23,16 +23,26 @@ const tableRef = ref();
|
||||
const currentRow = ref(null);
|
||||
const isDisabled = computed(() => currentRow.value === null);
|
||||
|
||||
function handleCurrentChange({ newValue }) {
|
||||
currentRow.value = newValue;
|
||||
console.log(currentRow.value);
|
||||
// function handleCurrentChange({ newValue }) {
|
||||
// currentRow.value = newValue;
|
||||
// console.log(currentRow.value);
|
||||
// }
|
||||
|
||||
function handleRadioChange({ row }) {
|
||||
currentRow.value = row;
|
||||
}
|
||||
|
||||
const loading = ref({
|
||||
table: true,
|
||||
});
|
||||
|
||||
const tableData = ref([]);
|
||||
async function initData() {
|
||||
console.log("============报表信息============");
|
||||
console.log("cateid:", props.cateid);
|
||||
console.log("valuesql:", props.valuesql);
|
||||
console.log("djid:", props.djid);
|
||||
|
||||
const { data: reportRes } = await axios.get("/getReport", {
|
||||
params: {
|
||||
cateId: props.cateid,
|
||||
@@ -42,8 +52,6 @@ async function initData() {
|
||||
ElMessage.error(`获取报表列表失败:${reportRes.message}`);
|
||||
return;
|
||||
}
|
||||
console.log("tableData.value=-=-=-=-");
|
||||
console.log(tableData.value);
|
||||
tableData.value = reportRes.data;
|
||||
|
||||
loading.value.table = false;
|
||||
@@ -141,7 +149,7 @@ function downloadFromResponse(res, type, defaultFileName = "") {
|
||||
title="打印报表"
|
||||
width="530px"
|
||||
class="g3dialogfooter"
|
||||
@open="initData"
|
||||
@opened="initData"
|
||||
draggable
|
||||
align-center
|
||||
>
|
||||
@@ -154,6 +162,10 @@ function downloadFromResponse(res, type, defaultFileName = "") {
|
||||
:data="tableData"
|
||||
:show-footer="true"
|
||||
:loading="loading.table"
|
||||
:radio-config="{
|
||||
highlight: true,
|
||||
trigger: 'row',
|
||||
}"
|
||||
:sort-config="{
|
||||
// showIcon: false,
|
||||
trigger: 'cell',
|
||||
@@ -180,10 +192,10 @@ function downloadFromResponse(res, type, defaultFileName = "") {
|
||||
show-overflow
|
||||
show-header-overflow
|
||||
height="100%"
|
||||
@current-row-change="handleCurrentChange"
|
||||
@radio-change="handleRadioChange"
|
||||
>
|
||||
<vxe-column field="seq" type="seq" width="30" align="center" title=" " fixed="left" />
|
||||
<vxe-column title="报表名称" width="452" field="b_name" align="center" />
|
||||
<vxe-column type="radio" width="60" align="center" />
|
||||
<vxe-column title="报表名称" width="400" field="b_name" align="center" />
|
||||
</vxe-table>
|
||||
</div>
|
||||
</div>
|
||||
@@ -274,4 +286,4 @@ function downloadFromResponse(res, type, defaultFileName = "") {
|
||||
width: 38px;
|
||||
height: 42px;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
@@ -1,39 +1,72 @@
|
||||
import { createApp } from "vue";
|
||||
import { createVNode, render } from "vue";
|
||||
import UploadProgress from "./index.vue";
|
||||
|
||||
let app: ReturnType<typeof createApp> | null = null;
|
||||
let instance: any = null;
|
||||
let container: HTMLElement | null = null;
|
||||
let vnode: any = null;
|
||||
|
||||
export function showUploadProgress(
|
||||
status: ProgressStatus = "uploading"
|
||||
) {
|
||||
if (!container) {
|
||||
container = document.createElement("div");
|
||||
container.className = "upload-progress-container";
|
||||
|
||||
export function showUploadProgress(status: ProgressStatus = "uploading") {
|
||||
if (!app) {
|
||||
const container = document.createElement("div");
|
||||
document.body.appendChild(container);
|
||||
|
||||
app = createApp(UploadProgress);
|
||||
instance = app.mount(container);
|
||||
vnode = createVNode(UploadProgress);
|
||||
|
||||
render(vnode, container);
|
||||
|
||||
instance = vnode.component?.proxy;
|
||||
}
|
||||
instance.open();
|
||||
instance.setStatus(status); // 外部传入状态
|
||||
}
|
||||
|
||||
export function updateUploadProgress(percent: number, status: ProgressStatus = "uploading") {
|
||||
if (instance) {
|
||||
instance.setPercent(percent);
|
||||
instance.setStatus(status); // 外部传入状态
|
||||
|
||||
if (percent >= 100) {
|
||||
setTimeout(() => {
|
||||
closeUploadProgress();
|
||||
}, 800); // 100%后等一下再关闭,显得自然
|
||||
}
|
||||
instance.open();
|
||||
instance.setStatus(status);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function updateUploadProgress(
|
||||
percent: number,
|
||||
status: ProgressStatus = "uploading"
|
||||
) {
|
||||
if (!instance) return;
|
||||
|
||||
instance.setPercent(percent);
|
||||
instance.setStatus(status);
|
||||
|
||||
if (percent >= 100) {
|
||||
setTimeout(() => {
|
||||
closeUploadProgress();
|
||||
}, 800);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function closeUploadProgress() {
|
||||
if (instance) {
|
||||
instance.close();
|
||||
}
|
||||
if (!instance) return;
|
||||
|
||||
instance.close();
|
||||
|
||||
// 等关闭动画结束后销毁 Vue 节点
|
||||
setTimeout(() => {
|
||||
|
||||
if (container) {
|
||||
render(null, container);
|
||||
container.remove();
|
||||
}
|
||||
|
||||
instance = null;
|
||||
vnode = null;
|
||||
container = null;
|
||||
|
||||
}, 300);
|
||||
}
|
||||
|
||||
// 如果你有 ProgressStatus 类型的需求,确保你导出它
|
||||
export type ProgressStatus = "uploading" | "completed" | "failed";
|
||||
|
||||
export type ProgressStatus =
|
||||
| "uploading"
|
||||
| "completed"
|
||||
| "failed";
|
||||
Reference in new issue
Block a user