app
wangxia 12 months ago
parent b248bcf13f
commit 1d273741a7

@ -0,0 +1,148 @@
<template>
<div class="g_p_10 g_position_rela">
<div class="g_bg_f g_p_10 g_radius_8">
<u-line-progress class="g_position_abso" v-if="ailoading" style="position: fixed; width: 100%; top: -13px; left: 0px; z-index: 99999" active-color="#3578f6" :percent="defaultPercent" :round="false" height="8" :show-percent="false" inactiveColor="#f5f5f5"></u-line-progress>
<gao-ChatSSEClient ref="sseTest" @onOpen="openCore" @onError="errorCore" @onMessage="messageCore" @onFinish="finishCore" />
<textarea class data-type="desp" v-model="aitext" placeholder="粘贴老乡信息, 用AI识别 " placeholder-style="color:#999" :maxlength="-1" :style="{ width: '100%', height: true ? '104px' : '104px' }"></textarea>
<div class>
<view class="g_flex_row_end flex_center">
<view class="iconfont icon-jia1 g_c_9 g_mr_8 g_fs_20"></view>
<view class="g_mr_8 g_w_72 g_fw_600">
<g-button size="small_auto" type="none" height="24" :fontSize="12" @clickBtn="getClipboard" :btnText="(aitext ? '清空' : '粘贴') + '内容'"></g-button>
</view>
<view @click.stop="getCoze" class="g_w_72 g_fw_600">
<g-button size="small_auto" gradual="linear-gradient(-130deg, #5c6cf7, #9963f9)" icon="icon-aitubiao" type="gradual" height="24" :fontSize="12" btnText="AI识别" @clickBtn="getCoze"></g-button>
</view>
</view>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
aitext: '',
timer: null,
timer1: null,
defaultPercent: 0,
ailoading: false,
aiConfig: {
token: '',
id: '',
},
}
},
created() {
this.getAiToken()
},
methods: {
openCore(respons) {
console.log('open sse', respons)
},
errorCore(err) {
console.log('error sse', err)
},
messageCore(msg) {
console.log('message sse', msg)
// if (msg.event == 'Done') {
// if (!that.formInfo.jobName) {
// clearInterval(that.timer)
// that.ailoading = false
// }
// } else {
// let job = JSON.parse(msg.data)
// checkDataInfo(job)
// }
},
getAiToken() {
let that = this
that.G.Get('/yishoudan/common/structure/getConfig', {}, (res) => {
console.log('res', res)
that.aiConfig = {
token: res.token,
id: res.workflowId,
}
})
},
getClipboard() {
let that = this
if (this.aitext) {
this.aitext = ''
} else {
uni.getClipboardData({
success(res) {
console.log(res)
that.aitext = res.data
},
fail() {
uni.showToast({
title: '读取剪切板失败',
icon: 'none',
})
},
})
}
},
getCoze() {
let that = this
if (!that.aitext) {
uni.showToast({
title: '请粘贴内容',
icon: 'none',
})
return false
}
//
that.ailoading = true
that.defaultPercent = 3
that.timer = setInterval(() => {
that.defaultPercent = that.defaultPercent < 15 ? (that.defaultPercent = 15) : that.defaultPercent + 1
console.log('12313123123123123')
if (that.defaultPercent >= 99) {
clearInterval(that.timer)
}
}, 500)
that.timer1 = setTimeout(() => {
console.log('5687678678678678678')
that.ailoading = false
clearInterval(that.timer)
setLoading()
}, 30000)
this.appCoze()
},
appCoze() {
let that = this
this.$refs.sseTest.startChat({
/**
* 将它换成你的地址
* 注意
* 如果使用 sse-server.js 要在手机端使用的话请确保你的手机和电脑处在一个局域网下并且是正常的ip地址
*/
url: 'https://api.coze.cn/v1/workflow/stream_run',
//
headers: {
Authorization: 'Bearer ' + that.aiConfig.token,
'Content-Type': 'application/json;charset=UTF-8',
},
// post
method: 'post',
body: {
parameters: {
notice_text: that.aitext,
},
// workflow_id: that.aiConfig.id,
workflow_id: '7492238568816656410',
},
})
},
},
}
</script>
<style>
</style>

