主要改动: - SQL: biz_support_unit → biz_org, 加 org_type, 加 business_nature; 删 biz_execution_unit, biz_service_org - SQL: biz_project.support_unit_id/name + service_org_id/name → org_id/name/type - SQL: biz_meeting.support_unit_name → org_name - SQL: biz_person.work_unit → org_id (FK) - 后端: 新 BizOrg entity/mapper/service/controller - 后端: BizProject/BizMeeting 字段重命名 - 后端: 删 12 个 BizSupportUnit/BizExecutionUnit/BizServiceOrg Java 文件 - 后端: BizPersonImportVO.workUnit → orgName (导入时查 biz_org 取 org_id) - 后端: BizAuthController.registerExecutor 完整实现 (原 registerSupplier stub) - 前端: 新 admin/Orgs.vue + manager/Orgs.vue (原 SupportUnits) - 前端: RegisterExecutor.vue (原 RegisterSupplier, 单页 2 步) - 前端: sponsor/executor/manager 多个文件 workUnit → orgId/orgName 重命名 - 前端: 统一 supplier → executor, 业务命名 sponsor(赞助方) / executor(执行方=供应商) - 前端: 全工程 execution → executor (company type / role / person unit_type)
92 lines
2.7 KiB
Vue
92 lines
2.7 KiB
Vue
<template>
|
|
<el-select
|
|
v-model="selected"
|
|
:placeholder="placeholder"
|
|
:disabled="disabled"
|
|
:clearable="clearable"
|
|
:filterable="filterable"
|
|
:multiple="multiple"
|
|
:loading="loading"
|
|
class="dict-select"
|
|
@change="handleChange"
|
|
>
|
|
<el-option
|
|
v-for="opt in options"
|
|
:key="opt.value"
|
|
:label="opt.label"
|
|
:value="valueField === 'label' ? opt.label : opt.value"
|
|
:disabled="opt.disabled"
|
|
/>
|
|
</el-select>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, watch, onMounted } from 'vue'
|
|
import { getActiveDict, DICT_TYPE } from '@/api/dict'
|
|
|
|
/**
|
|
* 公共字典下拉控件
|
|
* v-model 默认绑定 value (deptId/titleId), 也可改为绑定 label (name 字符串)
|
|
*
|
|
* 用法 1 (绑 ID):
|
|
* <dict-select v-model="form.deptId" dict-type="department" />
|
|
* <dict-select v-model="form.titleId" dict-type="title" :value-field="'value'" />
|
|
*
|
|
* 用法 2 (绑 name 字符串, 兼容旧业务字段如 form.department="内科"):
|
|
* <dict-select v-model="form.department" dict-type="department" :value-field="'label'" />
|
|
*
|
|
* 事件:
|
|
* @change(value, option) option.raw 含完整字段 (sort/status/...)
|
|
*/
|
|
const props = defineProps({
|
|
modelValue: { type: [String, Number, Array], default: null },
|
|
/** 字典类型, 必须从 DICT_TYPE 取 */
|
|
dictType: { type: String, required: true, validator: v => Object.values(DICT_TYPE).includes(v) },
|
|
/** v-model 绑的字段: 'value' (ID) 或 'label' (name 字符串) */
|
|
valueField: { type: String, default: 'value' },
|
|
placeholder: { type: String, default: '请选择' },
|
|
disabled: { type: Boolean, default: false },
|
|
clearable: { type: Boolean, default: true },
|
|
filterable: { type: Boolean, default: false },
|
|
multiple: { type: Boolean, default: false }
|
|
})
|
|
|
|
const emit = defineEmits(['update:modelValue', 'change'])
|
|
|
|
const options = ref([])
|
|
const loading = ref(false)
|
|
const selected = ref(props.modelValue ?? (props.multiple ? [] : null))
|
|
|
|
watch(() => props.modelValue, v => {
|
|
selected.value = v ?? (props.multiple ? [] : null)
|
|
})
|
|
|
|
async function load() {
|
|
loading.value = true
|
|
try {
|
|
options.value = await getActiveDict(props.dictType)
|
|
} catch (e) {
|
|
console.warn(`[DictSelect ${props.dictType}] load failed`, e)
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
function handleChange(val) {
|
|
selected.value = val
|
|
const opt = Array.isArray(val)
|
|
? options.value.filter(o => val.includes(props.valueField === 'label' ? o.label : o.value))
|
|
: options.value.find(o => (props.valueField === 'label' ? o.label : o.value) === val)
|
|
emit('update:modelValue', val)
|
|
emit('change', val, opt)
|
|
}
|
|
|
|
onMounted(load)
|
|
|
|
// 字典类型变化时重拉 (如动态切换)
|
|
watch(() => props.dictType, load)
|
|
</script>
|
|
|
|
<style scoped>
|
|
.dict-select { width: 100%; }
|
|
</style> |