鱼泡-伙伴匹配系统

第一次直播

项目介绍

帮助找到志同道合的伙伴

需求分析

  1. 标签分类

  2. 主动搜索

  3. 组队

    1. 创建队伍
    2. 加入队伍
    3. 根据标签查询队伍

前端项目初始化

项目初始化文件夹中一定不要带空格! 使用npm(node包管理器)来安装

Vite

脚手架:
vue cli
vite

项目中使用:vite

src:
https://vitejs.cn/guide/#scaffolding-your-first-vite-project

1. npm init vite@latest

2.
√ Project namel

4. 启动项目:npm run dev

Vant

src:https://vant-ui.github.io/vant/v3/#/zh-CN

轻量、可靠的移动端 Vue 组件库

根据官方文档进行配置:

1. # 通过 npm 安装 npm i unplugin-vue-components -D(这个插件就是按需引入,没必要全部都下载)

2. 修改配置: 在config文件中
import vue from '@vitejs/plugin-vue';
import Components from 'unplugin-vue-components/vite';
import { VantResolver } from 'unplugin-vue-components/resolvers';

export default {
  plugins: [
    vue(),
    Components({
      resolvers: [VantResolver()],
    }),
  ],
};

在main文件中挂载需要的组件:

import { createApp } from 'vue'  
import './style.css'  
import App from './App.vue'  
import { Button } from 'vant';  
import 'vant/lib/index.css';  
  
const app = createApp(App);  
app.use(Button);  
app.mount('#app');

在App.Vue首页写入组件代码:

<van-button type="primary">主要按钮</van-button>  
<van-button type="success">成功按钮</van-button>  
<van-button type="default">默认按钮</van-button>  
<van-button type="warning">警告按钮</van-button>  
<van-button type="danger">危险按钮</van-button>

整体框架设计

开发页面经验:

1.多参考
2.从整体到局部
3.先想清楚页面要做成什么样子,再写代码

