Files
zgty-mas-m/components/company-dept-dialog/company-dept-dialog.vue
2025-11-26 18:11:13 +08:00

197 lines
4.5 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<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>