获取手机号
This commit is contained in:
@@ -69,11 +69,13 @@ const initTableMixins = {
|
||||
const address = this.pageDataUrl ? this.pageDataUrl : loc() + "/pageData"
|
||||
this.tableLoading = true
|
||||
this.$axios.post(address, data ? data : this.pageForm).then((res) => {
|
||||
this.tableLoading = false
|
||||
if (res.code === 0) {
|
||||
this.tableData = res.data.list
|
||||
this.pageForm.totalCount = res.data.totalCount
|
||||
}
|
||||
}).finally(() => {
|
||||
// 列表请求成功或失败后均关闭加载遮罩,避免异常时持续转圈。
|
||||
this.tableLoading = false
|
||||
})
|
||||
},
|
||||
notifySuccess(msg) {
|
||||
|
||||
@@ -63,7 +63,6 @@ layout("/layouts/platform.html"){
|
||||
<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="primary" size="mini" :loading="syncTeacherMobileLoading" @click="syncTeacherMobile" icon="el-icon-mobile-phone">同步教职工手机号</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">
|
||||
@@ -121,8 +120,7 @@ layout("/layouts/platform.html"){
|
||||
pullTimeOptions: false,
|
||||
sourceTime: [],
|
||||
pullTimeDialogVisible: false,
|
||||
pullLoading: false,
|
||||
syncTeacherMobileLoading: false
|
||||
pullLoading: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -150,42 +148,6 @@ layout("/layouts/platform.html"){
|
||||
.catch(() => {})
|
||||
},
|
||||
|
||||
syncTeacherMobile() {
|
||||
this.$confirm("确定要同步教职工手机号吗?", "提示", {
|
||||
type: "warning",
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消"
|
||||
})
|
||||
.then(() => {
|
||||
this.syncTeacherMobileLoading = true
|
||||
this.$axios
|
||||
.post("/platform/sys/data/user/pull/syncTeacherMobile")
|
||||
.then((resp) => {
|
||||
if (resp.code === 0) {
|
||||
const data = resp.data || {}
|
||||
this.$alert(
|
||||
"接口总数:" + (data.total || 0) +
|
||||
"<br>总页数:" + (data.pages || 0) +
|
||||
"<br>拉取数量:" + (data.pulledCount || 0) +
|
||||
"<br>有效手机号数量:" + (data.validMobileCount || 0) +
|
||||
"<br>匹配用户数量:" + (data.matchedUserCount || 0) +
|
||||
"<br>更新用户数量:" + (data.updatedUserCount || 0),
|
||||
"同步完成",
|
||||
{
|
||||
dangerouslyUseHTMLString: true,
|
||||
confirmButtonText: "确定"
|
||||
}
|
||||
)
|
||||
this.pageData()
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
this.syncTeacherMobileLoading = false
|
||||
})
|
||||
})
|
||||
.catch(() => {})
|
||||
},
|
||||
|
||||
getSearchOptions() {
|
||||
this.$axios.post("/platform/sys/data/user/pull/searchOptions").then((resp) => {
|
||||
if (resp.code === 0) {
|
||||
|
||||
@@ -51,10 +51,11 @@ layout("/layouts/platform.html"){
|
||||
<el-card shadow="never">
|
||||
<table-tool label="系统当前用户数据">
|
||||
<el-button type="primary" size="mini" @click="updateDataDict" icon="el-icon-refresh">更新【码表】数据</el-button>
|
||||
<el-button v-if="$auth.hasRoleOr(['SYSADMIN', 'SCHOOL_UNION_ADMIN'])" type="primary" size="mini" @click="openMobileSync" icon="el-icon-phone">拉取【手机号】</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 v-loading="tableLoading" :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>
|
||||
@@ -67,7 +68,8 @@ layout("/layouts/platform.html"){
|
||||
</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="mobile" label="手机号" width="130"></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>
|
||||
@@ -75,14 +77,8 @@ layout("/layouts/platform.html"){
|
||||
<el-table-column prop="preparedBy" 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="nationality" label="国籍" sortable></el-table-column>
|
||||
<el-table-column prop="nation" label="民族" sortable></el-table-column>
|
||||
</el-table>
|
||||
<!--#include("/layouts/pagination.html"){}#-->
|
||||
</el-card>
|
||||
@@ -129,6 +125,51 @@ layout("/layouts/platform.html"){
|
||||
<el-button type="primary" @click="execUpdate" :disabled="updateLoading">确 定</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
<el-dialog title="拉取手机号" :visible.sync="mobileDialog" width="680px" @closed="closeMobilePolling">
|
||||
<el-alert title="后台逐人拉取,会员优先。关闭弹框不停止任务;无号码结果七天内跳过。" type="info" :closable="false"></el-alert>
|
||||
<el-form label-width="110px" style="margin-top: 16px" :disabled="mobileRunning || formLoading">
|
||||
<el-form-item label="人员范围">
|
||||
<el-select v-model="mobileScope" @change="invalidateMobilePreview">
|
||||
<el-option label="全部系统人员" value="ALL"></el-option>
|
||||
<el-option label="仅会员" value="MEMBER"></el-option>
|
||||
<el-option label="当前筛选的全部结果" value="FILTER"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="拉取模式">
|
||||
<el-radio-group v-model="mobileMode" @change="invalidateMobilePreview">
|
||||
<el-radio label="FILL">只补手机号为空的人员</el-radio>
|
||||
<el-radio label="REFRESH">重新核对(含已有号码)</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button :loading="mobilePreviewLoading" @click="previewMobileSync">预览本次人数</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<p v-if="mobilePreview">
|
||||
范围 {{mobilePreview.scopeCount}} 人,已有号码 {{mobilePreview.existingCount}} 人,
|
||||
冷却跳过 {{mobilePreview.cooldownCount}} 人,本次待请求 {{mobilePreview.total}} 人(按工号去重)。
|
||||
</p>
|
||||
<p v-if="mobilePreview && mobilePreview.total">按每秒最多 1 次请求执行,实际耗时还取决于接口响应速度。</p>
|
||||
<div v-if="mobileTask.taskId" v-loading="mobileStatusLoading && !mobileTask.status">
|
||||
<el-divider>最近任务</el-divider>
|
||||
<p>{{mobileStatusLabel}} · {{mobileTask.message}}</p>
|
||||
<p>任务范围:{{mobileTask.scope === 'MEMBER' ? '仅会员' : (mobileTask.scope === 'FILTER' ? '筛选结果' : '全部系统人员')}};
|
||||
模式:{{mobileTask.mode === 'REFRESH' ? '重新核对' : '只补空号'}}</p>
|
||||
<el-progress :percentage="mobileProgress"></el-progress>
|
||||
<p>已处理 {{mobileTask.processed || 0}} / {{mobileTask.total || 0}};
|
||||
已更新 {{mobileTask.updated || 0}};无号码 {{mobileTask.empty || 0}};
|
||||
失败 {{mobileTask.failed || 0}};跳过或未变更 {{mobileTask.skipped || 0}}。</p>
|
||||
<p v-if="!mobileRunning">任务与续传记录保留七天。继续任务会先处理剩余人员,再重试原失败项。</p>
|
||||
</div>
|
||||
<span slot="footer">
|
||||
<el-button @click="closeMobileSync">关闭</el-button>
|
||||
<el-button v-if="mobileRunning" type="warning" :loading="formLoading" @click="stopMobileSync">停止任务</el-button>
|
||||
<el-button v-if="!mobileRunning && mobileTask.taskId && mobileTask.processed < mobileTask.total" :loading="formLoading" @click="startMobileSync('RESUME')">继续任务</el-button>
|
||||
<el-button v-if="!mobileRunning && mobileTask.failed > 0" :loading="formLoading" @click="startMobileSync('RETRY')">仅重试失败项</el-button>
|
||||
<el-button type="primary" :loading="formLoading" :disabled="mobileRunning || mobileStatusLoading || mobilePreviewLoading || !mobilePreview || !mobilePreview.total" @click="startMobileSync('NEW')">开始拉取</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
@@ -139,6 +180,17 @@ layout("/layouts/platform.html"){
|
||||
mixins: [initTableMixins],
|
||||
data() {
|
||||
return {
|
||||
mobileDialog: false,
|
||||
mobileScope: "ALL",
|
||||
mobileMode: "FILL",
|
||||
mobileFilters: {},
|
||||
mobilePreview: null,
|
||||
mobilePreviewVersion: 0,
|
||||
mobilePreviewLoading: false,
|
||||
mobileStatusLoading: false,
|
||||
mobileTask: {},
|
||||
mobilePollTimer: null,
|
||||
mobileDisposed: false,
|
||||
updateDialog: false,
|
||||
pullTimeOptions: false,
|
||||
updateFromData: {
|
||||
@@ -176,7 +228,114 @@ layout("/layouts/platform.html"){
|
||||
components: {
|
||||
"member-all-change-info": MEMBER_ALL_CHANGE_INFO
|
||||
},
|
||||
computed: {
|
||||
mobileRunning() { return this.mobileTask.status === "RUNNING" },
|
||||
mobileProgress() {
|
||||
return this.mobileTask.total ? Math.min(100, Math.floor((this.mobileTask.processed || 0) * 100 / this.mobileTask.total)) : 0
|
||||
},
|
||||
mobileStatusLabel() {
|
||||
const labels = { RUNNING: "执行中", STOPPED: "已停止", PAUSED: "已暂停", INTERRUPTED: "已中断", COMPLETED: "已完成" }
|
||||
return labels[this.mobileTask.status] || "读取中"
|
||||
}
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.mobileDisposed = true
|
||||
this.closeMobilePolling()
|
||||
},
|
||||
methods: {
|
||||
// 打开时固定本次列表筛选条件;只读取进度,外部手机号请求必须由开始按钮触发。
|
||||
openMobileSync() {
|
||||
this.mobileFilters = Object.assign({}, this.pageForm)
|
||||
this.mobileDialog = true
|
||||
this.invalidateMobilePreview()
|
||||
this.loadMobileStatus()
|
||||
},
|
||||
invalidateMobilePreview() {
|
||||
this.mobilePreviewVersion++
|
||||
this.mobilePreview = null
|
||||
},
|
||||
// scope为ALL/MEMBER/FILTER,mode为FILL/REFRESH;筛选参数只参与FILTER,不传分页含义。
|
||||
mobileParams() {
|
||||
return Object.assign({}, this.mobileFilters, { scope: this.mobileScope, mode: this.mobileMode })
|
||||
},
|
||||
previewMobileSync() {
|
||||
if (this.mobilePreviewLoading) return
|
||||
const version = ++this.mobilePreviewVersion
|
||||
this.mobilePreview = null
|
||||
this.mobilePreviewLoading = true
|
||||
this.$axios.post("/platform/sys/data/user/update/mobilePreview", this.mobileParams())
|
||||
.then((res) => {
|
||||
// 选项改变后不显示旧请求的预览,避免按旧人数开始新范围任务。
|
||||
if (res.code === 0 && version === this.mobilePreviewVersion) this.mobilePreview = res.data
|
||||
})
|
||||
.catch(() => { this.$message.error("预览失败,请稍后重试") })
|
||||
.finally(() => { this.mobilePreviewLoading = false })
|
||||
},
|
||||
// NEW使用预览范围;RESUME/RETRY由后端按sourceTaskId恢复原任务范围及模式,不能被当前选项替换。
|
||||
startMobileSync(action) {
|
||||
if (this.formLoading || this.mobileRunning) return
|
||||
const params = Object.assign(this.mobileParams(), { action: action, sourceTaskId: this.mobileTask.taskId || "" })
|
||||
const refresh = action === "NEW" ? this.mobileMode === "REFRESH" : this.mobileTask.mode === "REFRESH"
|
||||
const message = refresh ? "本次会核对并更新已有手机号,确定开始吗?" : "确定在后台拉取手机号吗?"
|
||||
this.$confirm(message, "提示", { type: "warning" }).then(() => {
|
||||
this.formLoading = true
|
||||
return this.$axios.post("/platform/sys/data/user/update/mobileStart", params)
|
||||
.then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.mobileTask = res.data || {}
|
||||
this.invalidateMobilePreview()
|
||||
this.$message.success("任务已提交,可关闭弹框稍后查看")
|
||||
}
|
||||
})
|
||||
.catch(() => { this.$message.error("启动未成功,请查看最新任务状态") })
|
||||
.finally(() => {
|
||||
this.formLoading = false
|
||||
this.loadMobileStatus()
|
||||
})
|
||||
}).catch(() => {})
|
||||
},
|
||||
loadMobileStatus() {
|
||||
if (this.mobileStatusLoading || this.mobileDisposed || !this.mobileDialog) return
|
||||
this.closeMobilePolling()
|
||||
this.mobileStatusLoading = true
|
||||
this.$axios.post("/platform/sys/data/user/update/mobileStatus", {})
|
||||
.then((res) => {
|
||||
if (res.code === 0) {
|
||||
const wasRunning = this.mobileRunning
|
||||
this.mobileTask = res.data || {}
|
||||
if (wasRunning && !this.mobileRunning) this.pageData()
|
||||
}
|
||||
})
|
||||
.catch(() => { this.$message.error("读取任务进度失败,将稍后重试") })
|
||||
.finally(() => {
|
||||
this.mobileStatusLoading = false
|
||||
// 使用单次计时器串行轮询;弹框关闭或页面销毁后不再注册,避免重复绑定与泄漏。
|
||||
if (this.mobileDialog && !this.mobileDisposed) {
|
||||
this.mobilePollTimer = setTimeout(() => { this.loadMobileStatus() }, 3000)
|
||||
}
|
||||
})
|
||||
},
|
||||
stopMobileSync() {
|
||||
if (this.formLoading) return
|
||||
this.formLoading = true
|
||||
this.$axios.post("/platform/sys/data/user/update/mobileStop", { taskId: this.mobileTask.taskId })
|
||||
.then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.mobileTask = res.data || {}
|
||||
this.$message.success("停止请求已提交,等待当前工号处理结束")
|
||||
}
|
||||
})
|
||||
.catch(() => { this.$message.error("停止请求失败,请稍后重试") })
|
||||
.finally(() => { this.formLoading = false })
|
||||
},
|
||||
closeMobilePolling() {
|
||||
if (this.mobilePollTimer) clearTimeout(this.mobilePollTimer)
|
||||
this.mobilePollTimer = null
|
||||
},
|
||||
closeMobileSync() {
|
||||
this.$set(this, "mobileDialog", false)
|
||||
this.closeMobilePolling()
|
||||
},
|
||||
// 更新单位数据
|
||||
updateUnits() {
|
||||
this.$confirm("确定要更新单位数据吗?", "提示", {
|
||||
|
||||
@@ -20,14 +20,6 @@ layout("/layouts/platform.html"){
|
||||
>
|
||||
备份历史会员
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="$auth.hasRoleOr(['SYSADMIN','SCHOOL_UNION_ADMIN'])"
|
||||
type="primary"
|
||||
size="small"
|
||||
icon="el-icon-mobile-phone"
|
||||
:loading="syncMobileLoading"
|
||||
@click="syncMobile"
|
||||
>获取手机号</el-button>
|
||||
<el-button type="primary" size="small" icon="el-icon-download" @click="exportMember">会员档案导出</el-button>
|
||||
<el-popover
|
||||
placement="bottom"
|
||||
@@ -157,8 +149,7 @@ layout("/layouts/platform.html"){
|
||||
],
|
||||
checkedFields: [],
|
||||
|
||||
importDialog: false,
|
||||
syncMobileLoading: false
|
||||
importDialog: false
|
||||
}
|
||||
},
|
||||
components: {
|
||||
@@ -189,39 +180,6 @@ layout("/layouts/platform.html"){
|
||||
openArchive() {
|
||||
this.$refs.archiveMemberRef.archiveDialogVisible = true
|
||||
},
|
||||
syncMobile() {
|
||||
this.$confirm("将从手机号为空的会员中随机取500人获取手机号,确定继续吗?", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(() => {
|
||||
this.syncMobileLoading = true
|
||||
this.$axios.post(loc() + "/syncMobile").then((res) => {
|
||||
if (res.code === 0) {
|
||||
const data = res.data || {}
|
||||
const failedJobNos = data.failedJobNos || []
|
||||
this.$alert(
|
||||
"抽取人数:" + (data.sampleCount || 0) +
|
||||
"<br>请求人数:" + (data.requestUserCount || 0) +
|
||||
"<br>接口返回数量:" + (data.pulledCount || 0) +
|
||||
"<br>有效手机号数量:" + (data.validMobileCount || 0) +
|
||||
"<br>系统用户更新数量:" + (data.updatedUserCount || 0) +
|
||||
"<br>失败工号数量:" + failedJobNos.length,
|
||||
"手机号获取完成",
|
||||
{
|
||||
dangerouslyUseHTMLString: true,
|
||||
confirmButtonText: "确定"
|
||||
}
|
||||
)
|
||||
this.pageData()
|
||||
} else {
|
||||
this.$message.warning(res.msg || "手机号获取失败")
|
||||
}
|
||||
}).finally(() => {
|
||||
this.syncMobileLoading = false
|
||||
})
|
||||
}).catch(() => {})
|
||||
},
|
||||
openView(userId) {
|
||||
this.$refs.guava.view(() => {
|
||||
this.$refs.infoRef.onOpen(userId)
|
||||
|
||||
Reference in New Issue
Block a user