优化列表
This commit is contained in:
@@ -30,3 +30,13 @@ export function deleteLbAssessmentApply(id) {
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
/** 大模型解析申请评估文本为实体(不落库),请求可能较慢 */
|
||||
export function parseAssessmentApplyFromText(data) {
|
||||
return request({
|
||||
url: '/lbAssessmentApply/parseAssessmentApplyFromText',
|
||||
method: 'post',
|
||||
data,
|
||||
timeout: 120000
|
||||
})
|
||||
}
|
||||
|
||||
72
src/directive/dialog-drag/index.js
Normal file
72
src/directive/dialog-drag/index.js
Normal file
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* Element UI el-dialog:按住标题栏可拖拽移动
|
||||
* 使用:<el-dialog v-dialog-drag ...>
|
||||
*/
|
||||
import Vue from 'vue'
|
||||
|
||||
function bindDrag(el) {
|
||||
const header = el.querySelector('.el-dialog__header')
|
||||
const dialog = el.querySelector('.el-dialog')
|
||||
if (!header || !dialog) return
|
||||
|
||||
header.style.cursor = 'move'
|
||||
header.style.userSelect = 'none'
|
||||
|
||||
const onMouseDown = (e) => {
|
||||
if (e.button !== 0) return
|
||||
if (e.target.closest('.el-dialog__headerbtn')) return
|
||||
|
||||
const rect = dialog.getBoundingClientRect()
|
||||
const offsetX = e.clientX - rect.left
|
||||
const offsetY = e.clientY - rect.top
|
||||
const sty = dialog.style
|
||||
sty.margin = '0'
|
||||
sty.position = 'fixed'
|
||||
sty.left = `${rect.left}px`
|
||||
sty.top = `${rect.top}px`
|
||||
|
||||
const onMouseMove = (e2) => {
|
||||
const w = dialog.offsetWidth
|
||||
const h = dialog.offsetHeight
|
||||
const maxL = Math.max(0, document.documentElement.clientWidth - w)
|
||||
const maxT = Math.max(0, document.documentElement.clientHeight - h)
|
||||
let left = e2.clientX - offsetX
|
||||
let top = e2.clientY - offsetY
|
||||
if (left < 0) left = 0
|
||||
if (left > maxL) left = maxL
|
||||
if (top < 0) top = 0
|
||||
if (top > maxT) top = maxT
|
||||
sty.left = `${left}px`
|
||||
sty.top = `${top}px`
|
||||
}
|
||||
|
||||
const onMouseUp = () => {
|
||||
document.removeEventListener('mousemove', onMouseMove)
|
||||
document.removeEventListener('mouseup', onMouseUp)
|
||||
}
|
||||
|
||||
document.addEventListener('mousemove', onMouseMove)
|
||||
document.addEventListener('mouseup', onMouseUp)
|
||||
e.preventDefault()
|
||||
}
|
||||
|
||||
header.addEventListener('mousedown', onMouseDown)
|
||||
return () => header.removeEventListener('mousedown', onMouseDown)
|
||||
}
|
||||
|
||||
export default {
|
||||
inserted(el) {
|
||||
Vue.nextTick(() => {
|
||||
if (typeof el._dialogDragUnbind === 'function') {
|
||||
el._dialogDragUnbind()
|
||||
}
|
||||
el._dialogDragUnbind = bindDrag(el)
|
||||
})
|
||||
},
|
||||
unbind(el) {
|
||||
if (typeof el._dialogDragUnbind === 'function') {
|
||||
el._dialogDragUnbind()
|
||||
delete el._dialogDragUnbind
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,9 @@ import router from './router'
|
||||
|
||||
import '@/icons' // icon
|
||||
import '@/permission' // permission control
|
||||
import dialogDrag from '@/directive/dialog-drag'
|
||||
|
||||
Vue.directive('dialog-drag', dialogDrag)
|
||||
|
||||
/**
|
||||
* If you don't want to use mock-server
|
||||
|
||||
@@ -27,29 +27,26 @@
|
||||
|
||||
<el-card class="table-container" shadow="never">
|
||||
<el-table v-loading="loading" :data="list" style="width: 100%">
|
||||
<el-table-column label="申请人" prop="applicantName" min-width="120" />
|
||||
<el-table-column label="申请人电话" prop="applicantPhone" min-width="140" />
|
||||
<el-table-column label="年龄" prop="applicantAge" min-width="80" />
|
||||
<el-table-column label="从业经历" prop="workExperience" min-width="180" show-overflow-tooltip />
|
||||
<el-table-column label="同事姓名" prop="colleagueName" min-width="120" />
|
||||
<el-table-column label="同事电话" prop="colleaguePhone" min-width="140" />
|
||||
<el-table-column label="团队长姓名" prop="teamLeaderName" min-width="130" />
|
||||
<el-table-column label="申请时间" prop="applicationDatetime" min-width="170">
|
||||
<el-table-column label="申请人姓名" prop="applicantName" min-width="108" />
|
||||
<el-table-column label="申请人电话" prop="applicantPhone" min-width="126" />
|
||||
<el-table-column label="同事姓名" prop="colleagueName" min-width="108" />
|
||||
<el-table-column label="同事电话" prop="colleaguePhone" min-width="126" />
|
||||
<el-table-column label="团长姓名" prop="teamLeaderName" min-width="117" />
|
||||
<el-table-column label="双收益团队长" prop="teamBigLeaderName" min-width="94" />
|
||||
<el-table-column label="申请日期时间" prop="applicationDatetime" min-width="153">
|
||||
<template slot-scope="scope">
|
||||
{{ formatDateTime(scope.row.applicationDatetime) }}
|
||||
{{ formatDateTime(scope.row.applicationDatetime, false) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间" prop="createdAt" min-width="170">
|
||||
<el-table-column label="评估老师" prop="assessmentTeacherName" min-width="108" />
|
||||
<el-table-column label="主持人" prop="moderatorName" min-width="108" />
|
||||
<el-table-column label="会议号" prop="meetingNumber" min-width="126" />
|
||||
<el-table-column label="创建时间" prop="createdAt" min-width="153">
|
||||
<template slot-scope="scope">
|
||||
{{ formatDateTime(scope.row.createdAt) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="更新时间" prop="updatedAt" min-width="170">
|
||||
<template slot-scope="scope">
|
||||
{{ formatDateTime(scope.row.updatedAt) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" fixed="right" width="140">
|
||||
<el-table-column label="操作" fixed="right" width="126">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" @click="handleEdit(scope.row)">编辑</el-button>
|
||||
<el-button type="text" style="color:#F56C6C;" @click="handleDelete(scope.row)">删除</el-button>
|
||||
@@ -68,8 +65,23 @@
|
||||
/>
|
||||
</el-card>
|
||||
|
||||
<el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="760px" @close="resetForm">
|
||||
<el-dialog v-dialog-drag :title="dialogTitle" :visible.sync="dialogVisible" width="760px" @close="resetForm">
|
||||
<el-form ref="dataForm" :model="form" :rules="formRules" label-width="120px">
|
||||
<template v-if="!isEdit">
|
||||
<el-form-item label="申请评估文本">
|
||||
<el-input
|
||||
v-model="assessmentApplyText"
|
||||
type="textarea"
|
||||
:rows="7"
|
||||
placeholder="请输入评估申请的自然语言描述,点击下方「AI解析」自动填充下方表单"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label=" ">
|
||||
<el-button type="primary" plain :loading="parseAiLoading" @click="handleParseFromAssessmentText">
|
||||
AI解析
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</template>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="申请人" prop="applicantName">
|
||||
@@ -124,6 +136,57 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="评估老师" prop="assessmentTeacherName">
|
||||
<el-select
|
||||
v-model="form.assessmentTeacherName"
|
||||
clearable
|
||||
filterable
|
||||
placeholder="请选择评估老师"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in assessmentTeacherOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="主持人" prop="moderatorName">
|
||||
<el-select
|
||||
v-model="form.moderatorName"
|
||||
clearable
|
||||
filterable
|
||||
placeholder="请选择主持人"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in moderatorOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="腾讯会议号" prop="meetingNumber">
|
||||
<el-input
|
||||
v-model="form.meetingNumber"
|
||||
clearable
|
||||
placeholder="请输入腾讯会议号"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-form-item label="从业经历" prop="workExperience">
|
||||
<el-input
|
||||
v-model="form.workExperience"
|
||||
@@ -146,8 +209,10 @@ import {
|
||||
addLbAssessmentApply,
|
||||
deleteLbAssessmentApply,
|
||||
getLbAssessmentApplyList,
|
||||
parseAssessmentApplyFromText,
|
||||
updateLbAssessmentApply
|
||||
} from '@/api/lb-assessment-apply'
|
||||
import { getBusinessHeaders } from '@/utils/business-headers'
|
||||
|
||||
export default {
|
||||
name: 'LbAssessmentApply',
|
||||
@@ -155,11 +220,33 @@ export default {
|
||||
return {
|
||||
loading: false,
|
||||
submitLoading: false,
|
||||
parseAiLoading: false,
|
||||
assessmentApplyText: '',
|
||||
list: [],
|
||||
total: 0,
|
||||
dialogVisible: false,
|
||||
dialogTitle: '',
|
||||
isEdit: false,
|
||||
moderatorOptions: [
|
||||
{ label: '胡东梅老师', value: '胡东梅老师' },
|
||||
{ label: '张增利老师', value: '张增利老师' },
|
||||
{ label: '陈泽章老师', value: '陈泽章老师' },
|
||||
{ label: '覃淑恒老师', value: '覃淑恒老师' },
|
||||
{ label: '刘连超老师', value: '刘连超老师' },
|
||||
{ label: '刘兰心老师', value: '刘兰心老师' },
|
||||
{ label: '李海民老师', value: '李海民老师' },
|
||||
{ label: '闫丽娜老师', value: '闫丽娜老师' },
|
||||
{ label: '张凌峰老师', value: '张凌峰老师' },
|
||||
{ label: '张宝凤老师', value: '张宝凤老师' }
|
||||
],
|
||||
assessmentTeacherOptions: [
|
||||
{ label: '张健老师', value: '张健老师' },
|
||||
{ label: '秦理想老师', value: '秦理想老师' },
|
||||
{ label: '刘兰兰老师', value: '刘兰兰老师' },
|
||||
{ label: '张 锋老师', value: '张 锋老师' },
|
||||
{ label: '汪伟乐老师', value: '汪伟乐老师' },
|
||||
{ label: '李 佳老师', value: '李 佳老师' }
|
||||
],
|
||||
queryParams: {
|
||||
current: 1,
|
||||
size: 10,
|
||||
@@ -177,7 +264,10 @@ export default {
|
||||
colleagueName: '',
|
||||
colleaguePhone: '',
|
||||
teamLeaderName: '',
|
||||
applicationDatetime: ''
|
||||
applicationDatetime: '',
|
||||
moderatorName: '',
|
||||
assessmentTeacherName: '',
|
||||
meetingNumber: ''
|
||||
},
|
||||
formRules: {
|
||||
applicantName: [{ required: true, message: '请输入申请人', trigger: 'blur' }],
|
||||
@@ -189,6 +279,75 @@ export default {
|
||||
this.fetchList()
|
||||
},
|
||||
methods: {
|
||||
getTenantIdFromBusinessHeaders() {
|
||||
const headers = getBusinessHeaders()
|
||||
const value = headers && headers['X-Tenant-Id']
|
||||
return value ? String(value).trim() : ''
|
||||
},
|
||||
handleParseFromAssessmentText() {
|
||||
const text = (this.assessmentApplyText || '').trim()
|
||||
if (!text) {
|
||||
this.$message.warning('请先填写申请评估文本')
|
||||
return
|
||||
}
|
||||
const tenantId = this.getTenantIdFromBusinessHeaders()
|
||||
if (!tenantId) {
|
||||
this.$message.error('未获取到租户ID,请先登录或配置业务请求头中的租户')
|
||||
return
|
||||
}
|
||||
this.parseAiLoading = true
|
||||
parseAssessmentApplyFromText({ assessmentText: text, tenantId })
|
||||
.then((res) => {
|
||||
const payload = res && typeof res === 'object' ? res : {}
|
||||
const entity = payload.data !== undefined && payload.data !== null && typeof payload.data === 'object'
|
||||
? payload.data
|
||||
: payload
|
||||
this.applyParsedEntityToForm(entity)
|
||||
this.$message.success((payload.message) || '解析成功,已填入表单')
|
||||
})
|
||||
.finally(() => {
|
||||
this.parseAiLoading = false
|
||||
})
|
||||
},
|
||||
normalizeApplicationDatetimeValue(v) {
|
||||
if (v == null || v === '') return ''
|
||||
const s = String(v).replace('T', ' ')
|
||||
return s.length >= 19 ? s.slice(0, 19) : s
|
||||
},
|
||||
applyParsedEntityToForm(entity) {
|
||||
if (!entity || typeof entity !== 'object') return
|
||||
const keys = [
|
||||
'applicantName',
|
||||
'applicantPhone',
|
||||
'applicantAge',
|
||||
'workExperience',
|
||||
'colleagueName',
|
||||
'colleaguePhone',
|
||||
'teamLeaderName',
|
||||
'applicationDatetime',
|
||||
'moderatorName',
|
||||
'assessmentTeacherName',
|
||||
'meetingNumber'
|
||||
]
|
||||
keys.forEach((k) => {
|
||||
const v = entity[k]
|
||||
if (v === undefined || v === null) return
|
||||
if (k === 'applicantAge') {
|
||||
if (v === '') {
|
||||
this.form.applicantAge = undefined
|
||||
return
|
||||
}
|
||||
const n = Number(v)
|
||||
this.form.applicantAge = Number.isNaN(n) ? undefined : n
|
||||
return
|
||||
}
|
||||
if (k === 'applicationDatetime') {
|
||||
this.form.applicationDatetime = this.normalizeApplicationDatetimeValue(v)
|
||||
return
|
||||
}
|
||||
this.form[k] = v
|
||||
})
|
||||
},
|
||||
fetchList() {
|
||||
this.loading = true
|
||||
getLbAssessmentApplyList(this.buildListParams())
|
||||
@@ -260,6 +419,7 @@ export default {
|
||||
handleEdit(row) {
|
||||
this.dialogTitle = '编辑评估申请'
|
||||
this.isEdit = true
|
||||
this.assessmentApplyText = ''
|
||||
this.form = {
|
||||
id: row.id || '',
|
||||
applicantName: row.applicantName || '',
|
||||
@@ -269,7 +429,10 @@ export default {
|
||||
colleagueName: row.colleagueName || '',
|
||||
colleaguePhone: row.colleaguePhone || '',
|
||||
teamLeaderName: row.teamLeaderName || '',
|
||||
applicationDatetime: row.applicationDatetime || ''
|
||||
applicationDatetime: row.applicationDatetime || '',
|
||||
moderatorName: row.moderatorName || '',
|
||||
assessmentTeacherName: row.assessmentTeacherName || '',
|
||||
meetingNumber: row.meetingNumber || ''
|
||||
}
|
||||
this.dialogVisible = true
|
||||
this.$nextTick(() => {
|
||||
@@ -312,7 +475,10 @@ export default {
|
||||
colleagueName: this.form.colleagueName || undefined,
|
||||
colleaguePhone: this.form.colleaguePhone || undefined,
|
||||
teamLeaderName: this.form.teamLeaderName || undefined,
|
||||
applicationDatetime: this.form.applicationDatetime || undefined
|
||||
applicationDatetime: this.form.applicationDatetime || undefined,
|
||||
moderatorName: this.form.moderatorName || undefined,
|
||||
assessmentTeacherName: this.form.assessmentTeacherName || undefined,
|
||||
meetingNumber: this.form.meetingNumber || undefined
|
||||
}
|
||||
if (this.isEdit) payload.id = this.form.id
|
||||
Object.keys(payload).forEach((key) => {
|
||||
@@ -325,6 +491,7 @@ export default {
|
||||
this.resetFormData()
|
||||
},
|
||||
resetFormData() {
|
||||
this.assessmentApplyText = ''
|
||||
this.form = {
|
||||
id: '',
|
||||
applicantName: '',
|
||||
@@ -334,10 +501,13 @@ export default {
|
||||
colleagueName: '',
|
||||
colleaguePhone: '',
|
||||
teamLeaderName: '',
|
||||
applicationDatetime: ''
|
||||
applicationDatetime: '',
|
||||
moderatorName: '',
|
||||
assessmentTeacherName: '',
|
||||
meetingNumber: ''
|
||||
}
|
||||
},
|
||||
formatDateTime(dateTime) {
|
||||
formatDateTime(dateTime, withSeconds = true) {
|
||||
if (!dateTime) return '-'
|
||||
const date = new Date(String(dateTime).replace('T', ' '))
|
||||
if (Number.isNaN(date.getTime())) return String(dateTime)
|
||||
@@ -346,6 +516,9 @@ export default {
|
||||
const day = String(date.getDate()).padStart(2, '0')
|
||||
const hours = String(date.getHours()).padStart(2, '0')
|
||||
const minutes = String(date.getMinutes()).padStart(2, '0')
|
||||
if (!withSeconds) {
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}`
|
||||
}
|
||||
const seconds = String(date.getSeconds()).padStart(2, '0')
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
|
||||
}
|
||||
|
||||
@@ -46,13 +46,13 @@
|
||||
<el-table v-loading="loading" :data="list" style="width: 100%">
|
||||
<el-table-column label="用户ID" prop="userId" min-width="140" show-overflow-tooltip />
|
||||
<el-table-column label="姓名" prop="name" min-width="120" />
|
||||
<el-table-column label="上级ID" prop="parentId" min-width="140" show-overflow-tooltip />
|
||||
<el-table-column label="电话" prop="phone" min-width="120" />
|
||||
<el-table-column label="上级ID" prop="parentId" min-width="140" show-overflow-tooltip />
|
||||
<el-table-column label="上级姓名" min-width="120" show-overflow-tooltip>
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.parentName || scope.row.parentUserName || '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="电话" prop="phone" min-width="120" />
|
||||
<el-table-column label="地址" prop="address" min-width="160" show-overflow-tooltip />
|
||||
<el-table-column label="行业" prop="industry" min-width="120" />
|
||||
<el-table-column label="加入日期" prop="joinDate" min-width="120" />
|
||||
|
||||
Reference in New Issue
Block a user