123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295 |
- <template>
- <el-select
- v-loading.fullscreen="companyChangeLoading"
- :element-loading-text="'正在切换至 ' + getUserCompany().name + ' ......'"
- element-loading-background="rgba(0, 0, 0, 0.8)"
- element-loading-spinner="el-icon-loading"
- :value="value ? value : currentCompany"
- :remote-method="handleRemoteSearch"
- :placeholder="placeholder"
- style="width:380px"
- :disabled="disabled"
- reserve-keyword
- :size="size"
- filterable
- remote
- @change="setCurrentCompany"
- >
- <!-- 当selectAll为true 且为超管账号允许选择所有公司 -->
- <el-option v-if="selectAll && isSupertube" label="所有公司" value />
- <el-option
- v-for="(company, index) in companylist"
- :key="index"
- class="custom-company"
- :label="company.code + ' / ' + company.name"
- :value="company.code"
- />
- <p v-if="state.loading" class="company-loading">
- <i class="el-icon-loading" />
- 加载中...
- </p>
- <p v-if="state.noMore" class="company-more">没有更多数据了...</p>
- </el-select>
- </template>
- <script>
- import { mapState } from 'vuex'
- import { convertCompanylist } from '@/utils'
- import { requsetSupertubeCompany, requsetUserBindingCompany } from '@/apis/user'
- import { isBusinessCompany, isOnlyBusinessCompanyPath } from './utils'
- import { getUserCompany } from '@/utils/auth'
- export default {
- /**
- * @param placeholder
- * @param size 选择器尺寸
- * @param disabled 是否禁用
- * @param selectAll 超管账号是否可以选择所有公司
- * @param global 是否设置全局选中公司(全局使用/组件独立使用)
- */
- props: {
- selectAll: {
- type: Boolean,
- default: false
- },
- size: {
- type: String,
- default: 'small'
- },
- placeholder: {
- type: String,
- default: ''
- },
- disabled: {
- type: Boolean,
- default: false
- },
- global: {
- type: Boolean,
- default: false
- },
- value: {
- type: String,
- default: ''
- }
- },
- computed: {
- ...mapState({
- currentCompany: state => state.user.currentCompany,
- companylist: state => state.user.companylist,
- isSupertube: state => state.user.isSupertube
- })
- },
- data() {
- return {
- ScrollWrapper: null,
- initialization: true,
- companyChangeLoading: false,
- state: {
- loading: false,
- noMore: false
- },
- params: {
- name: '',
- page: 2,
- size: 10
- }
- }
- },
- async mounted() {
- this.initalData()
- this.ScrollWrapper = await this.getScrollWrapper()
- this.ScrollWrapper && this.bindEvent(this.ScrollWrapper)
- },
- beforeDetoryed() {
- this.ScrollWrapper && this.removeEvent(this.ScrollWrapper)
- },
- methods: {
- getUserCompany,
- async initalData() {
- // 区分是否超管用户请求不同接口
- this.state.loading = true
- const api = this.isSupertube ? requsetSupertubeCompany : requsetUserBindingCompany
- const { page, size, name } = this.params
- const params = {
- [this.isSupertube ? 'name' : 'companyName']: name,
- page,
- size
- }
- const { code, data } = await api(params)
- if (code === 0) {
- if (data.list.length < 10) this.state.noMore = true
- this.state.loading = false
- this.params.page++
- const _list = this.isSupertube ? data.list : convertCompanylist(data.list)
- this.$store.commit('user/setCompanylist', [...this.companylist, ..._list])
- return this.isSupertube ? data.list : convertCompanylist(data.list)
- }
- },
- setCurrentCompany(currentCompany) {
- this.$emit('update:value', currentCompany)
- this.$emit('change', currentCompany)
- if (!this.global) return null // 作为通用组件使用不设置全局选中公司
- // 只能选择业务公司的页面
- const path = this.$route.path
- if (isOnlyBusinessCompanyPath(path) && !isBusinessCompany(currentCompany)) {
- this.$message.warning('该页面只能选择业务公司')
- return
- }
- this.$store.commit('user/setCurrentCompany', currentCompany)
- if (this.isSupertube) return null // 超管用户不刷新路由
- this.changeRouterWithCompany()
- },
- async changeRouterWithCompany() {
- const { path, query } = this.$route
- query.redirect = path
- const keys = Object.keys(query).filter(key => key && key !== 'error')
- // 1.保存透传参数
- let queryString = ''
- const chunk = (qs, key, index) => {
- const next = `${key}=${query[key]}${index === keys.length ? '' : '&'}`
- return qs + next
- }
- // 2.重新获取用户信息和菜单
- this.companyChangeLoading = true
- const result = await this.$store.dispatch('user/reloadMenulist')
- this.companyChangeLoading = false
- switch (result) {
- /**
- * 登出
- */
- case 'noToken':
- await this.$store.dispatch('user/logout')
- this.$router.push(`/login`)
- break
- /**
- * 角色异常或该公司禁用,清空菜单返回首页
- */
- case 'disabled':
- this.$store.dispatch('user/disabledCompany')
- break
- /**
- * 切换路由
- */
- default:
- queryString = keys.reduce(chunk, '?')
- this.$router.replace('/reload' + queryString)
- break
- }
- },
- getScrollWrapper() {
- return new Promise(resolve => {
- setTimeout(() => {
- let optionEl = document.querySelector('.custom-company')
- if (optionEl && (optionEl = optionEl.parentElement)) {
- resolve(optionEl.parentElement)
- return
- }
- resolve(null)
- }, 500)
- })
- },
- async handleScroll() {
- const ScrollWrapper = this.ScrollWrapper
- const height = ScrollWrapper.clientHeight
- const scrollTop = ScrollWrapper.scrollTop
- const scrollHeight = ScrollWrapper.scrollHeight
- const { loading, noMore } = this.state
- // 是否允许下拉加载
- const isAllowLoad = !loading && !noMore
- if (height + scrollTop >= scrollHeight && isAllowLoad) {
- const list = await this.loadMore()
- // 保存到全局
- this.$store.commit('user/setCompanylist', [...this.companylist, ...(this.isSupertube ? list : convertCompanylist(list))])
- }
- },
- async loadMore() {
- // 区分超管用户和普通用户
- const api = this.isSupertube ? requsetSupertubeCompany : requsetUserBindingCompany
- this.state.loading = true
- const { page, size, name } = this.params
- const nameProp = this.isSupertube ? 'name' : 'companyName'
- const params = {
- [nameProp]: name,
- page,
- size
- }
- const { data } = await api(params)
- this.state.loading = false
- const isTransboundary = this.companylist.length >= Number(data.count) // 是否越界
- if (isTransboundary) {
- this.state.noMore = true
- this.sate.loading = false
- return []
- }
- this.params.page++
- return data.list
- },
- async handleRemoteSearch(name) {
- // 清空全局业务公司列表
- this.$store.commit('user/setCompanylist', [])
- this.params.name = name
- this.params.page = 1
- this.state.noMore = false
- this.state.loading = false
- // 获取列表数据
- const result = await this.initalData()
- if (result) this.$store.commit('user/setCompanylist', result)
- },
- bindEvent(ScrollWrapper) {
- ScrollWrapper.addEventListener('scroll', this.handleScroll)
- },
- removeEvent(ScrollWrapper) {
- ScrollWrapper.removeEventListener('scroll', this.handleScroll)
- }
- }
- }
- </script>
- <style lang="scss" scoped>
- .company-more {
- text-align: center;
- color: #999;
- font-size: 14px;
- line-height: 38px;
- }
- .company-loading {
- display: flex;
- font-size: 14px;
- justify-content: center;
- align-items: center;
- color: #999;
- gap: 10px;
- line-height: 38px;
- }
- </style>
|