@ -1,9 +1,9 @@
<template>
<view class="p-root-detail-fellow g_w_all g_h_all g_bg_f_5 g_kuaishou">
<view>
<view class="g_h_10"></view>
<g-panel-form-slot
:list="[
<view class="p-root-detail-fellow g_w_all g_h_all g_bg_f_5 g_kuaishou">
<view>
<AiApply class />
<view class="g_h_10"></view>
<g-panel-form-slot :list="[
{
icon: '',
label: '老乡电话',
@ -16,12 +16,10 @@
pColumn: 8,
require: true,
},
]"
@changeMobile="handleClickMobile"
></g-panel-form-slot>
<view class="g_h_10"></view>
<g-panel-form-slot
:list="[
]" @changeMobile="handleClickMobile"></g-panel-form-slot>
<view class="g_h_10"></view>
<g-panel-form-slot
:list="[
{
icon: '',
label: '姓名',
@ -96,19 +94,17 @@
pColumn: 8,
},
]"
@changeName="handleClickName"
@changeSex="handleClickSex"
@changeAge="handleClickAge"
@changeNation="handleClickNation"
@changeIDcard="handleClickIDcard"
@changeAddress="handleClickAddress"
@updateFile="updateFile"
@updateIDInfo="handlerIDInfo"
>
</g-panel-form-slot>
<view class="g_h_10"></view>
<g-panel-form-slot
:list="[
@changeName="handleClickName"
@changeSex="handleClickSex"
@changeAge="handleClickAge"
@changeNation="handleClickNation"
@changeIDcard="handleClickIDcard"
@changeAddress="handleClickAddress"
@updateFile="updateFile"
@updateIDInfo="handlerIDInfo"
></g-panel-form-slot>
<view class="g_h_10"></view>
<g-panel-form-slot :list="[
{
icon: '',
label: '上传附件',
@ -118,268 +114,271 @@
tip: 'slot-update-file',
pColumn: 16,
},
]"
@updateFile="updateFile"
>
<template v-slot:after>
<view class="g_flex_row_start g_p_10" v-if="imgList.length > 0">
<view v-for="(item, index) in imgList" class="g_position_rela" :class="index <= 2 ? 'g_mr_18' : ''" :key="index">
<i class="iconfont icon-guanbi img-close" @click="delImg(index)"></i>
<image :src="item" class="g_w_56 g_h_56 g_radius_8" />
</view>
</view> </template
></g-panel-form-slot>
<g-panel-fixed>
<slot>
<view class="g_flex_row_center">
<g-button btnText="取消" class="g_mr_16" size="small" type="default" @clickBtn="goReturn"></g-button>
<g-button btnText="确定" class=" " @clickBtn="handleSubmit" size="small" type="primary"></g-button>
</view>
</slot>
</g-panel-fixed>
</view>
</view>
]" @updateFile="updateFile">
<template v-slot:after>
<view class="g_flex_row_start g_p_10" v-if="imgList.length > 0">
<view v-for="(item, index) in imgList" class="g_position_rela" :class="index <= 2 ? 'g_mr_18' : ''" :key="index">
<i class="iconfont icon-guanbi img-close" @click="delImg(index)"></i>
<image :src="item" class="g_w_56 g_h_56 g_radius_8" />
</view>
</view>
</template>
</g-panel-form-slot>
<g-panel-fixed>
<slot>
<view class="g_flex_row_center">
<g-button btnText="取消" class="g_mr_16" size="small" type="default" @clickBtn="goReturn"></g-button>
<g-button btnText="确定" class @clickBtn="handleSubmit" size="small" type="primary"></g-button>
</view>
</slot>
</g-panel-fixed>
</view>
</view>
</template>
<script>
import { nationlist } from "../../utils/nation.js";
import AiApply from './components/AiApply.vue'
import { nationlist } from '../../utils/nation.js'
export default {
onReady() {
this.G.setNavStyle();
},
onShareAppMessage() {
return this.G.shareFun();
},
data() {
return {
cdnBaseImg: this.G.store().cdnBaseImg,
info: {
nation: "汉族",
},
nation: nationlist.map((item, index) => {
return item.name;
}),
nationIndex: 0,
imgList: [],
};
},
onLoad(options) {
let that = this;
console.log("快速报名:", options);
if (options) {
if (options.sex) {
options.sex = Number(options.sex);
} else {
options.sex = 1;
}
if (options.nation) {
options.nation = options.nation;
} else {
options.nation = "汉族";
}
this.info = options;
if (this.info.imgs) {
this.imgList = this.info.imgs.split(",");
}
}
console.log("获取老乡信息:", options);
},
onShow() {
let that = this;
// that.nation.forEach((item, index) => {
// if (item == that.info.nation) {
// console.log(that.info.nation);
// console.log(index);
// that.nationIndex = index;
// }
// });
// that.speed = 0;
// setTimeout(() => {
// }, 300);
},
created() {
let that = this;
},
methods: {
handleClickName(e) {
this.info.name = this.info.userName = e;
},
handleClickSex(e) {
this.info.sex = e;
},
handleClickAge(e) {
this.info.age = e;
},
handleClickMobile(e) {
this.info.tel = e;
},
handleClickNation(e) {
let that = this;
console.log(e.name);
this.info.nation = e.name;
that.nation.forEach((item, index) => {
if (item == e.name) {
// console.log(that.info.nation)
// console.log(index)
that.nationIndex = index;
}
});
},
/**
* 获取上传的身份信息
*/
handlerIDInfo(res) {
console.log("res", res);
let that = this;
that.info.name = res.info.name;
that.info.sex = res.info.sex ? (res.info.sex == "男" ? 1 : 2) : "";
that.info.age = res.info.age;
that.info.nation = res.info.nationality + "族";
that.info.idCard = res.info.num;
that.info.idCardImageUrl = res.image;
that.info.userName = res.info.name;
that.info.address = res.info.address;
that.nation.forEach((item, index) => {
console.log("item1", item);
console.log('that.info.nation + "族"', that.info.nation + "族");
if (item == that.info.nation) {
console.log("item2", item);
components: {
AiApply,
},
onReady() {
this.G.setNavStyle()
},
onShareAppMessage() {
return this.G.shareFun()
},
data() {
return {
cdnBaseImg: this.G.store().cdnBaseImg,
info: {
nation: '汉族',
},
nation: nationlist.map((item, index) => {
return item.name
}),
nationIndex: 0,
imgList: [],
}
},
onLoad(options) {
let that = this
console.log('快速报名:', options)
if (options) {
if (options.sex) {
options.sex = Number(options.sex)
} else {
options.sex = 1
}
if (options.nation) {
options.nation = options.nation
} else {
options.nation = '汉族'
}
this.info = options
if (this.info.imgs) {
this.imgList = this.info.imgs.split(',')
}
}
console.log('获取老乡信息:', options)
},
onShow() {
let that = this
// that.nation.forEach((item, index) => {
// if (item == that.info.nation) {
// console.log(that.info.nation);
// console.log(index);
// that.nationIndex = index;
// }
// });
// that.speed = 0;
// setTimeout(() => {
// }, 300);
},
created() {
let that = this
},
methods: {
handleClickName(e) {
this.info.name = this.info.userName = e
},
handleClickSex(e) {
this.info.sex = e
},
handleClickAge(e) {
this.info.age = e
},
handleClickMobile(e) {
this.info.tel = e
},
handleClickNation(e) {
let that = this
console.log(e.name)
this.info.nation = e.name
that.nation.forEach((item, index) => {
if (item == e.name) {
// console.log(that.info.nation)
// console.log(index)
that.nationIndex = index
}
})
},
/**
* 获取上传的身份信息
*/
handlerIDInfo(res) {
console.log('res', res)
let that = this
that.info.name = res.info.name
that.info.sex = res.info.sex ? (res.info.sex == '男' ? 1 : 2) : ''
that.info.age = res.info.age
that.info.nation = res.info.nationality + '族'
that.info.idCard = res.info.num
that.info.idCardImageUrl = res.image
that.info.userName = res.info.name
that.info.address = res.info.address
that.nation.forEach((item, index) => {
console.log('item1', item)
console.log('that.info.nation + "族"', that.info.nation + '族')
if (item == that.info.nation) {
console.log('item2', item)
that.nationIndex = index;
}
});
console.log("that.info", that.info);
console.log("that.nationIndex", that.nationIndex);
that.$forceUpdate();
},
//
delImg(ind) {
this.imgList.splice(
this.imgList.findIndex((item, index) => index == ind),
1
);
},
//
updateFile(e) {
let that = this;
if (that.imgList.length < 4) {
that.imgList.push(e);
uni.hideLoading();
} else {
uni.showToast({
title: "最多只能上传4张",
icon: "none",
});
}
},
handleClickIDcard(e) {
this.info.idCard = e;
if (this.info.idCard.length == 15 || this.info.idCard.length == 18) {
let info = this.G.getInfoByIDcard(this.info.idCard);
this.info.age = info.age;
this.info.sex = info.sex ? (info.sex == "男" ? 1 : 2) : "";
this.$forceUpdate();
}
// console.log(this.G.getInfoByIDcard(this.info.idCard));
},
handleClickAddress(e) {
this.info.address = e;
},
goReturn() {
uni.navigateBack();
},
handleSubmit() {
let that = this;
console.log("that.info.imgs", that.info.imgs);
console.log("that.imgList", that.imgList);
that.nationIndex = index
}
})
console.log('that.info', that.info)
console.log('that.nationIndex', that.nationIndex)
that.$forceUpdate()
},
//
delImg(ind) {
this.imgList.splice(
this.imgList.findIndex((item, index) => index == ind),
1
)
},
//
updateFile(e) {
let that = this
if (that.imgList.length < 4) {
that.imgList.push(e)
uni.hideLoading()
} else {
uni.showToast({
title: '最多只能上传4张',
icon: 'none',
})
}
},
handleClickIDcard(e) {
this.info.idCard = e
if (this.info.idCard.length == 15 || this.info.idCard.length == 18) {
let info = this.G.getInfoByIDcard(this.info.idCard)
this.info.age = info.age
this.info.sex = info.sex ? (info.sex == '男' ? 1 : 2) : ''
this.$forceUpdate()
}
// console.log(this.G.getInfoByIDcard(this.info.idCard));
},
handleClickAddress(e) {
this.info.address = e
},
goReturn() {
uni.navigateBack()
},
handleSubmit() {
let that = this
console.log('that.info.imgs', that.info.imgs)
console.log('that.imgList', that.imgList)
if (!that.info.name) {
uni.showToast({
icon: "none",
title: "请输入姓名",
});
return false;
}
if (!that.info.sex) {
uni.showToast({
icon: "none",
title: "请选择性别",
});
return false;
}
if (!that.info.age) {
uni.showToast({
icon: "none",
title: "请输入年龄",
});
return false;
}
if (!that.info.nation) {
uni.showToast({
icon: "none",
title: "请选择民族",
});
return false;
}
if (!that.G.setReg(that.info.tel, "tel")) {
uni.showToast({
icon: "none",
title: "请输入正确的手机号",
});
return false;
}
if (!that.G.setReg(that.info.idCard, "idcard")) {
uni.showToast({
icon: "none",
title: "请输入正确的身份证号",
});
return false;
}
console.log(that.info);
if (that.imgList.length > 0) {
that.info.imgs = that.imgList;
}
console.log("that.info.imgs", that.info.imgs);
uni.$emit("getTownsman", { info: that.info });
uni.navigateBack();
},
handleClickInfo() {
let that = this;
that.G.uploadImg((res) => {
console.log("res", res);
that.info.name = res.info.name;
that.info.sex = res.info.sex ? (res.info.sex == "男" ? 1 : 2) : "";
that.info.age = res.info.age;
that.info.nation = res.info.nationality;
that.info.idCard = res.info.num;
that.info.idCardImageUrl = res.image;
that.info.userName = res.info.name;
that.info.address = res.info.address;
that.nation.forEach((item, index) => {
if (item == that.info.nation) {
that.nationIndex = index;
}
});
that.$forceUpdate();
}, "idcard");
},
},
};
if (!that.info.name) {
uni.showToast({
icon: 'none',
title: '请输入姓名',
})
return false
}
if (!that.info.sex) {
uni.showToast({
icon: 'none',
title: '请选择性别',
})
return false
}
if (!that.info.age) {
uni.showToast({
icon: 'none',
title: '请输入年龄',
})
return false
}
if (!that.info.nation) {
uni.showToast({
icon: 'none',
title: '请选择民族',
})
return false
}
if (!that.G.setReg(that.info.tel, 'tel')) {
uni.showToast({
icon: 'none',
title: '请输入正确的手机号',
})
return false
}
if (!that.G.setReg(that.info.idCard, 'idcard')) {
uni.showToast({
icon: 'none',
title: '请输入正确的身份证号',
})
return false
}
console.log(that.info)
if (that.imgList.length > 0) {
that.info.imgs = that.imgList
}
console.log('that.info.imgs', that.info.imgs)
uni.$emit('getTownsman', { info: that.info })
uni.navigateBack()
},
handleClickInfo() {
let that = this
that.G.uploadImg((res) => {
console.log('res', res)
that.info.name = res.info.name
that.info.sex = res.info.sex ? (res.info.sex == '男' ? 1 : 2) : ''
that.info.age = res.info.age
that.info.nation = res.info.nationality
that.info.idCard = res.info.num
that.info.idCardImageUrl = res.image
that.info.userName = res.info.name
that.info.address = res.info.address
that.nation.forEach((item, index) => {
if (item == that.info.nation) {
that.nationIndex = index
}
})
that.$forceUpdate()
}, 'idcard')
},
},
}
</script>
<style>
.img-close {
position: absolute;
width: 18px;
height: 18px;
right: -6px;
top: -6px;
z-index: 99;
background-color: #666;
color: #fff;
font-size: 8px;
text-align: center;
line-height: 18px;
border-radius: 50%;
position: absolute;
width: 18px;
height: 18px;
right: -6px;
top: -6px;
z-index: 99;
background-color: #666;
color: #fff;
font-size: 8px;
text-align: center;
line-height: 18px;
border-radius: 50%;
}
</style>

