first commit
This commit is contained in:
@@ -0,0 +1,178 @@
|
||||
<template>
|
||||
<view class="min-height bg-main-light">
|
||||
<HeaderItem title="AI律师咨询"/>
|
||||
<view style="line-height: 35rpx"
|
||||
class="flex flex-col justify-start items-start text-25 p-30">
|
||||
<view v-for="(item, index) in list" :key="index" class="mb-25 w-100p">
|
||||
<view v-if="!item.isMine" class="flex justify-start items-start">
|
||||
<u-icon name="/static/robot.png" size="60rpx"/>
|
||||
<view class="shadow bg-white ml-15" style="border-radius: 0 15rpx 15rpx 15rpx; max-width: 80%">
|
||||
<view v-if="item.loading" class="p-15">
|
||||
<u-loading-icon mode="semicircle" :color="MAIN()"></u-loading-icon>
|
||||
</view>
|
||||
<template v-else>
|
||||
<zero-markdown-view :markdown="item.content"></zero-markdown-view>
|
||||
</template>
|
||||
</view>
|
||||
</view>
|
||||
<view v-else class="flex justify-end items-start w-100p">
|
||||
<view class="shadow p-15 text-white"
|
||||
style="border-radius: 15rpx 0 15rpx 15rpx; max-width: 80%; background-color: #006DFF">{{
|
||||
item.content
|
||||
}}
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="index === 0" class="mt-25">
|
||||
<view class="font-bold text-28 mb-25 text-center">猜你想问</view>
|
||||
<view class="font-bold text-28 mb-25 text-center" @click="send(quest.dictDataCode)"
|
||||
style="color: #006DFF"
|
||||
v-for="(quest, questIndex) in questionList" :key="questIndex">
|
||||
{{ quest.dictDataCode }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<u-gap height="140rpx"></u-gap>
|
||||
</view>
|
||||
<view class="stop" v-if="answering" @click="stopAI">
|
||||
<u-icon name="/static/stop.png" width="80rpx" height="80rpx"/>
|
||||
</view>
|
||||
<view class="footer">
|
||||
<view class="p-20 bg-white shadow-top flex justify-center items-center">
|
||||
<view class="flex-1 mr-15">
|
||||
<u-textarea maxlength="-1" auto-height v-model="content" border="none" placeholder="点此开始提问"/>
|
||||
</view>
|
||||
<view class="mr-25">
|
||||
<u-icon name="/static/send.png" size="60rpx" @click="send()"/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import CustomTabbar from "@/components/customTabbar.vue";
|
||||
import HeaderItem from "@/components/HeaderItem.vue";
|
||||
import {WS_API} from "@/config";
|
||||
import {sendChatReq, stopChatReq} from "@/api/lawOrg";
|
||||
import {getUserInfo} from "@/util/user";
|
||||
import {MAIN} from "@/config/color";
|
||||
import {dictDataReq} from "@/api/common";
|
||||
|
||||
export default {
|
||||
name: "index",
|
||||
components: {HeaderItem, CustomTabbar},
|
||||
data() {
|
||||
return {
|
||||
list: [],
|
||||
questionList: [],
|
||||
content: '',
|
||||
taskId: null,
|
||||
answering: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
MAIN() {
|
||||
return MAIN
|
||||
},
|
||||
async getQuestionsList() {
|
||||
const {data} = await dictDataReq({dictId: '165'})
|
||||
this.questionList = data
|
||||
},
|
||||
async send(content = null) {
|
||||
const contentItem = content || this.content
|
||||
console.log(contentItem, this.content)
|
||||
if (!contentItem.trim()) return this.$toast('请输入提问内容')
|
||||
if (!this.list[this.list.length - 1].done) return this.$toast('请等待AI律师回答完毕再继续提问')
|
||||
this.list.push({
|
||||
content: contentItem,
|
||||
isMine: true,
|
||||
loading: false,
|
||||
done: true,
|
||||
})
|
||||
this.scrollToBottom()
|
||||
this.answering = true
|
||||
this.list.push({
|
||||
content: '',
|
||||
isMine: false,
|
||||
loading: true,
|
||||
done: false,
|
||||
})
|
||||
this.taskId = null
|
||||
sendChatReq({
|
||||
query: contentItem,
|
||||
user: getUserInfo().uid
|
||||
}).then(() => {
|
||||
this.list[this.list.length - 1].done = true
|
||||
this.answering = false
|
||||
})
|
||||
this.content = ''
|
||||
},
|
||||
scrollToBottom() {
|
||||
setTimeout(() => {
|
||||
this.$nextTick(() => {
|
||||
uni.pageScrollTo({
|
||||
scrollTop: 99999,
|
||||
duration: 0
|
||||
})
|
||||
})
|
||||
}, 100)
|
||||
},
|
||||
async stopAI() {
|
||||
await stopChatReq({
|
||||
taskId: this.taskId
|
||||
})
|
||||
this.answering = false
|
||||
uni.closeSocket()
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
this.list.push({
|
||||
content: '您好!我是法律机器人,请问您想咨询什么问题呢?',
|
||||
isMine: false,
|
||||
loading: false,
|
||||
done: true,
|
||||
})
|
||||
uni.connectSocket({
|
||||
url: `${WS_API}/${getUserInfo().uid}`
|
||||
})
|
||||
uni.onSocketMessage(res => {
|
||||
if (res.data === '连接成功') return
|
||||
const aiData = JSON.parse(res.data)
|
||||
this.list[this.list.length - 1].loading = false
|
||||
if (aiData.answer !== '__END__') this.list[this.list.length - 1].content += aiData.answer
|
||||
this.taskId = aiData.taskId
|
||||
this.scrollToBottom()
|
||||
})
|
||||
this.getQuestionsList()
|
||||
},
|
||||
onUnload() {
|
||||
this.stopAI()
|
||||
},
|
||||
onHide() {
|
||||
this.stopAI()
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
page {
|
||||
background-color: #E0F2FE;
|
||||
}
|
||||
|
||||
.bg {
|
||||
background: url("https://sifa-api.wsdns.cn/api/file/20250420/bg.jpg") no-repeat 100% 100%;
|
||||
}
|
||||
|
||||
.stop {
|
||||
position: fixed;
|
||||
right: 10rpx;
|
||||
bottom: 160rpx;
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
border-radius: 100rpx;
|
||||
background: rgba(255, 255, 255, 0.4);
|
||||
box-shadow: 1px 1px 5px #3c9cff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,200 @@
|
||||
<template>
|
||||
<view class="min-height pos-r bg" style="background-color: #E0F2FE">
|
||||
<u-swiper v-if="swiperList.length" :list="swiperList" height="420rpx" indicator :custom-style="{zIndex: 0}"
|
||||
@click="$jump('/lawOrgPages/pages/action')"/>
|
||||
<view class="pos-a w-100p" style="left: 0; top: 360rpx">
|
||||
<view class="card m-25 flex flex-col justify-start items-start shadow"
|
||||
style="background-color: rgba(255,255,255,0.8); width: calc(100vw - 90rpx); padding-bottom: 45rpx">
|
||||
<view class="tag">
|
||||
<u-icon name="/static/line.png" size="30rpx"/>
|
||||
<view>线上办事</view>
|
||||
</view>
|
||||
<view class="mt-20 flex justify-around items-center w-100p">
|
||||
<view class="flex flex-col justify-center items-center shadow rounded-sm p-10"
|
||||
style="flex: 0 0 20%"
|
||||
v-for="(item, index) in navList"
|
||||
:key="index" @click="$jump(item.url)">
|
||||
<u-icon :name="`/static/index/${index + 1}.png`" size="80rpx"/>
|
||||
<text class=" mt-20" :class="[item.label.length > 5 ? 'text-20' : 'text-25']">{{ item.label }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<u-gap height="220rpx"></u-gap>
|
||||
<view class="p-25">
|
||||
<TitleItem title="企业法治体检"/>
|
||||
<view class="circle w-100p mb-20 shadow"
|
||||
@click="$jump('/legalOrgCheck/pages/index')"
|
||||
style="background-image: url('https://sifa-api.wsdns.cn/api/file/20250419/orgCheck.png'); background-size: cover;
|
||||
height: 180rpx"></view>
|
||||
<TitleItem title="法律自助服务"/>
|
||||
<view class="flex justify-center items-center flex-wrap">
|
||||
<view class="card mb-25 flex-1 flex justify-center items-center flex-shrink shadow"
|
||||
style="flex:0 0 295rpx; border-radius: 16rpx; padding: 25rpx 20rpx "
|
||||
:class="[index % 2 === 0 ? 'mr-15' : 'ml-15']"
|
||||
v-for="(item, index) in selfNavList"
|
||||
@click="jump(item.url)"
|
||||
:key="index">
|
||||
<view class="flex flex-col justify-center items-center mr-15">
|
||||
<text class="text-28">{{ item.label }}</text>
|
||||
<text class="text-20 mt-10" style="color: rgb(123, 160, 194)">{{ item.desc }}</text>
|
||||
</view>
|
||||
<u-icon :name="item.icon" size="40rpx"/>
|
||||
</view>
|
||||
</view>
|
||||
<view class="text-25 flex justify-between">
|
||||
<TitleItem title="法治宣传"/>
|
||||
<text class="text-20 text-blue-light mt-25" @click="$jump('/articlePages/pages/publicity')">查看更多</text>
|
||||
</view>
|
||||
<view class="circle w-100p mb-20 shadow"
|
||||
@click="$jump('/articlePages/pages/publicity')"
|
||||
style="background-image: url('https://sifa-api.wsdns.cn/api/file/20250419/propagate.png'); background-size: cover;
|
||||
height: 240rpx"></view>
|
||||
<TitleItem title="查询服务"/>
|
||||
<view class="flex justify-center items-center flex-wrap">
|
||||
<view @click="$jump('/lawOrgPages/pages/map')"
|
||||
class="card mb-20 flex-1 flex justify-center items-center flex-shrink mr-15 shadow"
|
||||
style="flex:0 0 295rpx; border-radius: 16rpx; padding: 25rpx 20rpx">
|
||||
<u-icon name="/static/index/map.png" size="40rpx"/>
|
||||
<view class="flex flex-col justify-center items-center ml-15">
|
||||
<text class="text-28">法律服务地图</text>
|
||||
<text class="text-20 mt-10" style="color: rgb(123, 160, 194)">法律服务机构导航</text>
|
||||
</view>
|
||||
</view>
|
||||
<view @click="$jump('/lawOrgPages/pages/index')"
|
||||
class="card mb-20 flex-1 flex justify-center items-center flex-shrink ml-15 shadow"
|
||||
style="flex:0 0 295rpx; border-radius: 16rpx; padding: 25rpx 20rpx">
|
||||
<u-icon name="/static/index/org.png" size="40rpx"/>
|
||||
<view class="flex flex-col justify-center items-center ml-15">
|
||||
<text class="text-28">人员机构查询</text>
|
||||
<text class="text-20 mt-10" style="color: rgb(123, 160, 194)">法律人员机构查询</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<u-gap height="100rpx"></u-gap>
|
||||
<custom-tabbar :current="0"/>
|
||||
<Login ref="Login"/>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import CustomTabbar from "@/components/customTabbar.vue";
|
||||
import {swiperListReq} from "@/api/common";
|
||||
import Login from "@/components/Login.vue";
|
||||
import TitleItem from "@/components/TitleItem.vue";
|
||||
|
||||
export default {
|
||||
components: {TitleItem, Login, CustomTabbar},
|
||||
data() {
|
||||
return {
|
||||
swiperList: [],
|
||||
navList: [
|
||||
{
|
||||
label: '法律援助',
|
||||
url: '/onlineSheetPages/pages/legalAid'
|
||||
},
|
||||
{
|
||||
label: '公证',
|
||||
url: '/onlineSheetPages/pages/notary'
|
||||
},
|
||||
{
|
||||
label: '司法鉴定',
|
||||
url: '/onlineSheetPages/pages/forensic'
|
||||
},
|
||||
{
|
||||
label: '民事商事仲裁',
|
||||
url: '/onlineSheetPages/pages/civil'
|
||||
},
|
||||
],
|
||||
selfNavList: [
|
||||
{
|
||||
label: 'AI律师咨询',
|
||||
desc: 'AI律师咨询',
|
||||
icon: '/static/index/self_0.png',
|
||||
url: '/pages/ai/index'
|
||||
},
|
||||
{
|
||||
label: '人工咨询',
|
||||
desc: '一键拨打热线电话',
|
||||
icon: '/static/index/self_1.png',
|
||||
url: '/userPages/pages/manual'
|
||||
},
|
||||
{
|
||||
label: '常见问题解答',
|
||||
desc: '智能常见问题解答',
|
||||
icon: '/static/index/self_2.png',
|
||||
url: '/legalOrgCheckSuggest/pages/index'
|
||||
},
|
||||
{
|
||||
label: '法律文书',
|
||||
desc: '智能生成法律文书',
|
||||
icon: '/static/index/self_3.png',
|
||||
url: '/legalLegalDoc/pages/index'
|
||||
},
|
||||
{
|
||||
label: '法律计算器',
|
||||
desc: '计算法定费用/赔偿',
|
||||
icon: '/static/index/self_4.png',
|
||||
url: '/userPages/pages/cal'
|
||||
},
|
||||
{
|
||||
label: '自助查询',
|
||||
desc: '法律 案例 文书',
|
||||
icon: '/static/index/self_5.png',
|
||||
url: '/articlePages/pages/search'
|
||||
},
|
||||
]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async getSwiperList() {
|
||||
const {data} = await swiperListReq()
|
||||
this.swiperList = data.map(item => {
|
||||
return item.image
|
||||
})
|
||||
},
|
||||
jump(url) {
|
||||
if (url === '/pages/ai/index') {
|
||||
uni.switchTab({url})
|
||||
} else uni.navigateTo({url})
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
// #defif
|
||||
this.$refs.Login.doLogin()
|
||||
this.getSwiperList()
|
||||
},
|
||||
onShareAppMessage() {
|
||||
return {
|
||||
title: "贵港公共法律服务",
|
||||
path: `/pages/index/index`
|
||||
}
|
||||
},
|
||||
onShareTimeline() {
|
||||
return {
|
||||
title: "贵港公共法律服务",
|
||||
path: `/pages/index/index`
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.bg {
|
||||
background: url("https://sifa-api.wsdns.cn/api/file/20250420/bg.jpg") no-repeat 100% 100%;
|
||||
}
|
||||
|
||||
.tag {
|
||||
color: #4095E5;
|
||||
background-color: rgba(116, 179, 255, 0.19);
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
padding: 5rpx 15rpx;
|
||||
border-radius: 6rpx;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,109 @@
|
||||
<template>
|
||||
<view class="bg-gray-light min-height">
|
||||
<u-navbar :autoBack="false" :bgColor="colors.LINEAR" :statusBarBgColor="colors.LINEAR" placeholder>
|
||||
<template #left></template>
|
||||
</u-navbar>
|
||||
<view class=" p-20 flex justify-between" style="padding-bottom: 100rpx" :style="{background: colors.LINEAR}"
|
||||
@click="userClick('/userPages/pages/profile')">
|
||||
<view class="flex justify-start items-center">
|
||||
<u-avatar :src="user.avatar" size="60"/>
|
||||
<view class="flex justify-start items-start flex-col ml-25">
|
||||
<u-text :text="user.nickname ? user.nickname : '点击登录' " color="white" size="15"/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="p-25">
|
||||
<view class="card">
|
||||
<u-button type="primary" :custom-style="{backgroundColor: '#00B48E', border: 0}" :hairline="false"
|
||||
@click="userClick('/userPages/pages/userData')"
|
||||
shape="circle" icon="/static/user/upload.png">认证企业
|
||||
</u-button>
|
||||
<u-cell-group :border="false">
|
||||
<u-cell is-link label="我的企业" icon="/static/user/身份证证件.png"
|
||||
@click="userClick('/userPages/pages/userData')"></u-cell>
|
||||
<u-cell is-link label="我的法制检查" icon="/static/user/上传.png"
|
||||
@click="userClick('/userPages/pages/userLawCheck')"></u-cell>
|
||||
<u-cell is-link label="我的专题反馈" icon="/static/user/24gf-portraitMale.png"
|
||||
@click="userClick('/userPages/pages/userFeedback')"></u-cell>
|
||||
<u-cell is-link label="联系客服" icon="/static/user/客服.png" :border="false"></u-cell>
|
||||
</u-cell-group>
|
||||
</view>
|
||||
</view>
|
||||
<view class="p-25">
|
||||
<u-button type="primary" shape="circle" v-if="logined">退出登录</u-button>
|
||||
</view>
|
||||
<u-gap height="140rpx"/>
|
||||
<Login ref="Login" @done="getUserData"/>
|
||||
<custom-tabbar :current="2"/>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {clearUserInfo, getUserInfo, setUserInfo} from "@/util/user";
|
||||
import * as COLORS from "@/config/color";
|
||||
import {loginByPhoneReq, userInfoReq} from "@/api/user";
|
||||
import {MAIN_API} from "@/config";
|
||||
import Login from "@/components/Login.vue";
|
||||
import {sysSettingInfoReq} from "@/api/common";
|
||||
import CustomTabbar from "@/components/customTabbar.vue";
|
||||
|
||||
export default {
|
||||
name: "index",
|
||||
components: {CustomTabbar, Login},
|
||||
data() {
|
||||
return {
|
||||
colors: COLORS,
|
||||
user: null,
|
||||
logined: false,
|
||||
gridStyle: {
|
||||
height: '180rpx'
|
||||
},
|
||||
loginCount: 0,
|
||||
servicePhone: ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
MAIN_API() {
|
||||
return MAIN_API
|
||||
},
|
||||
async getUserData() {
|
||||
const {data} = await userInfoReq()
|
||||
this.user = data
|
||||
this.logined = true
|
||||
},
|
||||
logout() {
|
||||
clearUserInfo()
|
||||
this.logined = false
|
||||
},
|
||||
login() {
|
||||
this.$refs.Login.doLogin()
|
||||
},
|
||||
userClick(url) {
|
||||
if (!this.logined) this.login()
|
||||
else this.$jump(url)
|
||||
},
|
||||
},
|
||||
onShow() {
|
||||
this.logined = !!getUserInfo().token
|
||||
if (this.logined) this.getUserData()
|
||||
else this.login()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.dot {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: -20rpx;
|
||||
width: 40rpx;
|
||||
heigth: 40rpx;
|
||||
border-radius: 40rpx;
|
||||
background-color: #E55744;
|
||||
color: white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user