123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335 |
- <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="!global ? value : currentCompany"
- :remote-method="isSupertube ? handleRemoteSearch : undefined"
- :placeholder="placeholder"
- style="width:380px"
- :disabled="disabled"
- :clearable="clearable"
- reserve-keyword
- :size="size"
- filterable
- remote
- @change="setCurrentCompany"
- >
- <!-- 当selectAll为true 且为超管账号允许选择所有公司 -->
- <el-option v-if="selectAll && isSupertube" class="custom-company" :label="allCompanyLabel" value="" />
- <el-option
- v-for="(company, index) in companylist"
- :key="index"
- class="custom-company"
- :label="genCompanyLabel(company)"
- :value="company.code"
- />
- <p v-if="state.loading" class="company-loading">
- <i class="el-icon-loading" />
- 加载中...
- </p>
- <p v-if="state.noMore || !isSupertube" class="company-more">没有更多数据了...</p>
- </el-select>
- </template>
- <script>
- import { requsetSupertubeCompany, requsetUserBindingCompany } from '@/apis/user'
- import { isBusinessCompany, isOnlyBusinessCompanyPath } from './utils'
- import { userStoreActions } from '@/store/modules/user'
- import { accountLevels } from '@/assets/js/statusList'
- import { getUserCompany } from '@/utils/auth'
- import { convertCompanylist } from '@/utils'
- import { mapGetters, mapState } from 'vuex'
- 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: ''
- },
- isSupplier: {
- type: Boolean,
- default: false
- },
- noCompanyCode: {
- type: String,
- default: () => false
- },
- clearable: {
- type: Boolean,
- default: () => false
- }
- },
- computed: {
- allCompanyLabel() { return this.currentLevel === accountLevels.supplier ? '所有供应商' : '所有业务公司' },
- ...mapGetters(['currentLevel']),
- ...mapState({
- currentCompany: state => state.user.currentCompany,
- companylist: state => state.user.companylist,
- isSupertube: state => state.user.isSupertube,
- originLevel: state => state.user.originLevel
- })
- },
- data: () => ({
- ScrollWrapper: null,
- initialization: true,
- companyChangeLoading: false,
- key: 1,
- state: {
- loading: false,
- noMore: false
- },
- params: {
- name: '',
- page: 2,
- size: 10
- }
- }),
- watch: {
- currentLevel: {
- handler() {
- if (!this.isSupertube) return
- this.params = {
- name: '',
- page: 1,
- size: 10
- }
- this.state = {
- loading: false,
- noMore: false
- }
- this.initalData()
- }
- }
- },
- async mounted() {
- this.isSupertube && await this.initalData()
- this.ScrollWrapper = await this.getScrollWrapper()
- this.ScrollWrapper && this.bindEvent(this.ScrollWrapper)
- },
- beforeDestroy() {
- this.ScrollWrapper && this.removeEvent(this.ScrollWrapper)
- },
- methods: {
- getUserCompany,
- genCompanyLabel(company) {
- const { name, code } = company
- if (this.noCompanyCode) return name
- return `${code}/${name}`
- },
- async initalData() {
- // 区分是否超管用户请求不同接口
- this.state.loading = true
- const api = this.isSupertube || this.isSupplier ? requsetSupertubeCompany : requsetUserBindingCompany
- const isSupplier = this.currentLevel === accountLevels.supplier
- const { page, size, name } = this.params
- const params = {
- ...(this.isSupertube ? { type: isSupplier ? '3' : '1' } : {}),
- [this.isSupertube ? 'name' : 'companyName']: name,
- page,
- size
- }
- const { data } = await api(params)
- 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)
- // const __list = this.isSupertube && this.currentLevel === '1' ? _list.map(item => ({ ...item, code: item.relation_code })) : _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
- if (isOnlyBusinessCompanyPath(path) && !isBusinessCompany(currentCompany)) {
- this.$message.warning('该页面只能选择业务公司')
- return
- }
- if (!currentCompany) { // 选择所有公司重置选项
- this.handleRemoteSearch()
- }
- this.$store.commit(userStoreActions.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.保存透传参数
- // 1.2 是否详情页
- const isDetailPath = path.indexOf('Detail') >= 0
- 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(userStoreActions.reloadMenu)
- this.companyChangeLoading = false
- switch (result) {
- case 'noToken': // 登出
- await this.$store.dispatch('user/logout')
- await this.$router.push(`/login`)
- break
- case 'disabled': // 角色异常或该公司禁用清空菜单返回首页
- await this.$store.dispatch('user/disabledCompany')
- break
- default: // 切换路由
- queryString = isDetailPath ? this.parsePathDetail2List(path) : keys.reduce(chunk, '?')
- await this.$router.replace('/reload' + queryString)
- break
- }
- },
- parsePathDetail2List(path) {
- const chunks = path.split('Detail')
- return `?redirect=${chunks[0]}`
- },
- 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()
- const _list = this.isSupertube ? list : convertCompanylist(list)
- // const __list = this.isSupertube && this.currentLevel === '1' ? _list.map(item => ({ ...item, code: item.relation_code })) : _list
- // 保存到全局
- this.$store.commit(userStoreActions.setCompanyList, [...this.companylist, ..._list])
- }
- },
- async loadMore() {
- // 区分超管用户和普通用户
- const api = this.isSupertube ? requsetSupertubeCompany : requsetUserBindingCompany
- const isSupplier = this.currentLevel === accountLevels.supplier
- 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.isSupertube ? { type: isSupplier ? '3' : '1' } : {})
- })
- this.state.loading = false
- const isTransborder = this.companylist.length >= Number(data.count) // 是否越界
- if (isTransborder) {
- this.state.noMore = true
- this.state.loading = false
- return []
- }
- this.params.page++
- return data.list
- },
- async handleRemoteSearch(name) {
- // 清空全局业务公司列表
- this.$store.commit(userStoreActions.setCompanyList, [])
- this.params.name = name
- this.params.page = 1
- this.state.noMore = false
- this.state.loading = false
- // 获取列表数据
- const result = await this.initalData()
- // const list = this.isSupertube && this.currentLevel === '1' ? result.map(item => ({ ...item, code: item.relation_code })) : result
- if (result) this.$store.commit(userStoreActions.setCompanyList, result)
- },
- selectAllCompany() {
- this.value = ''
- this.$nextTick(() => (this.key = this.key + 1))
- this.global && this.$store.commit(userStoreActions.setCurrentCompany, '')
- },
- bindEvent(ScrollWrapper) { this.isSupertube && ScrollWrapper.addEventListener('scroll', this.handleScroll) },
- removeEvent(ScrollWrapper) { this.isSupertube && 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>
|