@ -1,7 +1,9 @@
<template>
<view class="p-root-home-quick g_w_all g_bg_f_5 g_kuaishou">
<AiApply class=""/>
<view class="">
<view class="card-tip g_pt_24 g_pb_8 g_pl_20 g_c_6">老乡信息</view>
<view class="card-tip g_pt_12 g_pb_8 g_pl_20 g_c_6">老乡信息</view>
<view>
<view class="g_bg_f g_pl_15 g_pr_15 g_pt_10 g_ml_10 g_mr_10 g_radius_8 g_mb_12"
v-for="(item, index) in persenInfo" :key="index"
@ -54,7 +56,7 @@
</view>
</view>
</view>
<view class="g_flex_row_center flex_center g_flex_1 g_h_48 g_bg_f g_fs_16 g_c_main g_ml_10 g_mr_10 g_radius_8" @click="goFellow('')" v-if="persenInfo.length <= 2">
<view class="g_flex_row_center flex_center g_flex_1 g_h_48 g_bg_f g_fs_16 g_c_main g_ml_10 g_mr_10 g_radius_8" @click="goFellow('')" v-if="persenInfo.length <= 5">
<!-- <view class="g_w_18 g_h_18 g_mr_6 g_text_c g_radius_20 g_border_main g_fsi_18" style="line-height: 13px">+</view> -->
<view class="g_flex_column_center">
<i class="iconfont icon-jia1 g_c_min g_mr_6" style="font-size: 18px"></i>
@ -102,8 +104,11 @@
<script>
import { nationlist } from "../../utils/nation.js";
import dateUtil from "../../utils/dateUtil.js";
console.log("dateUtil", dateUtil);
import AiApply from "./components/AiApply.vue"
export default {
components:{
AiApply
},
onReady() {
this.G.setNavStyle();
let that = this;
@ -432,8 +437,54 @@ export default {
});
return false;
}
that.persenInfo.forEach((item) => {
that.submitFormSub(item);
let submitInfo = {
...that.updateInfo,
}
submitInfo.applyUserJson = JSON.stringify(
that.persenInfo.map((item) => {
return {
// interviewTime: dayjs(item.interviewTime).format("YYYY-MM-DD HH:mm"),
// receptionTime: item.receptionTime ? dayjs(item.receptionTime).format("YYYY-MM-DD HH:mm") : dayjs(item.interviewTime).format("YYYY-MM-DD HH:mm"),
idCard: item.idCard,
idCardImageUrl: item.idCardImageUrl,
userName: item.userName,
sex: item.sex,
age: item.age,
nation: item.nation,
tel: item.tel,
address: item.address,
images:
item.fujianGroup && item.fujianGroup.length > 0
? item.fujianGroup
.map((itm) => {
return itm.thumbUrl
})
.join(',')
: '',
// desp: item.desp,
// policyIdx: item.policyIdx,
// pickerStr: item.pickerStr,
}
})
)
console.log('submitInfo',submitInfo);
// return
that.G.Post('/yishoudan/common/order/addBatch', submitInfo, (res) => {
// uni.hideLoading();
uni.showToast({
icon: "success",
title: "报名成功",
duration: 2000,
});
// that.persenInfo = [];
// that.$forceUpdate();
setTimeout(() => {
uni.navigateTo({
url: "/root/home/applicationSuccess",
});
}, 1500);
});
},
submitFormSub($item) {

@ -1,234 +1,235 @@
<template>
<view class="p-bill-index g_w_all g_h_all g_bg_f_5 g_kuaishou">
<view class="m-search g_flex_row_between flex_center g_bg_f g_pl_10 g_pr_10 g_pb_8 g_pt_6 g_mb_10">
<u-search class="g_flex_1" :focus="true" @btnSearch="getSearch" height="80" v-model="keyword" :placeholder="placeholder" bg-color="#ededed" :show-action="false" @change="getSearch" @clear="getSearch" @custom="getSearch" @search="getSearch" search-icon-color="#999999" :maxlength="20"></u-search>
<view class="g_ml_8 g_fs_16" style="color: #576b95" hover-class="thover" @click="backPrev"></view>
</view>
<view v-if="whichPage == 'home' || whichPage == 'record'">
<g-list-job @uploadList="getList" :list="jobQuery.list" v-if="keyword || whichPage == 'record'" :from="whichPage" :loading="loading" :speed="speed" :query="jobQuery" emptyText="暂无搜索结果" emptySubText=" " />
</view>
<view v-if="whichPage == 'bill'">
<g-list-job @uploadList="getList" :list="jobQuery.list" v-if="keyword" :loading="loading" :speed="speed" :query="jobQuery" emptyText="暂无搜索结果" emptySubText=" " />
</view>
<view v-if="whichPage == 'apply'">
<g-list-apply @uploadList="getApplyList('concat')" :list="jobQuery.list" v-if="keyword" :tabActive="applyType" from="home" bg="" class="g_bg_f" @shareJob="shareJob" :loading="loading" :speed="speed" :isLogin="true" :query.sync="jobQuery" :navInfo="navInfo" />
</view>
</view>
<view class="p-bill-index g_w_all g_h_all g_bg_f_5 g_kuaishou">
<view class="m-search g_flex_row_between flex_center g_bg_f g_pl_10 g_pr_10 g_pb_8 g_pt_6 g_mb_10">
<u-search class="g_flex_1" :focus="true" @btnSearch="getSearch" height="80" v-model="keyword" :placeholder="placeholder" bg-color="#ededed" :show-action="false" @change="getSearch" @clear="getSearch" @custom="getSearch" @search="getSearch" search-icon-color="#999999" :maxlength="20"></u-search>
<view class="g_ml_8 g_fs_16" style="color: #576b95" hover-class="thover" @click="backPrev"></view>
</view>
<view v-if="whichPage == 'home' || whichPage == 'record'">
<g-list-job @uploadList="getList" :list="jobQuery.list" v-if="keyword || whichPage == 'record'" :from="whichPage" :loading="loading" :speed="speed" :query="jobQuery" emptyText="暂无搜索结果" emptySubText=" " />
</view>
<view v-if="whichPage == 'bill'">
<g-list-job @uploadList="getList" :list="jobQuery.list" v-if="keyword" :loading="loading" :speed="speed" :query="jobQuery" emptyText="暂无搜索结果" emptySubText=" " />
</view>
<view v-if="whichPage == 'apply'">
<g-list-apply @uploadList="getApplyList('concat')" :list="jobQuery.list" v-if="keyword" :tabActive="applyType" from="home" bg class="g_bg_f" @shareJob="shareJob" :loading="loading" :speed="speed" :isLogin="true" :query.sync="jobQuery" :navInfo="navInfo" />
</view>
</view>
</template>
<script>
export default {
onReady() {
this.G.setNavStyle();
},
onShareAppMessage() {
return this.G.shareFun();
},
onLoad(options) {
console.log(options);
this.whichPage = options.from;
if (this.whichPage == "record" || this.whichPage == "home") {
this.placeholder = "搜索职位名称";
uni.setNavigationBarTitle({
title: "搜索职位",
});
this.getList();
} else if (this.whichPage == "apply") {
// 0 1
this.applyType = options.active;
this.placeholder = "搜索姓名/职位/手机号";
uni.setNavigationBarTitle({
title: "搜索工单",
});
this.getApplyList();
}
},
//
name: "",
//
components: {},
//
props: {},
//
data() {
return {
whichPage: "",
keyword: "",
loading: true,
speed: -1,
applyType: 0,
jobQuery: {
page: 1,
size: 50,
list: [],
isFinish: -1,
},
placeholder: "搜索职位名称",
navInfo: {},
};
},
//
computed: {},
//
watch: {},
created() {},
mounted() {},
onShow() {
let that = this;
that.navInfo = that.G.getNavInfo();
},
//
methods: {
getSearch(e) {
console.log(e);
this.speed = -1;
this.keyword = e;
this.jobQuery.page = 1;
console.log(this.whichPage);
if (this.whichPage == "home" || this.whichPage == "record") {
this.getList();
} else if (this.whichPage == "apply") {
this.getApplyList();
}
},
backPrev() {
console.log("backPrev");
uni.navigateBack({
delta: 1,
});
},
getList($type = "init") {
let that = this;
that.G.Post(
that.api.job_list,
{
pageNum: that.jobQuery.page,
pageSize: that.jobQuery.size,
agencyId: that.whichPage == "home" || that.whichPage == "record" ? "" : uni.getStorageSync("apply-agencyId"),
keys: that.keyword,
recruitment: 1,
},
(res) => {
console.log("res", res);
if (res.recordCount == 0) {
that.loading = false;
} else {
that.loading = true;
}
that.speed = res.recordCount;
that.jobQuery.isFinish = res.recordList.length;
res.recordList = that.G.toGetAddressv3(res.recordList);
res.recordList = that.G.toGetAge(res.recordList);
res.recordList = that.G.yijobCopy(res.recordList);
if ($type == "init") {
that.jobQuery.list = [];
if (res.recordList.length > 0) {
that.jobQuery.list = res.recordList.map((item, index) => {
// console.log(item)
return {
...item,
title: item.jobName,
address: item.district + "丨" + item.age,
price: item.salaryClassify != 7 ? that.G.getSalaryClassifyValue(item.salaryClassify, item.salaryClassifyValue) : that.G.getSalaryClassifyValue(item.salaryClassify, item.minMonthlyPay, item.maxMonthlyPay),
logo: item.agencyLogo,
fuWuFei: that.G.setReturnFee(item.returnFee, item.returnFeeType),
gender: that.G.getGenderByMinAge(item),
time: that.G.setDeadLine(item.updateTime, "jiaofu"),
leafCateId: item.id,
// serverPrice: that.G.setReturnFee(item.returnFee, item.returnFeeType),
serverPrice: that.G.setReturnFee(item.agencyReturnFee, item.agencyReturnFeeType),
recruitmentSwitch: item.recruitment == 1 ? true : false,
recruitmentImage: item.recruitment,
isToday: item.today == 0 ? false : true,
active: 0,
};
});
}
} else {
that.jobQuery.list = that.jobQuery.list.concat(
res.recordList.map((item, index) => {
return {
...item,
title: item.jobName,
address: item.district + "丨" + item.age,
price: item.salaryClassify != 7 ? that.G.getSalaryClassifyValue(item.salaryClassify, item.salaryClassifyValue) : that.G.getSalaryClassifyValue(item.salaryClassify, item.minMonthlyPay, item.maxMonthlyPay),
logo: item.agencyLogo,
fuWuFei: that.G.setReturnFee(item.returnFee, item.returnFeeType),
gender: that.G.getGenderByMinAge(item),
time: that.G.setDeadLine(item.updateTime, "jiaofu"),
leafCateId: item.id,
// serverPrice: that.G.setReturnFee(item.returnFee, item.returnFeeType),
serverPrice: that.G.setReturnFee(item.agencyReturnFee, item.agencyReturnFeeType),
recruitmentSwitch: item.recruitment == 1 ? true : false,
recruitmentImage: item.recruitment,
isToday: item.today == 0 ? false : true,
active: 0,
};
})
);
}
if (that.whichPage == "record") {
that.jobQuery.list = that.jobQuery.list.filter((item) => {
return item.recruitmentImage == 1;
});
that.speed = that.jobQuery.list.length;
}
console.log("that.jobQuery.list", that.jobQuery.list);
console.log("speed", that.speed);
// that.loading = false;
}
);
},
/**
* 获取工单列表
*/
getApplyList($type = "init") {
let that = this;
that.G.Post(
that.api.order_list_new,
{
pageNum: that.jobQuery.page,
pageSize: that.jobQuery.size,
keys: that.keyword,
classify: that.applyType + 1,
status: "",
},
(res) => {
if (res.recordCount == 0) {
that.loading = false;
} else {
that.loading = true;
}
that.$forceUpdate();
that.speed = res.recordCount;
that.jobQuery.isFinish = res.recordList.length;
if (that.speed > 0) {
// uni.setBackgroundColor({
// backgroundColorBottom: "#ffffff",
// });
res.recordList.forEach((item, index) => {
item.time = that.G.getPointTime(item.updateTime, "MM--DD HH:MM");
item.status_text = that.G.getOrderStatus().filter((itm, inx) => {
return itm.id == item.status;
})[0].name;
item.setTitle = that.G.titleToStr(item);
});
} else {
// uni.setBackgroundColor({
// backgroundColorBottom: "#ededed",
// });
}
if ($type == "init") {
that.jobQuery.list = res.recordList;
// that.query.list = [...res.recordList, ...res.recordList, ...res.recordList, ...res.recordList, ...res.recordList];
} else {
that.jobQuery.list = that.jobQuery.list.concat(res.recordList);
}
}
);
},
},
};
onReady() {
this.G.setNavStyle()
},
onShareAppMessage() {
return this.G.shareFun()
},
onLoad(options) {
console.log(options)
this.whichPage = options.from
if (this.whichPage == 'record' || this.whichPage == 'home') {
this.placeholder = '搜索职位名称'
uni.setNavigationBarTitle({
title: '搜索职位',
})
this.getList()
} else if (this.whichPage == 'apply') {
// 0 1
this.applyType = options.active
this.placeholder = '搜索姓名/职位/手机号'
uni.setNavigationBarTitle({
title: '搜索工单',
})
this.getApplyList()
}
},
//
name: '',
//
components: {},
//
props: {},
//
data() {
return {
whichPage: '',
keyword: '',
loading: true,
speed: -1,
applyType: 0,
jobQuery: {
page: 1,
size: 50,
list: [],
isFinish: -1,
},
placeholder: '搜索职位名称',
navInfo: {},
}
},
//
computed: {},
//
watch: {},
created() {},
mounted() {},
onShow() {
let that = this
that.navInfo = that.G.getNavInfo()
},
//
methods: {
getSearch(e) {
console.log(e)
this.speed = -1
this.keyword = e
this.jobQuery.page = 1
console.log(this.whichPage)
if (this.whichPage == 'home' || this.whichPage == 'record') {
this.getList()
} else if (this.whichPage == 'apply') {
this.getApplyList()
}
},
backPrev() {
console.log('backPrev')
uni.navigateBack({
delta: 1,
})
},
getList($type = 'init') {
let that = this
let jobConfig = {
pageNum: that.jobQuery.page,
pageSize: that.jobQuery.size,
agencyId: that.whichPage == 'home' || that.whichPage == 'record' ? '' : uni.getStorageSync('apply-agencyId'),
classify: 2,
keys: that.keyword,
recruitment: 1,
}
that.G.Post(that.api.job_list, jobConfig, (res) => {
console.log('res', res)
if (res.recordCount == 0) {
that.loading = false
} else {
that.loading = true
}
that.speed = res.recordCount
that.jobQuery.isFinish = res.recordList.length
res.recordList = that.G.toGetAddressv3(res.recordList)
res.recordList = that.G.toGetAge(res.recordList)
res.recordList = that.G.yijobCopy(res.recordList)
if ($type == 'init') {
that.jobQuery.list = []
if (res.recordList.length > 0) {
that.jobQuery.list = res.recordList.map((item, index) => {
// console.log(item)
return {
...item,
title: item.jobName,
address: item.district + '丨' + item.age,
price: item.salaryClassify != 7 ? that.G.getSalaryClassifyValue(item.salaryClassify, item.salaryClassifyValue) : that.G.getSalaryClassifyValue(item.salaryClassify, item.minMonthlyPay, item.maxMonthlyPay),
logo: item.agencyLogo,
fuWuFei: that.G.setReturnFee(item.returnFee, item.returnFeeType),
gender: that.G.getGenderByMinAge(item),
time: that.G.setDeadLine(item.updateTime, 'jiaofu'),
leafCateId: item.id,
// serverPrice: that.G.setReturnFee(item.returnFee, item.returnFeeType),
serverPrice: that.G.setReturnFee(item.agencyReturnFee, item.agencyReturnFeeType),
recruitmentSwitch: item.recruitment == 1 ? true : false,
recruitmentImage: item.recruitment,
isToday: item.today == 0 ? false : true,
active: 0,
}
})
}
} else {
that.jobQuery.list = that.jobQuery.list.concat(
res.recordList.map((item, index) => {
return {
...item,
title: item.jobName,
address: item.district + '丨' + item.age,
price: item.salaryClassify != 7 ? that.G.getSalaryClassifyValue(item.salaryClassify, item.salaryClassifyValue) : that.G.getSalaryClassifyValue(item.salaryClassify, item.minMonthlyPay, item.maxMonthlyPay),
logo: item.agencyLogo,
fuWuFei: that.G.setReturnFee(item.returnFee, item.returnFeeType),
gender: that.G.getGenderByMinAge(item),
time: that.G.setDeadLine(item.updateTime, 'jiaofu'),
leafCateId: item.id,
// serverPrice: that.G.setReturnFee(item.returnFee, item.returnFeeType),
serverPrice: that.G.setReturnFee(item.agencyReturnFee, item.agencyReturnFeeType),
recruitmentSwitch: item.recruitment == 1 ? true : false,
recruitmentImage: item.recruitment,
isToday: item.today == 0 ? false : true,
active: 0,
}
})
)
}
if (that.whichPage == 'record') {
that.jobQuery.list = that.jobQuery.list.filter((item) => {
return item.recruitmentImage == 1
})
that.speed = that.jobQuery.list.length
}
console.log('that.jobQuery.list', that.jobQuery.list)
console.log('speed', that.speed)
// that.loading = false;
})
},
/**
* 获取工单列表
*/
getApplyList($type = 'init') {
let that = this
that.G.Post(
that.api.order_list_new,
{
pageNum: that.jobQuery.page,
pageSize: that.jobQuery.size,
keys: that.keyword,
classify: that.applyType + 1,
status: '',
},
(res) => {
if (res.recordCount == 0) {
that.loading = false
} else {
that.loading = true
}
that.$forceUpdate()
that.speed = res.recordCount
that.jobQuery.isFinish = res.recordList.length
if (that.speed > 0) {
// uni.setBackgroundColor({
// backgroundColorBottom: "#ffffff",
// });
res.recordList.forEach((item, index) => {
item.time = that.G.getPointTime(item.updateTime, 'MM--DD HH:MM')
item.status_text = that.G.getOrderStatus().filter((itm, inx) => {
return itm.id == item.status
})[0].name
item.setTitle = that.G.titleToStr(item)
})
} else {
// uni.setBackgroundColor({
// backgroundColorBottom: "#ededed",
// });
}
if ($type == 'init') {
that.jobQuery.list = res.recordList
// that.query.list = [...res.recordList, ...res.recordList, ...res.recordList, ...res.recordList, ...res.recordList];
} else {
that.jobQuery.list = that.jobQuery.list.concat(res.recordList)
}
}
)
},
},
}
</script>
<style scoped lang="less"></style>

@ -0,0 +1,13 @@
## 1.5.02025-04-01
返回完整的message、小程序解析逻辑优化改为使用fetch-event-source的解析逻辑
## 1.4.12025-03-28
onOepn回调方法返回sse请求的response对象、及返回err错误信息
## 1.4.02025-03-24
解析微信小程序返回的数据
## 1.3.22025-03-16
1. 示例项目添加了sse server供调试。
2. 发生了错误接口会无限运行的问题解决现在发生了错误会调用stop方法停止。
## 1.3.12025-03-10
修复了get请求无法stop的bug
## 1.3.02025-03-06
插件修改为 uni_modules 模式

@ -0,0 +1,126 @@
<script>
export default {
props: {},
data() {
return {
stopCount: 0,
renderjsData: {
url: "",
key: 0,
body: "",
method: ""
}
}
},
methods: {
stopChat() {
this.stopCount += 1
},
/**
* 开始chat对话
*/
startChat(config) {
const { body } = config;
this.renderjsData = Object.assign({}, this.renderjsData, {
key: this.renderjsData.key + 1,
...config,
body: body ? JSON.stringify(body) : 0,
});
},
open(...args) {
this.$emit("onInnerOpen", ...args)
},
message(msg) {
this.$emit("onInnerMessage", msg)
},
error(...args) {
this.$emit("onInnerError", ...args)
this.stopChat();
},
finish() {
this.$emit("onInnerFinish")
}
},
}
</script>
<script module="chat" lang="renderjs">
import { fetchEventSource } from '../fetch-event-source';
export default {
data() {
return {
ctrl: null,
}
},
methods: {
objToJson(obj) {
const json = {};
for (const key in obj) {
const val = obj[key];
if (typeof val === "string" || typeof val === 'number' || typeof val === 'boolean') {
json[key] = val;
}
}
return json;
},
/**
* 停止生成
*/
stopChatCore() {
this.ctrl?.abort();
},
/**
* 开始对话
*/
startChatCore({ url, body, headers, method }) {
if (!url) return;
try {
this.ctrl = new AbortController();
fetchEventSource(
url,
{
readJson: true,
method,
openWhenHidden: true,
signal: this.ctrl.signal,
headers: {
"Content-Type": "application/json",
...headers,
},
body: body ? body : undefined,
onopen: (response) => {
this.$ownerInstance.callMethod('open', this.objToJson(response));
},
onmessage: (data) => {
this.$ownerInstance.callMethod('message', data);
},
onerror: (err) => {
console.log(err)
this.$ownerInstance.callMethod('error', JSON.stringify(err));
},
}).then(() => {
this.$ownerInstance.callMethod('finish');
}).catch(err => {
console.log(err)
this.$ownerInstance.callMethod('error', err);
})
} catch (e) {
console.log(e);
}
}
}
}
</script>
<template>
<view
:renderjsData="renderjsData"
:change:renderjsData="chat.startChatCore"
:stopCount="stopCount"
:change:stopCount="chat.stopChatCore"
/>
</template>

@ -0,0 +1,74 @@
<script>
import {getLines, getMessages} from "../fetch-event-source/parse"
let requestTask;
export default {
props: {},
data() {
return {
onChunk: undefined
}
},
mounted() {
const onLine = getMessages(() => {}, () => {}, (line) => {
this.$emit("onInnerMessage", line)
})
this.onChunk = getLines(onLine);
},
methods: {
stopChat() {
requestTask.offChunkReceived(this.listener)
requestTask.abort();
},
decode(data) {
return decodeURIComponent(escape(String.fromCharCode(...data)));
},
/**
* 开始chat对话
* @param body
* @param url
* @param headers
* @param method
*/
startChat({ body, url, headers, method }) {
requestTask = uni.request({
url: url,
method,
header: {
Accept: 'text/event-stream',
...headers,
},
data: body,
enableChunked: true,
responseType: 'arraybuffer',
success: (res) => {
},
fail: (error) => {
this.$emit("onInnerError", error)
},
complete: () => {
this.$emit("onInnerFinish")
},
});
requestTask.onChunkReceived(this.listener)
this.$emit("onInnerOpen", requestTask)
},
listener({ data }) {
const type = Object.prototype.toString.call(data);
if (type ==="[object Uint8Array]") {
} else if (data instanceof ArrayBuffer) {
data = new Uint8Array(data);
}
this.onChunk(data)
},
},
}
</script>
<template>
<view />
</template>

@ -0,0 +1,89 @@
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
import { getBytes, getLines, getMessages } from './parse';
export const EventStreamContentType = 'text/event-stream';
const DefaultRetryInterval = 1000;
const LastEventId = 'last-event-id';
export function fetchEventSource(input, _a) {
var { signal: inputSignal, headers: inputHeaders, onopen: inputOnOpen, onmessage, onclose, onerror, openWhenHidden, fetch: inputFetch } = _a, rest = __rest(_a, ["signal", "headers", "onopen", "onmessage", "onclose", "onerror", "openWhenHidden", "fetch"]);
return new Promise((resolve, reject) => {
const headers = Object.assign({}, inputHeaders);
if (!headers.accept) {
headers.accept = EventStreamContentType;
}
let curRequestController;
function onVisibilityChange() {
curRequestController.abort();
if (!document.hidden) {
create();
}
}
if (!openWhenHidden) {
document.addEventListener('visibilitychange', onVisibilityChange);
}
let retryInterval = DefaultRetryInterval;
let retryTimer = 0;
function dispose() {
document.removeEventListener('visibilitychange', onVisibilityChange);
window.clearTimeout(retryTimer);
curRequestController.abort();
}
inputSignal === null || inputSignal === void 0 ? void 0 : inputSignal.addEventListener('abort', () => {
dispose();
resolve();
});
const fetch = inputFetch !== null && inputFetch !== void 0 ? inputFetch : window.fetch;
const onopen = inputOnOpen !== null && inputOnOpen !== void 0 ? inputOnOpen : defaultOnOpen;
async function create() {
var _a;
curRequestController = new AbortController();
try {
const response = await fetch(input, Object.assign(Object.assign({}, rest), { headers, signal: curRequestController.signal }));
await onopen(response);
await getBytes(response.body, getLines(getMessages(id => {
if (id) {
headers[LastEventId] = id;
}
else {
delete headers[LastEventId];
}
}, retry => {
retryInterval = retry;
}, onmessage)));
onclose === null || onclose === void 0 ? void 0 : onclose();
dispose();
resolve();
}
catch (err) {
if (!curRequestController.signal.aborted) {
try {
const interval = (_a = onerror === null || onerror === void 0 ? void 0 : onerror(err)) !== null && _a !== void 0 ? _a : retryInterval;
window.clearTimeout(retryTimer);
retryTimer = window.setTimeout(create, interval);
}
catch (innerErr) {
dispose();
reject(innerErr);
}
}
}
}
create();
});
}
function defaultOnOpen(response) {
const contentType = response.headers.get('content-type');
if (!(contentType === null || contentType === void 0 ? void 0 : contentType.startsWith(EventStreamContentType))) {
throw new Error(`Expected content-type to be ${EventStreamContentType}, Actual: ${contentType}`);
}
}
//# sourceMappingURL=fetch.js.map

@ -0,0 +1,2 @@
export { fetchEventSource, EventStreamContentType } from './fetch';
//# sourceMappingURL=index.js.map

@ -0,0 +1,128 @@
export async function getBytes(stream, onChunk) {
const reader = stream.getReader();
let result;
while (!(result = await reader.read()).done) {
onChunk(result.value);
}
}
export function getLines(onLine) {
let buffer;
let position;
let fieldLength;
let discardTrailingNewline = false;
return function onChunk(arr) {
if (buffer === undefined) {
buffer = arr;
position = 0;
fieldLength = -1;
}
else {
buffer = concat(buffer, arr);
}
const bufLength = buffer.length;
let lineStart = 0;
while (position < bufLength) {
if (discardTrailingNewline) {
if (buffer[position] === 10) {
lineStart = ++position;
}
discardTrailingNewline = false;
}
let lineEnd = -1;
for (; position < bufLength && lineEnd === -1; ++position) {
switch (buffer[position]) {
case 58:
if (fieldLength === -1) {
fieldLength = position - lineStart;
}
break;
case 13:
discardTrailingNewline = true;
case 10:
lineEnd = position;
break;
}
}
if (lineEnd === -1) {
break;
}
onLine(buffer.subarray(lineStart, lineEnd), fieldLength);
lineStart = position;
fieldLength = -1;
}
if (lineStart === bufLength) {
buffer = undefined;
}
else if (lineStart !== 0) {
buffer = buffer.subarray(lineStart);
position -= lineStart;
}
};
}
export function getMessages(onId, onRetry, onMessage) {
let message = newMessage();
let decoder;
// #ifdef MP-WEIXIN
decoder = {
decode(arraybuffer) {
return decodeURIComponent(escape(String.fromCharCode(...arraybuffer)))
}
};
// #endif
// #ifdef APP-PLUS || H5
decoder = new TextDecoder();
// #endif
return function onLine(line, fieldLength) {
if (line.length === 0) {
onMessage === null || onMessage === void 0 ? void 0 : onMessage(message);
message = newMessage();
}
else if (fieldLength > 0) {
const field = decoder.decode(line.subarray(0, fieldLength));
const valueOffset = fieldLength + (line[fieldLength + 1] === 32 ? 2 : 1);
const value = decoder.decode(line.subarray(valueOffset));
switch (field) {
case 'data':
message.data = message.data
? message.data + '\n' + value
: value;
break;
case 'event':
message.event = value;
break;
case 'id':
onId(message.id = value);
break;
case 'retry':
const retry = parseInt(value, 10);
if (!isNaN(retry)) {
onRetry(message.retry = retry);
}
break;
default:
const msg = decoder.decode(line, { stream: true });
message.data = msg
onMessage(message);
break;
}
}
};
}
function concat(a, b) {
const res = new Uint8Array(a.length + b.length);
res.set(a);
res.set(b, a.length);
return res;
}
function newMessage() {
return {
data: '',
event: '',
id: '',
retry: undefined,
};
}
//# sourceMappingURL=parse.js.map

@ -0,0 +1,58 @@
<template>
<!-- #ifdef MP-WEIXIN-->
<ChatWxApplet ref="chatRef" @onInnerOpen="open" @onInnerError="error" @onInnerMessage="message" @onInnerFinish="finish" />
<!-- #endif-->
<!-- #ifdef APP-PLUS || H5-->
<ChatAppAndWeb ref="chatRef" @onInnerOpen="open" @onInnerError="error" @onInnerMessage="message" @onInnerFinish="finish" />
<!-- #endif-->
</template>
<script>
// #ifdef MP-WEIXIN
import ChatWxApplet from "./children/ChatWxApplet.vue";
// #endif
// #ifdef APP-PLUS || H5
import ChatAppAndWeb from "./children/ChatAppAndWeb.vue";
// #endif
export default {
components: {
// #ifdef MP-WEIXIN
ChatWxApplet,
// #endif
// #ifdef APP-PLUS || H5
ChatAppAndWeb,
// #endif
},
methods: {
startChat(config) {
config["method"] = (config["method"] || "post").toUpperCase();
config["headers"] = config["headers"] || {};
console.log("this.$refs['chatRef']", this.$refs["chatRef"]);
this.$refs["chatRef"].startChat(config);
},
stopChat(...args) {
console.log("this.$refs['chatRef']stopChat", this.$refs["chatRef"]);
this.$refs["chatRef"].stopChat(...args);
},
open(...args) {
this.$emit("onOpen", ...args);
},
message(msg) {
this.$emit("onMessage", msg);
},
error(...args) {
this.$emit("onError", ...args);
},
finish() {
this.$emit("onFinish");
},
},
};
</script>

@ -0,0 +1,45 @@
// 检索字符,并且加上该字符的长度
const indexOfLen = (str) => {
const startIndex = str.indexOf(str);
if (startIndex !== -1) {
return startIndex + str.length
}
return -1;
}
/**
* 解析SSE数据
* sse返回的数据可能会有多个消息相连这里处理字符串返回数组
* @param data sse字符串数据
* @returns {*} 处理过后的数组
*/
export const parseSseData = (data) => {
try {
let lines = data.split("\n");
lines = lines.map(v => {
if (!v) return null;
let startInd = -1;
for (const ind of [indexOfLen("data: "), v.indexOf("{")]) {
if (ind !== -1) {
startInd = ind;
break;
}
}
if (startInd === -1) {
return v;
} else {
return v.substring(startInd, v.length).trim();
}
}).filter(Boolean);
return lines;
} catch (e) {
console.warn("解析失败:", e);
return data;
}
}

@ -0,0 +1,65 @@
{
"id": "gao-ChatSSEClient",
"name": "sse 客户端组件支持兼容v2、v3、安卓、ios、浏览器、微信小程序",
"displayName": "sse 客户端组件支持兼容v2、v3、安卓、ios、浏览器、微信小程序",
"version": "1.5.0",
"description": "sse 客户端组件支持兼容v2、v3、安卓、ios、浏览器、微信小程序",
"repository": "https://github.com/gaozhenqiang/uniapp-chatSSEClient",
"keywords": [
"sse",
"chat",
"微信小程序sse",
"流式接口",
"流式输出"
],
"dcloudext": {
"declaration": {
"ads": "无",
"data": "插件不采集任何数据",
"permissions": "无"
},
"contact": {
"qq": "1933669775"
},
"type": "component-vue",
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
}
},
"uni_modules": {
"platforms": {
"client": {
"Vue": {
"vue2": "y",
"vue3": "y"
},
"App": {
"app-vue": "y",
"app-harmony": "u",
"app-nvue": "u",
"app-uvue": "u"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y"
}
}
}
}
}

