197 lines
4.5 KiB
Vue
197 lines
4.5 KiB
Vue
<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>
|