地区选择开发,AI接口联调

This commit is contained in:
francis_fh
2026-01-22 12:57:01 +08:00
parent 7dcfbd35fe
commit f73d3f7a8c
7 changed files with 813 additions and 134 deletions

View File

@@ -551,7 +551,9 @@ const scrollToBottom = throttle(function () {
}, 500);
function getGuess() {
$api.chatRequest('/guest', { sessionId: chatSessionID.value }, 'POST').then((res) => {
// $api.chatRequest('/guest', { sessionId: chatSessionID.value }, 'POST').then((res) => {
$api.chatRequest('/guest', undefined, 'POST').then((res) => {
console.log('getGuess ---- res:', res);
guessList.value = res.data;
showGuess.value = true;
nextTick(() => {
@@ -804,22 +806,22 @@ function refreshMarkdown(index) {
}
const jobSearchQueries = [
'青岛有哪些薪资 12K 以上的岗位适合我?',
'青岛 3 年工作经验能找到哪些 12K 以上的工作?',
'青岛哪些公司在招聘,薪资范围在 12K 以上?',
'青岛有哪些企业提供 15K 以上的岗位?',
'青岛哪些公司在招 3-5 年经验的岗位?',
'我有三年的工作经验,能否推荐一些适合我的青岛的国企 岗位?',
'青岛国企目前在招聘哪些岗位?',
'青岛有哪些适合 3 年经验的国企岗位?',
'青岛国企招聘的岗位待遇如何?',
'青岛国企岗位的薪资水平是多少?',
'青岛哪些国企支持双休 & 五险一金完善?',
'青岛有哪些公司支持远程办公?',
'青岛有哪些外企的岗位,薪资 12K 以上的多吗?',
'青岛哪些企业在招聘 Web3.0 相关岗位?',
'青岛哪些岗位支持海外远程?薪资如何?',
'青岛招聘 AI/大数据相关岗位的公司有哪些?',
'喀什地区有哪些薪资 12K 以上的岗位适合我?',
'喀什地区 3 年工作经验能找到哪些 12K 以上的工作?',
'喀什地区哪些公司在招聘,薪资范围在 12K 以上?',
'喀什地区有哪些企业提供 15K 以上的岗位?',
'喀什地区哪些公司在招 3-5 年经验的岗位?',
'我有三年的工作经验,能否推荐一些适合我的喀什地区的国企 岗位?',
'喀什地区国企目前在招聘哪些岗位?',
'喀什地区有哪些适合 3 年经验的国企岗位?',
'喀什地区国企招聘的岗位待遇如何?',
'喀什地区国企岗位的薪资水平是多少?',
'喀什地区哪些国企支持双休 & 五险一金完善?',
'喀什地区有哪些公司支持远程办公?',
'喀什地区有哪些外企的岗位,薪资 12K 以上的多吗?',
'喀什地区哪些企业在招聘 Web3.0 相关岗位?',
'喀什地区哪些岗位支持海外远程?薪资如何?',
'喀什地区招聘 AI/大数据相关岗位的公司有哪些?',
];
function changeQueries(value) {

425
pages/city-select/index.vue Normal file
View File

@@ -0,0 +1,425 @@
<template>
<view class="city-select-container">
<!-- 顶部导航栏 -->
<!-- <view class="nav-bar">
<view class="nav-left" @click="navBack">
<uni-icons type="left" size="24" color="#333"></uni-icons>
</view>
<view class="nav-title">选择城市</view>
<view class="nav-right"></view>
</view> -->
<!-- 搜索框 -->
<view class="search-box">
<uni-icons class="search-icon" type="search" size="20" color="#999"></uni-icons>
<input
class="search-input"
placeholder="搜索城市名/拼音"
placeholder-style="color: #999"
v-model="searchText"
@input="handleSearch"
>
</view>
<!-- 定位城市 -->
<!-- <view class="location-section">
<view class="section-title">定位城市</view>
<view class="location-city" :class="{ active: selectedCity.code === locationCity.code }" @click="selectCity(locationCity)">
{{ locationCity.name }}
</view>
</view> -->
<!-- 热门城市 -->
<!-- <view class="hot-section">
<view class="section-title">热门城市</view>
<view class="hot-cities">
<view
class="city-item"
:class="{ active: selectedCity.code === item.code }"
v-for="item in hotCities"
:key="item.code"
@click="selectCity(item)"
>
{{ item.name }}
</view>
</view>
</view> -->
<!-- 城市数量统计 -->
<!-- <view class="city-count" v-if="allCities.length > 0">
共找到 {{ allCities.length }} 个城市
</view> -->
<!-- 城市列表 -->
<view class="city-list-section">
<scroll-view
class="city-list-content"
scroll-y
:scroll-into-view="currentScrollId"
:scroll-with-animation="true"
>
<view
class="city-group"
v-for="group in cityGroups"
:key="group.letter"
:id="`city-group-${group.letter}`"
>
<view class="group-title">{{ group.letter }}</view>
<view
class="city-item"
:class="{ active: selectedCity.code === item.code }"
v-for="item in group.cities"
:key="item.code"
@click="selectCity(item)"
>
{{ item.name }}
</view>
</view>
</scroll-view>
<!-- 右侧字母索引 -->
<view class="letter-index">
<view
class="letter-item"
v-for="letter in letters"
:key="letter"
@click="scrollToLetter(letter)"
:class="{ active: currentLetter === letter }"
>
{{ letter }}
</view>
</view>
</view>
</view>
</template>
<script setup>
import { ref, reactive, onMounted, computed, inject } from 'vue';
const { $api, navTo } = inject('globalFunction');
// 搜索文本
const searchText = ref('');
// 定位城市
const locationCity = ref({ code: '110100', name: '北京' });
// 选中的城市
const selectedCity = ref({ code: '', name: '' });
// 当前显示的字母
const currentLetter = ref('');
// 当前滚动到的城市组ID
const currentScrollId = ref('');
// 城市数据
const allCities = ref([]);
// 字母列表
const letters = ref(['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']);
// 按字母分组的城市
const cityGroups = computed(() => {
const groups = {};
const filteredCities = allCities.value.filter(city => {
if (!searchText.value) return true;
return city.name.includes(searchText.value) || city.pinyin?.includes(searchText.value.toUpperCase());
});
console.log('过滤后用于分组的城市:', filteredCities);
// 初始化字母分组
letters.value.forEach(letter => {
groups[letter] = { letter, cities: [] };
});
// 将城市分配到对应字母组
filteredCities.forEach(city => {
const firstLetter = city.pinyin || '#';
// 如果字母不在预定义列表中,将其添加到分组中
if (!groups[firstLetter]) {
groups[firstLetter] = { letter: firstLetter, cities: [] };
}
groups[firstLetter].cities.push(city);
});
const result = Object.values(groups).filter(group => group.cities.length > 0);
// 对城市组进行排序
result.sort((a, b) => {
// '#' 符号应该排在最前面
if (a.letter === '#') return -1;
if (b.letter === '#') return 1;
// 其他字母按字母顺序排序
return a.letter.localeCompare(b.letter);
});
console.log('最终分组结果:', result);
return result;
});
// 获取城市数据
const getCityData = async () => {
try {
// 直接获取所有城市数据,新接口已经返回了所有层级的数据
const res = await $api.createRequest('/cms/dict/sysarea/listCity', {});
console.log('城市数据接口返回:', res);
if (res.code === 200 && res.data) {
console.log('原始城市数据:', res.data);
// 显示接口返回的所有城市数据
const filteredCities = res.data;
console.log('过滤后城市数据:', filteredCities);
// 直接使用后端返回的zm字段作为拼音首字母并转换为大写
allCities.value = filteredCities.map(city => ({
...city,
pinyin: (city.zm || '#').toUpperCase()
}));
console.log('使用后端zm字段的城市数据:', allCities.value);
// 按拼音首字母排序
allCities.value.sort((a, b) => {
// 首先按拼音首字母排序
if (a.pinyin !== b.pinyin) {
// '#' 符号应该排在最前面
if (a.pinyin === '#') return -1;
if (b.pinyin === '#') return 1;
return a.pinyin.localeCompare(b.pinyin);
}
// 首字母相同时,按城市名称排序
return a.name.localeCompare(b.name);
});
}
} catch (error) {
console.error('获取城市数据失败:', error);
}
};
// 获取拼音首字母(使用更准确的映射表)
const getPinyinFirstLetter = (name) => {
const firstChar = name.charAt(0);
// 查找对应的拼音首字母
for (const [letter, chars] of Object.entries(pinyinMap)) {
if (chars.includes(firstChar)) {
return letter;
}
}
// 如果没有找到,返回#
return '#';
};
// 处理搜索
const handleSearch = () => {
// 搜索逻辑已在cityGroups计算属性中处理
};
// 选择城市
const selectCity = (city) => {
selectedCity.value = city;
// 返回上一页并传递选择的城市
uni.navigateBack({
delta: 1,
success: () => {
// 发送事件通知首页选择了城市
uni.$emit('citySelected', city);
}
});
};
// 滚动到指定字母
const scrollToLetter = (letter) => {
currentLetter.value = letter;
// 更新滚动ID触发scroll-view滚动
currentScrollId.value = `city-group-${letter}`;
};
// 返回上一页
const navBack = () => {
uni.navigateBack({ delta: 1 });
};
// 组件挂载时获取城市数据
onMounted(() => {
getCityData();
});
</script>
<style scoped>
.city-select-container {
background-color: #f5f5f5;
min-height: 100vh;
padding-top: 16px;
}
/* 导航栏 */
.nav-bar {
display: flex;
align-items: center;
justify-content: space-between;
height: 44px;
padding: 0 16px;
background-color: #fff;
border-bottom: 1px solid #e5e5e5;
}
.nav-left,
.nav-right {
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
}
.nav-title {
font-size: 18px;
font-weight: 500;
color: #333;
}
/* 搜索框 */
.search-box {
display: flex;
align-items: center;
margin: 12px 16px;
padding:8px 16px;
background-color: #fff;
border-radius: 20px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}
.search-icon {
margin-right: 8px;
}
.search-input {
flex: 1;
font-size: 14px;
color: #333;
border: none;
outline: none;
}
/* 定位城市 */
.location-section {
padding: 16px;
background-color: #fff;
margin-bottom: 8px;
}
.section-title {
font-size: 14px;
color: #666;
margin-bottom: 12px;
}
.location-city {
display: inline-block;
padding: 8px 20px;
background-color: #f0f9ff;
color: #007aff;
border-radius: 20px;
font-size: 14px;
}
.location-city.active {
background-color: #007aff;
color: #fff;
}
/* 热门城市 */
.hot-section {
padding: 16px;
background-color: #fff;
margin-bottom: 8px;
}
.city-count {
padding: 0 16px 12px;
background-color: #fff;
font-size: 12px;
color: #999;
margin-bottom: 8px;
}
.hot-cities {
display: flex;
flex-wrap: wrap;
gap: 12px;
}
.city-item {
padding: 8px 20px;
background-color: #f5f5f5;
color: #333;
border-radius: 20px;
font-size: 14px;
}
.city-item.active {
background-color: #007aff;
color: #fff;
}
/* 城市列表 */
.city-list-section {
display: flex;
background-color: #fff;
height: calc(100vh - 180px);
}
.city-list-content {
flex: 1;
overflow-y: auto;
}
.city-group {
padding: 0 16px;
}
.group-title {
font-size: 14px;
color: #666;
margin: 12px 0 8px 0;
padding-left: 4px;
}
.city-list-content .city-item {
display: block;
padding: 12px 4px;
margin-bottom: 0;
background-color: transparent;
border-radius: 0;
border-bottom: 1px solid #f0f0f0;
}
.city-list-content .city-item.active {
background-color: transparent;
color: #007aff;
}
/* 右侧字母索引 */
.letter-index {
width: 30px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background-color: #f5f5f5;
}
.letter-item {
width: 24px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
color: #666;
margin: 2px 0;
}
.letter-item.active {
color: #007aff;
font-weight: bold;
}
</style>

View File

@@ -250,10 +250,16 @@
</view>
</view>
</scroll-view>
<view class="jobs-add button-click" @click="navTo('/packageA/pages/addPosition/addPosition')">
<uni-icons class="iconsearch" color="#666D7F" type="plusempty" size="18"></uni-icons>
<text>添加</text>
</view>
<view class="jobs-add button-click" @click="navTo('/pages/city-select/index')" style="padding-right:0;">
<!-- <uni-icons class="iconsearch" color="#666D7F" type="plusempty" size="18"></uni-icons> -->
<text>{{ selectedCity.name || '地区' }}</text>
<image class="right-sx" :class="{ active: showFilter }" src="@/static/icon/shaixun.png"></image>
</view>
</view>
<view class="filter-bottom">
<view class="btm-left">
@@ -317,7 +323,7 @@
<view class="falls-card-company" v-show="isShowJw !== 3">
{{ config.appInfo.areaName }}
<!-- {{ job.jobLocation }} -->
<dict-Label dictType="area" :value="job.jobLocationAreaCode"></dict-Label>
<dict-Label dictType="jobLocationAreaCode" :value="job.jobLocationAreaCode"></dict-Label>
</view>
<view class="falls-card-pepleNumber">
<view>
@@ -394,7 +400,7 @@
<view class="falls-card-company" v-show="isShowJw !== 3">
{{ config.appInfo.areaName }}
<!-- {{ job.jobLocation }} -->
<dict-Label dictType="area" :value="job.jobLocationAreaCode"></dict-Label>
<dict-Label dictType="jobLocationAreaCode" :value="job.jobLocationAreaCode"></dict-Label>
</view>
<view class="falls-card-pepleNumber">
<view>
@@ -631,6 +637,8 @@ const inputText = ref('');
const showFilter = ref(false);
const selectFilterModel = ref(null);
const showModel = ref(false);
// 选中的城市
const selectedCity = ref({ code: '', name: '' });
const rangeOptions = ref([
{ value: 0, text: '推荐' },
{ value: 1, text: '最热' },
@@ -723,6 +731,7 @@ onMounted(() => {
// 在组件挂载时绑定事件监听,确保只绑定一次
// 先移除可能存在的旧监听,避免重复绑定
uni.$off('showLoginModal');
uni.$off('citySelected');
// 绑定新的监听
uni.$on('showLoginModal', () => {
@@ -731,6 +740,15 @@ onMounted(() => {
pageNull.value = 0;
});
// 监听城市选择事件
uni.$on('citySelected', (city) => {
console.log('收到citySelected事件选择的城市:', city);
selectedCity.value = city;
// 可以在这里添加根据城市筛选职位的逻辑
conditionSearch.value.jobLocationAreaCode = city.code;
getJobRecommend('refresh');
});
// 获取企业信息
getCompanyInfo();
});
@@ -738,6 +756,7 @@ onMounted(() => {
onUnmounted(() => {
// 组件销毁时移除事件监听
uni.$off('showLoginModal');
uni.$off('citySelected');
});
onShow(() => {
@@ -1728,6 +1747,9 @@ defineExpose({ loadData });
min-width: 80rpx;
padding: 8rpx 12rpx;
white-space: nowrap;
.right-sx
width: 28rpx;
height: 28rpx;
.filter-bottom
display: flex
justify-content: space-between