@ -0,0 +1,125 @@
# sse 客户端组件支持v2、v3、安卓、ios、浏览器、微信小程序
## 使用说明
### 导入组件
点击右上角 `下载插件并导入HBuilderX`
uniapp插件地址https://ext.dcloud.net.cn/plugin?id=20971
或者你可以参考我的示例
### 示例代码
```javascript
<template>
<button @click="start">开始</button>
<button @click="stop">停止</button>
<template v-if="loading">
<view>{{ openLoading ? "正在连接sse..." : '连接完成!' }}</view>
<view>{{ loading ? "加载中..." : '' }}</view>
</template>
<view>
{{ responseText }}
</view>
<gao-ChatSSEClient
ref="chatSSEClientRef"
@onOpen="openCore"
@onError="errorCore"
@onMessage="messageCore"
@onFinish="finishCore"
/>
</template>
<script setup>
import { ref } from 'vue'
const chatSSEClientRef = ref(null);
const responseText = ref("");
const loading = ref(false);
const openLoading = ref(false);
const openCore = (response) => {
openLoading.value = false;
console.log("open sse", response);
}
const errorCore = (err) => {
console.log("error sse", err);
}
const messageCore = (msg) => {
console.log("message sse", msg);
responseText.value += `${msg}\n`
}
const finishCore = () => {
console.log("finish sse")
loading.value = false;
}
const start = () => {
if (loading.value) return;
openLoading.value = true;
loading.value = true;
responseText.value = "";
chatSSEClientRef.value.startChat({
/**
* 将它换成你的地址
* 注意:
* 如果使用 sse-server.js 要在手机端使用的话请确保你的手机和电脑处在一个局域网下并且是正常的ip地址
*/
url: import.meta.env.VITE_CHAT_URL || 'http://localhost:3000/sse',
// 请求头
headers: {
Authorization: import.meta.env.VITE_CHAT_AUTHORIZATION,
},
// 默认为 post
method: 'post',
body: {
"stream":true,
"model": "deepseek-chat",
"messages": [
{"role": "system", "content": "你是来自艺咖科技的数字员工,你的名字叫小咖。"}]
}
})
}
const stop = () => {
chatSSEClientRef.value.stopChat()
console.log("stop");
}
</script>
```
# 温馨提示
示例项目根目录的`sse-server.js`文件提供了一个简单的sse测试服务使用 `node sse-server.js`运行
**提出问题之前请先确保你的接口没有问题**
---
**请仔细阅读我提供的示例代码。**
**如果你的程序有问题请先下载我提供的示例项目调试!**
---
如果想了解原理请看我掘金的文章: [点击前往](https://juejin.cn/post/7435632766375084082)
本插件依赖于 `fetch-event-source`将编辑后的js集成因为我修改了原来库解析的逻辑使其更适用于中国宝宝体质。
---
**如果这个组件解决了你的问题,麻烦去[github](https://github.com/gaozhenqiang/uniapp-chatSSEClient/) 帮我点个赞,谢谢大家**
有新需求或者bug可以在github上提issues或者加我q `1933669775`
# 常见问题
## ios报错TypeError: Load failed
后端接口处理一下跨域即可解决。
Loading…
Cancel
Save