feat:部门选择

This commit is contained in:
houjunxiang
2025-11-26 18:11:13 +08:00
parent 96cc747150
commit fcc04865f9
15 changed files with 344 additions and 83 deletions

View File

@@ -0,0 +1,196 @@
<template>
<view v-if="dialogStore.show" class="company-dept-dialog">
<view class="company-dept-dialog__mask" @tap="handleCancel" />
<view class="company-dept-dialog__panel">
<view class="company-dept-dialog__header">
<text class="company-dept-dialog__title">{{ dialogStore.title }}</text>
</view>
<view class="company-dept-dialog__body">
<!-- 公司选择 -->
<view class="company-dept-dialog__field">
<text class="company-dept-dialog__label">公司</text>
<uni-data-select
v-model="selectedCompanyModel"
:localdata="companyOptionsForSelect"
collection=""
field="companyName"
orderby=""
:clear-icon="false"
@change="onCompanyChangeUni"
/>
</view>
<!-- 部门选择 -->
<view class="company-dept-dialog__field">
<text class="company-dept-dialog__label">部门</text>
<uni-data-select
v-model="selectedDeptModel"
:localdata="deptOptionsForSelect"
collection=""
field="deptName"
orderby=""
:clear-icon="false"
@change="onDeptChangeUni"
/>
</view>
</view>
<view class="company-dept-dialog__footer">
<u-button @tap="handleCancel">取消</u-button>
<u-button type="primary" :disabled="!isConfirmEnabled" @tap="handleConfirm"> 确定 </u-button>
</view>
</view>
</view>
</template>
<script setup>
import { computed, ref, watch } from 'vue'
import { storeToRefs } from 'pinia'
import nx from '@/nx'
const dialogStore = nx.$store('company-dept')
const { companyList, selectedCompanyId, selectedDeptId } = storeToRefs(dialogStore)
const deptOptions = computed(() => dialogStore.getDeptsByCompanyId(selectedCompanyModel.value))
// 用于 uni-data-select 的格式:必须包含 value 和 text 字段
const companyOptionsForSelect = computed(() =>
companyList.value.map(item => ({
value: item.companyId,
text: item.companyName
}))
)
const deptOptionsForSelect = computed(() =>
deptOptions.value.map(item => ({
value: item.deptId,
text: item.deptName
}))
)
// 双向绑定模型uni-data-select 使用 value 绑定)
const selectedCompanyModel = ref(selectedCompanyId.value)
const selectedDeptModel = ref(selectedDeptId.value)
// 监听 store 变化,同步到 model应对外部触发更新
watch(
() => selectedCompanyId.value,
newVal => {
if (newVal !== selectedCompanyModel.value) {
selectedCompanyModel.value = newVal
}
}
)
watch(
() => selectedDeptId.value,
newVal => {
if (newVal !== selectedDeptModel.value) {
selectedDeptModel.value = newVal
}
}
)
// uni-data-select 的 change 回调
const onCompanyChangeUni = e => {
const companyId = e
if (companyId !== undefined && companyId !== null) {
dialogStore.setSelectedCompany(companyId)
// 重置部门选择
dialogStore.setSelectedDept('')
selectedDeptModel.value = ''
}
}
const onDeptChangeUni = e => {
const deptId = e
if (deptId !== undefined && deptId !== null) {
dialogStore.setSelectedDept(deptId)
}
}
// 按钮状态
const isConfirmEnabled = computed(() => !!dialogStore.selectedCompanyId && !!dialogStore.selectedDeptId)
// 操作
const handleCancel = () => {
dialogStore.cancel()
}
const handleConfirm = () => {
if (!isConfirmEnabled.value) return
dialogStore.confirm()
}
</script>
<style scoped lang="scss">
.company-dept-dialog {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: 15000;
display: flex;
align-items: center;
justify-content: center;
&__mask {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.45);
}
&__panel {
position: relative;
width: 45vw;
background: #ffffff;
border-radius: 12px;
padding: 24px 20px 16px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.18);
}
@media (max-width: 700px) {
&__panel {
width: 70vw;
}
}
&__header {
margin-bottom: 20px;
}
&__title {
display: block;
font-size: 18px;
font-weight: 600;
color: #1f1f1f;
text-align: center;
line-height: 1.4;
}
&__body {
display: flex;
flex-direction: column;
gap: 16px;
}
&__field {
display: flex;
flex-direction: column;
gap: 8px;
}
&__label {
font-size: 14px;
color: #606266;
}
&__footer {
display: flex;
justify-content: space-between;
gap: 12px;
margin-top: 24px;
}
}
</style>