DepartSelect.vue 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. <template>
  2. <BasicModal v-bind="config" :maxHeight="500" :title="currTitle" v-model:visible="visible" wrapClassName="loginSelectModal">
  3. <a-form ref="formRef" v-bind="layout" :colon="false" class="loginSelectForm">
  4. <a-form-item v-if="isMultiTenant" :validate-status="validate_status">
  5. <!--label内容-->
  6. <template #label>
  7. <a-tooltip placement="topLeft">
  8. <template #title>
  9. <span>您隶属于多租户,请选择当前所属租户</span>
  10. </template>
  11. <a-avatar style="background-color: #87d068" :size="30"> 租户 </a-avatar>
  12. </a-tooltip>
  13. </template>
  14. <!--部门下拉内容-->
  15. <a-select v-model:value="tenantSelected" placeholder="请选择登录部门" :class="{ 'valid-error': validate_status == 'error' }">
  16. <template #suffixIcon>
  17. <Icon icon="ant-design:gold-outline" />
  18. </template>
  19. <template v-for="tenant in tenantList" :key="tenant.id">
  20. <a-select-option :value="tenant.id">{{ tenant.name }}</a-select-option>
  21. </template>
  22. </a-select>
  23. </a-form-item>
  24. <a-form-item v-if="isMultiDepart" :validate-status="validate_status1">
  25. <!--label内容-->
  26. <template #label>
  27. <a-tooltip placement="topLeft">
  28. <template #title>
  29. <span>您隶属于多部门,请选择当前所在部门</span>
  30. </template>
  31. <a-avatar style="background-color: rgb(104, 208, 203)" :size="30"> 部门 </a-avatar>
  32. </a-tooltip>
  33. </template>
  34. <!--部门下拉内容-->
  35. <a-select v-model:value="departSelected" placeholder="请选择登录部门" :class="{ 'valid-error': validate_status1 == 'error' }">
  36. <template #suffixIcon>
  37. <Icon icon="ant-design:gold-outline" />
  38. </template>
  39. <template v-for="depart in departList" :key="depart.orgCode">
  40. <a-select-option :value="depart.orgCode">{{ depart.departName }}</a-select-option>
  41. </template>
  42. </a-select>
  43. </a-form-item>
  44. </a-form>
  45. <template #footer>
  46. <a-button @click="close">关闭</a-button>
  47. <a-button @click="handleSubmit" type="primary">确认</a-button>
  48. </template>
  49. </BasicModal>
  50. </template>
  51. <script lang="ts" setup>
  52. import { ref, computed, watch, unref } from 'vue';
  53. import { Avatar } from 'ant-design-vue';
  54. import { BasicModal } from '/@/components/Modal';
  55. import { getUserDeparts, selectDepart } from '/@/views/system/depart/depart.api';
  56. import { getUserTenants } from '/@/views/system/tenant/tenant.api';
  57. import { useMessage } from '/@/hooks/web/useMessage';
  58. import { useUserStore } from '/@/store/modules/user';
  59. const userStore = useUserStore();
  60. const { createMessage, notification } = useMessage();
  61. const props = defineProps({
  62. title: { type: String, default: '部门选择' },
  63. closable: { type: Boolean, default: false },
  64. username: { type: String, default: '' },
  65. });
  66. const layout = {
  67. labelCol: { span: 4 },
  68. wrapperCol: { span: 18 },
  69. };
  70. const config = {
  71. maskClosable: false,
  72. closable: false,
  73. canFullscreen: false,
  74. width: '500px',
  75. minHeight: 20,
  76. maxHeight: 20,
  77. };
  78. const currTitle = ref('');
  79. const isMultiTenant = ref(false);
  80. const currentTenantName = ref('');
  81. const tenantSelected = ref();
  82. const tenantList = ref([]);
  83. const validate_status = ref('');
  84. const isMultiDepart = ref(false);
  85. const currentDepartName = ref('');
  86. const departSelected = ref('');
  87. const departList = ref([]);
  88. const validate_status1 = ref('');
  89. //弹窗显隐
  90. const visible = ref(false);
  91. /**
  92. * 弹窗打开前处理
  93. */
  94. async function show() {
  95. //加载部门
  96. await loadDepartList();
  97. //加载租户
  98. await loadTenantList();
  99. //标题配置
  100. if (unref(isMultiTenant) && unref(isMultiDepart)) {
  101. currTitle.value = '切换租户和部门';
  102. } else if (unref(isMultiTenant)) {
  103. currTitle.value =
  104. unref(currentTenantName) && unref(currentTenantName).length > 0 ? `租户切换(当前租户 :${unref(currentTenantName)})` : props.title;
  105. } else if (unref(isMultiDepart)) {
  106. currTitle.value =
  107. unref(currentDepartName) && unref(currentDepartName).length > 0 ? `部门切换(当前部门 :${unref(currentDepartName)})` : props.title;
  108. }
  109. //model显隐
  110. if (unref(isMultiTenant) || unref(isMultiDepart)) {
  111. visible.value = true;
  112. }
  113. }
  114. /**
  115. *加载部门信息
  116. */
  117. async function loadDepartList() {
  118. const result = await getUserDeparts();
  119. if (!result.list || result.list.length == 0) {
  120. return;
  121. }
  122. let currentDepart = result.list.filter((item) => item.orgCode == result.orgCode);
  123. departList.value = result.list;
  124. departSelected.value = currentDepart && currentDepart.length > 0 ? result.orgCode : '';
  125. currentDepartName.value = currentDepart && currentDepart.length > 0 ? currentDepart[0].departName : '';
  126. isMultiDepart.value = true;
  127. }
  128. /**
  129. *加载租户信息
  130. */
  131. async function loadTenantList() {
  132. const result = await getUserTenants();
  133. if (!result.list || result.list.length == 0) {
  134. return;
  135. }
  136. let tenantId = userStore.getTenant;
  137. let currentTenant = result.list.filter((item) => item.id == tenantId);
  138. currentTenantName.value = currentTenant && currentTenant.length > 0 ? currentTenant[0].name : '';
  139. tenantList.value = result.list;
  140. tenantSelected.value = tenantId;
  141. isMultiTenant.value = true;
  142. }
  143. /**
  144. * 提交数据
  145. */
  146. async function handleSubmit() {
  147. if (unref(isMultiTenant) && unref(tenantSelected) == null) {
  148. validate_status.value = 'error';
  149. return false;
  150. }
  151. if (unref(isMultiDepart) && !unref(departSelected)) {
  152. validate_status1.value = 'error';
  153. return false;
  154. }
  155. departResolve()
  156. .then(() => {
  157. if (unref(isMultiTenant)) {
  158. userStore.setTenant(unref(tenantSelected));
  159. }
  160. createMessage.success('切换成功');
  161. //切换租户后要刷新首页
  162. window.location.reload();
  163. })
  164. .catch((e) => {
  165. console.log('登录选择出现问题', e);
  166. })
  167. .finally(() => {
  168. if (unref(isMultiTenant)) {
  169. userStore.setTenant(unref(tenantSelected));
  170. }
  171. close();
  172. });
  173. }
  174. /**
  175. *切换选择部门
  176. */
  177. function departResolve() {
  178. return new Promise(async (resolve, reject) => {
  179. if (!unref(isMultiDepart)) {
  180. resolve();
  181. } else {
  182. const result = await selectDepart({
  183. username: userStore.getUserInfo.username,
  184. orgCode: unref(departSelected),
  185. loginTenantId: unref(tenantSelected),
  186. });
  187. if (result.userInfo) {
  188. const userInfo = result.userInfo;
  189. userStore.setUserInfo(userInfo);
  190. resolve();
  191. } else {
  192. requestFailed(result);
  193. userStore.logout();
  194. reject();
  195. }
  196. }
  197. });
  198. }
  199. /**
  200. * 请求失败处理
  201. */
  202. function requestFailed(err) {
  203. notification.error({
  204. message: '登录失败',
  205. description: ((err.response || {}).data || {}).message || err.message || '请求出现错误,请稍后再试',
  206. duration: 4,
  207. });
  208. }
  209. /**
  210. * 关闭model
  211. */
  212. function close() {
  213. departClear();
  214. }
  215. /**
  216. *初始化数据
  217. */
  218. function departClear() {
  219. currTitle.value = '';
  220. isMultiTenant.value = false;
  221. currentTenantName.value = '';
  222. tenantSelected.value = '';
  223. tenantList.value = [];
  224. validate_status.value = '';
  225. isMultiDepart.value = false;
  226. currentDepartName.value = '';
  227. departSelected.value = '';
  228. departList.value = [];
  229. validate_status1.value = '';
  230. visible.value = false;
  231. }
  232. /**
  233. * 监听username
  234. */
  235. watch(
  236. () => props.username,
  237. (value) => {
  238. value && loadDepartList();
  239. }
  240. );
  241. defineExpose({
  242. show,
  243. });
  244. </script>
  245. <style lang="less" scoped>
  246. .loginSelectForm {
  247. margin-bottom: -20px;
  248. }
  249. .loginSelectModal {
  250. top: 20px;
  251. }
  252. .valid-error .ant-select-selection__placeholder {
  253. color: #f5222d;
  254. }
  255. </style>