You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

400 lines
8.5 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<u-popup v-model="showPopup" mode="bottom" :mask-close-able="false" :border-radius="20">
<view class="company-selector">
<!-- 标题栏 -->
<view class="selector-header">
<text class="header-title">选择公司</text>
<view class="header-close" @click="handleCancel">
<u-icon name="close" size="40"></u-icon>
</view>
</view>
<!-- 搜索区域 -->
<view class="search-section">
<view class="search-input-wrapper">
<input
class="search-input"
v-model="searchKeyword"
placeholder="请输入公司名称"
@confirm="handleSearch"
confirm-type="search"
/>
<view class="search-btn" @click="handleSearch">
<u-icon name="search" color="#fff" size="36"></u-icon>
<text>搜索</text>
</view>
</view>
</view>
<!-- 列表区域 -->
<scroll-view class="list-section" scroll-y>
<view v-if="loading" class="loading-wrapper">
<u-loading mode="circle" size="40"></u-loading>
<text class="loading-text">加载中...</text>
</view>
<view v-else-if="companyList.length === 0 && !hasSearched" class="empty-wrapper">
<text class="empty-text">请输入公司名称进行搜索</text>
</view>
<view v-else-if="companyList.length === 0 && hasSearched" class="empty-wrapper">
<text class="empty-text">未找到相关公司</text>
</view>
<view v-else>
<view
v-for="(item, index) in companyList"
:key="index"
class="company-item"
:class="{ 'company-item-active': selectedItem && selectedItem.name === item.name }"
@click="handleSelect(item)"
>
<view class="company-name">{{ item.name }}</view>
<view v-if="selectedItem && selectedItem.name === item.name" class="check-icon">
<u-icon name="checkmark" color="#409eff" size="40"></u-icon>
</view>
</view>
</view>
</scroll-view>
<!-- 底部按钮 -->
<view class="footer-section">
<view class="footer-btn cancel-btn" @click="handleCancel">
<text>取消</text>
</view>
<view
class="footer-btn confirm-btn"
:class="{ 'confirm-btn-disabled': !selectedItem }"
@click="handleConfirm "
>
<text>确认</text>
</view>
</view>
</view>
</u-popup>
</template>
<script>
export default {
name: 'CompanySelector',
props: {
// 控制弹窗显示隐藏
value: {
type: Boolean,
default: false
}
},
data() {
return {
showPopup: false,
searchKeyword: '',
companyList: [],
selectedItem: null,
loading: false,
hasSearched: false
}
},
watch: {
value(newVal) {
this.showPopup = newVal;
if (newVal) {
// 弹窗打开时重置状态
this.resetData();
}
},
showPopup(newVal) {
this.$emit('input', newVal);
}
},
mounted() {
this.showPopup = this.value;
},
methods: {
// 重置数据
resetData() {
this.searchKeyword = '';
this.companyList = [];
this.selectedItem = null;
this.hasSearched = false;
this.loading = false;
},
// 搜索公司
async handleSearch() {
if (!this.searchKeyword.trim()) {
uni.showToast({
title: '请输入公司名称',
icon: 'none'
});
return;
}
this.loading = true;
this.hasSearched = true;
this.selectedItem = null;
try {
const res = await this.$u.api.otherCompany({
company_name: this.searchKeyword.trim()
});
this.loading = false;
// 处理返回的数据,检查是否有错误码
console.log("res123",res)
// 如果返回的是错误格式 {errorcode:1001,errormsg:""},说明没有数据
if (res && typeof res === 'object' && res.errorcode === 1001) {
this.companyList = [];
// 触发无数据事件,通知父组件
this.$emit('no-data', this.searchKeyword.trim());
} else if (Array.isArray(res)) {
// 如果返回的是数组,正常处理
this.companyList = res;
if (this.companyList.length === 0) {
// 触发无数据事件,通知父组件
this.$emit('no-data', this.searchKeyword.trim());
}
} else {
// 其他情况,设置为空数组
this.companyList = [];
// 触发无数据事件,通知父组件
this.$emit('no-data', this.searchKeyword.trim());
}
} catch (error) {
this.loading = false;
console.error('搜索公司失败:', error);
uni.showToast({
title: '搜索失败,请稍后重试',
icon: 'none'
});
// 触发无数据事件,通知父组件
this.$emit('no-data', this.searchKeyword.trim());
this.companyList = [];
}
},
// 选择公司
handleSelect(item) {
this.selectedItem = item;
},
// 取消
handleCancel() {
this.showPopup = false;
this.resetData();
},
// 确认
async handleConfirm() {
if (!this.selectedItem) {
uni.showToast({
title: '请先选择一家公司',
icon: 'none'
});
return;
}
// 获取公司名称优先使用name字段如果没有则使用company_name
const companyName = this.selectedItem.name;
if (!companyName) {
uni.showToast({
title: '公司名称不存在',
icon: 'none'
});
return;
}
// 显示加载提示
uni.showLoading({
title: '加载中...',
mask: true
});
try {
// 请求公司详情接口
const res = await this.$u.api.otherCompanyDetail({
company_name: companyName
});
uni.hideLoading();
// 将接口返回的数据传递给父组件
if (res) {
this.$emit('confirm',res);
}
this.showPopup = false;
this.resetData();
} catch (error) {
uni.hideLoading();
console.error('获取公司详情失败:', error);
uni.showToast({
title: '获取公司详情失败,请稍后重试',
icon: 'none'
});
}
}
}
}
</script>
<style lang="scss" scoped>
.company-selector {
background-color: #fff;
border-radius: 20rpx 20rpx 0 0;
display: flex;
flex-direction: column;
max-height: 80vh;
.selector-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 30rpx;
border-bottom: 1rpx solid #ebeef5;
.header-title {
font-size: 36rpx;
font-weight: 600;
color: #303133;
}
.header-close {
width: 60rpx;
height: 60rpx;
display: flex;
align-items: center;
justify-content: center;
}
}
.search-section {
padding: 30rpx;
border-bottom: 1rpx solid #ebeef5;
.search-input-wrapper {
display: flex;
align-items: center;
gap: 20rpx;
.search-input {
flex: 1;
height: 80rpx;
background-color: #f5f7fa;
border-radius: 8rpx;
padding: 0 20rpx;
font-size: 28rpx;
color: #303133;
}
.search-btn {
display: flex;
align-items: center;
justify-content: center;
gap: 8rpx;
height: 80rpx;
padding: 0 30rpx;
background-color: #409eff;
border-radius: 8rpx;
color: #fff;
font-size: 28rpx;
font-weight: 500;
}
}
}
.list-section {
flex: 1;
min-height: 400rpx;
max-height: 60vh;
padding: 20rpx 0;
.loading-wrapper {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 100rpx 0;
.loading-text {
margin-top: 20rpx;
font-size: 28rpx;
color: #909399;
}
}
.empty-wrapper {
display: flex;
align-items: center;
justify-content: center;
padding: 100rpx 0;
.empty-text {
font-size: 28rpx;
color: #909399;
}
}
.company-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 30rpx;
border-bottom: 1rpx solid #f5f7fa;
.company-name {
flex: 1;
font-size: 30rpx;
color: #303133;
}
.check-icon {
width: 40rpx;
height: 40rpx;
display: flex;
align-items: center;
justify-content: center;
}
&.company-item-active {
background-color: #ecf5ff;
.company-name {
color: #409eff;
font-weight: 500;
}
}
}
}
.footer-section {
display: flex;
align-items: center;
gap: 20rpx;
padding: 30rpx;
border-top: 1rpx solid #ebeef5;
background-color: #fff;
.footer-btn {
flex: 1;
height: 88rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 8rpx;
font-size: 32rpx;
font-weight: 500;
&.cancel-btn {
background-color: #f5f7fa;
color: #606266;
}
&.confirm-btn {
background-color: #409eff;
color: #fff;
&.confirm-btn-disabled {
background-color: #c0c4cc;
color: #fff;
}
}
}
}
}
</style>