设计

  1. 导航条

  2. 内容

  3. tab栏

    1. 主页(推荐页 + 广告
      1. 搜索页
      2. banner
      3. 推荐信息流
    2. 队伍页
    3. 用户页

总体浏览:
image.png

设置:

  1. 导航栏
<van-nav-bar  
    title="标题"  
    left-text="返回"  
    left-arrow  
    @click-left="onClickLeft"  
    @click-right="onClickRight"  
>  
  %% 插槽 %%
  <template #right>  
    <van-icon name="search" size="18"/>  
  </template>  
  </van-nav-bar>
  1. 标签栏
<!--  下面的边栏-->  
  <van-tabbar v-model="active"  @change="onChange">  
    <van-tabbar-item name="index" icon="home-o">主页</van-tabbar-item>  
    <van-tabbar-item name="team" icon="search">队伍</van-tabbar-item>  
    <van-tabbar-item name="user" icon="friends-o">个人</van-tabbar-item>  
  </van-tabbar>

整体代码:

<script setup lang="ts">  
    import {ref} from "vue";  
    import {showToast} from "vant";  
    import Index from "../pages/index.vue";  // 显示的页面需要引入  
    import Team from "../pages/team.vue";  
    import Profile from "../pages/profile.vue";  
    const onClickLeft = () => console.log("左")  
    const onClickRight = () => console.log("右")  
    const active = ref("index");  
    // 使用showToast展示相对应的标签 会有一个浮动的窗口  
    const onChange = (index) => showToast(`标签 ${index}`);  
</script>  
<template>  
  <van-nav-bar      title="标题"  
      left-text="返回"  
      left-arrow  
      @click-left="onClickLeft"  
      @click-right="onClickRight"  
  >  
    <template #right>  
      <van-icon name="search" size="18"/>  
    </template>    </van-nav-bar><!--  下面的边栏-->  
  <van-tabbar v-model="active"  @change="onChange">  
    <van-tabbar-item name="index" icon="home-o">主页</van-tabbar-item>  
    <van-tabbar-item name="team" icon="search">队伍</van-tabbar-item>  
    <van-tabbar-item name="user" icon="friends-o">个人</van-tabbar-item>  
  </van-tabbar><!--通过active进行激活 判断显示哪一个页面-->  
  <div id="content">  
    <template v-if="active === 'index'">  
      <index></index>    </template>    <template v-if="active === 'team'">  
      <team></team>    </template>    <template v-if="active === 'user'">  
      <profile></profile>    </template>  </div></template>  
<style scoped>  
</style>

后端数据库开发

  1. 标签表的开发
    字段:

id int 主键

标签名 varchar 非空(必须唯一,唯一索引)

上传标签的用户 userId int(如果要根据 userId 查已上传标签的话,最好加上,普通索引)

父标签 id ,parentId,int(分类)

是否为父标签 isParent, tinyint(0 不是父标签、1 - 父标签)

创建时间 createTime,datetime

更新时间 updateTime,datetime

是否删除 isDelete, tinyint(0、1)

create table tag  
(  
    id         bigint auto_increment comment 'id'  
        primary key,  
    tagName    varchar(256)                       null comment '标签名称',  
    userId     bigint                             null comment '用户 id',  
    parentId   bigint                             null comment '父标签 id',  
    isParent   tinyint                            null comment '0 - 不是, 1 - 父标签',  
    createTime datetime default CURRENT_TIMESTAMP null comment '创建时间',  
    updateTime datetime default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP,  
    isDelete   tinyint  default 0                 not null comment '是否删除',  
    constraint uniIdx_tagName  
        unique (tagName)  
);
  1. 用户表 添加标签字段(表示这个用户具有什么标签)

image.png

后端开发接口

  1. 复制user-center的项目,删除相关的文件,把所有user-center名字修改为partner-matching

标签

一个用户存在tag字段:包括了多个标签,mysql数据库中tag字段包含了json数据[“xxx”,“xxxx”]

通过tag字段去搜索相对应的用户

举个例子: 查询有java、python这两个标签的用户

1. 使用sql查询带有特定标签的用户

@Override  
    public List<User> searchUserByTags(List<String> tagNameLists) {  
//        如果搜索到的数据都是空的 报异常  
        if (CollectionUtils.isEmpty(tagNameLists)) {  
            throw new BusinessException(ErrorCode.PARAMS_ERROR);  
        }  
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();  
        // 拼接tag select * from user where tags like "xxx" and tag like "xxx"  
        for (String tag : tagNameLists) {  
            // 拼接操作  
            queryWrapper = queryWrapper.like("tags", tag);  
        }  
        List<User> users = userMapper.selectList(queryWrapper);  
  
        List<User> collect = users.stream().map(this::getSafetyUser).collect(Collectors.toList());  
        return collect;  
    }

具体操作:

  1. 通过前端传入数据
  2. 构造queryWrapper建立查询条件:tags like “xxx” and tag like “xxx”
  3. 拿到数据后使用stream中的map进行脱敏,返回数据

2. 内存中查询

gson依赖:

<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.9</version>
</dependency>

具体步骤:

  1. 通过前端传入数据
  2. 查询所有用户的数据
  3. 从数据中拿到tag并且将json格式的String字符串转换为set类型String字符串
    1. String json: = "tag1,tag2,tag3" -> Set<String>: [tag1, tag2, tag3]
  4. 比较数据,如果存在保存用户,不存在去除用户(使用的是stream流进行处理)
    @Override  
    public List<User> searchUserByTags2(List<String> tagNameLists) {  
        //        如果搜索到的数据都是空的 报异常  
        if (CollectionUtils.isEmpty(tagNameLists)) {  
            throw new BusinessException(ErrorCode.PARAMS_ERROR);  
        }  
  
        // 1. 查询所有的用户  
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();  
        List<User> userList = userMapper.selectList(queryWrapper);  
//        创建 gson:将json转换为java数据  
        Gson gson = new Gson();  
//        2. 判断前端的标签是否符合数据库中每一个用户存在的标签  
        return userList.stream().filter(user ->{  
            String taguser = user.getTags();  
            if(StringUtils.isEmpty(taguser)){  
                return false;  
            }  
            Type type = new TypeToken<Set<String>>() {  
            }.getType();  
            Set<String> tagSet = gson.fromJson(taguser, type);  
            for (String tag : tagSet) {  
                if(!tagSet.contains(tag)){ // 如果tagSet中不包含这个标签,直接跳过这个用户  
                    return false;  
                }  
            }  
            return true; // 到这边就是可以进入下一个步骤了  
        }).map(this::getSafetyUser)  
                .collect(Collectors.toList());  
    }

如何测试方法运行时间

核心思想:System.currentTimeMillis()

List<String> tagList = Arrays.asList("Java", "Python");  
long start1 = System.currentTimeMillis();  
List<User> users1 = userService.searchUserByTags(tagList);  
long result1 = System.currentTimeMillis() - start1;  
long start2 = System.currentTimeMillis();  
List<User> users2 = userService.searchUserByTags2(tagList);  
long result2 = System.currentTimeMillis() - start2;  
System.out.println("使用sql查询用时:" + result1);  
System.out.println("使用内存查询用时:" + result2);  
System.out.println("测试结束");
使用sql查询用时:1156
使用内存查询用时:59
  1. 根据业务的数据量可以自由选择查询方法
  2. 同时使用两种不同的查询,谁先返回用谁

第二次直播

规划

  1. 之前标签接口再调试
  2. 前端开发
  3. 整合路由 30-50
  4. 后端api swagger + knife4j
  5. 爬虫 用户信息

接口调试10

弃用接口方法:

  1. 在方法前+ @Deprecated

  2. 将方法私有化 private (❓设置有问题)

  3. stream / parallelStream 流失处理

  4. Optional 可选类(java8 快速判断 是否为空 否则为xxx 类似ifnull)

Set<String> tagSet = gson.fromJson(taguser, type);  
tagSet = Optional.ofNullable(tagSet).orElse(new HashSet<>());

如果json解析为null,则设置为空的HashSet

前端整合路由11

  1. 整合路由

地址:https://router.vuejs.org/zh/guide/#html

安装Vue route:一个html动态访问不同的组件

npm install vue-router@4

如何使用route?

配置信息:

const router = VueRouter.createRouter({  
    // 4. 内部提供了 history 模式的实现。为了简单起见,我们在这里使用 hash 模式。  
    history: VueRouter.createWebHashHistory(),  
    routes, // `routes: routes` 的缩写  
})  
  
app.use(router)
const routes = [  
    {path: '/', component: Index},  
    {path: '/team', component: Team},  
    {path: '/profile', component: Profile},  
]  
export default routes;

页面显示跳转:

显示route的跳转页面 
  <div id="content">  
    <router-view/>  
    </div>
    <!--  下面的边栏-->  
  <van-tabbar route @change="onChange">  
    <van-tabbar-item to="/" icon="home-o" name="index">主页</van-tabbar-item>  
    <van-tabbar-item to="/team" icon="search" name="team">队伍</van-tabbar-item>  
    <van-tabbar-item to="/profile" icon="friends-o" name="profile">个人</van-tabbar-item>  
  </van-tabbar>

在js中触发事件如何跳转页面?

const router = useRouter(); 创建一个实例

const onClickRight = () => {  
  router.push('/search')   使用push到指定的页面
};

搜索页面

如何设计一个搜索页面:

去看其他客户端或者网页是怎么做的 模仿!

image.png

通过搜索 选中标签 添加到已选标签中

ref的用处:

const searchText = ref('');


建了一个初始值为空字符串的响应式引用。这个引用可以在组件中进行双向绑定,并且当其值发生变化时,Vue会自动更新所有使用这个引用的地方。

用户信息页面12

创建信息实体

export type userType = {  
    id : number;  
    user : string;  
    userAccount : string;  
    avatarUrl : string;  
    gender : number;  
    phone : string;  
    email : string;  
    userStatus : string;  
    userRole : string;  
    planetCode : string;  
    tags : string[];  
    createTime : Date;  
}

image.png

创建页面

使用vant组件cell:

  <van-cell-group inset>  
<!--    设置 is-link 属性后会在单元格右侧显示箭头,并且可以通过 arrow-direction 属性控制箭头方向。-->  
  <van-cell title="昵称" is-link to="/user/edit" :value="user.username"/>  
  <van-cell title="账号"  :value="user.userAccount"/>  
  <van-cell title="头像" is-link to="/user/edit">  
    <img style="height: 48px" :src="user.avatarUrl">  
  </van-cell>  <van-cell title="性别" is-link to="/user/edit" :value="user.gender"/>  
  <van-cell title="电话" is-link  to="/user/edit" :value="user.phone"/>  
  <van-cell title="邮箱" is-link to="/user/edit" :value="user.email"/>  
  <van-cell title="星球编号"   :value="user.planetCode"/>  
  <van-cell title="注册时间" :value="user.createTime.toISOString()"/>  
  </van-cell-group>

image.png

image.png

使用route传参

创建的个人信息页面:
image.png

页面会进行跳转:to="/user/edit"

通过route传递参数到edit页面,然后进行修改回传

  • 30
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
东南亚位于我国倡导推进的“一带一路”海陆交汇地带,作为当今全球发展最为迅速的地区之一,近年来区域内生产总值实现了显著且稳定的增长。根据东盟主要经济体公布的最新数据,印度尼西亚2023年国内生产总值(GDP)增长5.05%;越南2023年经济增长5.05%;马来西亚2023年经济增速为3.7%;泰国2023年经济增长1.9%;新加坡2023年经济增长1.1%;柬埔寨2023年经济增速预计为5.6%。 东盟国家在“一带一路”沿线国家中的总体GDP经济规模、贸易总额与国外直接投资均为最大,因此有着举足轻重的地位和作用。当前,东盟与中国已互相成为双方最大的交易伙伴。中国-东盟贸易总额已从2013年的443亿元增长至 2023年合计超逾6.4万亿元,占中国外贸总值的15.4%。在过去20余年中,东盟国家不断在全球多变的格局里面临挑战并寻求机遇。2023东盟国家主要经济体受到国内消费、国外投资、货币政策、旅游业复苏、和大宗商品出口价企稳等方面的提振,经济显现出稳步增长态势和强韧性的潜能。 本调研报告旨在深度挖掘东南亚市场的增长潜力与发展机会,分析东南亚市场竞争态势、销售模式、客户偏好、整体市场营商环境,为国内企业出海开展业务提供客观参考意见。 本文核心内容: 市场空间:全球行业市场空间、东南亚市场发展空间。 竞争态势:全球份额,东南亚市场企业份额。 销售模式:东南亚市场销售模式、本地代理商 客户情况:东南亚本地客户及偏好分析 营商环境:东南亚营商环境分析 本文纳入的企业包括国外及印尼本土企业,以及相关上下游企业等,部分名单 QYResearch是全球知名的大型咨询公司,行业涵盖各高科技行业产业链细分市场,横跨如半导体产业链(半导体设备及零部件、半导体材料、集成电路、制造、封测、分立器件、传感器、光电器件)、光伏产业链(设备、硅料/硅片、电池片、组件、辅料支架、逆变器、电站终端)、新能源汽车产业链(动力电池及材料、电驱电控、汽车半导体/电子、整车、充电桩)、通信产业链(通信系统设备、终端设备、电子元器件、射频前端、光模块、4G/5G/6G、宽带、IoT、数字经济、AI)、先进材料产业链(金属材料、高分子材料、陶瓷材料、纳米材料等)、机械制造产业链(数控机床、工程机械、电气机械、3C自动化、工业机器人、激光、工控、无人机)、食品药品、医疗器械、农业等。邮箱:market@qyresearch.com

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值