first commit

This commit is contained in:
2026-08-26 14:25:17 +08:00
commit 06debfd1fc
10595 changed files with 1836924 additions and 0 deletions
@@ -0,0 +1,634 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
#app {
display: flex;
width: 100%;
min-height: calc(100vh - 64px);
justify-content: center;
align-items: center;
background-color: #f0f2f5;
}
.box-card {
width: calc(100% - 20px);
min-height: calc(100vh - 84px);
position: relative;
}
.box-card .el-card__body {
min-height: calc(100vh - 170px);
position: relative;
}
.box-card-title {
font-size: 20px;
}
.card-body {
display: flex;
justify-content: center;
min-height: calc(100vh - 170px);
position: relative;
}
.card-body-center {
width: 60%;
min-width: 800px;
min-height: calc(100vh - 170px);
position: relative;
padding-bottom: 70px;
box-sizing: border-box;
}
.card-body-center-bottom {
position: absolute;
left: 0;
bottom: 0;
width: 100%;
display: flex;
justify-content: center;
}
.card-body-center-bottom button {
margin: 0 10px;
}
.card-body-center > .el-carousel {
height: calc(100vh - 300px);
min-height: 560px;
position: relative;
overflow-y: hidden;
margin-top: 10px;
}
.card-body-center > .el-carousel > .el-carousel__container {
height: 100%;
}
.carousel-table-item {
display: flex;
justify-content: center;
width: 100%;
height: 100%;
padding: 10px 0;
box-sizing: border-box;
}
.carousel-table-item-center {
height: 100%;
width: 90%;
min-width: 800px;
position: relative;
display: flex;
flex-direction: column;
overflow: hidden;
}
.carousel-table-item-center .el-card__body {
flex: 1;
height: auto;
min-height: 0;
overflow-x: hidden;
overflow-y: auto;
box-sizing: border-box;
padding-bottom: 20px;
}
.check-group {
display: block;
overflow: visible;
padding: 0 10px 5px 0;
height: auto;
min-height: 100%;
box-sizing: border-box;
}
.check-group .el-radio,
.check-group .el-checkbox {
display: block;
width: 100%;
box-sizing: border-box;
padding: 12px;
margin: 0 !important;
margin-top: 15px !important;
}
.check-group .el-checkbox__label,
.check-group .el-radio__label {
width: calc(100% - 16px);
}
.option-extra {
float: right;
color: #f56c6c;
}
.carousel-table-item-relation .el-card__body,
.carousel-table-item-form .el-card__body {
position: relative;
height: 100%;
box-sizing: border-box;
}
.carousel-table-item-form .el-card__body {
overflow-y: auto;
}
.result-card {
width: 100%;
margin-top: 6px;
}
.result-card .el-card__body {
min-height: 170px;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.result-text {
font-size: 12px;
color: rgb(100, 100, 100);
margin-top: 20px;
}
</style>
<div id="app" v-cloak>
<el-card class="box-card" shadow="never">
<div slot="header" class="clearfix">
<span class="box-card-title">DataKid</span>
</div>
<div class="card-body">
<div class="card-body-center">
<el-steps :active="active" align-center>
<el-step title="选择数据表" icon="el-icon-document-copy"></el-step>
<el-step title="选择数据列" icon="el-icon-s-unfold"></el-step>
<el-step title="数据列对应" icon="el-icon-s-operation"></el-step>
<el-step title="提交数据" icon="el-icon-upload"></el-step>
<el-step title="导入结果" icon="el-icon-bell"></el-step>
</el-steps>
<el-carousel indicator-position="none" :autoplay="false" arrow="never" ref="carousel" direction="vertical">
<el-carousel-item class="carousel-table-item">
<el-card class="carousel-table-item-center">
<div slot="header" class="clearfix">
<el-input
style="width: 200px"
v-model.trim="tableKeyword"
placeholder="请输入关键字查询"
clearable>
</el-input>
<el-button type="primary" icon="el-icon-search" @click="filterTables"></el-button>
<el-button v-if="formData.tableName" style="float: right; padding: 10px 0" type="text">
当前选中:{{ formData.tableName }}
</el-button>
</div>
<el-radio-group class="check-group" v-model="formData.tableName">
<el-radio
v-for="item in filteredTables"
:key="item.table_name"
:label="item.table_name"
border>
{{ item.table_name }}{{ item.table_comment ? " ( " + item.table_comment + " )" : "" }}
<span class="option-extra">rows: {{ item.table_rows || 0 }}</span>
</el-radio>
</el-radio-group>
</el-card>
</el-carousel-item>
<el-carousel-item class="carousel-table-item">
<el-card class="carousel-table-item-center">
<div slot="header" class="clearfix">
<el-input
style="width: 200px"
v-model.trim="columnKeyword"
placeholder="请输入关键字查询"
clearable>
</el-input>
<el-button type="primary" icon="el-icon-search" @click="filterColumns"></el-button>
<el-button style="float: right; padding: 10px 0" type="text">
{{ formData.tableName }}
</el-button>
</div>
<el-checkbox-group class="check-group" v-model="formData.columns">
<el-checkbox
v-for="item in filteredColumns"
:key="item.column_name"
:label="item.column_name"
border>
{{ item.column_name }}{{ item.column_comment ? " ( " + item.column_comment + " )" : "" }}
<span class="option-extra">{{ item.column_type }}</span>
</el-checkbox>
</el-checkbox-group>
</el-card>
</el-carousel-item>
<el-carousel-item class="carousel-table-item">
<el-card style="width: 100%" class="carousel-table-item-relation">
<el-table :data="relation" height="100%" style="width: 100%" border size="medium">
<el-table-column prop="column_name" label="列名"></el-table-column>
<el-table-column prop="column_comment" label="描述" show-overflow-tooltip></el-table-column>
<el-table-column prop="is_nullable" label="可为空"></el-table-column>
<el-table-column prop="column_type" label="类型"></el-table-column>
<el-table-column prop="column_key" label="key"></el-table-column>
<el-table-column min-width="200px">
<template slot="header">
目标列
<el-popover
placement="top-start"
title="提示"
trigger="hover"
content="Excel 对应的表头名称,用于和表数据列对应">
<i slot="reference" class="el-icon-question"></i>
</el-popover>
</template>
<template slot-scope="{ row }">
<el-input
v-model.trim="row.relation"
size="medium"
placeholder="目标列">
</el-input>
</template>
</el-table-column>
</el-table>
</el-card>
</el-carousel-item>
<el-carousel-item class="carousel-table-item">
<el-card style="width: 100%" class="carousel-table-item-form">
<el-form label-width="120px" :model="formData" ref="form" :rules="formRules">
<el-form-item label="&emsp;" label-width="135px" class="view-header"></el-form-item>
<el-form-item prop="method" label="导入方式">
<el-radio-group v-model="formData.method">
<el-radio-button :label="1">追加或更新</el-radio-button>
<el-radio-button :label="2">仅追加</el-radio-button>
<el-radio-button :label="3">仅更新</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item v-if="[1, 3].includes(formData.method)" prop="field" label="关键字段">
<el-select v-model="formData.field" clearable filterable placeholder="请选择" style="width: 50%">
<el-option
v-for="item in relation"
:key="item.column_name"
:label="item.column_name"
:value="item.column_name">
</el-option>
</el-select>
</el-form-item>
<el-form-item prop="plugins" label="可选插件">
<el-checkbox-group v-model="formData.plugins">
<el-checkbox
v-for="item in plugins"
:key="item.name"
:label="item.name"
border>
{{ item.description }}
</el-checkbox>
</el-checkbox-group>
</el-form-item>
<el-form-item label="文&emsp;&emsp;件" class="is-required">
<el-upload
ref="upload"
drag
action="#"
:auto-upload="false"
:limit="1"
:file-list="fileList"
:on-change="handleFileChange"
:on-remove="handleFileRemove">
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
<div slot="tip" class="el-upload__tip" style="color: #F56C6C">只能上传 xls/xlsx 文件</div>
</el-upload>
</el-form-item>
</el-form>
</el-card>
</el-carousel-item>
<el-carousel-item style="padding: 10px">
<el-card class="result-card">
<el-progress type="circle" :percentage="resultPercentage" :status="resultProgressStatus"></el-progress>
<div class="result-text">{{ resultSummary }}</div>
<div style="margin-top: 10px" v-if="result.cacheKey">
<el-link
type="danger"
icon="el-icon-download"
style="font-size: 13px;"
:href="loc() + '/exportErrors?cacheKey=' + result.cacheKey">
下载错误记录
</el-link>
</div>
</el-card>
</el-carousel-item>
</el-carousel>
<div class="card-body-center-bottom">
<el-button size="medium" @click="prev" :disabled="active === 0 || loading">上一步</el-button>
<el-button type="primary" size="medium" :loading="loading" @click="active < 4 ? next() : carry()">
{{ active < 4 ? primaryButtonText : "完成" }}
</el-button>
</div>
</div>
</div>
</el-card>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: "#app",
data() {
return {
active: 0,
loading: false,
tableKeyword: "",
columnKeyword: "",
tables: [],
filteredTables: [],
columns: [],
filteredColumns: [],
relation: [],
plugins: [],
fileList: [],
cacheTableName: "",
result: {
total: 0,
success: 0,
cacheKey: ""
},
formRules: {
method: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
field: [{ required: true, message: "必填", trigger: ["blur", "change"] }]
},
formData: {
tableName: "",
columns: [],
method: 1,
field: "",
plugins: []
}
}
},
computed: {
primaryButtonText() {
if (this.active === 3 && this.formData.method === 3) {
return "更新"
}
return "下一步"
},
resultSummary() {
const total = this.result.total || 0
const success = this.result.success || 0
const fail = Math.max(total - success, 0)
if (fail > 0) {
return "总记录数 " + total + " 条,成功 " + success + " 条,失败 " + fail + " 条!"
}
return "总记录数 " + total + " 条,成功 " + success + " 条!"
},
resultProgressStatus() {
const total = this.result.total || 0
const success = this.result.success || 0
if (total > 0 && success < total) {
return "exception"
}
return "success"
},
resultPercentage() {
if (!this.result.total) {
return 0
}
return Number(((this.result.success / this.result.total) * 100).toFixed(2))
}
},
methods: {
loc,
normalizeRecord(item) {
const normalized = {}
Object.keys(item || {}).forEach(key => {
normalized[(key || "").toLowerCase()] = item[key]
})
return normalized
},
async loadTables() {
const resp = await this.$axios.post(loc() + "/tableNames")
if (resp.code === 0) {
this.tables = Array.isArray(resp.data)
? resp.data.map(item => this.normalizeRecord(item))
: []
this.filteredTables = this.tables.slice()
}
},
async loadPlugins() {
this.plugins = await this.$businessTool.getEnumOptions("SysDataImportPlugin")
},
async loadColumns() {
const resp = await this.$axios.post(loc() + "/columns", {
tableName: this.formData.tableName
})
if (resp.code === 0) {
this.columns = Array.isArray(resp.data)
? resp.data.map(item => this.normalizeRecord(item))
: []
this.filteredColumns = this.columns.slice()
}
},
filterTables() {
const keyword = (this.tableKeyword || "").toLowerCase()
if (!keyword) {
this.filteredTables = this.tables.slice()
return
}
this.filteredTables = this.tables.filter(item => {
const tableName = (item.table_name || "").toLowerCase()
const tableComment = (item.table_comment || "").toLowerCase()
return tableName.includes(keyword) || tableComment.includes(keyword)
})
},
filterColumns() {
const keyword = (this.columnKeyword || "").toLowerCase()
if (!keyword) {
this.filteredColumns = this.columns.slice()
return
}
this.filteredColumns = this.columns.filter(item => {
const columnName = (item.column_name || "").toLowerCase()
const columnComment = (item.column_comment || "").toLowerCase()
return columnName.includes(keyword) || columnComment.includes(keyword)
})
},
buildRelation() {
this.relation = this.columns
.filter(item => this.formData.columns.includes(item.column_name))
.map(item => Object.assign({}, item, { relation: "" }))
},
async next() {
if (this.active === 0) {
if (!this.formData.tableName) {
this.$notify({
title: "警告",
message: "请选择数据表",
type: "warning"
})
return
}
if (this.cacheTableName !== this.formData.tableName) {
await this.loadColumns()
this.formData.columns = []
this.formData.field = ""
this.cacheTableName = this.formData.tableName
}
} else if (this.active === 1) {
if (!this.formData.columns.length) {
this.$notify({
title: "警告",
message: "请选择数据列",
type: "warning"
})
return
}
this.buildRelation()
} else if (this.active === 2) {
if (this.relation.find(item => !item.relation)) {
this.$notify({
title: "警告",
message: "存在未填写的目标列",
type: "warning"
})
return
}
} else if (this.active === 3) {
const success = await this.doSubmit()
if (!success) {
return
}
}
this.$refs.carousel.next()
this.active++
},
prev() {
if (this.active <= 0) {
return
}
this.$refs.carousel.prev()
this.active--
},
validateSubmitForm() {
let validForm = true
this.$refs.form.validate(valid => {
validForm = valid
})
if (!validForm || !this.fileList.length) {
this.$notify({
title: "警告",
message: "存在未填写的必填项",
type: "warning"
})
return false
}
return true
},
async doSubmit() {
if (!this.validateSubmitForm()) {
return false
}
const formData = new FormData()
formData.append("tableName", this.formData.tableName)
formData.append("method", this.formData.method)
formData.append("field", this.formData.field || "")
formData.append("relation", JSON.stringify(this.relation))
formData.append("plugins", JSON.stringify(this.formData.plugins || []))
formData.append("file", this.fileList[0].raw, this.fileList[0].name)
this.loading = true
try {
const resp = await this.$axios.post(loc() + "/importData", formData, {
headers: {
"Content-Type": "multipart/form-data"
}
})
if (resp.code !== 0) {
this.$notify.error({
title: "错误",
message: resp.msg
})
this.result = { total: 0, success: 0, cacheKey: "" }
return false
}
this.result = resp.data || { total: 0, success: 0, cacheKey: "" }
return true
} finally {
this.loading = false
}
},
handleFileRemove(file, fileList) {
this.fileList = fileList
},
handleFileChange(file, fileList) {
const extension = ((file.name || "").split(".").pop() || "").toLowerCase()
const remove = () => {
const removeIndex = fileList.findIndex(item => item.uid === file.uid)
if (removeIndex > -1) {
fileList.splice(removeIndex, 1)
}
}
if (file.size === 0) {
this.$message.warning("您选择的是空文件")
remove()
} else if (!["xls", "xlsx"].includes(extension)) {
this.$message.warning("上传文件只能是 xls/xlsx 格式")
remove()
}
this.fileList = fileList
},
carry() {
this.active = 0
this.tableKeyword = ""
this.columnKeyword = ""
this.columns = []
this.filteredColumns = []
this.relation = []
this.fileList = []
this.cacheTableName = ""
this.result = {
total: 0,
success: 0,
cacheKey: ""
}
this.formData = {
tableName: "",
columns: [],
method: 1,
field: "",
plugins: []
}
if (this.$refs.upload) {
this.$refs.upload.clearFiles()
}
this.filterTables()
this.$refs.carousel.setActiveItem(0)
}
},
async created() {
await this.loadTables()
await this.loadPlugins()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,15 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak></div>
<script nonce="${cspNonce!}">
new Vue({
el: "#app"
})
</script>
<!--#
}
#-->
@@ -0,0 +1,211 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.pullTimeRadioGroup .el-checkbox {
width: 100%;
margin: 0 0 10px 0;
}
.pullTimeRadioGroup .el-checkbox.is-bordered {
margin-left: 0 !important;
display: flex;
align-items: center;
}
.pullTimeRadioGroup .el-checkbox__input {
flex-shrink: 0;
}
.pullTimeRadioGroup .el-checkbox__label {
flex: 1;
}
</style>
<div id="app" v-cloak>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="拉取时间">
<el-select clearable v-model="pageForm.pullTime" placeholder="请选择拉取时间" :clearable="false" @change="doSearch">
<el-option v-for="item in pullTimeOptions" :label="item.pullTime" :value="item.pullTime"></el-option>
</el-select>
</search-item>
<search-item label="姓名">
<el-input placeholder="请输入姓名" clearable v-model="pageForm.userName" style="width: 100%"></el-input>
</search-item>
<search-item label="工号">
<el-input placeholder="请输入工号" clearable v-model="pageForm.loginName" style="width: 100%"></el-input>
</search-item>
<search-item label="所属单位">
<el-select placeholder="请选择所属单位" v-model="pageForm.unitName" clearable filterable>
<el-option v-for="item in unitNameOptions" :key="item" :label="item" :value="item"></el-option>
</el-select>
</search-item>
<search-item label="在职状态">
<el-select v-model="pageForm.userState" clearable filterable>
<el-option v-for="item in userStateOptions" :label="item" :value="item"></el-option>
</el-select>
</search-item>
<search-item label="用人方式">
<el-select v-model="pageForm.preparedBy" clearable filterable>
<el-option v-for="item in preparedByOptions" :label="item" :value="item"></el-option>
</el-select>
</search-item>
<search-item label="人员类型">
<el-select v-model="pageForm.personType" clearable filterable>
<el-option v-for="item in personTypeOptions" :label="item" :value="item"></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool :label="pageForm.pullTime ? pageForm.pullTime + '数据' : '全部数据'">
<el-button type="primary" size="mini" :loading="pullLoading" @click="pull" icon="el-icon-download">拉取信息中心数据</el-button>
<el-button type="danger" size="mini" @click="openDelete" icon="el-icon-delete">删除本地数据源</el-button>
</table-tool>
<el-table :key="tableKey" :data="tableData" @sort-change="pageOrder" header-align="center" v-loading="tableLoading">
<el-table-column type="index" width="70" label="序号" fixed="left" :index="indexMethod"></el-table-column>
<el-table-column prop="pullTime" label="拉取时间" width="170" fixed="left"></el-table-column>
<el-table-column prop="loginname" label="工号" width="100" fixed="left"></el-table-column>
<el-table-column prop="username" label="姓名" fixed="left" width="120" show-overflow-tooltip></el-table-column>
<el-table-column prop="sex" label="性别" sortable></el-table-column>
<el-table-column prop="mobile" label="手机号" width="120"></el-table-column>
<el-table-column prop="birthday" label="生日" sortable width="120">
<template slot-scope="{row}">{{$moment(row.birthday).format('YYYY-MM-DD')}}</template>
</el-table-column>
<el-table-column prop="userState" label="在职状态" sortable width="120"></el-table-column>
<el-table-column prop="arrivalAtSchoolDate" label="来校时间" sortable width="120"></el-table-column>
<el-table-column prop="personType" label="人员类型" sortable width="120"></el-table-column>
<!-- <el-table-column prop="technicalTitle" label="技术职称" sortable width="120"></el-table-column>
<el-table-column prop="position" label="干部职务" sortable width="120" show-overflow-tooltip></el-table-column>
<el-table-column prop="education" label="学历" show-overflow-tooltip sortable width="120"></el-table-column>
<el-table-column prop="academicDegree" label="学位" show-overflow-tooltip sortable width="120"></el-table-column>-->
<el-table-column prop="unitName" label="单位" show-overflow-tooltip sortable width="120"></el-table-column>
<el-table-column prop="unitId" label="单位编码" sortable width="120"></el-table-column>
<el-table-column prop="political" label="政治面貌" sortable></el-table-column>
<el-table-column prop="nation" label="民族" sortable></el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<el-dialog title="选择数据源" :visible.sync="pullTimeDialogVisible" width="30%">
<el-checkbox-group v-model="sourceTime" style="width: 100%" class="pullTimeRadioGroup">
<el-checkbox :label="item.pullTime" border v-for="item in pullTimeOptions" :key="item.pullTime">
<div style="display: flex; justify-content: space-between">
{{item.pullTime}}
<span style="color: red">rows:{{item.num}}</span>
</div>
</el-checkbox>
</el-checkbox-group>
<span slot="footer" class="dialog-footer">
<el-button @click="pullTimeDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="doDeleteUser">确 定</el-button>
</span>
</el-dialog>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: "#app",
mixins: [initTableMixins],
data() {
return {
unitNameOptions: [],
userStateOptions: [],
preparedByOptions: [],
personTypeOptions: [],
pullTimeOptions: false,
sourceTime: [],
pullTimeDialogVisible: false,
pullLoading: false
}
},
methods: {
pull() {
this.$confirm("确定要拉取数据源吗?", "提示", {
type: "warning",
confirmButtonText: "确定",
cancelButtonText: "取消"
})
.then(() => {
this.pullLoading = true
this.$axios
.post("/platform/sys/data/user/pull/pullData")
.then((resp) => {
if (resp.code === 0) {
this.$message.success(resp.msg)
this.getPullTimeOptions()
this.doSearch()
}
})
.finally(() => {
this.pullLoading = false
})
})
.catch(() => {})
},
getSearchOptions() {
this.$axios.post("/platform/sys/data/user/pull/searchOptions").then((resp) => {
if (resp.code === 0) {
this.unitNameOptions = resp.data.unitNames
this.userStateOptions = resp.data.userStates
this.personTypeOptions = resp.data.personTypes
this.preparedByOptions = resp.data.preparedBys
}
})
},
getPullTimeOptions() {
this.$axios.post("/platform/sys/data/user/pull/pullTimeOptions").then((resp) => {
if (resp.code === 0) {
this.pullTimeOptions = resp.data
if (this.pullTimeOptions.length > 0) {
this.pageForm.pullTime = this.pullTimeOptions[0].pullTime
this.pageData()
} else {
this.tableData = []
this.pageForm.totalCount = 0
}
}
})
},
openDelete() {
this.pullTimeDialogVisible = true
this.getPullTimeOptions()
},
doDeleteUser() {
this.$confirm("确定要删除数据源吗?", "提示", {
type: "warning",
confirmButtonText: "确定",
cancelButtonText: "取消"
}).then(() => {
this.$axios
.post("/platform/sys/data/user/pull/deleteByPullTime", {
pullTime: JSON.stringify(this.sourceTime)
})
.then((resp) => {
if (resp.code === 0) {
this.$message.success(resp.msg)
this.pullTimeDialogVisible = false
this.doSearch()
}
})
})
}
},
created() {
// this.pageData()
this.getSearchOptions()
this.getPullTimeOptions()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,313 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.pullTimeRadioGroup .el-radio {
width: 100%;
margin-bottom: 10px;
}
.pullTimeRadioGroup .el-radio.is-bordered + .el-radio.is-bordered {
margin-left: 0;
}
.condition-builder {
border: 1px solid #dcdfe6;
border-radius: 4px;
padding: 10px;
margin-bottom: 10px;
}
</style>
<div id="app" v-cloak>
<guava ref="guava">
<template>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="姓名">
<el-input placeholder="请输入姓名" clearable v-model="pageForm.userName" style="width: 100%"></el-input>
</search-item>
<search-item label="工号">
<el-input placeholder="请输入工号" clearable v-model="pageForm.loginName" style="width: 100%"></el-input>
</search-item>
<search-item label="所属单位">
<el-select placeholder="请选择所属单位" v-model="pageForm.unitId" clearable style="width: 100%">
<el-option v-for="i in unitOptions" :label="i.name" :key="i.id" :value="i.id"></el-option>
</el-select>
</search-item>
<search-item label="在职状态">
<dict-select v-model="pageForm.userState" code="USER_STATE" style="width: 100%"></dict-select>
</search-item>
<search-item label="人员类型">
<dict-select v-model="pageForm.personType" code="USER_PERSON_TYPE" style="width: 100%"></dict-select>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool label="系统当前用户数据">
<!--<el-button type="primary" size="mini" @click="updateDataDict" icon="el-icon-refresh">更新【码表】数据</el-button>-->
<el-button type="primary" size="mini" @click="updateUnits" icon="el-icon-refresh">更新【单位】数据</el-button>
<el-button type="primary" size="mini" @click="openUpdate" icon="el-icon-refresh">更新【人员】数据</el-button>
</table-tool>
<el-table :key="tableKey" :data="tableData" @sort-change="pageOrder" header-align="center">
<el-table-column type="index" width="70" label="序号" fixed="left"></el-table-column>
<el-table-column prop="loginname" label="工号" width="100" fixed="left"></el-table-column>
<el-table-column prop="username" label="姓名" fixed="left" width="120" show-overflow-tooltip></el-table-column>
<el-table-column prop="changeTypes" label="变更类型" width="140">
<template slot-scope="{row}">
<span style="color: #0e78c5; cursor: pointer" @click="openCurrentUserChangeInfo(row)">
{{getChangeTypes(row.changeTypes)}}
</span>
</template>
</el-table-column>
<el-table-column prop="changeTime" label="变更时间" sortable width="150"></el-table-column>
<el-table-column prop="sex" label="性别" sortable></el-table-column>
<!-- <el-table-column prop="mobile" label="手机号" width="120"></el-table-column>-->
<el-table-column prop="birthday" label="生日" sortable width="120">
<template slot-scope="{row}">{{$moment(row.birthday).format('YYYY-MM-DD')}}</template>
</el-table-column>
<el-table-column prop="userState" label="在职状态" sortable width="120"></el-table-column>
<el-table-column prop="personType" label="人员类型" sortable width="120"></el-table-column>
<el-table-column prop="arrivalAtSchoolDate" label="来校年月" sortable width="120"></el-table-column>
<!--<el-table-column prop="technicalTitle" label="技术职称" sortable width="120"></el-table-column>
<el-table-column prop="position" label="职务" sortable width="120" show-overflow-tooltip></el-table-column>
<el-table-column prop="education" label="学历" show-overflow-tooltip sortable width="120"></el-table-column>
<el-table-column prop="academicDegree" label="学位" show-overflow-tooltip sortable width="120"></el-table-column>-->
<el-table-column prop="unitName" label="单位" show-overflow-tooltip sortable width="120"></el-table-column>
<el-table-column prop="unitId" label="单位编码" sortable width="120"></el-table-column>
<el-table-column prop="political" label="政治面貌" sortable></el-table-column>
<el-table-column prop="nation" label="民族" sortable></el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
<template #view>
<member-all-change-info ref="memberAllChangeInfoRef"></member-all-change-info>
</template>
</guava>
<el-dialog title="选择数据源" :visible.sync="updateDialog" width="70%">
<el-timeline>
<el-timeline-item timestamp="数据源" placement="top">
<el-radio-group v-model="updateFromData.pullTime" style="width: 100%" class="pullTimeRadioGroup">
<el-radio :label="item.pullTime" border v-for="item in pullTimeOptions" :key="item.pullTime">
<span>
{{item.pullTime}}
<span style="float: right; color: red">rows:{{item.num}}</span>
</span>
</el-radio>
</el-radio-group>
</el-timeline-item>
<el-timeline-item timestamp="更新方式" placement="top">
<el-radio-group class="checkGroup" style="width: 100%" v-model="updateFromData.updateMode" size="small">
<el-row>
<el-radio border label="ALL">全部更新</el-radio>
<el-radio border label="INCR">仅更新新增人员</el-radio>
</el-row>
</el-radio-group>
</el-timeline-item>
<el-timeline-item timestamp="高级条件筛选" placement="top">
<el-switch v-model="enableAdvancedConditions" active-text="启用高级条件"></el-switch>
<div v-if="enableAdvancedConditions" class="condition-builder">
<!-- 条件构建器组件 -->
<condition-group :group="updateFromData.conditionGroup" :field_options="fieldOptions" @remove="removeRootGroup"></condition-group>
</div>
</el-timeline-item>
</el-timeline>
<span slot="footer" class="dialog-footer">
<el-button @click="updateDialog = false" :disabled="updateLoading">取 消</el-button>
<el-button type="primary" @click="execUpdate" :disabled="updateLoading" :loading="updateLoading">确 定</el-button>
</span>
</el-dialog>
</div>
<script nonce="${cspNonce!}">
<!--#include("../../../zhgh/staffmanage/member/change/common/memberAllChangeInfo.js"){}#-->
new Vue({
el: "#app",
mixins: [initTableMixins],
data() {
return {
updateDialog: false,
pullTimeOptions: false,
updateFromData: {
pullTime: null,
updateMode: "ALL",
conditionGroup: {
logic: "AND",
conditions: [],
groups: []
}
},
updateLoading: false,
unitOptions: [],
changeTypeData: [],
enableAdvancedConditions: false,
// 可选字段列表
fieldOptions: [
{ label: "姓名", value: "username" },
{ label: "工号", value: "loginname" },
{ label: "性别", value: "sex" },
{ label: "生日", value: "birthday" },
{ label: "手机号", value: "mobile" },
{ label: "在职状态", value: "userState" },
{ label: "进站时间", value: "postDoctoralJoinDate" },
{ label: "人员类型", value: "personType" },
{ label: "来校年月", value: "arrivalAtSchoolDate" },
{ label: "单位", value: "unitName" },
{ label: "单位编码", value: "unitId" },
{ label: "学历", value: "education" },
{ label: "学位", value: "academicDegree" }
]
}
},
components: {
"member-all-change-info": MEMBER_ALL_CHANGE_INFO
},
methods: {
// 更新单位数据
updateUnits() {
this.$confirm("确定要更新单位数据吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/platform/sys/data/user/update/updateUnits")
.then((resp) => {
if (resp.code === 0) {
this.$message.success("更新成功")
} else {
this.$message.error(resp.msg)
}
})
})
},
// 更新码表数据
updateDataDict() {
this.$confirm("确定要更新码表数据吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/platform/sys/data/user/update/updateDataDict")
.then((resp) => {
if (resp.code === 0) {
this.$message.success("更新成功")
} else {
this.$message.error(resp.msg)
}
})
})
},
openCurrentUserChangeInfo(row) {
this.$refs.guava.view(() => {
this.$refs.memberAllChangeInfoRef.onOpen(row.id)
})
},
getChangeTypes(changeTypes) {
if (!changeTypes) return null
const changeTypesList = JSON.parse(changeTypes)
if (changeTypesList) {
if (!changeTypesList || changeTypesList.length === 0 || !this.changeTypeData || this.changeTypeData.length === 0) return null
return changeTypesList
.map((v) => {
return this.changeTypeData.find((item) => item.code === v).changeTypeName
})
.join(",")
}
return null
},
openUpdate() {
this.updateDialog = true
this.updateLoading = false
this.$nextTick(() => {
this.updateFromData = {
updateMode: "ALL",
pullTime: null,
conditionGroup: {
logic: "AND",
conditions: [],
groups: []
}
}
this.enableAdvancedConditions = false
})
},
getPullTimeOptions() {
this.$axios.post("/platform/sys/data/user/update/pullTimeOptions").then((resp) => {
if (resp.code === 0) {
this.pullTimeOptions = resp.data
}
})
},
execUpdate() {
if (!this.updateFromData.pullTime) {
this.$message.warning("请选择数据源时间")
return
}
if (!this.updateFromData.updateMode) {
this.$message.warning("请选择更新方式")
return
}
// 如果未启用高级条件,则移除条件组
if (!this.enableAdvancedConditions) {
this.updateFromData.conditionGroup = null
}
this.$confirm("确定要更新数据吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
this.updateLoading = true
this.$axios
.post("/platform/sys/data/user/update/updateUserFormSource", { param: JSON.stringify(this.updateFromData) })
.then((resp) => {
if (resp.code === 0) {
this.$message.success(resp.msg)
this.updateDialog = false
this.pageData()
}
})
.finally(() => {
this.updateLoading = false
})
})
},
listUnit() {
this.$businessTool.listUnit(this.pageForm.unionId).then((res) => {
this.unitOptions = res
})
},
removeRootGroup() {
// 重置根条件组
this.updateFromData.conditionGroup = {
logic: "AND",
conditions: [],
groups: []
}
}
},
async created() {
this.listUnit()
this.getPullTimeOptions()
this.pageData()
this.changeTypeData = await this.$businessTool.getEnumOptions("MemberChangeType")
}
})
</script>
<!--#
}
#-->