feat(purchase): 履约验收人员选择改为el-select下拉+远程搜索

1. 采购人员和资产管理员改为el-select组件,支持remote远程搜索
2. 搜索时调用后端接口模糊匹配教职工姓名或工号
3. 下拉选项显示格式为 姓名 (工号)
This commit is contained in:
吴红兵
2026-03-04 10:28:32 +08:00
parent 1abc557699
commit 501af39a14
2 changed files with 127 additions and 25 deletions

View File

@@ -225,6 +225,28 @@ export function getDeptMembers() {
}); });
} }
/**
* 获取二级部门列表(供履约验收选择部门用)
*/
export function getSecondDeptList() {
return request({
url: '/purchase/purchasingapply/getSecondDeptList',
method: 'get'
});
}
/**
* 搜索教职工(供履约验收选择人员用)
* @param keyword 搜索关键字(姓名/工号)
*/
export function searchTeachers(keyword: string) {
return request({
url: '/purchase/purchasingapply/searchTeachers',
method: 'get',
params: { keyword }
});
}
/** /**
* 保存采购代表(指定单人或部门多人) * 保存采购代表(指定单人或部门多人)
* @param id 采购申请ID * @param id 采购申请ID

View File

@@ -64,12 +64,54 @@
</el-col> </el-col>
<el-col :span="8" class="mb20"> <el-col :span="8" class="mb20">
<el-form-item label="采购人员" prop="purchaserId"> <el-form-item label="采购人员" prop="purchaserId">
<org-selector v-model:orgList="purchaserList" type="user" :multiple="false" @update:orgList="onPurchaserChange" /> <el-select
v-model="form.purchaserId"
placeholder="请输入姓名或工号搜索"
filterable
remote
clearable
reserve-keyword
:remote-method="searchPurchaser"
:loading="purchaserLoading"
style="width: 100%"
@change="onPurchaserChange"
>
<el-option
v-for="item in purchaserOptions"
:key="item.teacherNo"
:label="item.name + ' (' + item.teacherNo + ')'"
:value="item.teacherNo"
>
<span>{{ item.name }}</span>
<span style="color: #999; font-size: 12px; margin-left: 8px;">{{ item.teacherNo }}</span>
</el-option>
</el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="8" class="mb20"> <el-col :span="8" class="mb20">
<el-form-item label="资产管理员" prop="assetAdminId"> <el-form-item label="资产管理员" prop="assetAdminId">
<org-selector v-model:orgList="assetAdminList" type="user" :multiple="false" @update:orgList="onAssetAdminChange" /> <el-select
v-model="form.assetAdminId"
placeholder="请输入姓名或工号搜索"
filterable
remote
clearable
reserve-keyword
:remote-method="searchAssetAdmin"
:loading="assetAdminLoading"
style="width: 100%"
@change="onAssetAdminChange"
>
<el-option
v-for="item in assetAdminOptions"
:key="item.teacherNo"
:label="item.name + ' (' + item.teacherNo + ')'"
:value="item.teacherNo"
>
<span>{{ item.name }}</span>
<span style="color: #999; font-size: 12px; margin-left: 8px;">{{ item.teacherNo }}</span>
</el-option>
</el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="8" class="mb20" v-if="form.hasContract === '0'"> <el-col :span="8" class="mb20" v-if="form.hasContract === '0'">
@@ -90,7 +132,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, watch, onMounted } from 'vue' import { ref, reactive, watch, onMounted } from 'vue'
import type { FormInstance, FormRules } from 'element-plus' import type { FormInstance, FormRules } from 'element-plus'
import { getContracts } from '/@/api/purchase/purchasingrequisition' import { getContracts, searchTeachers } from '/@/api/purchase/purchasingrequisition'
const props = defineProps<{ const props = defineProps<{
modelValue: Record<string, any> modelValue: Record<string, any>
@@ -108,8 +150,14 @@ const formRef = ref<FormInstance>()
const contractOptions = ref<any[]>([]) const contractOptions = ref<any[]>([])
const contractLoading = ref(false) const contractLoading = ref(false)
const contractLoaded = ref(false) const contractLoaded = ref(false)
const purchaserList = ref<any[]>([])
const assetAdminList = ref<any[]>([]) // 采购人员相关
const purchaserOptions = ref<any[]>([])
const purchaserLoading = ref(false)
// 资产管理员相关
const assetAdminOptions = ref<any[]>([])
const assetAdminLoading = ref(false)
const form = reactive({ const form = reactive({
hasContract: '0', hasContract: '0',
@@ -130,16 +178,12 @@ const form = reactive({
const syncFormFromModel = (val: Record<string, any> | undefined) => { const syncFormFromModel = (val: Record<string, any> | undefined) => {
Object.assign(form, val || {}) Object.assign(form, val || {})
// 同步采购人员、资产管理员回 org-selector // 加载已选人员信息用于回显
if (form.purchaserId && form.purchaserName) { if (form.purchaserId && form.purchaserName) {
purchaserList.value = [{ id: form.purchaserId, name: form.purchaserName, type: 'user' }] purchaserOptions.value = [{ teacherNo: form.purchaserId, name: form.purchaserName }]
} else {
purchaserList.value = []
} }
if (form.assetAdminId && form.assetAdminName) { if (form.assetAdminId && form.assetAdminName) {
assetAdminList.value = [{ id: form.assetAdminId, name: form.assetAdminName, type: 'user' }] assetAdminOptions.value = [{ teacherNo: form.assetAdminId, name: form.assetAdminName }]
} else {
assetAdminList.value = []
} }
} }
@@ -164,6 +208,38 @@ const loadContractOptions = async () => {
} }
} }
const searchPurchaser = async (query: string) => {
if (!query) {
purchaserOptions.value = []
return
}
purchaserLoading.value = true
try {
const res = await searchTeachers(query)
purchaserOptions.value = res?.data || []
} catch (_) {
purchaserOptions.value = []
} finally {
purchaserLoading.value = false
}
}
const searchAssetAdmin = async (query: string) => {
if (!query) {
assetAdminOptions.value = []
return
}
assetAdminLoading.value = true
try {
const res = await searchTeachers(query)
assetAdminOptions.value = res?.data || []
} catch (_) {
assetAdminOptions.value = []
} finally {
assetAdminLoading.value = false
}
}
const onContractSelectVisibleChange = (visible: boolean) => { const onContractSelectVisibleChange = (visible: boolean) => {
if (visible && form.hasContract === '1' && contractOptions.value.length === 0) { if (visible && form.hasContract === '1' && contractOptions.value.length === 0) {
loadContractOptions() loadContractOptions()
@@ -174,7 +250,7 @@ watch(
() => props.modelValue, () => props.modelValue,
(val) => { (val) => {
syncFormFromModel(val) syncFormFromModel(val)
// 回显已有合同ID时主动加载合同列表以便下拉显示合同名称后端已排除其他申请的合同,当前申请合同会在列表中) // 回显已有合同ID时主动加载合同列表以便下拉显示合同名称后端已排除"其他申请"的合同,当前申请合同会在列表中)
if (form.hasContract === '1' && form.contractId && props.purchaseId && !contractLoaded.value && !contractLoading.value) { if (form.hasContract === '1' && form.contractId && props.purchaseId && !contractLoaded.value && !contractLoading.value) {
loadContractOptions() loadContractOptions()
} }
@@ -220,25 +296,29 @@ onMounted(() => {
} }
}) })
const onPurchaserChange = (list: any[]) => { const onPurchaserChange = (teacherNo: string) => {
if (list?.length) { if (!teacherNo) {
const u = list[0]
form.purchaserId = u.userId || u.id || ''
form.purchaserName = u.name || u.realName || ''
} else {
form.purchaserId = '' form.purchaserId = ''
form.purchaserName = '' form.purchaserName = ''
return
}
const selected = purchaserOptions.value.find((item: any) => item.teacherNo === teacherNo)
if (selected) {
form.purchaserId = selected.teacherNo
form.purchaserName = selected.name
} }
} }
const onAssetAdminChange = (list: any[]) => { const onAssetAdminChange = (teacherNo: string) => {
if (list?.length) { if (!teacherNo) {
const u = list[0]
form.assetAdminId = u.userId || u.id || ''
form.assetAdminName = u.name || u.realName || ''
} else {
form.assetAdminId = '' form.assetAdminId = ''
form.assetAdminName = '' form.assetAdminName = ''
return
}
const selected = assetAdminOptions.value.find((item: any) => item.teacherNo === teacherNo)
if (selected) {
form.assetAdminId = selected.teacherNo
form.assetAdminName = selected.name
} }
} }