Files
ks-app-employment-service/pages/job/companySearch.vue
2025-10-23 17:16:16 +08:00

413 lines
10 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="company-search-page">
<!-- 头部导航 -->
<view class="header">
<view class="header-left" @click="goBack">
<image src="@/static/icon/back.png" class="back-icon"></image>
</view>
<view class="header-title">选择企业</view>
<view class="header-right"></view>
</view>
<!-- 搜索框 -->
<view class="search-container">
<view class="search-box">
<view class="search-icon">🔍</view>
<input
class="search-input"
placeholder="请输入企业名称进行搜索"
v-model="searchKeyword"
@input="onSearchInput"
@confirm="onSearchConfirm"
/>
<view class="clear-btn" v-if="searchKeyword" @click="clearSearch">
<view class="clear-icon"></view>
</view>
</view>
</view>
<!-- 搜索结果 -->
<scroll-view class="content" scroll-y="true" :style="{ height: scrollViewHeight }">
<!-- 加载状态 -->
<view class="loading-container" v-if="loading">
<view class="loading-text">搜索中...</view>
</view>
<!-- 搜索结果列表 -->
<view class="result-list" v-else-if="searchResults.length > 0">
<view
class="result-item"
v-for="(company, index) in searchResults"
:key="company.id || index"
@click="selectCompany(company)"
>
<view class="company-info">
<view class="company-name">{{ company.name }}</view>
<view class="company-detail" v-if="company.address">
<text class="detail-label">地址</text>
<text class="detail-value">{{ company.address }}</text>
</view>
<view class="company-detail" v-if="company.contact">
<text class="detail-label">联系人</text>
<text class="detail-value">{{ company.contact }}</text>
</view>
</view>
<view class="select-icon">
<view class="arrow-icon">></view>
</view>
</view>
</view>
<!-- 空状态 -->
<view class="empty-container" v-else-if="searchKeyword && !loading">
<view class="empty-icon">🔍</view>
<view class="empty-text">未找到相关企业</view>
<view class="empty-tip">请尝试其他关键词</view>
</view>
<!-- 初始状态 -->
<view class="initial-container" v-else-if="!searchKeyword">
<view class="initial-icon">🔍</view>
<view class="initial-text">请输入企业名称进行搜索</view>
</view>
<!-- 底部安全区域 -->
<view class="bottom-safe-area"></view>
</scroll-view>
</view>
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue';
import { createRequest } from '@/utils/request';
// 搜索相关状态
const searchKeyword = ref('');
const searchResults = ref([]);
const loading = ref(false);
const scrollViewHeight = ref('calc(100vh - 200rpx)');
// 防抖定时器
let debounceTimer = null;
// 计算滚动视图高度
const calculateScrollViewHeight = () => {
const systemInfo = uni.getSystemInfoSync();
const windowHeight = systemInfo.windowHeight;
const headerHeight = 100; // 头部高度
const searchHeight = 100; // 搜索框高度
const scrollHeight = windowHeight - headerHeight - searchHeight;
scrollViewHeight.value = `${scrollHeight}px`;
};
// 页面加载时计算高度
onMounted(() => {
calculateScrollViewHeight();
});
// 搜索输入处理(防抖)
const onSearchInput = () => {
// 清除之前的定时器
if (debounceTimer) {
clearTimeout(debounceTimer);
}
// 设置新的定时器500ms后执行搜索
debounceTimer = setTimeout(() => {
if (searchKeyword.value.trim()) {
searchCompanies();
} else {
searchResults.value = [];
}
}, 500);
};
// 搜索确认
const onSearchConfirm = () => {
if (searchKeyword.value.trim()) {
searchCompanies();
}
};
// 搜索企业
const searchCompanies = async () => {
if (!searchKeyword.value.trim()) {
searchResults.value = [];
return;
}
try {
loading.value = true;
const response = await createRequest('/app/company/likeList', {
name: searchKeyword.value.trim()
}, 'GET', false);
if (response.code === 200) {
searchResults.value = response.data || [];
} else {
uni.showToast({
title: response.msg || '搜索失败',
icon: 'none'
});
searchResults.value = [];
}
} catch (error) {
console.error('搜索企业失败:', error);
uni.showToast({
title: '搜索失败,请重试',
icon: 'none'
});
searchResults.value = [];
} finally {
loading.value = false;
}
};
// 选择企业
const selectCompany = (company) => {
// 返回上一页并传递选中的企业信息
uni.navigateBack({
success: () => {
// 通过事件总线或全局数据传递选中的企业信息
getApp().globalData = getApp().globalData || {};
getApp().globalData.selectedCompany = company;
}
});
};
// 清除搜索
const clearSearch = () => {
searchKeyword.value = '';
searchResults.value = [];
if (debounceTimer) {
clearTimeout(debounceTimer);
}
};
// 返回上一页
const goBack = () => {
uni.navigateBack();
};
</script>
<style lang="scss" scoped>
.company-search-page {
height: 100vh;
background-color: #f5f5f5;
display: flex;
flex-direction: column;
position: relative;
overflow: hidden;
}
.header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 20rpx 30rpx;
background: #fff;
border-bottom: 1rpx solid #eee;
.header-left {
width: 60rpx;
height: 60rpx;
display: flex;
align-items: center;
justify-content: center;
.back-icon {
width: 40rpx;
height: 40rpx;
}
}
.header-title {
font-size: 36rpx;
font-weight: 600;
color: #333;
}
.header-right {
width: 60rpx;
}
}
.search-container {
padding: 20rpx 30rpx;
background: #fff;
border-bottom: 1rpx solid #eee;
.search-box {
display: flex;
align-items: center;
background: #f8f8f8;
border-radius: 12rpx;
padding: 0 20rpx;
height: 80rpx;
.search-icon {
font-size: 32rpx;
color: #999;
margin-right: 20rpx;
}
.search-input {
flex: 1;
height: 80rpx;
background: transparent;
border: none;
font-size: 28rpx;
color: #333;
&::placeholder {
color: #999;
}
}
.clear-btn {
width: 40rpx;
height: 40rpx;
display: flex;
align-items: center;
justify-content: center;
margin-left: 20rpx;
.clear-icon {
font-size: 24rpx;
color: #999;
}
}
}
}
.content {
flex: 1;
padding: 0;
overflow: hidden;
}
.loading-container {
display: flex;
justify-content: center;
align-items: center;
height: 200rpx;
.loading-text {
font-size: 28rpx;
color: #999;
}
}
.result-list {
background: #fff;
.result-item {
display: flex;
align-items: center;
padding: 30rpx;
border-bottom: 1rpx solid #f0f0f0;
&:last-child {
border-bottom: none;
}
&:active {
background: #f8f8f8;
}
.company-info {
flex: 1;
.company-name {
font-size: 32rpx;
font-weight: 600;
color: #333;
margin-bottom: 10rpx;
}
.company-detail {
font-size: 24rpx;
color: #666;
margin-bottom: 5rpx;
&:last-child {
margin-bottom: 0;
}
.detail-label {
color: #999;
}
.detail-value {
color: #666;
}
}
}
.select-icon {
width: 40rpx;
height: 40rpx;
display: flex;
align-items: center;
justify-content: center;
.arrow-icon {
font-size: 24rpx;
color: #999;
}
}
}
}
.empty-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 400rpx;
.empty-icon {
font-size: 120rpx;
color: #ccc;
margin-bottom: 30rpx;
}
.empty-text {
font-size: 32rpx;
color: #333;
margin-bottom: 10rpx;
}
.empty-tip {
font-size: 24rpx;
color: #999;
}
}
.initial-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 400rpx;
.initial-icon {
font-size: 120rpx;
color: #ccc;
margin-bottom: 30rpx;
}
.initial-text {
font-size: 28rpx;
color: #999;
}
}
.bottom-safe-area {
height: 120rpx;
background: transparent;
}
</style>