Compare commits
No commits in common. "main" and "main-ai对话" have entirely different histories.
|
|
@ -1,3 +1,2 @@
|
|||
# 忽略 unpackage 文件夹
|
||||
/unpackage/
|
||||
/docs
|
||||
|
|
@ -1,97 +1,98 @@
|
|||
// 这里的vm,就是我们在vue文件里面的this,所以我们能在这里获取vuex的变量,比如存放在里面的token
|
||||
// 同时,我们也可以在此使用getApp().globalData,如果你把token放在getApp().globalData的话,也是可以使用的
|
||||
const install = (Vue, vm) => {
|
||||
Vue.prototype.$u.http.setConfig({
|
||||
// baseUrl: 'https://xy.apps.service.zheke.com',
|
||||
// imgUrl: 'https://xy.apps.service.zheke.com/',
|
||||
baseUrl: "http://120.55.234.65:8082",
|
||||
imgUrl: "http://120.55.234.65:8082/",
|
||||
// imgUrl:'http://115.238.47.235:8987/',
|
||||
// baseUrl: 'http://115.238.47.235:8993',
|
||||
// 如果将此值设置为true,拦截回调中将会返回服务端返回的所有数据response,而不是response.data
|
||||
// 设置为true后,就需要在this.$u.http.interceptor.response进行多一次的判断,请打印查看具体值
|
||||
originalData: true,
|
||||
// 设置自定义头部content-type
|
||||
// header: {
|
||||
// 'content-type': 'xxx'
|
||||
// }
|
||||
});
|
||||
// 请求拦截,配置Token等参数
|
||||
Vue.prototype.$u.http.interceptor.request = (config) => {
|
||||
// config.header.Token = 'xxxxxx';
|
||||
// 方式一,存放在vuex的token,假设 ,见:https://uviewui.com/components/globalVariable.html
|
||||
config.header.Authorization = "Bearer " + vm.vuex_token;
|
||||
// 方式二,如果没有使用uView封装的vuex方法,那么需要使用$store.state获取
|
||||
// config.header.token = vm.$store.state.token;
|
||||
Vue.prototype.$u.http.setConfig({
|
||||
// baseUrl: 'https://xy.apps.service.zheke.com',
|
||||
// imgUrl: 'https://xy.apps.service.zheke.com/',
|
||||
baseUrl: 'http://120.55.234.65:8082',
|
||||
imgUrl: 'http://120.55.234.65:8082/',
|
||||
// imgUrl:'http://115.238.47.235:8987/',
|
||||
// baseUrl: 'http://115.238.47.235:8993',
|
||||
// 如果将此值设置为true,拦截回调中将会返回服务端返回的所有数据response,而不是response.data
|
||||
// 设置为true后,就需要在this.$u.http.interceptor.response进行多一次的判断,请打印查看具体值
|
||||
originalData: true,
|
||||
// 设置自定义头部content-type
|
||||
// header: {
|
||||
// 'content-type': 'xxx'
|
||||
// }
|
||||
});
|
||||
// 请求拦截,配置Token等参数
|
||||
Vue.prototype.$u.http.interceptor.request = (config) => {
|
||||
|
||||
// 方式三,如果token放在了globalData,通过getApp().globalData获取
|
||||
// config.header.token = getApp().globalData.username;
|
||||
// config.header.Token = 'xxxxxx';
|
||||
// 方式一,存放在vuex的token,假设 ,见:https://uviewui.com/components/globalVariable.html
|
||||
config.header.Authorization = 'Bearer ' + vm.vuex_token;
|
||||
// 方式二,如果没有使用uView封装的vuex方法,那么需要使用$store.state获取
|
||||
// config.header.token = vm.$store.state.token;
|
||||
|
||||
// 方式四,如果token放在了Storage本地存储中,拦截是每次请求都执行的,所以哪怕您重新登录修改了Storage,下一次的请求将会是最新值
|
||||
// const token = uni.getStorageSync('token');
|
||||
// config.header.token = token;
|
||||
// 方式三,如果token放在了globalData,通过getApp().globalData获取
|
||||
// config.header.token = getApp().globalData.username;
|
||||
|
||||
// 注释 7/15
|
||||
// uni.showLoading({
|
||||
// title: '请求中...'
|
||||
// });
|
||||
// 注释
|
||||
// 方式四,如果token放在了Storage本地存储中,拦截是每次请求都执行的,所以哪怕您重新登录修改了Storage,下一次的请求将会是最新值
|
||||
// const token = uni.getStorageSync('token');
|
||||
// config.header.token = token;
|
||||
|
||||
// setTimeout(function () {
|
||||
// uni.hideLoading();
|
||||
// }, 2000);
|
||||
// 注释 7/15
|
||||
// uni.showLoading({
|
||||
// title: '请求中...'
|
||||
// });
|
||||
// 注释
|
||||
|
||||
return config;
|
||||
};
|
||||
// 响应拦截,判断状态码是否通过
|
||||
Vue.prototype.$u.http.interceptor.response = (res) => {
|
||||
// uni.hideLoading();
|
||||
// setTimeout(function () {
|
||||
// uni.hideLoading();
|
||||
// }, 2000);
|
||||
|
||||
// 检查是否为401未授权错误
|
||||
if (res.statusCode === 401) {
|
||||
handleAuthError(vm);
|
||||
return false;
|
||||
}
|
||||
return config;
|
||||
}
|
||||
// 响应拦截,判断状态码是否通过
|
||||
Vue.prototype.$u.http.interceptor.response = (res) => {
|
||||
// uni.hideLoading();
|
||||
|
||||
return res.data;
|
||||
// 检查是否为401未授权错误
|
||||
if (res.statusCode === 401) {
|
||||
handleAuthError(vm);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (res.succeed == true || res.success == true) {
|
||||
// return res.data || res;
|
||||
return res;
|
||||
} else {
|
||||
// uni.showToast({
|
||||
// title: res.error,
|
||||
// duration: 2000,
|
||||
// icon: 'none'
|
||||
// });
|
||||
// uni.navigateTo({
|
||||
// url: "/pages/login/login/login",
|
||||
// });
|
||||
return res.data;
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
};
|
||||
if (res.succeed == true || res.success == true) {
|
||||
// return res.data || res;
|
||||
return res;
|
||||
} else {
|
||||
// uni.showToast({
|
||||
// title: res.error,
|
||||
// duration: 2000,
|
||||
// icon: 'none'
|
||||
// });
|
||||
// uni.navigateTo({
|
||||
// url: "/pages/login/login/login",
|
||||
// });
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 提取处理401错误的函数
|
||||
function handleAuthError(vm) {
|
||||
vm.$u.vuex("vuex_user", "");
|
||||
vm.$u.vuex("vuex_token", "");
|
||||
uni.clearStorage();
|
||||
vm.$u.vuex("vuex_user", "");
|
||||
vm.$u.vuex("vuex_token", "");
|
||||
uni.clearStorage();
|
||||
|
||||
// 显示提示
|
||||
uni.showToast({
|
||||
title: "登录已过期,请重新登录!",
|
||||
icon: "none",
|
||||
duration: 1500,
|
||||
});
|
||||
// 显示提示
|
||||
uni.showToast({
|
||||
title: '登录已过期,请重新登录!',
|
||||
icon: 'none',
|
||||
duration: 1500
|
||||
});
|
||||
|
||||
// 延迟跳转到登录页
|
||||
uni.reLaunch({
|
||||
url: "/pages/login/login/index",
|
||||
});
|
||||
// 延迟跳转到登录页
|
||||
uni.reLaunch({
|
||||
url: '/pages/login/login/index'
|
||||
});
|
||||
}
|
||||
|
||||
export default {
|
||||
install,
|
||||
};
|
||||
install
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,117 @@
|
|||
<template>
|
||||
<view class="empty-container">
|
||||
<image :src="getImage" class="empty-image" mode="widthFix"></image>
|
||||
<text class="empty-text">{{ text }}</text>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 暂无数据
|
||||
import noDataDefault from "@/static/common/img/noData/no-data.png";
|
||||
// 暂无搜索
|
||||
import noDataSearch from "@/static/common/img/noData/no-search.png";
|
||||
// 暂无消息
|
||||
import noDataMessage from "@/static/common/img/noData/no-message.png";
|
||||
// 网络异常
|
||||
import errorNet from "@/static/common/img/noData/error-net.png";
|
||||
// 数据加载失败
|
||||
import errorData from "@/static/common/img/noData/error-data.png";
|
||||
// 维护中
|
||||
import maintenance from "@/static/common/img/noData/maintenance.png";
|
||||
// 暂无附件简历
|
||||
import noAttachmentResume from "@/static/common/img/noData/no-attachment-resume.png";
|
||||
// 暂无收藏
|
||||
import noCollection from "@/static/common/img/noData/no-collection.png";
|
||||
// 暂无评论
|
||||
import noComments from "@/static/common/img/noData/no-comments.png";
|
||||
// 暂无内容
|
||||
import noContent from "@/static/common/img/noData/no-content.png";
|
||||
// 暂无文件
|
||||
import noFile from "@/static/common/img/noData/no-file.png";
|
||||
// 暂无好友
|
||||
import noFriends from "@/static/common/img/noData/no-friends.png";
|
||||
// 暂无网络
|
||||
import noInternet from "@/static/common/img/noData/no-internet.png";
|
||||
// 暂无权限
|
||||
import noPermissions from "@/static/common/img/noData/no-permissions.png";
|
||||
// 暂无图片
|
||||
import noPicture from "@/static/common/img/noData/no-picture.png";
|
||||
|
||||
export default {
|
||||
name: "NoData",
|
||||
props: {
|
||||
// 图片类型
|
||||
type: {
|
||||
type: String,
|
||||
default: "default",
|
||||
},
|
||||
// 描述文字,默认值为"暂无数据"
|
||||
text: {
|
||||
type: String,
|
||||
default: "暂无数据",
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
getImage() {
|
||||
const imageMap = {
|
||||
default: noDataDefault,
|
||||
search: noDataSearch,
|
||||
message: noDataMessage,
|
||||
errorNet: errorNet,
|
||||
errorData: errorData,
|
||||
maintenance: maintenance,
|
||||
resume: noAttachmentResume,
|
||||
collection: noCollection,
|
||||
comments: noComments,
|
||||
content: noContent,
|
||||
file: noFile,
|
||||
friends: noFriends,
|
||||
internet: noInternet,
|
||||
permissions: noPermissions,
|
||||
picture: noPicture,
|
||||
};
|
||||
return imageMap[this.type] || imageMap.default;
|
||||
},
|
||||
},
|
||||
data: {
|
||||
/*
|
||||
<no-data type="default" text="暂无数据" />
|
||||
<no-data type="errorNet" text="网络错误" />
|
||||
<no-data type="search" text="暂无搜索内容" />
|
||||
<no-data type="errorData" text="数据加载失败" />
|
||||
<no-data type="message" text="暂无消息" />
|
||||
<no-data type="maintenance" text="系统维护中" />
|
||||
<no-data type="resume" text="暂无简历附件" />
|
||||
<no-data type="collection" text="暂无收藏" />
|
||||
<no-data type="comments" text="暂无评论" />
|
||||
<no-data type="content" text="暂无内容" />
|
||||
<no-data type="file" text="暂无文件" />
|
||||
<no-data type="friends" text="暂无好友" />
|
||||
<no-data type="internet" text="无网络连接" />
|
||||
<no-data type="permissions" text="暂无权限" />
|
||||
<no-data type="picture" text="暂无图片" /> */
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.empty-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 20rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.empty-image {
|
||||
width: 400rpx;
|
||||
height: 400rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-size: 32rpx;
|
||||
color: #000;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,167 +0,0 @@
|
|||
<template>
|
||||
<u-tabbar
|
||||
v-if="show"
|
||||
:value="currentIndex"
|
||||
:show="true"
|
||||
:bg-color="style.backgroundColor"
|
||||
:border-top="style.borderTop"
|
||||
:fixed="true"
|
||||
:height="style.height"
|
||||
:list="formattedTabList"
|
||||
@change="handleTabChange"
|
||||
>
|
||||
</u-tabbar>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import tabbarConfig from "@/config/tabbar.config.js";
|
||||
|
||||
export default {
|
||||
name: "TabBar",
|
||||
props: {
|
||||
// 当前页面路径(可选)
|
||||
currentPath: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
// 是否显示 TabBar
|
||||
show: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentIndex: 0,
|
||||
tabList: tabbarConfig.tabs,
|
||||
style: tabbarConfig.style,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
// 格式化为 uview tabbar 所需格式
|
||||
formattedTabList() {
|
||||
return this.tabList.map((item) => ({
|
||||
text: item.text,
|
||||
iconPath: item.icon,
|
||||
selectedIconPath: item.activeIcon,
|
||||
pagePath: item.pagePath,
|
||||
count: item.badge || 0,
|
||||
isDot: item.dot || false,
|
||||
}));
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
// 监听 currentPath 变化
|
||||
currentPath: {
|
||||
handler(newPath) {
|
||||
if (newPath) {
|
||||
this.updateActiveTab(newPath);
|
||||
}
|
||||
},
|
||||
immediate: true,
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.initActiveTab();
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 初始化激活的 tab
|
||||
*/
|
||||
initActiveTab() {
|
||||
const path = this.currentPath || this.getCurrentPagePath();
|
||||
this.updateActiveTab(path);
|
||||
},
|
||||
|
||||
/**
|
||||
* 更新激活的 tab
|
||||
*/
|
||||
updateActiveTab(path) {
|
||||
const index = this.tabList.findIndex((item) =>
|
||||
this.isPathMatch(path, item.pagePath)
|
||||
);
|
||||
if (index !== -1) {
|
||||
this.currentIndex = index;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 路径匹配判断
|
||||
*/
|
||||
isPathMatch(currentPath, targetPath) {
|
||||
const normalize = (path) => path.replace(/^\//, "");
|
||||
return normalize(currentPath) === normalize(targetPath);
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取当前页面路径
|
||||
*/
|
||||
getCurrentPagePath() {
|
||||
const pages = getCurrentPages();
|
||||
console.log('pages',pages);
|
||||
|
||||
if (pages.length > 0) {
|
||||
return "/" + pages[pages.length - 1].route;
|
||||
}
|
||||
return "";
|
||||
},
|
||||
|
||||
/**
|
||||
* 处理 tab 切换
|
||||
*/
|
||||
handleTabChange(index) {
|
||||
if (this.currentIndex === index) {
|
||||
this.$emit("reclick", this.tabList[index].pagePath, index);
|
||||
return;
|
||||
}
|
||||
|
||||
const targetTab = this.tabList[index];
|
||||
if (!targetTab) return;
|
||||
|
||||
this.currentIndex = index;
|
||||
this.$emit("change", targetTab.pagePath, index);
|
||||
|
||||
// 跳转
|
||||
this.navigateToTab(targetTab.pagePath);
|
||||
},
|
||||
|
||||
/**
|
||||
* 跳转到 tab 页面
|
||||
*/
|
||||
navigateToTab(url) {
|
||||
uni.switchTab({
|
||||
url,
|
||||
fail: () => {
|
||||
// 降级方案
|
||||
uni.reLaunch({ url });
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 设置角标
|
||||
* @param {number} index - tab 索引
|
||||
* @param {string|number} badge - 角标内容
|
||||
*/
|
||||
setBadge(index, badge) {
|
||||
if (this.tabList[index]) {
|
||||
this.$set(this.tabList[index], "badge", badge);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 显示/隐藏小红点
|
||||
* @param {number} index - tab 索引
|
||||
* @param {boolean} show - 是否显示
|
||||
*/
|
||||
setDot(index, show) {
|
||||
if (this.tabList[index]) {
|
||||
this.$set(this.tabList[index], "dot", show);
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
/**
|
||||
* TabBar 配置文件
|
||||
* 集中管理底部导航栏配置
|
||||
*/
|
||||
|
||||
export const TAB_BAR_CONFIG = [
|
||||
{
|
||||
text: "在线咨询",
|
||||
icon: "/static/tabbar/tabbar-icon1.png",
|
||||
activeIcon: "/static/tabbar/tabbar-icon1-active.png",
|
||||
pagePath: "/pages/consultation/index",
|
||||
// 可选配置
|
||||
badge: "", // 角标文字
|
||||
dot: false, // 是否显示小红点
|
||||
},
|
||||
{
|
||||
text: "人工转接",
|
||||
icon: "/static/tabbar/tabbar-icon4.png",
|
||||
activeIcon: "/static/tabbar/tabbar-icon4-active.png",
|
||||
pagePath: "/pages/transfer/index",
|
||||
badge: "",
|
||||
dot: false,
|
||||
},
|
||||
{
|
||||
text: "我的",
|
||||
icon: "/static/tabbar/tabbar-icon3.png",
|
||||
activeIcon: "/static/tabbar/tabbar-icon3-active.png",
|
||||
pagePath: "/pages/my/index",
|
||||
badge: "",
|
||||
dot: false,
|
||||
},
|
||||
];
|
||||
|
||||
// TabBar 样式配置
|
||||
export const TAB_BAR_STYLE = {
|
||||
color: "#999999", // 未激活颜色
|
||||
selectedColor: "#4a6cf7", // 激活颜色
|
||||
backgroundColor: "#ffffff", // 背景色
|
||||
borderTop: false, // 是否显示顶部边框
|
||||
height: 148, // 高度(rpx)
|
||||
};
|
||||
|
||||
export default {
|
||||
tabs: TAB_BAR_CONFIG,
|
||||
style: TAB_BAR_STYLE,
|
||||
};
|
||||
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
/**
|
||||
* WebSocket 配置文件
|
||||
*
|
||||
* 集中管理 WebSocket 相关配置
|
||||
*/
|
||||
|
||||
// 根据环境选择 WebSocket 地址
|
||||
const getWebSocketUrl = () => {
|
||||
// #ifdef H5
|
||||
// H5 开发环境
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
return 'ws://localhost:8082/ws/chat'
|
||||
}
|
||||
// H5 生产环境
|
||||
return 'wss://120.55.234.65:8082/ws/chat'
|
||||
// #endif
|
||||
}
|
||||
|
||||
export default {
|
||||
// WebSocket 服务器地址(动态获取)
|
||||
url: getWebSocketUrl(),
|
||||
|
||||
// 重连配置
|
||||
reconnect: {
|
||||
enabled: true, // 是否启用自动重连
|
||||
maxAttempts: 10, // 最大重连次数
|
||||
interval: 3000, // 重连间隔(毫秒)
|
||||
incrementInterval: true, // 是否递增重连间隔
|
||||
maxInterval: 30000 // 最大重连间隔
|
||||
},
|
||||
|
||||
// 心跳配置
|
||||
heartbeat: {
|
||||
enabled: true, // 是否启用心跳
|
||||
interval: 30000, // 心跳间隔(毫秒)
|
||||
timeout: 10000, // 心跳超时时间
|
||||
pingMessage: { // 心跳消息格式
|
||||
type: 'ping',
|
||||
timestamp: () => Date.now()
|
||||
}
|
||||
},
|
||||
|
||||
// 消息队列配置
|
||||
messageQueue: {
|
||||
enabled: true, // 是否启用消息队列
|
||||
maxSize: 100, // 队列最大长度
|
||||
clearOnConnect: false // 连接成功后是否清空队列
|
||||
},
|
||||
|
||||
// 日志配置
|
||||
log: {
|
||||
enabled: true, // 是否启用日志
|
||||
level: 'info' // 日志级别:debug, info, warn, error
|
||||
},
|
||||
|
||||
// 消息类型定义
|
||||
messageTypes: {
|
||||
// 文字消息
|
||||
TEXT: 'text',
|
||||
// 图片消息
|
||||
IMAGE: 'image',
|
||||
// 语音消息
|
||||
VOICE: 'voice',
|
||||
// 系统消息
|
||||
SYSTEM: 'system',
|
||||
// 心跳
|
||||
PING: 'ping',
|
||||
PONG: 'pong',
|
||||
// 已读回执
|
||||
READ: 'read',
|
||||
// 输入中
|
||||
TYPING: 'typing',
|
||||
// 人工转接
|
||||
TRANSFER: 'transfer'
|
||||
},
|
||||
|
||||
// 事件名称定义
|
||||
events: {
|
||||
OPEN: 'open',
|
||||
CLOSE: 'close',
|
||||
ERROR: 'error',
|
||||
MESSAGE: 'message',
|
||||
RECONNECT: 'reconnect',
|
||||
RECONNECT_FAILED: 'reconnect_failed'
|
||||
}
|
||||
}
|
||||
|
||||
201
pages.json
|
|
@ -11,30 +11,15 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"pages": [
|
||||
{
|
||||
"path": "pages/home/index/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "首页",
|
||||
"enablePullDownRefresh": false,
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/test/websocket-test",
|
||||
"style": {
|
||||
"navigationBarTitleText": "WebSocket 测试",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/chat/chat-detail",
|
||||
"style": {
|
||||
"navigationBarTitleText": "聊天",
|
||||
"navigationStyle": "custom",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
},
|
||||
"pages": [
|
||||
{
|
||||
"path": "pages/home/index/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "首页",
|
||||
"enablePullDownRefresh": false,
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/home/messageBoard/index",
|
||||
"style": {
|
||||
|
|
@ -42,7 +27,20 @@
|
|||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "pages/notes/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "留言板",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/my/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "我的",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/my/personalInfo",
|
||||
"style": {
|
||||
|
|
@ -53,7 +51,7 @@
|
|||
{
|
||||
"path": "pages/home/admissions/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "在线咨询",
|
||||
"navigationBarTitleText": "招办在线",
|
||||
"enablePullDownRefresh": false,
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
|
|
@ -67,28 +65,13 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/consultation/index",
|
||||
"path": "pages/home/conversations/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "在线咨询",
|
||||
"navigationBarTitleText": "会话列表",
|
||||
"enablePullDownRefresh": false,
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/transfer/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "人工转接",
|
||||
"enablePullDownRefresh": false,
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/my/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "我的",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/login/login/index",
|
||||
"style": {
|
||||
|
|
@ -106,18 +89,138 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/home/history/history",
|
||||
"path": "pages/login/login/login",
|
||||
"style": {
|
||||
"navigationBarTitleText": "登录",
|
||||
"enablePullDownRefresh": false,
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/login/register/register",
|
||||
"style": {
|
||||
"navigationBarTitleText": "注册",
|
||||
"enablePullDownRefresh": false,
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/login/perfect/perfect",
|
||||
"style": {
|
||||
"navigationBarTitleText": "",
|
||||
"enablePullDownRefresh": false,
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/login/graduateCertification/graduateCertification",
|
||||
"style": {
|
||||
"navigationBarTitleText": "",
|
||||
"enablePullDownRefresh": false,
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/message/msgList/msgList",
|
||||
"style": {
|
||||
"navigationBarTitleText": "",
|
||||
"enablePullDownRefresh": false,
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/message/dialogBox/dialogBox",
|
||||
"style": {
|
||||
"navigationBarTitleText": "",
|
||||
"enablePullDownRefresh": false,
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/message/interactionList/interactionList",
|
||||
"style": {
|
||||
"navigationBarTitleText": "互动消息",
|
||||
"enablePullDownRefresh": false,
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/message/sysList/sysList",
|
||||
"style": {
|
||||
"navigationBarTitleText": "系统消息",
|
||||
"enablePullDownRefresh": false,
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/message/attentionList/attentionList",
|
||||
"style": {
|
||||
"navigationBarTitleText": "新增关注",
|
||||
"enablePullDownRefresh": false,
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/message/adminList/adminList",
|
||||
"style": {
|
||||
"navigationBarTitleText": "管理列表",
|
||||
"enablePullDownRefresh": false,
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/login/ForgetPassword/ForgetPassword",
|
||||
"style": {
|
||||
"navigationBarTitleText": "",
|
||||
"enablePullDownRefresh": false,
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/login/confirmPwd/confirmPwd",
|
||||
"style": {
|
||||
"navigationBarTitleText": "确认密码",
|
||||
"enablePullDownRefresh": false,
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/login/roleSelection",
|
||||
"style": {
|
||||
"navigationBarTitleText": "角色选择",
|
||||
"enablePullDownRefresh": false,
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/login/teacherCertification",
|
||||
"style": {
|
||||
"navigationBarTitleText": "教职工认证",
|
||||
"enablePullDownRefresh": false,
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/login/recognitionResult/recognitionResult",
|
||||
"style": {
|
||||
"navigationBarTitleText": "提示",
|
||||
"enablePullDownRefresh": false,
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/login/recognitionResult/recognitionFailed",
|
||||
"style": {
|
||||
"navigationBarTitleText": "认证失败",
|
||||
"enablePullDownRefresh": false,
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
}
|
||||
],
|
||||
"subPackages": [],
|
||||
"globalStyle": {
|
||||
"navigationBarTextStyle": "black",
|
||||
"navigationBarTitleText": "源小新",
|
||||
"navigationBarTitleText": "英星AI",
|
||||
"navigationBarBackgroundColor": "#F8F8F8",
|
||||
"backgroundColor": "#F8F8F8"
|
||||
},
|
||||
|
|
@ -128,16 +231,16 @@
|
|||
"backgroundColor": "#ffffff",
|
||||
"list": [
|
||||
{
|
||||
"pagePath": "pages/consultation/index",
|
||||
"pagePath": "pages/home/conversations/index",
|
||||
"iconPath": "static/tabbar/icon_home.png",
|
||||
"selectedIconPath": "static/tabbar/icon_home_active.png",
|
||||
"text": "在线咨询"
|
||||
"text": "会话列表"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/transfer/index",
|
||||
"pagePath": "pages/notes/index",
|
||||
"iconPath": "static/tabbar/icon_message.png",
|
||||
"selectedIconPath": "static/tabbar/icon_message_active.png",
|
||||
"text": "人工转接"
|
||||
"text": "留言板"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/my/index",
|
||||
|
|
|
|||
|
|
@ -1,379 +0,0 @@
|
|||
<template>
|
||||
<view class="chat-detail-page">
|
||||
<!-- 顶部导航 -->
|
||||
<view class="chat-header">
|
||||
<view class="header-left" @click="goBack">
|
||||
<u-icon name="arrow-left" color="#333" size="20"></u-icon>
|
||||
</view>
|
||||
<view class="header-title">{{ userName }}</view>
|
||||
<view class="header-right" @click="showUserInfo">
|
||||
<u-icon name="more-dot-fill" color="#333" size="20"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 消息列表 -->
|
||||
<scroll-view
|
||||
class="message-list"
|
||||
scroll-y
|
||||
:scroll-into-view="scrollIntoView"
|
||||
scroll-with-animation
|
||||
>
|
||||
<view
|
||||
v-for="(msg, index) in messageList"
|
||||
:key="msg.id"
|
||||
:id="'msg-' + msg.id"
|
||||
class="message-item"
|
||||
>
|
||||
<!-- 我发送的消息 -->
|
||||
<view v-if="msg.isSelf" class="message-self">
|
||||
<view class="message-content-wrapper">
|
||||
<view class="message-content">{{ msg.content }}</view>
|
||||
</view>
|
||||
<image class="message-avatar" :src="myAvatar"></image>
|
||||
</view>
|
||||
|
||||
<!-- 对方发送的消息 -->
|
||||
<view v-else class="message-other">
|
||||
<image class="message-avatar" :src="otherAvatar"></image>
|
||||
<view class="message-content-wrapper">
|
||||
<view class="message-content">{{ msg.content }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 空状态 -->
|
||||
<view v-if="messageList.length === 0" class="empty-message">
|
||||
<text>暂无消息</text>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 输入栏 -->
|
||||
<view class="input-bar">
|
||||
<view class="input-wrapper">
|
||||
<input
|
||||
class="input-field"
|
||||
v-model="inputValue"
|
||||
placeholder="请输入消息..."
|
||||
confirm-type="send"
|
||||
@confirm="sendMessage"
|
||||
/>
|
||||
</view>
|
||||
<view class="send-button" @click="sendMessage">
|
||||
<text>发送</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ChatDetail',
|
||||
data() {
|
||||
return {
|
||||
// 用户信息
|
||||
userId: '',
|
||||
userName: '',
|
||||
|
||||
// 头像
|
||||
myAvatar: '/static/avatar/default-avatar.png',
|
||||
otherAvatar: '/static/avatar/default-avatar.png',
|
||||
|
||||
// 消息列表
|
||||
messageList: [
|
||||
{
|
||||
id: 1,
|
||||
content: '你好,请问学校的招生政策是怎样的?',
|
||||
isSelf: false,
|
||||
timestamp: '2024-01-15 09:45'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
content: '你好!我们学校今年的招生政策主要包括...',
|
||||
isSelf: true,
|
||||
timestamp: '2024-01-15 09:46'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
content: '好的,谢谢老师!那请问学费是多少呢?',
|
||||
isSelf: false,
|
||||
timestamp: '2024-01-15 09:47'
|
||||
},
|
||||
],
|
||||
|
||||
// 输入框
|
||||
inputValue: '',
|
||||
|
||||
// 滚动位置
|
||||
scrollIntoView: '',
|
||||
}
|
||||
},
|
||||
|
||||
onLoad(options) {
|
||||
// 获取传入的用户信息
|
||||
this.userId = options.userId || ''
|
||||
this.userName = options.name || '用户'
|
||||
|
||||
console.log('[聊天详情] 用户ID:', this.userId)
|
||||
console.log('[聊天详情] 用户名:', this.userName)
|
||||
|
||||
// 加载历史消息
|
||||
this.loadHistoryMessages()
|
||||
|
||||
// 滚动到底部
|
||||
this.$nextTick(() => {
|
||||
this.scrollToBottom()
|
||||
})
|
||||
},
|
||||
|
||||
methods: {
|
||||
// 返回
|
||||
goBack() {
|
||||
uni.navigateBack()
|
||||
},
|
||||
|
||||
// 显示用户信息
|
||||
showUserInfo() {
|
||||
uni.showToast({
|
||||
title: '用户信息',
|
||||
icon: 'none'
|
||||
})
|
||||
},
|
||||
|
||||
// 发送消息
|
||||
sendMessage() {
|
||||
if (!this.inputValue.trim()) {
|
||||
uni.showToast({
|
||||
title: '请输入消息内容',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 构建消息对象
|
||||
const message = {
|
||||
id: Date.now(),
|
||||
content: this.inputValue,
|
||||
isSelf: true,
|
||||
timestamp: this.formatTime(new Date())
|
||||
}
|
||||
|
||||
// 添加到消息列表
|
||||
this.messageList.push(message)
|
||||
|
||||
// 清空输入框
|
||||
this.inputValue = ''
|
||||
|
||||
// 滚动到底部
|
||||
this.$nextTick(() => {
|
||||
this.scrollToBottom()
|
||||
})
|
||||
|
||||
// TODO: 通过 WebSocket 发送消息
|
||||
// wsManager.send({
|
||||
// type: 'message',
|
||||
// toUserId: this.userId,
|
||||
// content: message.content
|
||||
// })
|
||||
|
||||
console.log('[聊天详情] 发送消息:', message)
|
||||
|
||||
// 模拟对方回复
|
||||
setTimeout(() => {
|
||||
this.receiveMessage('收到,我马上处理')
|
||||
}, 1000)
|
||||
},
|
||||
|
||||
// 接收消息
|
||||
receiveMessage(content) {
|
||||
const message = {
|
||||
id: Date.now(),
|
||||
content: content,
|
||||
isSelf: false,
|
||||
timestamp: this.formatTime(new Date())
|
||||
}
|
||||
|
||||
this.messageList.push(message)
|
||||
|
||||
this.$nextTick(() => {
|
||||
this.scrollToBottom()
|
||||
})
|
||||
},
|
||||
|
||||
// 加载历史消息
|
||||
loadHistoryMessages() {
|
||||
// TODO: 从服务器加载历史消息
|
||||
// this.$u.api.getChatHistory({
|
||||
// userId: this.userId
|
||||
// }).then(res => {
|
||||
// this.messageList = res.data
|
||||
// })
|
||||
|
||||
console.log('[聊天详情] 加载历史消息')
|
||||
},
|
||||
|
||||
// 滚动到底部
|
||||
scrollToBottom() {
|
||||
if (this.messageList.length > 0) {
|
||||
const lastMsg = this.messageList[this.messageList.length - 1]
|
||||
this.scrollIntoView = 'msg-' + lastMsg.id
|
||||
}
|
||||
},
|
||||
|
||||
// 格式化时间
|
||||
formatTime(date) {
|
||||
const hours = date.getHours().toString().padStart(2, '0')
|
||||
const minutes = date.getMinutes().toString().padStart(2, '0')
|
||||
return `${hours}:${minutes}`
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.chat-detail-page {
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #f5f6fa;
|
||||
}
|
||||
|
||||
/* ===== 顶部导航 ===== */
|
||||
.chat-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 44px;
|
||||
padding: 0 15px;
|
||||
background: #fff;
|
||||
border-bottom: 1rpx solid #e5e5e5;
|
||||
}
|
||||
|
||||
.header-left,
|
||||
.header-right {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
font-size: 17px;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
/* ===== 消息列表 ===== */
|
||||
.message-list {
|
||||
flex: 1;
|
||||
padding: 15px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.message-item {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
/* 我发送的消息 */
|
||||
.message-self {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.message-self .message-content-wrapper {
|
||||
max-width: 70%;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.message-self .message-content {
|
||||
background: #4a6cf7;
|
||||
color: #fff;
|
||||
padding: 12px 15px;
|
||||
border-radius: 8px;
|
||||
font-size: 15px;
|
||||
line-height: 1.5;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
/* 对方发送的消息 */
|
||||
.message-other {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.message-other .message-content-wrapper {
|
||||
max-width: 70%;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.message-other .message-content {
|
||||
background: #fff;
|
||||
color: #333;
|
||||
padding: 12px 15px;
|
||||
border-radius: 8px;
|
||||
font-size: 15px;
|
||||
line-height: 1.5;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
/* 头像 */
|
||||
.message-avatar {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 8px;
|
||||
background-color: #e8e8e8;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* 空状态 */
|
||||
.empty-message {
|
||||
text-align: center;
|
||||
padding: 100px 20px;
|
||||
color: #999;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* ===== 输入栏 ===== */
|
||||
.input-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px 15px;
|
||||
background: #fff;
|
||||
border-top: 1rpx solid #e5e5e5;
|
||||
padding-bottom: calc(10px + env(safe-area-inset-bottom));
|
||||
}
|
||||
|
||||
.input-wrapper {
|
||||
flex: 1;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.input-field {
|
||||
height: 36px;
|
||||
padding: 0 15px;
|
||||
background: #f5f5f5;
|
||||
border-radius: 18px;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.send-button {
|
||||
width: 60px;
|
||||
height: 36px;
|
||||
background: #4a6cf7;
|
||||
border-radius: 18px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #fff;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.send-button:active {
|
||||
opacity: 0.8;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
|
@ -1,346 +0,0 @@
|
|||
<template>
|
||||
<view class="page-container">
|
||||
<view class="page-header">
|
||||
<PageHeader title="在线咨询" :is-back="false" :border-bottom="false" />
|
||||
</view>
|
||||
|
||||
<scroll-view
|
||||
class="page-main"
|
||||
scroll-y
|
||||
enable-back-to-top
|
||||
>
|
||||
<view class="main-content">
|
||||
<!-- 聊天会话列表 -->
|
||||
<view
|
||||
class="chat-item"
|
||||
v-for="(item, index) in chatList"
|
||||
:key="item.id"
|
||||
@click="openChat(item)"
|
||||
>
|
||||
<view class="chat-avatar-wrapper">
|
||||
<image class="chat-avatar" :src="item.avatar"></image>
|
||||
<!-- 未读数角标 -->
|
||||
<view class="unread-badge" v-if="item.unreadCount > 0">
|
||||
{{ item.unreadCount > 99 ? '99+' : item.unreadCount }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="chat-content">
|
||||
<view class="chat-header">
|
||||
<text class="chat-name">{{ item.name }}</text>
|
||||
<text class="chat-time">{{ item.lastMessageTime }}</text>
|
||||
</view>
|
||||
<view class="chat-preview">
|
||||
<text class="preview-text">{{ item.lastMessage }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 无数据提示 -->
|
||||
<view class="empty-container" v-if="chatList.length === 0">
|
||||
<image class="empty-image" src="/static/common/icon/empty-chat.png"></image>
|
||||
<text class="empty-text">暂无咨询消息</text>
|
||||
<text class="empty-hint">学生咨询后会显示在这里</text>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<view class="page-tabbar">
|
||||
<TabBar :currentPath="'/pages/consultation/index'" @change="handleTabChange" />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import TabBar from "@/components/TabBar-optimized.vue";
|
||||
import PageHeader from "@/components/PageHeader.vue";
|
||||
|
||||
export default {
|
||||
name: "ConsultationPage",
|
||||
components: {
|
||||
TabBar,
|
||||
PageHeader,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 聊天会话列表(模拟数据)
|
||||
chatList: [
|
||||
{
|
||||
id: 1,
|
||||
userId: 'user_001',
|
||||
name: '山东考生1',
|
||||
avatar: '/static/avatar/default-avatar.png',
|
||||
lastMessage: '你好,在吗',
|
||||
lastMessageTime: '09:50',
|
||||
unreadCount: 2,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
userId: 'user_002',
|
||||
name: '河北考生2',
|
||||
avatar: '/static/avatar/default-avatar.png',
|
||||
lastMessage: '我是保研的是否了解到了后续计划,谁信谁的呢们爱国士...',
|
||||
lastMessageTime: '09:50',
|
||||
unreadCount: 0,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
userId: 'user_003',
|
||||
name: '山东考生34523',
|
||||
avatar: '/static/avatar/default-avatar.png',
|
||||
lastMessage: '请问,学校宿舍几人间?',
|
||||
lastMessageTime: '09:50',
|
||||
unreadCount: 1,
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
userId: 'user_004',
|
||||
name: '招办王老师',
|
||||
avatar: '/static/avatar/default-avatar.png',
|
||||
lastMessage: '你好,在吗',
|
||||
lastMessageTime: '09:50',
|
||||
unreadCount: 0,
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
userId: 'user_005',
|
||||
name: '山东考生34523',
|
||||
avatar: '/static/avatar/default-avatar.png',
|
||||
lastMessage: '请问,学校宿舍几人间?',
|
||||
lastMessageTime: '09:50',
|
||||
unreadCount: 3,
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
userId: 'user_006',
|
||||
name: '招办王老师',
|
||||
avatar: '/static/avatar/default-avatar.png',
|
||||
lastMessage: '你好,在吗',
|
||||
lastMessageTime: '09:50',
|
||||
unreadCount: 0,
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
// 加载聊天列表
|
||||
this.loadChatList();
|
||||
},
|
||||
|
||||
onShow() {
|
||||
// 页面显示时刷新列表
|
||||
this.refreshChatList();
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleTabChange(path, index) {
|
||||
console.log("切换到标签页:", path, index);
|
||||
},
|
||||
|
||||
// 打开聊天页面
|
||||
openChat(item) {
|
||||
console.log('打开聊天:', item);
|
||||
uni.navigateTo({
|
||||
url: `/pages/chat/chat-detail?userId=${item.userId}&name=${item.name}`
|
||||
});
|
||||
},
|
||||
|
||||
// 加载聊天列表
|
||||
loadChatList() {
|
||||
// TODO: 接入真实API
|
||||
// this.$u.api.getChatList().then(res => {
|
||||
// this.chatList = res.data;
|
||||
// });
|
||||
|
||||
console.log('[在线咨询] 加载聊天列表');
|
||||
},
|
||||
|
||||
// 刷新聊天列表
|
||||
refreshChatList() {
|
||||
console.log('[在线咨询] 刷新聊天列表');
|
||||
// TODO: 刷新数据
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* ===== 页面容器 - 主流三段式布局 ===== */
|
||||
.page-container {
|
||||
/* 固定定位,占满整个视口 */
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
|
||||
/* Flex 布局 */
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
/* 背景色 */
|
||||
background-color: #f5f6fa;
|
||||
|
||||
/* 防止溢出 */
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* ===== 头部导航 ===== */
|
||||
.page-header {
|
||||
/* 不收缩,固定高度 */
|
||||
flex-shrink: 0;
|
||||
|
||||
/* 层级 */
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
/* ===== 内容区域 ===== */
|
||||
.page-main {
|
||||
/* 占据剩余空间 */
|
||||
flex: 1;
|
||||
|
||||
/* 重要:防止 flex 子元素溢出 */
|
||||
height: 0;
|
||||
|
||||
/* 允许滚动 */
|
||||
overflow-y: auto;
|
||||
|
||||
/* iOS 滚动优化 */
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
/* ===== 内容内层 ===== */
|
||||
.main-content {
|
||||
/* 内边距 */
|
||||
padding: 10px;
|
||||
|
||||
/* 底部留出 TabBar 空间 + 安全区域 */
|
||||
padding-bottom: calc(50px + env(safe-area-inset-bottom) + 10px);
|
||||
|
||||
/* 最小高度(确保可以滚动) */
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
/* ===== 底部导航 ===== */
|
||||
.page-tabbar {
|
||||
/* 不收缩,固定高度 */
|
||||
flex-shrink: 0;
|
||||
|
||||
/* 层级 */
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
/* ===== 聊天列表项 ===== */
|
||||
.chat-item {
|
||||
display: flex;
|
||||
padding: 15px;
|
||||
background: #fff;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.chat-item:active {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.chat-avatar-wrapper {
|
||||
position: relative;
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
.chat-avatar {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: 8px;
|
||||
background-color: #e8e8e8;
|
||||
}
|
||||
|
||||
.unread-badge {
|
||||
position: absolute;
|
||||
top: -5px;
|
||||
right: -5px;
|
||||
min-width: 18px;
|
||||
height: 18px;
|
||||
padding: 0 5px;
|
||||
background: #ff4d4f;
|
||||
border-radius: 9px;
|
||||
color: #fff;
|
||||
font-size: 11px;
|
||||
line-height: 18px;
|
||||
text-align: center;
|
||||
border: 2px solid #fff;
|
||||
}
|
||||
|
||||
.chat-content {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.chat-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.chat-name {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
max-width: 200px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.chat-time {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.chat-preview {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.preview-text {
|
||||
font-size: 13px;
|
||||
color: #999;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
/* ===== 空状态 ===== */
|
||||
.empty-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 100px 20px;
|
||||
}
|
||||
|
||||
.empty-image {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-size: 16px;
|
||||
color: #666;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.empty-hint {
|
||||
font-size: 13px;
|
||||
color: #999;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
|
@ -1,26 +1,23 @@
|
|||
<template>
|
||||
<view class="admissions-container">
|
||||
<header-bar title="在线咨询" @leftClick="handleLeftClick"></header-bar>
|
||||
<view class="header">
|
||||
<div class="header-left">
|
||||
<u-icon
|
||||
class="header-left-icon"
|
||||
name="arrow-left"
|
||||
@click="handleLeftClick"
|
||||
></u-icon>
|
||||
</div>
|
||||
<text class="header-title">招办在线</text>
|
||||
<div></div>
|
||||
</view>
|
||||
|
||||
<view class="admissions-content">
|
||||
<!-- 自定义tab -->
|
||||
<view class="custom-tab">
|
||||
<view
|
||||
v-for="tab in tabList"
|
||||
:key="tab.id"
|
||||
:class="['tab-item', { active: activeTab === tab.id }]"
|
||||
@click="switchTab(tab.id)"
|
||||
>
|
||||
<text class="tab-text">{{ tab.name }}</text>
|
||||
<view class="tab-underline" v-if="activeTab === tab.id"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="teacher-list">
|
||||
<!-- 教师列表 -->
|
||||
<view
|
||||
class="teacher-item"
|
||||
v-for="(teacher, index) in currentList"
|
||||
v-for="(teacher, index) in teacherList"
|
||||
:key="index"
|
||||
>
|
||||
<image class="teacher-avatar" :src="teacher.avatar"></image>
|
||||
|
|
@ -35,9 +32,9 @@
|
|||
</view>
|
||||
<view class="teacher-department">{{ teacher.department }}</view>
|
||||
</view>
|
||||
<view class="ask-button" @click="handleAskQuestion(teacher)">
|
||||
立即提问
|
||||
</view>
|
||||
<view class="ask-button" @click="handleAskQuestion(teacher)">{{
|
||||
teacher.online ? "立即提问" : "留言"
|
||||
}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
|
@ -53,21 +50,14 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import HeaderBar from "@/components/HeaderBar.vue"; // 导入头部组件
|
||||
import LeaveMessage from "@/components/LeaveMessage.vue";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
HeaderBar, // 注册头部组件
|
||||
LeaveMessage,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeTab: "1", // 当前激活的tab
|
||||
tabList: [
|
||||
{ id: "1", name: "招生在线", key: "admissions" },
|
||||
{ id: "2", name: "迎新在线", key: "welcome" },
|
||||
],
|
||||
showLeaveMessage: false,
|
||||
teacherList: [
|
||||
{
|
||||
|
|
@ -99,41 +89,10 @@ export default {
|
|||
online: false,
|
||||
},
|
||||
],
|
||||
welcomeList: [
|
||||
{
|
||||
id: 5,
|
||||
name: "李老师",
|
||||
department: "学生处",
|
||||
avatar: "/static/common/images/avatar.png",
|
||||
online: true,
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: "张老师",
|
||||
department: "宿管中心",
|
||||
avatar: "/static/common/images/student.png",
|
||||
online: true,
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
name: "迎新办陈老师",
|
||||
department: "后勤服务中心",
|
||||
avatar: "/static/common/images/student.png",
|
||||
online: false,
|
||||
},
|
||||
],
|
||||
currentTeacher: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
currentList() {
|
||||
return this.activeTab === "1" ? this.teacherList : this.welcomeList;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
switchTab(tab) {
|
||||
this.activeTab = tab;
|
||||
},
|
||||
handleLeftClick() {
|
||||
uni.navigateBack();
|
||||
},
|
||||
|
|
@ -200,44 +159,6 @@ export default {
|
|||
}
|
||||
|
||||
.admissions-content {
|
||||
.custom-tab {
|
||||
padding: 0 30rpx;
|
||||
margin: 24rpx 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.tab-item {
|
||||
position: relative;
|
||||
padding: 12rpx 0;
|
||||
margin-right: 60rpx;
|
||||
cursor: pointer;
|
||||
|
||||
.tab-text {
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
color: #505866;
|
||||
letter-spacing: 0.04rpx;
|
||||
}
|
||||
|
||||
&.active .tab-text {
|
||||
color: #4f6aff;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tab-underline {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
right: 0;
|
||||
width: 80rpx;
|
||||
height: 4rpx;
|
||||
background-color: #4f6aff;
|
||||
border-radius: 2rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.teacher-list {
|
||||
.teacher-item {
|
||||
display: flex;
|
||||
|
|
|
|||
|
|
@ -1,655 +0,0 @@
|
|||
<template>
|
||||
<view class="history-page">
|
||||
<header-bar title="历史记录" @leftClick="handleLeftClick"></header-bar>
|
||||
|
||||
<view class="tab-container">
|
||||
<view class="custom-tab">
|
||||
<view
|
||||
v-for="tab in tabList"
|
||||
:key="tab.id"
|
||||
:class="['tab-item', { active: activeTab === tab.id }]"
|
||||
@click="switchTab(tab.id)"
|
||||
>
|
||||
<text class="tab-text">{{ tab.name }}</text>
|
||||
<view class="tab-underline" v-if="activeTab === tab.id"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="more-icon-container" @click="toggleMoreMenu">
|
||||
<image
|
||||
class="more-icon"
|
||||
src="/static/common/images/icon-more.png"
|
||||
mode="scaleToFill"
|
||||
></image>
|
||||
</view>
|
||||
|
||||
<!-- 右上角弹出菜单:批量删除 -->
|
||||
<view v-if="isMoreMenuVisible" class="more-menu" @click.stop>
|
||||
<view class="menu-card" @click="handleBatchDeleteClick">
|
||||
<!-- <image
|
||||
class="menu-icon"
|
||||
src="/static/common/images/icon_delete.png"
|
||||
mode="widthFix"
|
||||
/> -->
|
||||
<u-icon name="trash" color="#FF647D" size="28"></u-icon>
|
||||
<text class="menu-text">批量删除</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 点击其他区域关闭弹层 -->
|
||||
<view v-if="isMoreMenuVisible" class="overlay" @click="hideMoreMenu"></view>
|
||||
|
||||
<!-- 内容区域包装器 -->
|
||||
<view class="content-wrapper">
|
||||
<!-- 历史记录列表(按日期分组,日期固定在上方) -->
|
||||
<view class="history-list">
|
||||
<view
|
||||
class="date-group"
|
||||
v-for="group in groupedHistoryList"
|
||||
:key="group.header"
|
||||
>
|
||||
<view class="date-header">{{ group.header }}</view>
|
||||
|
||||
<view class="history-item" v-for="item in group.items" :key="item.id">
|
||||
<!-- 批量删除模式下的选择框 -->
|
||||
<view
|
||||
class="item-checkbox"
|
||||
v-if="isBatchDeleteMode"
|
||||
@click="toggleItemSelection(item.id)"
|
||||
>
|
||||
<view
|
||||
class="checkbox"
|
||||
:class="{ checked: selectedItems.includes(item.id) }"
|
||||
>
|
||||
<text class="checkmark" v-if="selectedItems.includes(item.id)"
|
||||
>✓</text
|
||||
>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 历史记录内容 -->
|
||||
<view class="item-content">
|
||||
<view class="item-header">
|
||||
<view class="item-icon">
|
||||
<text class="icon-text">B</text>
|
||||
</view>
|
||||
<view class="item-title">{{ item.title }}</view>
|
||||
</view>
|
||||
<view class="item-description">{{ item.content }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 批量删除操作栏 -->
|
||||
<view class="batch-actions" v-if="isBatchDeleteMode">
|
||||
<view class="select-all-container" @click="toggleSelectAll">
|
||||
<view class="checkbox" :class="{ checked: selectAll }">
|
||||
<text class="checkmark" v-if="selectAll">✓</text>
|
||||
</view>
|
||||
<text class="select-all-text">全选</text>
|
||||
</view>
|
||||
<view class="function-btn">
|
||||
<view class="cancel-btn" @click="cancelBatchDelete">取消</view>
|
||||
<view class="delete-btn" @click="batchDelete">删除</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 提示 -->
|
||||
<u-toast ref="uToast" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import HeaderBar from "@/components/HeaderBar.vue";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
HeaderBar,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeTab: "1", // 当前激活的tab
|
||||
tabList: [
|
||||
{ id: "1", name: "AI咨询" },
|
||||
{ id: "2", name: "人工咨询" },
|
||||
],
|
||||
isBatchDeleteMode: false, // 是否为批量删除模式
|
||||
isMoreMenuVisible: false, // 右上角更多菜单是否可见
|
||||
selectedItems: [], // 选中的项目
|
||||
selectAll: false, // 是否全选
|
||||
historyList: [
|
||||
{
|
||||
id: 1,
|
||||
title: "学校哪些专业比较好?",
|
||||
content:
|
||||
"学校哪些专业比较好?学校哪些专业比较好?学校哪些专业比较好?学校哪些专业比较好?学校哪些专业比较好?学校哪些专业比较好?学校哪些专业比较好?",
|
||||
time: new Date().getTime(), // 今天
|
||||
type: "ai",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: "学校哪些专业比较好?",
|
||||
content:
|
||||
"学校哪些专业比较好?学校哪些专业比较好?学校哪些专业比较好?学校哪些专业比较好?学校哪些专业比较好?学校哪些专业比较好?学校哪些专业比较好?",
|
||||
time: new Date().getTime(), // 今天
|
||||
type: "ai",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: "学校哪些专业比较好?",
|
||||
content:
|
||||
"学校哪些专业比较好?学校哪些专业比较好?学校哪些专业比较好?学校哪些专业比较好?学校哪些专业比较好?学校哪些专业比较好?学校哪些专业比较好?",
|
||||
time: new Date().getTime(), // 今天
|
||||
type: "ai",
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
title: "学校哪些专业比较好?",
|
||||
content:
|
||||
"学校哪些专业比较好?学校哪些专业比较好?学校哪些专业比较好?学校哪些专业比较好?学校哪些专业比较好?学校哪些专业比较好?学校哪些专业比较好?",
|
||||
time: new Date().getTime(), // 今天
|
||||
type: "ai",
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
title: "学校哪些专业比较好?",
|
||||
content:
|
||||
"学校哪些专业比较好?学校哪些专业比较好?学校哪些专业比较好?学校哪些专业比较好?学校哪些专业比较好?学校哪些专业比较好?学校哪些专业比较好?",
|
||||
time: new Date().getTime() - 24 * 60 * 60 * 1000 * 2, // 2天前
|
||||
type: "ai",
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
title: "学校哪些专业比较好?",
|
||||
content:
|
||||
"学校哪些专业比较好?学校哪些专业比较好?学校哪些专业比较好?学校哪些专业比较好?学校哪些专业比较好?学校哪些专业比较好?学校哪些专业比较好?",
|
||||
time: new Date().getTime() - 365 * 24 * 60 * 60 * 1000, // 去年
|
||||
type: "human",
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
title: "学校哪些专业比较好?",
|
||||
content:
|
||||
"学校哪些专业比较好?学校哪些专业比较好?学校哪些专业比较好?学校哪些专业比较好?学校哪些专业比较好?学校哪些专业比较好?学校哪些专业比较好?",
|
||||
time: new Date().getTime() - 24 * 60 * 60 * 1000 * 5, // 5天前
|
||||
type: "human",
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
// 根据当前tab过滤历史记录
|
||||
filteredHistoryList() {
|
||||
return this.historyList.filter((item) => {
|
||||
if (this.activeTab === "1") {
|
||||
return item.type === "ai";
|
||||
} else {
|
||||
return item.type === "human";
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// 按日期分组后的历史记录(日期标题固定在上方)
|
||||
groupedHistoryList() {
|
||||
// 先按时间倒序
|
||||
const list = [...this.filteredHistoryList].sort(
|
||||
(a, b) => b.time - a.time
|
||||
);
|
||||
const groups = [];
|
||||
let currentHeader = null;
|
||||
let currentItems = [];
|
||||
|
||||
list.forEach((item) => {
|
||||
const header = this.formatTime(item.time);
|
||||
if (header !== currentHeader) {
|
||||
if (currentItems.length) {
|
||||
groups.push({ header: currentHeader, items: currentItems });
|
||||
}
|
||||
currentHeader = header;
|
||||
currentItems = [item];
|
||||
} else {
|
||||
currentItems.push(item);
|
||||
}
|
||||
});
|
||||
if (currentItems.length) {
|
||||
groups.push({ header: currentHeader, items: currentItems });
|
||||
}
|
||||
return groups;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
// 格式化时间显示
|
||||
formatTime(timestamp) {
|
||||
const now = new Date();
|
||||
const date = new Date(timestamp);
|
||||
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
|
||||
const itemDate = new Date(
|
||||
date.getFullYear(),
|
||||
date.getMonth(),
|
||||
date.getDate()
|
||||
);
|
||||
|
||||
// 计算时间差
|
||||
const diffTime = today.getTime() - itemDate.getTime();
|
||||
const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24));
|
||||
|
||||
// 今天
|
||||
if (diffDays === 0) {
|
||||
return `${String(date.getMonth() + 1).padStart(2, "0")}/${String(
|
||||
date.getDate()
|
||||
).padStart(2, "0")}`;
|
||||
}
|
||||
|
||||
// 本周内(1-6天前)
|
||||
if (diffDays > 0 && diffDays <= 6) {
|
||||
const weekdays = [
|
||||
"周日",
|
||||
"周一",
|
||||
"周二",
|
||||
"周三",
|
||||
"周四",
|
||||
"周五",
|
||||
"周六",
|
||||
];
|
||||
return weekdays[date.getDay()];
|
||||
}
|
||||
|
||||
// 今年但不是本周
|
||||
if (date.getFullYear() === now.getFullYear()) {
|
||||
return `${String(date.getMonth() + 1).padStart(2, "0")}/${String(
|
||||
date.getDate()
|
||||
).padStart(2, "0")}`;
|
||||
}
|
||||
|
||||
// 往年
|
||||
return `${date.getFullYear()}/${String(date.getMonth() + 1).padStart(
|
||||
2,
|
||||
"0"
|
||||
)}/${String(date.getDate()).padStart(2, "0")}`;
|
||||
},
|
||||
|
||||
handleLeftClick() {
|
||||
uni.navigateBack();
|
||||
},
|
||||
|
||||
switchTab(tab) {
|
||||
this.activeTab = tab;
|
||||
},
|
||||
|
||||
// 显示/隐藏右上角更多菜单
|
||||
toggleMoreMenu() {
|
||||
this.isMoreMenuVisible = !this.isMoreMenuVisible;
|
||||
},
|
||||
// 点击蒙层隐藏更多菜单
|
||||
hideMoreMenu() {
|
||||
this.isMoreMenuVisible = false;
|
||||
},
|
||||
// 取消批量删除模式
|
||||
cancelBatchDelete() {
|
||||
this.isBatchDeleteMode = false;
|
||||
},
|
||||
|
||||
// 点击“批量删除”菜单项,进入批量删除模式
|
||||
handleBatchDeleteClick() {
|
||||
this.isMoreMenuVisible = false;
|
||||
if (!this.isBatchDeleteMode) {
|
||||
this.toggleBatchDeleteMode();
|
||||
}
|
||||
},
|
||||
|
||||
// 切换批量删除模式
|
||||
toggleBatchDeleteMode() {
|
||||
this.isBatchDeleteMode = !this.isBatchDeleteMode;
|
||||
if (!this.isBatchDeleteMode) {
|
||||
// 退出批量删除模式时清空选中项
|
||||
this.selectedItems = [];
|
||||
this.selectAll = false;
|
||||
}
|
||||
},
|
||||
|
||||
// 切换单个项目选中状态
|
||||
toggleItemSelection(itemId) {
|
||||
const index = this.selectedItems.indexOf(itemId);
|
||||
if (index > -1) {
|
||||
this.selectedItems.splice(index, 1);
|
||||
} else {
|
||||
this.selectedItems.push(itemId);
|
||||
}
|
||||
// 更新全选状态
|
||||
this.selectAll =
|
||||
this.selectedItems.length === this.filteredHistoryList.length;
|
||||
},
|
||||
|
||||
// 切换全选状态
|
||||
toggleSelectAll() {
|
||||
this.selectAll = !this.selectAll;
|
||||
if (this.selectAll) {
|
||||
this.selectedItems = this.filteredHistoryList.map((item) => item.id);
|
||||
} else {
|
||||
this.selectedItems = [];
|
||||
}
|
||||
},
|
||||
|
||||
// 批量删除选中项
|
||||
batchDelete() {
|
||||
if (this.selectedItems.length === 0) {
|
||||
this.$refs.uToast.show({
|
||||
title: "请选择要删除的项目",
|
||||
type: "warning",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 删除选中的项目
|
||||
this.historyList = this.historyList.filter(
|
||||
(item) => !this.selectedItems.includes(item.id)
|
||||
);
|
||||
|
||||
// 重置状态
|
||||
this.selectedItems = [];
|
||||
this.selectAll = false;
|
||||
this.isBatchDeleteMode = false;
|
||||
|
||||
this.$refs.uToast.show({
|
||||
title: "删除成功",
|
||||
type: "success",
|
||||
});
|
||||
},
|
||||
|
||||
handleDelete(item, callback) {
|
||||
console.log("handleDelete", item);
|
||||
|
||||
setTimeout(() => {
|
||||
this.$refs.uToast.show({
|
||||
title: "撤回成功",
|
||||
type: "success",
|
||||
});
|
||||
callback(true);
|
||||
}, 1500);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.history-page {
|
||||
height: 100vh;
|
||||
background-color: #ffffff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
padding-top: 88rpx;
|
||||
|
||||
.tab-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.custom-tab {
|
||||
padding: 0 30rpx;
|
||||
margin: 24rpx 0;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.tab-item {
|
||||
position: relative;
|
||||
padding: 12rpx 0;
|
||||
margin-right: 80rpx;
|
||||
cursor: pointer;
|
||||
|
||||
.tab-text {
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
color: #505866;
|
||||
letter-spacing: 0.04rpx;
|
||||
}
|
||||
|
||||
&.active .tab-text {
|
||||
color: #4f6aff;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tab-underline {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
right: 0;
|
||||
width: 80rpx;
|
||||
height: 4rpx;
|
||||
background-color: #4f6aff;
|
||||
border-radius: 2rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.more-icon-container {
|
||||
width: 50rpx;
|
||||
height: 50rpx;
|
||||
margin-right: 30rpx;
|
||||
|
||||
.more-icon {
|
||||
width: 50rpx;
|
||||
height: 10rpx;
|
||||
margin-right: 30rpx;
|
||||
}
|
||||
}
|
||||
|
||||
/* 右上角更多菜单弹层 */
|
||||
.more-menu {
|
||||
position: absolute;
|
||||
top: 80rpx;
|
||||
right: 30rpx;
|
||||
z-index: 100;
|
||||
background-color: #ffffff;
|
||||
border: 1rpx solid rgba(79, 106, 255, 0.12);
|
||||
border-radius: 24rpx;
|
||||
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.08);
|
||||
padding: 24rpx 28rpx;
|
||||
}
|
||||
|
||||
.menu-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6rpx;
|
||||
|
||||
// .menu-icon {
|
||||
// color: #FF647D;
|
||||
// width: 32rpx;
|
||||
// height: 32rpx;
|
||||
// margin-right: 12rpx;
|
||||
// }
|
||||
|
||||
.menu-text {
|
||||
font-size: 28rpx;
|
||||
color: #ff647d;
|
||||
letter-spacing: 2rpx;
|
||||
}
|
||||
}
|
||||
|
||||
/* 点击其它区域关闭的遮罩(透明) */
|
||||
.overlay {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 99;
|
||||
background: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
.content-wrapper {
|
||||
padding: 30rpx;
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.history-list {
|
||||
.date-group {
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
|
||||
.date-header {
|
||||
font-size: 26rpx;
|
||||
color: #9aa0a8;
|
||||
margin-bottom: 16rpx;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.history-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
padding: 24rpx 0;
|
||||
|
||||
.item-checkbox {
|
||||
margin-right: 24rpx;
|
||||
padding-top: 8rpx;
|
||||
cursor: pointer;
|
||||
width: 48rpx;
|
||||
flex: 0 0 48rpx; /* 固定宽度,避免内容因显隐而抖动 */
|
||||
|
||||
.checkbox {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
border: 2rpx solid #d9d9d9;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: #ffffff;
|
||||
|
||||
&.checked {
|
||||
background-color: #ff4757;
|
||||
border-color: #ff4757;
|
||||
|
||||
.checkmark {
|
||||
color: #ffffff;
|
||||
font-size: 22rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.item-content {
|
||||
flex: 1;
|
||||
|
||||
.item-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 24rpx;
|
||||
|
||||
.item-icon {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
background-color: #4f6aff;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 16rpx;
|
||||
|
||||
.icon-text {
|
||||
color: #ffffff;
|
||||
font-size: 24rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.item-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.item-description {
|
||||
letter-spacing: 0.04rpx;
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
line-height: 1.5;
|
||||
margin-bottom: 12rpx;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 3;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.batch-actions {
|
||||
height: 130rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 30rpx;
|
||||
border-top: 1rpx solid #eeeeee;
|
||||
|
||||
.select-all-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
|
||||
.checkbox {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
border: 2rpx solid #d9d9d9;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: #ffffff;
|
||||
|
||||
&.checked {
|
||||
background-color: #ff4757;
|
||||
border-color: #ff4757;
|
||||
|
||||
.checkmark {
|
||||
color: #ffffff;
|
||||
font-size: 22rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.select-all-text {
|
||||
margin-left: 16rpx;
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
|
||||
.function-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20rpx;
|
||||
|
||||
.cancel-btn {
|
||||
background-color: #e5e3e3e4;
|
||||
color: #333333;
|
||||
padding: 16rpx 32rpx;
|
||||
border-radius: 16rpx;
|
||||
font-size: 28rpx;
|
||||
cursor: pointer;
|
||||
}
|
||||
.delete-btn {
|
||||
background-color: #ff4757;
|
||||
color: #ffffff;
|
||||
padding: 16rpx 32rpx;
|
||||
border-radius: 16rpx;
|
||||
font-size: 28rpx;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -19,7 +19,7 @@
|
|||
>
|
||||
</view>
|
||||
|
||||
<view class="qa-section">
|
||||
<!-- <view class="qa-section">
|
||||
<view class="qa-header">
|
||||
<text class="qa-title">大家都在问</text>
|
||||
<view class="more-link">
|
||||
|
|
@ -37,6 +37,16 @@
|
|||
</view>
|
||||
</view>
|
||||
|
||||
<button class="chat-button" @click="isChat = true">
|
||||
<image
|
||||
class="chat-icon"
|
||||
src="/static/common/images/icon_chat.png"
|
||||
></image>
|
||||
<text class="chat-text">开启对话</text>
|
||||
</button>
|
||||
</view> -->
|
||||
|
||||
<view class="start-chat">
|
||||
<button class="chat-button" @click="handleStartChat">
|
||||
<image
|
||||
class="chat-icon"
|
||||
|
|
@ -51,9 +61,6 @@
|
|||
class="feature-item"
|
||||
v-for="(item, index) in features"
|
||||
:key="index"
|
||||
:style="{
|
||||
background: item.background,
|
||||
}"
|
||||
@click="handleFeatureClick(item)"
|
||||
>
|
||||
<image :src="item.icon" class="feature-icon"></image>
|
||||
|
|
@ -287,20 +294,18 @@ export default {
|
|||
],
|
||||
features: [
|
||||
{
|
||||
title: "在线咨询",
|
||||
title: "招办在线",
|
||||
icon: "/static/common/images/icon_admissions.png",
|
||||
path: "/pages/home/admissions/index",
|
||||
background: "linear-gradient(0deg, #F4FBFE 0%, #F4FBFE 100%)",
|
||||
},
|
||||
// {
|
||||
// title: "留言板",
|
||||
// icon: "/static/common/images/icon_messageBoard.png",
|
||||
// path: "/pages/home/messageBoard/index",
|
||||
// },
|
||||
{
|
||||
title: "留言板",
|
||||
icon: "/static/common/images/icon_messageBoard.png",
|
||||
path: "/pages/home/messageBoard/index",
|
||||
},
|
||||
{
|
||||
title: "电话咨询",
|
||||
icon: "/static/common/images/icon_phone.png",
|
||||
background: "linear-gradient(0deg, #F4FBF9 0%, #F4FBF9 100%)",
|
||||
},
|
||||
],
|
||||
popupShow: false,
|
||||
|
|
@ -766,7 +771,7 @@ export default {
|
|||
|
||||
.main-content {
|
||||
padding: 30rpx;
|
||||
padding-top: 60rpx;
|
||||
padding-top: 100rpx;
|
||||
|
||||
.welcome-message {
|
||||
// display: inline-block;
|
||||
|
|
@ -779,8 +784,8 @@ export default {
|
|||
|
||||
.avatar {
|
||||
display: inline-block;
|
||||
width: 50rpx;
|
||||
height: 44rpx;
|
||||
width: 42rpx;
|
||||
height: 34rpx;
|
||||
margin-right: 12rpx;
|
||||
}
|
||||
|
||||
|
|
@ -889,19 +894,20 @@ export default {
|
|||
gap: 30rpx;
|
||||
|
||||
.feature-item {
|
||||
height: 150rpx;
|
||||
height: 210rpx;
|
||||
border-radius: 16rpx;
|
||||
background-color: #fafafc;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding-left: 30rpx;
|
||||
gap: 20rpx;
|
||||
justify-content: center;
|
||||
// gap: 20rpx;
|
||||
flex: 1;
|
||||
|
||||
.feature-icon {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
margin-top: 16rpx;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
|
||||
.feature-text {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,425 @@
|
|||
<template>
|
||||
<view class="flex-col page">
|
||||
<!-- <image src="/static/common/img/16530269846087107196.png" class="image"/> -->
|
||||
<u-navbar title="重置密码"></u-navbar>
|
||||
<view class="flex-col group" v-if="state === 1">
|
||||
<text class="text">重置密码</text>
|
||||
<view class="flex-col group_7">
|
||||
<view class="flex-col">
|
||||
<!-- <text class="text_1">手机号</text> -->
|
||||
<view class="text-wrapper flex-row view">
|
||||
<u-input
|
||||
v-model="phone"
|
||||
:disabled="disabled"
|
||||
placeholder="请输入手机号"
|
||||
type="text"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex-col group_6">
|
||||
<!-- <text class="text_1">短信验证码</text> -->
|
||||
<view class="text-wrapper flex-row view" style="padding: 0">
|
||||
<u-input
|
||||
v-model="code"
|
||||
placeholder="请输入短信验证码"
|
||||
type="text"
|
||||
/>
|
||||
<u-button
|
||||
:disabled="!(send == '发送验证码')"
|
||||
class="custom-style"
|
||||
style="background: transparent"
|
||||
@click="sendCode"
|
||||
>{{ send }}
|
||||
</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- <navigator class="text_6" url="/pages/login/login/login">登录</navigator> -->
|
||||
<u-button
|
||||
class="flex-col items-center text-wrapper_1"
|
||||
shape="circle"
|
||||
type="primary"
|
||||
@click="login"
|
||||
>
|
||||
<text class="text_7">重置密码</text>
|
||||
</u-button>
|
||||
</view>
|
||||
<view class="flex-col group" v-if="state === 2">
|
||||
<text class="text">遇见身边的校友</text>
|
||||
<view class="flex-col group_7">
|
||||
<view class="flex-col">
|
||||
<u-input
|
||||
v-model="passWord"
|
||||
class="view text-wrapper"
|
||||
placeholder="请输入新密码"
|
||||
type="password"
|
||||
/>
|
||||
</view>
|
||||
<view class="flex-col group_6">
|
||||
<u-input
|
||||
v-model="passWordTwo"
|
||||
class="view text-wrapper"
|
||||
placeholder="请确认新密码"
|
||||
type="password"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
<view class="tips">
|
||||
<image src="/static/common/img/infoCircle.png"></image>
|
||||
提示:密码长度应该大于5,必须包含字母、数字、特殊字符,且不能包含中文!
|
||||
</view>
|
||||
<u-button
|
||||
class="flex-col items-center text-wrapper_1"
|
||||
shape="circle"
|
||||
throttle-time="1000"
|
||||
type="primary"
|
||||
@click="login"
|
||||
>
|
||||
<text class="text_7">立即重置</text>
|
||||
</u-button>
|
||||
<u-button
|
||||
class="flex-col items-center text-wrapper_1"
|
||||
shape="circle"
|
||||
style=" margin-top: 10px"
|
||||
type="primary"
|
||||
@click="state = 1"
|
||||
>
|
||||
<text class="text_7">返回</text>
|
||||
</u-button>
|
||||
</view>
|
||||
<u-top-tips ref="uTips" :navbar-height="0"></u-top-tips>
|
||||
<u-toast ref="uToast"/>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import md5 from "js-md5";
|
||||
import {aesEncrypt} from "@/utils/encrypt.js";
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
show: false,
|
||||
phone: "",
|
||||
passWord: "",
|
||||
code: "",
|
||||
passWordTwo: "",
|
||||
agreement: false,
|
||||
disabled: false,
|
||||
send: "发送验证码",
|
||||
state: 1,
|
||||
};
|
||||
},
|
||||
onLoad(e) {
|
||||
},
|
||||
methods: {
|
||||
// 提示
|
||||
tips(title, type, time) {
|
||||
this.$refs.uToast.show({
|
||||
title: title ? title : "",
|
||||
type: type ? type : "success",
|
||||
duration: time ? time + "" : "1500",
|
||||
});
|
||||
},
|
||||
// 发送验证码
|
||||
sendCode() {
|
||||
var reg = new RegExp("^[1][3,4,5,6,7,8,9][0-9]{9}$", "g"); //手机号
|
||||
if (this.phone === "" || !reg.test(this.phone)) {
|
||||
// this.$tips("请输入正确的手机号码", "error");
|
||||
this.$refs.uToast.show({
|
||||
title: '请输入正确的手机号码',
|
||||
type: 'error',
|
||||
})
|
||||
return;
|
||||
}
|
||||
|
||||
const timestamp = Date.now();
|
||||
const base64Key = btoa('xiaoyout!#@12345');
|
||||
const signStr = this.phone + timestamp + base64Key;
|
||||
const sign = md5(signStr);
|
||||
|
||||
this.$u.apiList
|
||||
.GetAppValidateCode({
|
||||
phone: this.phone,
|
||||
t: timestamp.toString(),
|
||||
sign: sign,
|
||||
type: 2,
|
||||
})
|
||||
.then((res) => {
|
||||
//中间数字加密
|
||||
// let result =this.userName.replace(this.userName.substring(3,7),"****")
|
||||
// this.userName = result
|
||||
this.disabled = true;
|
||||
// this.$tips("发送成功");
|
||||
this.$refs.uToast.show({
|
||||
title: '发送成功',
|
||||
type: 'success',
|
||||
})
|
||||
var second = 60;
|
||||
this.send = second + "秒后重试";
|
||||
var time = setInterval(() => {
|
||||
this.send = second + "秒后重试";
|
||||
second--;
|
||||
if (second <= 0) {
|
||||
this.disabled = false;
|
||||
this.send = "发送验证码";
|
||||
clearInterval(time);
|
||||
}
|
||||
}, 1000);
|
||||
})
|
||||
.catch((err) => {
|
||||
// this.$tips(err.error, "error");
|
||||
this.$refs.uToast.show({
|
||||
title: err.error,
|
||||
type: 'error',
|
||||
})
|
||||
});
|
||||
},
|
||||
login() {
|
||||
if (this.state == 1) {
|
||||
if (this.phone === "") {
|
||||
return this.tips("请输入手机号", "error");
|
||||
}
|
||||
if (this.code === "") {
|
||||
return this.tips("请输入验证码", "error");
|
||||
}
|
||||
this.$u.apiList.ForgotPasswordValidate({
|
||||
phone: this.phone,
|
||||
code: this.code,
|
||||
}).then((res) => {
|
||||
console.info("🚀 ~ file:ForgetPassword method: line:189 -----", res)
|
||||
this.state = 2;
|
||||
}).catch((err) => {
|
||||
this.tips(err.error, "error");
|
||||
});
|
||||
|
||||
return
|
||||
}
|
||||
if (this.state == 2) {
|
||||
if (this.passWord === "") {
|
||||
return this.tips("请输入新密码", "error");
|
||||
}
|
||||
let reg = /^(?=.*[a-zA-Z])(?=.*\d)(?=.*[\W_]).{5,}$/;
|
||||
if (!reg.test(this.passWord)) {
|
||||
/* return this.$tips(
|
||||
"密码必须包含字母、数字、特殊字符,且不能包含中文!",
|
||||
"error"
|
||||
); */
|
||||
return this.$refs.uToast.show({
|
||||
title: "密码必须包含字母、数字、特殊字符,且不能包含中文!",
|
||||
type: 'error',
|
||||
})
|
||||
}
|
||||
if (this.passWordTwo === "") {
|
||||
return this.tips("请确认新密码", "error");
|
||||
}
|
||||
if (this.passWord != this.passWordTwo) {
|
||||
return this.tips("请检查两次密码是否一致", "error");
|
||||
}
|
||||
}
|
||||
const req = {
|
||||
phone: this.phone,
|
||||
code: this.code,
|
||||
newPassWord: aesEncrypt(this.passWord),
|
||||
};
|
||||
console.log(req, "res-");
|
||||
// return
|
||||
this.$u.apiList
|
||||
.ForgotPassword(req)
|
||||
.then((res) => {
|
||||
console.log(res, "res---");
|
||||
uni.showToast({
|
||||
title: "重置成功",
|
||||
duration: 2000,
|
||||
});
|
||||
setTimeout(() => {
|
||||
uni.navigateTo({
|
||||
url: "/",
|
||||
});
|
||||
}, 2000);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err, "err---");
|
||||
// this.$tips(err.error, "error");
|
||||
this.$refs.uToast.show({
|
||||
title: err.error,
|
||||
type: 'error',
|
||||
})
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.custom-style {
|
||||
color: #3cb5fb !important;
|
||||
padding: 0 !important;
|
||||
height: 70rpx !important;
|
||||
line-height: 60rpx !important;
|
||||
}
|
||||
|
||||
.custom-style::after {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.page {
|
||||
padding-bottom: 0.015rem;
|
||||
background-color: rgb(255, 255, 255);
|
||||
overflow-y: auto;
|
||||
width: 100%;
|
||||
overflow-x: hidden;
|
||||
height: 100%;
|
||||
|
||||
.image {
|
||||
flex-shrink: 0;
|
||||
align-self: flex-start;
|
||||
width: 102%;
|
||||
}
|
||||
|
||||
.group {
|
||||
padding: 1.0rem 0.29rem;
|
||||
|
||||
.text {
|
||||
align-self: left;
|
||||
// color: rgb(46, 155, 255);
|
||||
color: #000;
|
||||
font-size: 0.22rem;
|
||||
font-family: PingFang;
|
||||
line-height: 0.17rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.group_7 {
|
||||
margin-top: 0.29rem;
|
||||
|
||||
.text-wrapper {
|
||||
border: solid 2rpx #dcdfe6;
|
||||
border-radius: 100rpx;
|
||||
background: #f6f8fa;
|
||||
}
|
||||
|
||||
.group_6 {
|
||||
margin-top: 0.2rem;
|
||||
}
|
||||
|
||||
.text_1 {
|
||||
margin-left: 0.01rem;
|
||||
align-self: flex-start;
|
||||
color: rgb(51, 51, 51);
|
||||
font-size: 0.15rem;
|
||||
font-family: PingFang;
|
||||
line-height: 0.14rem;
|
||||
}
|
||||
|
||||
.view {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 20rpx;
|
||||
padding: 20rpx 50rpx !important;
|
||||
}
|
||||
}
|
||||
|
||||
.text_6 {
|
||||
width: 100%;
|
||||
text-align: right;
|
||||
margin-left: 0.01rem;
|
||||
margin-top: 0.2rem;
|
||||
align-self: flex-start;
|
||||
color: #1F2232;
|
||||
font-size: 0.13rem;
|
||||
font-family: PingFang;
|
||||
line-height: 0.13rem;
|
||||
}
|
||||
|
||||
.text-wrapper_1 {
|
||||
margin: 50rpx 0rpx 40rpx;
|
||||
padding: 50rpx 0 50rpx;
|
||||
// background-image: linear-gradient(90deg, rgb(135, 230, 254) 0%, rgb(91, 192, 254) 52%, rgb(46, 155, 255) 100%);
|
||||
background: #3cb4fb;
|
||||
box-shadow: 0px 6rpx 9rpx rgba(38, 122, 199, 0.34);
|
||||
border-radius: 100rpx;
|
||||
|
||||
.text_7 {
|
||||
color: rgb(255, 255, 255);
|
||||
font-size: 32rpx;
|
||||
font-family: PingFang;
|
||||
line-height: 32rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.group_1 {
|
||||
margin-top: 0.12rem;
|
||||
|
||||
.text_8 {
|
||||
color: rgb(102, 102, 102);
|
||||
font-size: 24rpx;
|
||||
font-family: PingFang;
|
||||
line-height: 0.13rem;
|
||||
}
|
||||
|
||||
.text_9 {
|
||||
margin-left: 0.035rem;
|
||||
color: rgb(25, 140, 255);
|
||||
font-size: 0.14rem;
|
||||
font-family: PingFang;
|
||||
line-height: 0.13rem;
|
||||
}
|
||||
}
|
||||
|
||||
.group_2 {
|
||||
margin-top: 0.36rem;
|
||||
justify-content: center;
|
||||
|
||||
.section_1 {
|
||||
flex-shrink: 0;
|
||||
width: 0.17rem;
|
||||
}
|
||||
|
||||
.group_3 {
|
||||
margin-left: 0.11rem;
|
||||
height: 0.18rem;
|
||||
line-height: 0.18rem;
|
||||
font-size: 0;
|
||||
|
||||
.text_10 {
|
||||
color: rgb(153, 153, 153);
|
||||
font-size: 0.11rem;
|
||||
font-family: PingFang;
|
||||
}
|
||||
|
||||
.text_11 {
|
||||
color: rgb(25, 140, 255);
|
||||
font-size: 0.11rem;
|
||||
font-family: PingFang;
|
||||
}
|
||||
|
||||
.text_12 {
|
||||
color: rgb(102, 102, 102);
|
||||
font-size: 0.11rem;
|
||||
font-family: PingFang;
|
||||
}
|
||||
|
||||
.text_13 {
|
||||
color: rgb(25, 140, 255);
|
||||
font-size: 0.11rem;
|
||||
font-family: PingFang;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tips {
|
||||
font-size: 24rpx;
|
||||
color: #EF3920;
|
||||
display: flex;
|
||||
margin-top: 20rpx;
|
||||
|
||||
image {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
margin-right: 10rpx;
|
||||
margin-top: 5rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,177 @@
|
|||
<template>
|
||||
<view class="authentication-page">
|
||||
<u-navbar title="身份认证"> </u-navbar>
|
||||
|
||||
<view class="title">请填写您的真实信息</view>
|
||||
|
||||
<view class="form-container">
|
||||
<view class="input-item">
|
||||
<text>姓名</text>
|
||||
<input
|
||||
v-model="name"
|
||||
maxlength="20"
|
||||
type="text"
|
||||
placeholder="请输入"
|
||||
placeholder-class="placeholder"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<view class="input-item">
|
||||
<text>身份证号</text>
|
||||
<input
|
||||
v-model="idCard"
|
||||
maxlength="18"
|
||||
type="text"
|
||||
placeholder="请输入"
|
||||
placeholder-class="placeholder"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="btn-container">
|
||||
<button class="next-btn" @click="handleNext">下一步</button>
|
||||
</view>
|
||||
|
||||
<u-toast ref="uToast" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import test from "@/uview-ui/libs/function/test.js";
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
name: "",
|
||||
idCard: "",
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
handleNext() {
|
||||
// 调用后端API获取token
|
||||
this.getTokenFromBackend();
|
||||
|
||||
if (!this.name) {
|
||||
return this.$refs.uToast.show({
|
||||
title: "请输入姓名",
|
||||
type: "warning",
|
||||
});
|
||||
}
|
||||
if (!this.idCard) {
|
||||
return this.$refs.uToast.show({
|
||||
title: "请输入身份证号",
|
||||
type: "warning",
|
||||
});
|
||||
}
|
||||
// 验证身份证号码格式
|
||||
if (!test.idCard(this.idCard)) {
|
||||
return this.$refs.uToast.show({
|
||||
title: "请输入正确的身份证号码",
|
||||
type: "warning",
|
||||
});
|
||||
}
|
||||
// 处理下一步逻辑
|
||||
// console.log("提交信息", this.name, this.idCard);
|
||||
},
|
||||
|
||||
// 获取token
|
||||
getTokenFromBackend() {
|
||||
this.$u.api.getAPIToken().then((res) => {
|
||||
const token = res.verifyToken
|
||||
|
||||
// 跳转到百度人脸核验页面
|
||||
this.redirectToBaiduVerification(token);
|
||||
});
|
||||
},
|
||||
|
||||
redirectToBaiduVerification(token) {
|
||||
// 获取当前域名
|
||||
const currentDomain = window.location.origin;
|
||||
|
||||
// 编码回调URL
|
||||
// const callbackUrl = encodeURIComponent(`${currentDomain}/success.html`);
|
||||
const callbackUrl = "/pages/login/recognitionResult/recognitionResult";
|
||||
|
||||
// 构建跳转URL
|
||||
const verifyUrl = `https://brain.baidu.com/face/print/verify/verify?token=${token}&successUrl=${callbackUrl}&failedUrl=${callbackUrl}`;
|
||||
|
||||
const verifyObj = {
|
||||
url: verifyUrl,
|
||||
name:'身份认证'
|
||||
};
|
||||
|
||||
// 在uni-app中跳转
|
||||
this.$u.route({
|
||||
url: `/pages/webview/index?data=${encodeURIComponent(
|
||||
JSON.stringify(verifyObj)
|
||||
)}`,
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.authentication-page {
|
||||
padding: 0 30rpx;
|
||||
|
||||
.title {
|
||||
font-family: PingFang SC, PingFang SC;
|
||||
font-weight: bold;
|
||||
font-size: 32rpx;
|
||||
color: rgba(0, 0, 0, 0.9);
|
||||
line-height: 52rpx;
|
||||
text-align: left;
|
||||
margin-top: 30rpx;
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.form-container {
|
||||
background-color: #ffffff;
|
||||
border-radius: 16rpx;
|
||||
padding: 0 30rpx;
|
||||
margin-bottom: 60rpx;
|
||||
|
||||
.input-item {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 30rpx 0;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
text {
|
||||
font-size: 28rpx;
|
||||
color: rgba(0, 0, 0, 0.9);
|
||||
}
|
||||
|
||||
input {
|
||||
flex: 1;
|
||||
text-align: right;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.placeholder {
|
||||
color: rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btn-container {
|
||||
.next-btn {
|
||||
background-color: #45b5ff;
|
||||
color: #ffffff;
|
||||
height: 90rpx;
|
||||
line-height: 90rpx;
|
||||
border-radius: 45rpx;
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,338 @@
|
|||
<template>
|
||||
<view class="flex-col page">
|
||||
<!-- <image src="/static/common/img/16530269846087107196.png" class="image" /> -->
|
||||
<u-navbar title="确认密码"></u-navbar>
|
||||
<view class="flex-col group">
|
||||
<text class="text">确认密码后登录</text>
|
||||
<view class="flex-col group_7">
|
||||
<view class="flex-col">
|
||||
<view class="flex-row" style="padding: 0">
|
||||
<u-input type="password" v-model="user.passWord" placeholder="请输入密码" class="view text-wrapper"/>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex-col group_6">
|
||||
<u-input type="password" v-model="isPassWord" placeholder="请确认密码" class="view text-wrapper" />
|
||||
</view>
|
||||
<view class="tips">
|
||||
<image src="/static/common/img/infoCircle.png"></image> 提示:密码长度应该大于5,必须包含字母、数字、特殊字符,且不能包含中文!
|
||||
</view>
|
||||
</view>
|
||||
<u-button class="flex-col items-center text-wrapper_1" throttle-time="1000" type="primary" shape="circle"
|
||||
@click="login"><text class="text_7">确定</text></u-button>
|
||||
<!-- 此次接入人脸验证 登录 ==> 确定 -->
|
||||
</view>
|
||||
<u-toast ref="uToast" />
|
||||
<u-top-tips ref="uTips" :navbar-height="0"></u-top-tips>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {aesEncrypt} from '@/utils/encrypt.js'
|
||||
import md5 from "js-md5";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
show: false,
|
||||
userName: "",
|
||||
isPassWord: "",
|
||||
agreement: false,
|
||||
user: {
|
||||
phone: '',
|
||||
passWord: '',
|
||||
code:''
|
||||
}
|
||||
};
|
||||
},
|
||||
onLoad(e) {
|
||||
if (e.phone) {
|
||||
this.user.phone = e.phone
|
||||
this.user.code = e.code
|
||||
} else {
|
||||
uni.navigateTo({
|
||||
url: "../register/register",
|
||||
});
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
login() {
|
||||
if (this.user.passWord === "") {
|
||||
return this.$refs.uToast.show({
|
||||
title: '请输入密码',
|
||||
type: 'error',
|
||||
})
|
||||
}
|
||||
if (this.user.passWord.length < 5) {
|
||||
// return this.$tips("您的密码长度应该大于5", "error");
|
||||
return this.$refs.uToast.show({
|
||||
title: '您的密码长度应该大于5',
|
||||
type: 'error',
|
||||
})
|
||||
}
|
||||
if (this.isPassWord === "") {
|
||||
return this.$refs.uToast.show({
|
||||
title: '请确认密码',
|
||||
type: 'error',
|
||||
})
|
||||
// return this.$tips("请确认密码", "error");
|
||||
}
|
||||
if (this.isPassWord !== this.user.passWord) {
|
||||
return this.$refs.uToast.show({
|
||||
title: '请确认两次密码是否一致',
|
||||
type: 'error',
|
||||
})
|
||||
// return this.$tips("请确认两次密码是否一致", "error");
|
||||
}
|
||||
uni.showLoading({
|
||||
title: "注册中",
|
||||
});
|
||||
const req = {...this.user}
|
||||
req.passWord = aesEncrypt(this.user.passWord)
|
||||
// 生成13位时间戳
|
||||
const timestamp = Date.now();
|
||||
// 生成签名
|
||||
const base64Key = btoa('xiaoyout!#@12345');
|
||||
const signStr = this.user.phone + timestamp + base64Key;
|
||||
const sign = md5(signStr);
|
||||
req.timeStamp = timestamp.toString();
|
||||
req.sign = sign;
|
||||
console.log(req,'req')
|
||||
// return
|
||||
this.$u.api.RegisterUser(req).then((res) => {
|
||||
const newReq = {...this.user}
|
||||
newReq.passWord = aesEncrypt(this.user.passWord)
|
||||
this.$u.api.LoginApp(newReq).then((ress) => {
|
||||
uni.hideLoading();
|
||||
// 保存登录后得到的用户数据
|
||||
this.$u.vuex('vuex_user', ress.user)
|
||||
this.$u.vuex('vuex_token', ress.token)
|
||||
this.$refs.uToast.show({
|
||||
title: '注册成功',
|
||||
type: 'success',
|
||||
})
|
||||
// uni.navigateTo({
|
||||
// url: "../perfect/perfect",
|
||||
// });
|
||||
setTimeout(()=>{
|
||||
// 这里改为进行人脸识别
|
||||
this.toBaiduApi();
|
||||
return
|
||||
|
||||
uni.navigateTo({
|
||||
url: "/pages/login/roleSelection",
|
||||
});
|
||||
},300)
|
||||
|
||||
}).catch((e) => {
|
||||
uni.hideLoading();
|
||||
});
|
||||
|
||||
}).catch((e) => {
|
||||
uni.hideLoading();
|
||||
// this.$tips( e.error, 'error')
|
||||
this.$refs.uToast.show({
|
||||
title: e.error,
|
||||
type: 'error',
|
||||
})
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
// 跳转至人脸验证
|
||||
toBaiduApi(){
|
||||
this.$u.api.getAPIToken().then((res) => {
|
||||
const token = res.result.verify_token;
|
||||
|
||||
// 跳转到百度人脸核验页面
|
||||
this.redirectToBaiduVerification(token);
|
||||
});
|
||||
},
|
||||
redirectToBaiduVerification(token) {
|
||||
// 获取当前域名
|
||||
const currentDomain = window.location.origin;
|
||||
|
||||
// 编码回调URL - 使用相对路径,让uni-app处理路由
|
||||
// 百度人脸核验会在回调URL后附加verify_result和verify_info参数
|
||||
const successUrl = encodeURIComponent(
|
||||
`${currentDomain}/#/pages/login/recognitionResult/recognitionResult?token=${token}`
|
||||
);
|
||||
const failedUrl = encodeURIComponent(
|
||||
`${currentDomain}/#/pages/login/recognitionResult/recognitionFailed?token=${token}`
|
||||
);
|
||||
|
||||
// 构建跳转URL
|
||||
const verifyUrl = `https://brain.baidu.com/face/print/verify/verify?token=${token}&successUrl=${successUrl}&failedUrl=${failedUrl}`;
|
||||
|
||||
console.log("跳转到百度人脸核验页面:", verifyUrl);
|
||||
|
||||
// 直接跳转到百度人脸核验页面
|
||||
window.location.href = verifyUrl;
|
||||
return;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.custom-style {
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.custom-style::after {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.page {
|
||||
padding-bottom: 0.015rem;
|
||||
background-color: rgb(255, 255, 255);
|
||||
overflow-y: auto;
|
||||
width: 100%;
|
||||
overflow-x: hidden;
|
||||
height: 100%;
|
||||
|
||||
.image {
|
||||
flex-shrink: 0;
|
||||
align-self: flex-start;
|
||||
width: 102%;
|
||||
}
|
||||
|
||||
.group {
|
||||
padding: 0.15rem 0.29rem;
|
||||
|
||||
.text {
|
||||
font-family: PingFang;
|
||||
font-weight: bold;
|
||||
font-size: 48rpx;
|
||||
color: #000000;
|
||||
margin-top: 200rpx;
|
||||
}
|
||||
|
||||
.group_7 {
|
||||
margin-top: 0.29rem;
|
||||
|
||||
.text-wrapper {
|
||||
border: solid 2rpx #dcdfe6;
|
||||
border-radius: 100rpx;
|
||||
background: #f6f8fa;
|
||||
}
|
||||
|
||||
.group_6 {
|
||||
margin-top: 0.2rem;
|
||||
}
|
||||
|
||||
.text_1 {
|
||||
margin-left: 0.01rem;
|
||||
align-self: flex-start;
|
||||
color: rgb(51, 51, 51);
|
||||
font-size: 0.15rem;
|
||||
font-family: PingFang;
|
||||
line-height: 0.14rem;
|
||||
}
|
||||
|
||||
.view {
|
||||
margin-top: 20rpx;
|
||||
padding: 20rpx 50rpx !important;
|
||||
}
|
||||
}
|
||||
|
||||
.text_6 {
|
||||
margin-left: 0.01rem;
|
||||
margin-top: 0.13rem;
|
||||
align-self: flex-start;
|
||||
color: rgb(25, 140, 255);
|
||||
font-size: 0.13rem;
|
||||
font-family: PingFang;
|
||||
line-height: 0.13rem;
|
||||
}
|
||||
|
||||
.text-wrapper_1 {
|
||||
margin: 0.35rem 0rem 0;
|
||||
padding: 20rpx 50rpx;
|
||||
height: 108rpx;
|
||||
/* background-image: linear-gradient(90deg,
|
||||
rgb(135, 230, 254) 0%,
|
||||
rgb(91, 192, 254) 52%,
|
||||
rgb(46, 155, 255) 100%);
|
||||
box-shadow: 0px 0.03rem 0.09rem rgba(38, 122, 199, 0.34); */
|
||||
background: #3cb5fb;
|
||||
border-radius: 0.23rem;
|
||||
|
||||
.text_7 {
|
||||
color: rgb(255, 255, 255);
|
||||
font-size: 0.16rem;
|
||||
font-family: PingFang;
|
||||
line-height: 0.15rem;
|
||||
}
|
||||
}
|
||||
|
||||
.group_1 {
|
||||
margin-top: 0.12rem;
|
||||
|
||||
.text_8 {
|
||||
color: rgb(102, 102, 102);
|
||||
font-size: 0.14rem;
|
||||
font-family: PingFang;
|
||||
line-height: 0.13rem;
|
||||
}
|
||||
|
||||
.text_9 {
|
||||
margin-left: 0.035rem;
|
||||
color: rgb(25, 140, 255);
|
||||
font-size: 0.14rem;
|
||||
font-family: PingFang;
|
||||
line-height: 0.13rem;
|
||||
}
|
||||
}
|
||||
|
||||
.group_2 {
|
||||
margin-top: 0.36rem;
|
||||
justify-content: center;
|
||||
|
||||
.section_1 {
|
||||
flex-shrink: 0;
|
||||
width: 0.17rem;
|
||||
}
|
||||
|
||||
.group_3 {
|
||||
margin-left: 0.11rem;
|
||||
height: 0.18rem;
|
||||
line-height: 0.18rem;
|
||||
font-size: 0;
|
||||
|
||||
.text_10 {
|
||||
color: rgb(153, 153, 153);
|
||||
font-size: 0.11rem;
|
||||
font-family: PingFang;
|
||||
}
|
||||
|
||||
.text_11 {
|
||||
color: rgb(25, 140, 255);
|
||||
font-size: 0.11rem;
|
||||
font-family: PingFang;
|
||||
}
|
||||
|
||||
.text_12 {
|
||||
color: rgb(102, 102, 102);
|
||||
font-size: 0.11rem;
|
||||
font-family: PingFang;
|
||||
}
|
||||
|
||||
.text_13 {
|
||||
color: rgb(25, 140, 255);
|
||||
font-size: 0.11rem;
|
||||
font-family: PingFang;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.tips{
|
||||
font-size: 24rpx;
|
||||
color: #EF3920;
|
||||
display: flex;
|
||||
margin-top: 20rpx;
|
||||
image{
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -69,17 +69,12 @@
|
|||
</view>
|
||||
<view class="input-wrapper">
|
||||
<input
|
||||
:password="!isShowPassword"
|
||||
type="text"
|
||||
class="form-input"
|
||||
placeholder="请输入密码"
|
||||
v-model="loginParams.password"
|
||||
@blur="validatePassword"
|
||||
/>
|
||||
<view class="show-password-icon" @click="toggleShowPassword">
|
||||
<u-icon v-show="!isShowPassword" name="eye-fill" color="#2979ff" size="32"></u-icon>
|
||||
<u-icon v-show="isShowPassword" name="eye-off" color="#2979ff" size="32"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
<text v-if="errors.password" class="error-tip">{{
|
||||
errors.password
|
||||
|
|
@ -162,7 +157,6 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
isTeacher: false, // 是否是教师
|
||||
isShowPassword: false, // 是否显示密码
|
||||
|
||||
// 登录参数
|
||||
loginParams: {
|
||||
|
|
@ -203,17 +197,11 @@ export default {
|
|||
this.clearErrors();
|
||||
this.clearLoginParams();
|
||||
this.loginType = type;
|
||||
this.isShowPassword = false;
|
||||
if (this.loginType === "code") {
|
||||
this.refreshCaptcha();
|
||||
}
|
||||
},
|
||||
|
||||
// 切换显示密码
|
||||
toggleShowPassword() {
|
||||
this.isShowPassword = !this.isShowPassword;
|
||||
},
|
||||
|
||||
// 刷新图形验证码
|
||||
refreshCaptcha() {
|
||||
// 获取图形验证码
|
||||
|
|
@ -456,7 +444,7 @@ export default {
|
|||
|
||||
// 跳转至首页
|
||||
const url = this.isTeacher
|
||||
? "/pages/consultation/index"
|
||||
? "/pages/notes/index"
|
||||
: "/pages/home/index/index";
|
||||
uni.reLaunch({
|
||||
url: url,
|
||||
|
|
@ -706,18 +694,6 @@ export default {
|
|||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.show-password-icon {
|
||||
position: absolute;
|
||||
right: 10rpx;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
height: 60rpx;
|
||||
width: 60rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,532 @@
|
|||
<template>
|
||||
<view class="flex-col page">
|
||||
<!-- <image src="/static/common/img/loginBg.png" class="image" /> -->
|
||||
<view class="img-box">
|
||||
|
||||
</view>
|
||||
<view class="login-box">
|
||||
<view class="tab-list">
|
||||
<view v-for="tab in tabList" :key="tab.id" class="tab-item"
|
||||
:class="activeTab === tab.id ? 'tab-selected' : 'not-selected'" @click="onTab(tab.id)">
|
||||
<text class="tab-text">{{tab.label}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex-col group">
|
||||
<text class="text"></text>
|
||||
|
||||
<view class="flex-col group_7">
|
||||
<view class="flex-col">
|
||||
<!-- <text class="text_1">手机号</text> -->
|
||||
<!-- @input="changeInput($event)" -->
|
||||
<!-- <u-input type="number" v-model="userName" placeholder="请输入手机号" class="view text-wrapper" /> -->
|
||||
<u-input type="number" v-model="userName" placeholder="请输入手机号" class="view text-wrapper" maxlength="11"/>
|
||||
</view>
|
||||
<view class="error-tips" v-if="errorPhone"><image class="error-img" src="/static/common/img/infoCircle.png"></image> 请输入正确手机号</view>
|
||||
<view style="height: 0;width: 0;border: 0;padding: 0;margin: 0;overflow: hidden;">
|
||||
<u-input placeholder='' />
|
||||
</view>
|
||||
<view class="flex-col group_6">
|
||||
<!-- <text class="text_1">密码</text> -->
|
||||
<u-input type="password" v-model="passWord" placeholder="请输入密码" class="view text-wrapper" />
|
||||
</view>
|
||||
<!-- 密码必须包含字母、数字、特殊字符,且不能包含中文 -->
|
||||
<view class="error-tips" v-if="errorPwd"><image class="error-img" src="/static/common/img/infoCircle.png"></image> {{errormsg}}</view>
|
||||
|
||||
</view>
|
||||
<navigator class="text_6" style="width: 100%; text-align: right;" url="/pages/login/ForgetPassword/ForgetPassword">忘记密码?</navigator>
|
||||
<u-button class="flex-col items-center text-wrapper_1" throttle-time='1000' type="primary" shape="circle"
|
||||
@click="login"><text class="text_7">登录</text></u-button>
|
||||
<view class="justify-center group_1">
|
||||
<text class="text_8">还没有账号?</text>
|
||||
<navigator class="text_9" url="/pages/login/register/register">立即注册</navigator>
|
||||
</view>
|
||||
<!-- <view class="flex-row group_2">
|
||||
<u-checkbox-group class="section_1" :size='34'>
|
||||
<u-checkbox v-model="agreement"> </u-checkbox>
|
||||
</u-checkbox-group>
|
||||
<view class="group_3">
|
||||
<text class="text_10">已阅读并同意</text>
|
||||
<text class="text_11">《用户服务协议》</text>
|
||||
<text class="text_12">&</text>
|
||||
<text class="text_13">《用户隐私保护政策》</text>
|
||||
</view>
|
||||
</view> -->
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
<u-top-tips ref="uTips" :navbar-height='0'></u-top-tips>
|
||||
<u-toast ref="uToast" />
|
||||
</view>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
toBaiduApi
|
||||
} from '@/utils/faceVerify.js'
|
||||
import {
|
||||
aesEncrypt
|
||||
} from '@/utils/encrypt.js'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
show: false,
|
||||
userName: "",
|
||||
passWord: "",
|
||||
agreement: true,
|
||||
tabList: [{
|
||||
id: 1,
|
||||
label: '密码登录'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
label: '验证码登录'
|
||||
}
|
||||
],
|
||||
activeTab: 1,
|
||||
errorPhone: false,
|
||||
errorPwd: false,
|
||||
errormsg: "",
|
||||
};
|
||||
},
|
||||
onLoad(e) {},
|
||||
onHide(){
|
||||
this.userName= ""
|
||||
this.passWord= ""
|
||||
},
|
||||
onShow() {
|
||||
this.userName= ""
|
||||
this.passWord= ""
|
||||
setTimeout(() => {
|
||||
const lifeData = uni.getStorageSync('lifeData');
|
||||
if (lifeData.vuex_user && lifeData.vuex_token) {
|
||||
this.$u.api.getUser().then(res => {
|
||||
// if(!this.vuex_user.isCard){
|
||||
// uni.navigateTo({
|
||||
// url: '/pages/Face/index/index'
|
||||
// });
|
||||
// return
|
||||
// }
|
||||
uni.switchTab({
|
||||
url: '../../main/index/index'
|
||||
});
|
||||
})
|
||||
}
|
||||
}, 200)
|
||||
},
|
||||
methods: {
|
||||
changeInput(e){
|
||||
setTimeout(() => {
|
||||
this.userName = e.target.value
|
||||
}, 0);
|
||||
},
|
||||
onTab(id) {
|
||||
if(id == 1){
|
||||
this.activeTab = id
|
||||
}else{
|
||||
/* uni.showToast({
|
||||
title: '暂未开放',
|
||||
icon: 'none'
|
||||
}) */
|
||||
this.$refs.uToast.show({
|
||||
title: '暂未开放',
|
||||
type: "warning",
|
||||
});
|
||||
}
|
||||
|
||||
},
|
||||
login() {
|
||||
// this.$u.vuex("vuex_msgList", '');
|
||||
// this.$u.vuex('vuex_user', '')
|
||||
// this.$u.vuex('vuex_token', '')
|
||||
// uni.clearStorage();
|
||||
if (!/^1[3-9]\d{9}$/.test(this.userName)) {
|
||||
// 校验手机号格式是否正确
|
||||
this.errorPhone = true;
|
||||
// return this.$tips("请输入正确的手机号", "error");
|
||||
return;
|
||||
} else {
|
||||
this.errorPhone = false;
|
||||
}
|
||||
// 校验密码格式先注释掉 因为重置密码的时候密码是1q2w3e
|
||||
// if (!/^(?=.*[A-Za-z])(?=.*\d)(?=.*[@$!%*?&.])[A-Za-z\d@$!%*?&.]{5,}$/.test(this.passWord)) {
|
||||
/* if (this.passWord.length < 6) {
|
||||
// 校验密码是否包含字母、数字、特殊字符,且长度至少为6
|
||||
this.errorPwd = true;
|
||||
// return this.$tips("密码必须包含字母、数字、特殊字符,且不能包含中文", "error");
|
||||
return;
|
||||
} else {
|
||||
this.errorPwd = false;
|
||||
} */
|
||||
/* if (!this.agreement) {
|
||||
return this.$tips("请同意用户服务协议及用户隐私保护政策", "error");
|
||||
} */
|
||||
if (this.passWord.length===0) {
|
||||
this.errorPwd = true;
|
||||
this.errormsg = "请输入密码";
|
||||
console.log("请输入密码");
|
||||
return
|
||||
}else if (this.passWord.length>0&&this.passWord.length < 6) {
|
||||
this.errorPwd = true;
|
||||
this.errormsg = "密码长度不能少于6位";
|
||||
console.log("密码长度不能少于6位");
|
||||
return
|
||||
}else{
|
||||
this.errorPwd = false;
|
||||
this.errormsg = "";
|
||||
}
|
||||
uni.showLoading({
|
||||
title: "登录中",
|
||||
});
|
||||
//
|
||||
let data = {
|
||||
phone: this.userName,
|
||||
password: aesEncrypt(this.passWord),
|
||||
}
|
||||
this.$u.api.LoginApp(data).then((res) => {
|
||||
uni.hideLoading();
|
||||
if (!res.succeed && !res.token) {
|
||||
/* uni.showToast({
|
||||
title: res.error,
|
||||
duration: 2000,
|
||||
icon: 'none'
|
||||
}); */
|
||||
// this.$tips(res.error, "error");
|
||||
this.$refs.uToast.show({
|
||||
title: err.error,
|
||||
type: "error",
|
||||
});
|
||||
return
|
||||
}
|
||||
// this.$tips("登录成功", "success")
|
||||
this.$refs.uToast.show({
|
||||
title: "登录成功",
|
||||
type: "success",
|
||||
});
|
||||
/* uni.showToast({
|
||||
title: "登录成功",
|
||||
duration: 2000,
|
||||
}); */
|
||||
// 保存登录后得到的用户数据
|
||||
this.$u.vuex('vuex_user', res.user)
|
||||
this.$u.vuex('vuex_token', res.token)
|
||||
this.$u.vuex('vuex_glyType', res.glyType)
|
||||
// if(!res.user.isCard){
|
||||
// uni.navigateTo({
|
||||
// url: '/pages/Face/index/index'
|
||||
// });
|
||||
// return
|
||||
// }
|
||||
if (res.user.isFill) {
|
||||
uni.switchTab({
|
||||
url: '/pages/home/home/home'
|
||||
});
|
||||
} else {
|
||||
// uni.navigateTo({
|
||||
// // url: "../perfect/perfect",
|
||||
// url: "../roleSelection",
|
||||
// });
|
||||
|
||||
// 没认证先前往人脸识别
|
||||
toBaiduApi(this);
|
||||
|
||||
return
|
||||
// 这里先注释
|
||||
uni.navigateTo({
|
||||
url: "/pages/login/roleSelection?source=login",
|
||||
});
|
||||
}
|
||||
}).catch(err => {
|
||||
// this.$tips(err.error, "error");
|
||||
this.$refs.uToast.show({
|
||||
title: err.error,
|
||||
type: "error",
|
||||
});
|
||||
/* uni.showToast({
|
||||
title: err.error,
|
||||
icon: 'none'
|
||||
}) */
|
||||
})
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.page {
|
||||
padding-bottom: 30rpx;
|
||||
background-color: rgb(255, 255, 255);
|
||||
overflow-y: auto;
|
||||
width: 100%;
|
||||
overflow-x: hidden;
|
||||
height: 100%;
|
||||
background: url(/static/common/img/loginBg.png);
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
background-position: top;
|
||||
|
||||
.img-box {
|
||||
height: 420rpx;
|
||||
}
|
||||
|
||||
.image {
|
||||
flex-shrink: 0;
|
||||
align-self: flex-start;
|
||||
width: 102%;
|
||||
}
|
||||
|
||||
.group {
|
||||
background: #fff;
|
||||
padding: 20rpx 25rpx;
|
||||
width: calc(100% - 50rpx);
|
||||
margin: 0 auto;
|
||||
border-radius: 30rpx;
|
||||
|
||||
.text {
|
||||
align-self: center;
|
||||
color: rgb(46, 155, 255);
|
||||
font-size: 32rpx;
|
||||
font-family: PingFang;
|
||||
line-height: 32rpx;
|
||||
}
|
||||
|
||||
.group_7 {
|
||||
margin-top: 40rpx;
|
||||
|
||||
.text-wrapper {
|
||||
border: solid 2rpx #dcdfe6;
|
||||
border-radius: 100rpx;
|
||||
background: #f6f8fa;
|
||||
|
||||
}
|
||||
|
||||
.group_6 {
|
||||
margin-top: 30rpx;
|
||||
}
|
||||
|
||||
.text_1 {
|
||||
margin-left: 10rpx;
|
||||
align-self: flex-start;
|
||||
color: rgb(51, 51, 51);
|
||||
font-size: 32rpx;
|
||||
font-family: PingFang;
|
||||
line-height: 30rpx;
|
||||
}
|
||||
|
||||
.view {
|
||||
margin-top: 20rpx;
|
||||
padding: 20rpx 50rpx !important;
|
||||
}
|
||||
}
|
||||
|
||||
.text_6 {
|
||||
margin-left: 5rpx;
|
||||
margin-top: 50rpx;
|
||||
align-self: flex-start;
|
||||
// color: rgb(25, 140, 255);
|
||||
color:#1F2232;
|
||||
font-size: 28rpx;
|
||||
font-family: PingFang;
|
||||
line-height: 28rpx;
|
||||
}
|
||||
|
||||
.text-wrapper_1 {
|
||||
margin: 50rpx 0rpx 40rpx;
|
||||
padding: 50rpx 0 50rpx;
|
||||
// background-image: linear-gradient(90deg, rgb(135, 230, 254) 0%, rgb(91, 192, 254) 52%, rgb(46, 155, 255) 100%);
|
||||
background: #3cb4fb;
|
||||
box-shadow: 0px 6rpx 9rpx rgba(38, 122, 199, 0.34);
|
||||
border-radius: 100rpx;
|
||||
|
||||
.text_7 {
|
||||
color: rgb(255, 255, 255);
|
||||
font-size: 32rpx;
|
||||
font-family: PingFang;
|
||||
line-height: 30rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.group_1 {
|
||||
margin-top: 24rpx;
|
||||
|
||||
.text_8 {
|
||||
color: #8697AC;
|
||||
font-size: 30rpx;
|
||||
font-family: PingFang;
|
||||
line-height: 26rpx;
|
||||
}
|
||||
|
||||
.text_9 {
|
||||
margin-left: 0.035rem;
|
||||
color: #2E9CFE;
|
||||
font-size: 30rpx;
|
||||
font-family: PingFang;
|
||||
line-height: 26rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.group_2 {
|
||||
margin-top: 40rpx;
|
||||
justify-content: center;
|
||||
|
||||
.section_1 {
|
||||
flex-shrink: 0;
|
||||
width: 34rpx;
|
||||
}
|
||||
|
||||
.group_3 {
|
||||
margin-left: 24rpx;
|
||||
height: 24rpx;
|
||||
font-size: 0;
|
||||
|
||||
.text_10 {
|
||||
color: rgb(153, 153, 153);
|
||||
font-size: 24rpx;
|
||||
font-family: PingFang;
|
||||
}
|
||||
|
||||
.text_11 {
|
||||
color: rgb(25, 140, 255);
|
||||
font-size: 24rpx;
|
||||
font-family: PingFang;
|
||||
}
|
||||
|
||||
.text_12 {
|
||||
color: rgb(102, 102, 102);
|
||||
font-size: 24rpx;
|
||||
font-family: PingFang;
|
||||
}
|
||||
|
||||
.text_13 {
|
||||
color: rgb(25, 140, 255);
|
||||
font-size: 24rpx;
|
||||
font-family: PingFang;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.login-box{
|
||||
background: #fff;
|
||||
width: calc(100% - 50rpx);
|
||||
margin: 0 auto;
|
||||
border-radius: 30rpx;
|
||||
// height: calc(100% - 350rpx);
|
||||
overflow: hidden;
|
||||
padding-bottom:100rpx;
|
||||
|
||||
}
|
||||
|
||||
$tab-height: 52px;
|
||||
$active-color: #fff;
|
||||
$default-color: #90ecf1;
|
||||
$primary-color: #666;
|
||||
|
||||
.tab-list {
|
||||
display: flex;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
border-radius: 30rpx 30rpx 0 0;
|
||||
background-color: $default-color;
|
||||
overflow: hidden; // 重点
|
||||
|
||||
.tab-item {
|
||||
flex: 1;
|
||||
height: $tab-height;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 30rpx;
|
||||
// opacity: 0.65; // 暂时删除,不选中样式需要重新编写
|
||||
|
||||
font-weight: 600;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
|
||||
.tab-selected {
|
||||
color:#3cb5fb;
|
||||
opacity: 1;
|
||||
background: #ffffff;
|
||||
border-radius: 24rpx 24rpx 0 0;
|
||||
box-shadow: 48rpx 80rpx 0 $active-color, -34rpx 90rpx 0 0 $active-color; // 重点
|
||||
.tab-text::after{
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 160rpx;
|
||||
bottom: 10rpx;
|
||||
width: 32rpx;
|
||||
height: 8rpx;
|
||||
background: #3CB5FB;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.tab-selected::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: -12rpx;
|
||||
bottom: 0;
|
||||
width: 24rpx;
|
||||
height: $tab-height;
|
||||
border-top-left-radius: 48rpx;
|
||||
background-color: $active-color;
|
||||
transform: skewX(-15deg); // 重点
|
||||
}
|
||||
|
||||
.tab-selected::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: -12rpx;
|
||||
bottom: 0;
|
||||
width: 24rpx;
|
||||
height: $tab-height;
|
||||
border-top-right-radius: 24rpx;
|
||||
background-color: $active-color;
|
||||
transform: skewX(15deg); // 重点
|
||||
}
|
||||
.not-selected {
|
||||
color: $primary-color;
|
||||
}
|
||||
|
||||
.not-selected::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 12rpx;
|
||||
bottom: 0;
|
||||
width: 24rpx;
|
||||
height: $tab-height;
|
||||
background: $default-color;
|
||||
border-bottom-left-radius: 24rpx;
|
||||
transform: skewX(15deg); // 重点
|
||||
}
|
||||
|
||||
.not-selected::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: 12rpx;
|
||||
bottom: 0;
|
||||
width: 24rpx;
|
||||
height: $tab-height;
|
||||
background: $default-color;
|
||||
border-bottom-right-radius: 24rpx;
|
||||
transform: skewX(-15deg); // 重点
|
||||
z-index: -1;
|
||||
}
|
||||
}
|
||||
.error-tips{
|
||||
font-size: 24rpx;
|
||||
color: #EF3920;
|
||||
display: flex;
|
||||
text-align: center;
|
||||
margin-top: 10rpx;
|
||||
// padding-left: 30rpx;
|
||||
.error-img{
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
margin-right: 5rpx;
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,158 @@
|
|||
<template>
|
||||
<view class="flex-col page">
|
||||
<u-navbar :border-bottom="false" :background="background"> </u-navbar>
|
||||
<view class="flex-col group_3">
|
||||
<h3 class="text_3">填写学校信息</h3>
|
||||
<view class="flex-col group_4">
|
||||
<view class="justify-between list-item group_5">
|
||||
<text class="text_8">学历</text>
|
||||
<u-input v-model="form.educational" placeholder="请选择学历" type="select" @click="show = true" />
|
||||
<u-action-sheet :list="educationalList" v-model="show" @click="educationalSelect()" ></u-action-sheet>
|
||||
</view>
|
||||
<view class="justify-between list-item">
|
||||
<text class="text_8">学校</text>
|
||||
<u-input v-model="form.shool" placeholder="请选择学校" type="select" @click="show = true" />
|
||||
</view>
|
||||
<view class="justify-between list-item">
|
||||
<text class="text_8">学院</text>
|
||||
<u-input v-model="form.college" placeholder="请选择学院" type="select" @click="show = true" />
|
||||
</view>
|
||||
<view class="justify-between list-item">
|
||||
<text class="text_8">专业</text>
|
||||
<u-input v-model="form.major" placeholder="请选择专业" type="select" @click="show = true" />
|
||||
<u-action-sheet :list="actionSheetList" v-model="show" @click="actionSheetCallback()" ></u-action-sheet>
|
||||
</view>
|
||||
<view class="justify-between list-item">
|
||||
<text class="text_8">时间</text>
|
||||
<u-input v-model="form.time" placeholder="请选择时间" type="select" @click="show = true" />
|
||||
</view>
|
||||
</view>
|
||||
<u-button shape="circle" class="button text-wrapper_1" type="primary"
|
||||
>完成</u-button
|
||||
>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import uButton from "../../../uview-ui/components/u-button/u-button.vue";
|
||||
export default {
|
||||
components: { uButton },
|
||||
data() {
|
||||
return {
|
||||
form:{
|
||||
educational:'',//学历
|
||||
shool:'',//学校
|
||||
college:'',//学院
|
||||
major:'',//专业
|
||||
time:'',//时间
|
||||
},
|
||||
background: {
|
||||
backgroundColor: "#fff",
|
||||
},
|
||||
value: "",
|
||||
show: false,
|
||||
educationalList:[//学历选择列表
|
||||
{
|
||||
text:'专科',
|
||||
},
|
||||
{
|
||||
text:'本科',
|
||||
},
|
||||
{
|
||||
text:'专科',
|
||||
}
|
||||
],
|
||||
actionSheetList: [
|
||||
{
|
||||
text: "男",
|
||||
},
|
||||
{
|
||||
text: "女",
|
||||
},
|
||||
{
|
||||
text: "保密",
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
onLoad(e) {
|
||||
;
|
||||
},
|
||||
methods: {
|
||||
educationalSelect(index){
|
||||
this.form.educational = this.actionSheetList[index].text;
|
||||
},
|
||||
actionSheetCallback(index) {
|
||||
|
||||
this.form.major = this.actionSheetList[index].text;
|
||||
},
|
||||
save() {
|
||||
uni.switchTab({
|
||||
url: "/pages/main/index/index",
|
||||
});
|
||||
},
|
||||
skip() {
|
||||
uni.switchTab({
|
||||
url: "/pages/main/index/index",
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.page {
|
||||
background: #fff;
|
||||
height: 100%;
|
||||
.text-wrapper_1 {
|
||||
padding: 0.15rem 0 0.14rem;
|
||||
background-image: linear-gradient(
|
||||
90deg,
|
||||
#87e6fe 0%,
|
||||
#5bc0fe 52%,
|
||||
#2e9bff 100%
|
||||
);
|
||||
box-shadow: 0px 0.03rem 0.09rem rgba(38, 122, 199, 0.34);
|
||||
border-radius: 0.23rem;
|
||||
}
|
||||
.button {
|
||||
margin: 0.6rem 0.15rem 0;
|
||||
}
|
||||
}
|
||||
|
||||
.group_3 {
|
||||
padding-left: 0.16rem;
|
||||
padding-top: 0.3rem;
|
||||
.text_3 {
|
||||
align-self: center;
|
||||
color: rgb(51, 51, 51);
|
||||
font-size: 0.18rem;
|
||||
font-family: PingFang;
|
||||
line-height: 0.17rem;
|
||||
}
|
||||
.group_4 {
|
||||
margin-top: 0.44rem;
|
||||
.list-item {
|
||||
padding: 0.1rem 0.2rem 0.09rem 0;
|
||||
border-bottom: solid 0.005rem rgb(199, 199, 204);
|
||||
.text_8 {
|
||||
color: #000;
|
||||
font-size: 0.18rem;
|
||||
font-family: PingFang;
|
||||
line-height: 0.38rem;
|
||||
margin-right: 0.1rem;
|
||||
}
|
||||
.text_26 {
|
||||
color: #000;
|
||||
font-size: 0.17rem;
|
||||
font-family: PingFang;
|
||||
line-height: 0.16rem;
|
||||
}
|
||||
}
|
||||
.group_5 {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,147 @@
|
|||
<template>
|
||||
<view class="recognition-result-page">
|
||||
<u-navbar title="认证结果" :is-back="false"></u-navbar>
|
||||
|
||||
<view class="result-container">
|
||||
<image
|
||||
:src="isSuccess ? resultSuccess : resultError"
|
||||
class="result-image"
|
||||
mode="widthFix"
|
||||
></image>
|
||||
<text class="result-text">{{
|
||||
isSuccess ? "认证通过" : "认证未通过"
|
||||
}}</text>
|
||||
</view>
|
||||
|
||||
<view class="btn-container">
|
||||
<button class="next-btn" @click="handleNext">
|
||||
{{ isSuccess ? "进入系统" : "重新识别" }}
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import resultSuccess from "@/static/common/img/result-success.png";
|
||||
import resultError from "@/static/common/img/result-error.png";
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
resultSuccess,
|
||||
resultError,
|
||||
isSuccess: false,
|
||||
verifyResult: null,
|
||||
verifyInfo: null,
|
||||
token: null,
|
||||
};
|
||||
},
|
||||
onLoad(options) {
|
||||
// 获取token参数
|
||||
if (options && options.token) {
|
||||
this.token = options.token;
|
||||
console.log("获取到token:", this.token);
|
||||
// 使用token查询认证结果
|
||||
this.queryVerificationResult();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 查询认证结果
|
||||
queryVerificationResult() {
|
||||
if (!this.token) {
|
||||
console.error("token为空,无法查询认证结果");
|
||||
return;
|
||||
}
|
||||
|
||||
// 调用API查询认证结果
|
||||
this.$u.api
|
||||
.getVerifyInfo(this.token)
|
||||
.then((res) => {})
|
||||
.catch((err) => {
|
||||
console.log("API调用过程中出错:", err);
|
||||
});
|
||||
},
|
||||
handleNext() {
|
||||
if (this.isSuccess) {
|
||||
uni.switchTab({
|
||||
url: "/pages/main/index/index",
|
||||
});
|
||||
} else {
|
||||
this.toBaiduApi();
|
||||
}
|
||||
},
|
||||
|
||||
toBaiduApi() {
|
||||
this.$u.api.getAPIToken().then((res) => {
|
||||
const token = res.result.verify_token;
|
||||
|
||||
// 跳转到百度人脸核验页面
|
||||
this.redirectToBaiduVerification(token);
|
||||
});
|
||||
},
|
||||
redirectToBaiduVerification(token) {
|
||||
// 获取当前域名
|
||||
const currentDomain = window.location.origin;
|
||||
|
||||
// 编码回调URL - 使用相对路径,让uni-app处理路由
|
||||
// 百度人脸核验会在回调URL后附加verify_result和verify_info参数
|
||||
const successUrl = encodeURIComponent(
|
||||
`${currentDomain}/#/pages/login/recognitionResult/recognitionResult?token=${token}`
|
||||
);
|
||||
const failedUrl = encodeURIComponent(
|
||||
`${currentDomain}/#/pages/login/recognitionResult/recognitionFailed?token=${token}`
|
||||
);
|
||||
|
||||
// 构建跳转URL
|
||||
const verifyUrl = `https://brain.baidu.com/face/print/verify/verify?token=${token}&successUrl=${successUrl}&failedUrl=${failedUrl}`;
|
||||
|
||||
console.log("跳转到百度人脸核验页面:", verifyUrl);
|
||||
|
||||
// 直接跳转到百度人脸核验页面
|
||||
window.location.href = verifyUrl;
|
||||
|
||||
return;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.recognition-result-page {
|
||||
padding: 0 24rpx;
|
||||
|
||||
.result-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 130rpx 0 36rpx;
|
||||
text-align: center;
|
||||
|
||||
.result-image {
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
margin-bottom: 36rpx;
|
||||
}
|
||||
|
||||
.result-text {
|
||||
font-family: PingFang SC, PingFang SC;
|
||||
font-size: 32rpx;
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-container {
|
||||
.next-btn {
|
||||
background-color: #45b5ff;
|
||||
color: #ffffff;
|
||||
height: 90rpx;
|
||||
line-height: 90rpx;
|
||||
border-radius: 45rpx;
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,155 @@
|
|||
<template>
|
||||
<view class="recognition-result-page">
|
||||
<u-navbar title="认证结果" :is-back="false"></u-navbar>
|
||||
|
||||
<view class="result-container">
|
||||
<image
|
||||
:src="isSuccess ? resultSuccess : resultError"
|
||||
class="result-image"
|
||||
mode="widthFix"
|
||||
></image>
|
||||
<text class="result-text">{{
|
||||
isSuccess ? "认证通过" : "认证未通过"
|
||||
}}</text>
|
||||
</view>
|
||||
|
||||
<view class="btn-container">
|
||||
<button class="next-btn" @click="handleNext">
|
||||
{{ isSuccess ? "进入系统" : "重新识别" }}
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import resultSuccess from "@/static/common/img/result-success.png";
|
||||
import resultError from "@/static/common/img/result-error.png";
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
resultSuccess,
|
||||
resultError,
|
||||
isSuccess: true,
|
||||
token: null,
|
||||
userInfo: {
|
||||
realName: "", // 姓名
|
||||
// idCard: "", // 身份证号
|
||||
},
|
||||
};
|
||||
},
|
||||
onLoad(options) {
|
||||
// 获取token参数
|
||||
if (options && options.token) {
|
||||
this.token = options.token;
|
||||
console.log("获取到token:", this.token);
|
||||
// 使用token查询认证结果
|
||||
this.queryVerificationResult();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 查询认证结果
|
||||
queryVerificationResult() {
|
||||
if (!this.token) {
|
||||
console.log("token为空,无法查询认证结果");
|
||||
return;
|
||||
}
|
||||
|
||||
// 调用API查询认证结果
|
||||
this.$u.api.getVerifyInfo(this.token).then((res) => {
|
||||
const result = res.result.idcard_confirm;
|
||||
this.userInfo.realName = result.name;
|
||||
// this.userInfo.idCard = result.idcard_number;
|
||||
// console.log("this.userInfo", this.userInfo);
|
||||
|
||||
if (result.idcard_number) {
|
||||
this.getSchoolInfo(result.idcard_number);
|
||||
this.updateCardFn(result.idcard_number);
|
||||
} else {
|
||||
this.$u.vuex("vuex_userInfo", this.userInfo);
|
||||
}
|
||||
});
|
||||
// .catch((err) => {
|
||||
// console.log("API调用过程中出错:", err);
|
||||
// });
|
||||
},
|
||||
|
||||
// 根据身份证号获取学校信息
|
||||
getSchoolInfo(card) {
|
||||
this.$u.api
|
||||
.getInfoByCard({
|
||||
card,
|
||||
// card: "362429199209242513",
|
||||
})
|
||||
.then((res) => {
|
||||
// console.log("返回结果:", res);
|
||||
if (res.length > 0) {
|
||||
this.userInfo = {
|
||||
...this.userInfo,
|
||||
...res[0],
|
||||
};
|
||||
}
|
||||
|
||||
this.$u.vuex("vuex_userInfo", this.userInfo);
|
||||
});
|
||||
},
|
||||
// 更新idCard
|
||||
updateCardFn(card) {
|
||||
this.$u.api
|
||||
.updateCard({
|
||||
userId: this.vuex_user.id,
|
||||
idCode: card,
|
||||
})
|
||||
.then((res) => {
|
||||
console.log("返回结果:", res);
|
||||
});
|
||||
},
|
||||
|
||||
handleNext() {
|
||||
uni.navigateTo({
|
||||
url: "/pages/login/roleSelection",
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.recognition-result-page {
|
||||
padding: 0 24rpx;
|
||||
|
||||
.result-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 130rpx 0 36rpx;
|
||||
text-align: center;
|
||||
|
||||
.result-image {
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
margin-bottom: 36rpx;
|
||||
}
|
||||
|
||||
.result-text {
|
||||
font-family: PingFang SC, PingFang SC;
|
||||
font-size: 32rpx;
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-container {
|
||||
.next-btn {
|
||||
background-color: #45b5ff;
|
||||
color: #ffffff;
|
||||
height: 90rpx;
|
||||
line-height: 90rpx;
|
||||
border-radius: 45rpx;
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,633 @@
|
|||
<template>
|
||||
<view class="flex-col page">
|
||||
<!-- <image src="/static/common/img/16530269846087107196.png" class="image" /> -->
|
||||
<u-navbar title="注册"></u-navbar>
|
||||
<view class="flex-col group">
|
||||
<text class="text">手机号注册</text>
|
||||
<view class="flex-col group_7">
|
||||
<view class="flex-col">
|
||||
<!-- <text class="text_1">手机号</text> -->
|
||||
<view class="text-wrapper flex-row view" style="padding: 0">
|
||||
<u-input type="number" v-model="userName" placeholder="请输入手机号" maxlength="11" :disabled="disabled" />
|
||||
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex-col group_6" v-show="showCap">
|
||||
<view class="text-wrapper flex-row view" style="padding: 0">
|
||||
<u-input type="text" v-model="captchaCode" placeholder="请输入图形验证码" />
|
||||
<image :src="captchaImg" class="captcha-img" @click="refreshCaptcha" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex-col group_6">
|
||||
<!-- <text class="text_1">短信验证码</text> -->
|
||||
<view class="text-wrapper flex-row view" style="padding: 0">
|
||||
<u-input type="text" v-model="passWord" placeholder="请输入短信验证码" />
|
||||
<u-button style='background:transparent;' class="custom-style" :disabled="!(send == '获取验证码')" @click="sendCode">{{ send }}
|
||||
</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<u-button class="flex-col items-center text-wrapper_1" throttle-time="1000" type="primary" shape="circle"
|
||||
@click="login"><text class="text_7">注册</text></u-button>
|
||||
<view class="justify-center group_1">
|
||||
<text class="text_8">已有账号</text>
|
||||
<navigator class="text_9" url="/pages/login/login/login">立即登录</navigator>
|
||||
</view>
|
||||
<!-- <view class="flex-row group_2">
|
||||
<u-checkbox-group class="section_1" :size="34">
|
||||
<u-checkbox v-model="agreement"> </u-checkbox>
|
||||
</u-checkbox-group>
|
||||
<view class="group_3">
|
||||
<text class="text_10">已阅读并同意</text>
|
||||
<text class="text_11">《用户服务协议》</text>
|
||||
<text class="text_12">&</text>
|
||||
<text class="text_13">《用户隐私保护政策》</text>
|
||||
</view>
|
||||
</view> -->
|
||||
</view>
|
||||
<u-top-tips ref="uTips" :navbar-height="0"></u-top-tips>
|
||||
<u-toast ref="uToast" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import md5 from "js-md5";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
show: false,
|
||||
userName: "",
|
||||
passWord: "",
|
||||
agreement: false,
|
||||
send: "获取验证码",
|
||||
disabled: false,
|
||||
captchaCode: "", // 图形验证码
|
||||
captchaImg: "", // 验证码图片
|
||||
captchaId: "", // 验证码ID
|
||||
showCap: false,
|
||||
};
|
||||
},
|
||||
onLoad(e) {
|
||||
// this.refreshCaptcha();
|
||||
},
|
||||
methods: {
|
||||
// 刷新验证码
|
||||
refreshCaptcha() {
|
||||
const timestamp = Date.now();
|
||||
this.captchaId = timestamp;
|
||||
uni.request({
|
||||
url: 'http://sl.vrgon.com:8003/api/Token/Captcha?id=' + timestamp,
|
||||
method: 'GET',
|
||||
responseType: 'arraybuffer',
|
||||
headers: {
|
||||
'Accept': '*/*',
|
||||
},
|
||||
success: (res) => {
|
||||
if (res.statusCode === 200 && res.data) {
|
||||
// res.data 是 ArrayBuffer 类型,将其转换为 Blob
|
||||
const blob = new Blob([res.data], { type: 'image/gif' }); // 根据实际图片类型调整
|
||||
const reader = new FileReader();
|
||||
reader.onload = () => {
|
||||
// 将 Blob 读取为 Data URL (Base64 编码的图片)
|
||||
this.captchaImg = reader.result;
|
||||
};
|
||||
reader.onerror = (e) => {
|
||||
console.error("FileReader error:", e);
|
||||
this.$refs.uToast.show({
|
||||
title: '图片转换失败',
|
||||
type: "error",
|
||||
});
|
||||
};
|
||||
reader.readAsDataURL(blob);
|
||||
} else {
|
||||
console.error('获取验证码失败,状态码或数据异常:', res);
|
||||
this.$refs.uToast.show({
|
||||
title: '获取验证码失败',
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('验证码请求失败:', err);
|
||||
this.$refs.uToast.show({
|
||||
title: '获取验证码失败,请检查网络或CORS设置',
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
// 获取验证码
|
||||
sendCode() {
|
||||
var reg = new RegExp("^[1][3,4,5,6,7,8,9][0-9]{9}$", "g"); //手机号
|
||||
if (this.userName === "" || !reg.test(this.userName)) {
|
||||
this.$refs.uToast.show({
|
||||
title: "请输入正确的手机号码",
|
||||
type: "error",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// if (!this.captchaCode) {
|
||||
// this.$refs.uToast.show({
|
||||
// title: "请输入图形验证码",
|
||||
// type: "error",
|
||||
// });
|
||||
// return;
|
||||
// }
|
||||
|
||||
// 生成13位时间戳
|
||||
const timestamp = Date.now();
|
||||
// 生成签名
|
||||
const base64Key = btoa('xiaoyout!#@12345');
|
||||
const signStr = this.userName + timestamp + base64Key;
|
||||
const sign = md5(signStr);
|
||||
|
||||
this.$u.apiList.GetPhoneValidateCode({
|
||||
phone: this.userName,
|
||||
t: timestamp.toString(),
|
||||
sign: sign,
|
||||
captchaCode: this.showCap ? this.captchaCode : '' ,
|
||||
captchaId: this.showCap ? this.captchaId.toString() : ''
|
||||
}).then((res)=>{
|
||||
//中间数字加密
|
||||
// let result =this.userName.replace(this.userName.substring(3,7),"****")
|
||||
// this.userName = result
|
||||
this.disabled = true
|
||||
// this.$tips("发送成功");
|
||||
this.$refs.uToast.show({
|
||||
title: "发送成功",
|
||||
type: "success",
|
||||
});
|
||||
var second = 60;
|
||||
this.send = second + "秒后重试";
|
||||
var time = setInterval(() => {
|
||||
this.send = second + "秒后重试";
|
||||
second--;
|
||||
if (second <= 0) {
|
||||
this.disabled = false
|
||||
this.send = "获取验证码";
|
||||
clearInterval(time);
|
||||
}
|
||||
}, 1000);
|
||||
})
|
||||
.catch((err)=>{
|
||||
console.log('err-----',err)
|
||||
if(err?.data?.needcap && !this.showCap) {
|
||||
this.showCap = true
|
||||
this.$refs.uToast.show({
|
||||
title: '请输入图形验证码',
|
||||
type: "error",
|
||||
});
|
||||
this.refreshCaptcha()
|
||||
return
|
||||
}
|
||||
this.$refs.uToast.show({
|
||||
title: err.error,
|
||||
type: "error",
|
||||
});
|
||||
this.refreshCaptcha()
|
||||
})
|
||||
},
|
||||
|
||||
login() {
|
||||
// uni.navigateTo({
|
||||
// url: "/pages/login/confirmPwd/confirmPwd?phone="+this.userName,
|
||||
// });
|
||||
// return
|
||||
var reg = new RegExp("^[1][3,4,5,7,8,9][0-9]{9}$", "g"); //手机号
|
||||
if (this.userName === "" || !reg.test(this.userName)) {
|
||||
// this.$tips("请输入正确的手机号码", "error");
|
||||
this.$refs.uToast.show({
|
||||
title: "请输入正确的手机号码",
|
||||
type: "error",
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (this.passWord === "") {
|
||||
// return this.$tips("请输入验证码", "error");
|
||||
return this.$refs.uToast.show({
|
||||
title: "请输入验证码",
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
// if (!this.agreement) {
|
||||
// return this.$tips("请同意用户服务协议及用户隐私保护政策", "error");
|
||||
// }
|
||||
const data = {
|
||||
phone:this.userName,
|
||||
code : this.passWord
|
||||
}
|
||||
this.$u.apiList.IsPhoneCode(data).then((res)=>{
|
||||
setTimeout(() => {
|
||||
uni.navigateTo({
|
||||
url: "/pages/login/confirmPwd/confirmPwd?phone="+this.userName+"&code="+this.passWord,
|
||||
});
|
||||
}, 1000);
|
||||
})
|
||||
.catch((err)=>{
|
||||
// this.$tips(err.error, "error");
|
||||
this.$refs.uToast.show({
|
||||
title: err.error,
|
||||
type: "error",
|
||||
});
|
||||
})
|
||||
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.custom-style {
|
||||
color: #3CB5FB !important;
|
||||
padding: 0 !important;
|
||||
height: 70rpx !important;
|
||||
line-height: 60rpx !important;
|
||||
}
|
||||
|
||||
.custom-style::after {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.page {
|
||||
padding-bottom: 0.015rem;
|
||||
background-color: rgb(255, 255, 255);
|
||||
overflow-y: auto;
|
||||
width: 100%;
|
||||
overflow-x: hidden;
|
||||
height: 100%;
|
||||
|
||||
.image {
|
||||
flex-shrink: 0;
|
||||
align-self: flex-start;
|
||||
width: 102%;
|
||||
}
|
||||
|
||||
.group {
|
||||
padding: 0.7rem 0.29rem;
|
||||
|
||||
.text {
|
||||
align-self: left;
|
||||
// color: rgb(46, 155, 255);
|
||||
color: #000;
|
||||
font-size: 0.22rem;
|
||||
font-family: PingFang;
|
||||
line-height: 0.17rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.group_7 {
|
||||
margin-top: 0.29rem;
|
||||
|
||||
.text-wrapper {
|
||||
border: solid 2rpx #dcdfe6;
|
||||
border-radius: 100rpx;
|
||||
background: #f6f8fa;
|
||||
}
|
||||
|
||||
.group_6 {
|
||||
margin-top: 0.2rem;
|
||||
}
|
||||
|
||||
.text_1 {
|
||||
margin-left: 0.01rem;
|
||||
align-self: flex-start;
|
||||
color: rgb(51, 51, 51);
|
||||
font-size: 0.15rem;
|
||||
font-family: PingFang;
|
||||
line-height: 0.14rem;
|
||||
}
|
||||
|
||||
.view {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 20rpx;
|
||||
padding: 20rpx 50rpx !important;
|
||||
}
|
||||
}
|
||||
|
||||
.text_6 {
|
||||
margin-left: 0.01rem;
|
||||
margin-top: 0.13rem;
|
||||
align-self: flex-start;
|
||||
color: rgb(25, 140, 255);
|
||||
font-size: 0.13rem;
|
||||
font-family: PingFang;
|
||||
line-height: 0.13rem;
|
||||
}
|
||||
|
||||
.text-wrapper_1 {
|
||||
margin: 50rpx 0rpx 40rpx;
|
||||
padding: 50rpx 0 50rpx;
|
||||
// background-image: linear-gradient(90deg, rgb(135, 230, 254) 0%, rgb(91, 192, 254) 52%, rgb(46, 155, 255) 100%);
|
||||
background: #3cb4fb;
|
||||
box-shadow: 0px 6rpx 9rpx rgba(38, 122, 199, 0.34);
|
||||
border-radius: 100rpx;
|
||||
|
||||
.text_7 {
|
||||
color: rgb(255, 255, 255);
|
||||
font-size: 32rpx;
|
||||
font-family: PingFang;
|
||||
line-height: 32rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.group_1 {
|
||||
margin-top: 0.12rem;
|
||||
|
||||
.text_8 {
|
||||
color: rgb(102, 102, 102);
|
||||
font-size: 0.14rem;
|
||||
font-family: PingFang;
|
||||
line-height: 0.13rem;
|
||||
}
|
||||
|
||||
.text_9 {
|
||||
margin-left: 0.035rem;
|
||||
color: rgb(25, 140, 255);
|
||||
font-size: 0.14rem;
|
||||
font-family: PingFang;
|
||||
line-height: 0.13rem;
|
||||
}
|
||||
}
|
||||
|
||||
.group_2 {
|
||||
margin-top: 0.36rem;
|
||||
justify-content: center;
|
||||
|
||||
.section_1 {
|
||||
flex-shrink: 0;
|
||||
width: 0.17rem;
|
||||
}
|
||||
|
||||
.group_3 {
|
||||
margin-left: 0.11rem;
|
||||
height: 0.18rem;
|
||||
line-height: 0.18rem;
|
||||
font-size: 0;
|
||||
|
||||
.text_10 {
|
||||
color: rgb(153, 153, 153);
|
||||
font-size: 0.11rem;
|
||||
font-family: PingFang;
|
||||
}
|
||||
|
||||
.text_11 {
|
||||
color: rgb(25, 140, 255);
|
||||
font-size: 0.11rem;
|
||||
font-family: PingFang;
|
||||
}
|
||||
|
||||
.text_12 {
|
||||
color: rgb(102, 102, 102);
|
||||
font-size: 0.11rem;
|
||||
font-family: PingFang;
|
||||
}
|
||||
|
||||
.text_13 {
|
||||
color: rgb(25, 140, 255);
|
||||
font-size: 0.11rem;
|
||||
font-family: PingFang;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.captcha-img {
|
||||
width: 200rpx;
|
||||
height: 70rpx;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
|
||||
<!-- <template>
|
||||
<view class="flex-col page">
|
||||
<view class="flex-col group">
|
||||
<text class="text">注册账号</text>
|
||||
<view class="flex-col group_1">
|
||||
<view class="flex-col group_2">
|
||||
<u-select
|
||||
@click="show = true"
|
||||
:mode="'single-column'"
|
||||
v-model="show"
|
||||
:list="shoolList"
|
||||
@confirm="confirm"
|
||||
@cancel="cancel"
|
||||
></u-select>
|
||||
<view class="justify-between section_1" @click="show = true">
|
||||
<text
|
||||
:style="{ color: this.shoolname !== '' ? '#000' : '#c1c4cc' }"
|
||||
>{{ this.shoolname != "" ? this.shoolname : "请选择学校" }}</text
|
||||
>
|
||||
<image
|
||||
src="/static/common/img/select.png"
|
||||
class="image_1"
|
||||
/>
|
||||
</view>
|
||||
<view class="text-wrapper flex-col">
|
||||
<u-input
|
||||
v-model="userName"
|
||||
type="text"
|
||||
placeholder="请输入用户名"
|
||||
/>
|
||||
</view>
|
||||
<view class="text-wrapper flex-col view_1">
|
||||
<u-input
|
||||
v-model="passWord"
|
||||
type="password"
|
||||
placeholder="请输入密码"
|
||||
/>
|
||||
</view>
|
||||
<view class="text-wrapper flex-col">
|
||||
<u-input
|
||||
v-model="twopassWord"
|
||||
type="password"
|
||||
placeholder="请确认密码"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex-row group_3">
|
||||
<view class="flex-col text-wrapper_1">
|
||||
<u-input
|
||||
v-model="Code"
|
||||
type="text"
|
||||
placeholder="请输入验证码"
|
||||
/>
|
||||
<text class="text_6"></text>
|
||||
</view>
|
||||
<view class="flex-col items-end text-wrapper_2">
|
||||
<text>6789</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view>
|
||||
<u-button class="flex-col items-center text-wrapper_3" @click="register" :throttle-time='1000'>注册</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
show: false,
|
||||
userName: "",
|
||||
passWord: "",
|
||||
twopassWord: "",
|
||||
Code: "",
|
||||
shoolname: "",
|
||||
shoolList: [
|
||||
{
|
||||
value: "1",
|
||||
label: "学校一",
|
||||
},
|
||||
{
|
||||
value: "2",
|
||||
label: "学校二",
|
||||
},
|
||||
{
|
||||
value: "3",
|
||||
label: "学校三",
|
||||
},
|
||||
{
|
||||
value: "4",
|
||||
label: "学校四",
|
||||
}
|
||||
],
|
||||
};
|
||||
},
|
||||
onLoad(e) {
|
||||
;
|
||||
},
|
||||
methods: {
|
||||
confirm(e) {
|
||||
this.shoolname = "";
|
||||
e.map((val, index) => {
|
||||
this.shoolname += this.shoolname == "" ? val.label : "-" + val.label;
|
||||
});
|
||||
},
|
||||
cancel(e) {
|
||||
;
|
||||
},
|
||||
register(){
|
||||
uni.showLoading({
|
||||
title: '注册中'
|
||||
});
|
||||
|
||||
setTimeout(()=>{
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: '注册成功',
|
||||
duration: 2000
|
||||
});
|
||||
},1000)
|
||||
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="css">
|
||||
.text-wrapper {
|
||||
margin-top: 0.095rem;
|
||||
padding: 0.03rem 0.17rem;
|
||||
background-color: rgb(246, 247, 250);
|
||||
border-radius: 0.1rem;
|
||||
}
|
||||
.text_2 {
|
||||
margin-left: 0.17rem;
|
||||
}
|
||||
.page {
|
||||
padding: 0.045rem 0 1.5rem;
|
||||
background-color: rgb(255, 255, 255);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.image {
|
||||
margin-left: 0.26rem;
|
||||
margin-right: 0.23rem;
|
||||
width: 3.27rem;
|
||||
height: 0.09rem;
|
||||
}
|
||||
.group {
|
||||
margin-top: 0.72rem;
|
||||
padding-left: 0.34rem;
|
||||
padding-right: 0.31rem;
|
||||
}
|
||||
.text {
|
||||
margin-left: 0.045rem;
|
||||
color: rgb(0, 0, 0);
|
||||
font-size: 0.24rem;
|
||||
line-height: 0.23rem;
|
||||
letter-spacing: 0.024rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.group_1 {
|
||||
margin-top: 0.67rem;
|
||||
}
|
||||
.text-wrapper_3 {
|
||||
margin-top: 0.54rem;
|
||||
padding: 0.13rem 0;
|
||||
color: rgb(255, 255, 255);
|
||||
font-size: 0.15rem;
|
||||
line-height: 0.14rem;
|
||||
letter-spacing: 0.03rem;
|
||||
white-space: nowrap;
|
||||
background-color: rgba(46, 155, 255, 0.5);
|
||||
border-radius: 0.1rem;
|
||||
}
|
||||
.group_2 {
|
||||
color: rgb(193, 196, 204);
|
||||
font-size: 0.15rem;
|
||||
line-height: 0.14rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.group_3 {
|
||||
margin-top: 0.08rem;
|
||||
}
|
||||
.section_1 {
|
||||
padding: 0.13rem 0.17rem;
|
||||
background-color: rgb(246, 247, 250);
|
||||
border-radius: 0.1rem;
|
||||
}
|
||||
.view_1 {
|
||||
margin-top: 0.09rem;
|
||||
}
|
||||
.text-wrapper_1 {
|
||||
padding: 0 0.17rem;
|
||||
flex: 1 1 auto;
|
||||
color: rgb(193, 196, 204);
|
||||
font-size: 0.15rem;
|
||||
line-height: 0.14rem;
|
||||
white-space: nowrap;
|
||||
background-color: rgb(246, 247, 250);
|
||||
border-radius: 0.1rem;
|
||||
height: 0.4rem;
|
||||
}
|
||||
.text-wrapper_2 {
|
||||
margin-left: 0.08rem;
|
||||
padding: 0.14rem 0.1rem ;
|
||||
color: rgb(106, 134, 241);
|
||||
font-size: 0.18rem;
|
||||
line-height: 0.14rem;
|
||||
letter-spacing: 0.036rem;
|
||||
white-space: nowrap;
|
||||
background-color: rgba(211, 220, 255, 0.5);
|
||||
border-radius: 0.1rem;
|
||||
height: 0.4rem;
|
||||
}
|
||||
.image_1 {
|
||||
margin-right: 0.035rem;
|
||||
margin-top: 0.05rem;
|
||||
width: 0.14rem;
|
||||
height: 0.09rem;
|
||||
}
|
||||
.text_6 {
|
||||
margin-left: 0.17rem;
|
||||
}
|
||||
</style> -->
|
||||
|
|
@ -0,0 +1,242 @@
|
|||
<template>
|
||||
<view class="flex-col page">
|
||||
<u-navbar
|
||||
:custom-back="backFn"
|
||||
:background="background"
|
||||
:border-bottom="false"
|
||||
title=""
|
||||
></u-navbar>
|
||||
<view>
|
||||
<view class="title">
|
||||
<h3>请选择登录角色</h3>
|
||||
<text class="tips"
|
||||
>温馨提示:因为系统中存在多个角色,请选择角色后再登录</text
|
||||
>
|
||||
</view>
|
||||
<view class="selectList">
|
||||
<view
|
||||
class="item flex-row"
|
||||
:class="{ 'item-selected': [0,2].includes(vuex_user.userType) }"
|
||||
@click="goStudent"
|
||||
>
|
||||
<view class="name">
|
||||
<text class="text">我是学生</text>
|
||||
<text class="text text-en">Student</text>
|
||||
</view>
|
||||
<view class="student"></view>
|
||||
</view>
|
||||
<view
|
||||
class="item flex-row"
|
||||
:class="{ 'item-selected': vuex_user.userType == '1' }"
|
||||
@click="goTeacher"
|
||||
>
|
||||
<view class="name">
|
||||
<text class="text">我是教师</text>
|
||||
<text class="text text-en">Teacher</text>
|
||||
</view>
|
||||
<view class="teacher"></view>
|
||||
</view>
|
||||
<!-- <view
|
||||
class="item flex-row"
|
||||
:class="{ 'item-selected': vuex_user.userType == '2' }"
|
||||
@click="goGraduate"
|
||||
>
|
||||
<view class="name">
|
||||
<text class="text">我是毕业生</text>
|
||||
<text class="text text-en">Graduate</text>
|
||||
</view>
|
||||
<view class="graduate"></view>
|
||||
</view> -->
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import uButton from "../../uview-ui/components/u-button/u-button.vue";
|
||||
|
||||
export default {
|
||||
components: { uButton },
|
||||
data() {
|
||||
return {
|
||||
background: {
|
||||
backgroundColor: "transparent",
|
||||
},
|
||||
source: "",
|
||||
userRole: uni.getStorageSync("role"),
|
||||
};
|
||||
},
|
||||
onLoad(e) {
|
||||
console.log(e, "e");
|
||||
this.source = e.source;
|
||||
},
|
||||
methods: {
|
||||
backFn() {
|
||||
console.log(this.source, "source---");
|
||||
if (this.source === "my") {
|
||||
uni.switchTab({
|
||||
url: "/pages/my/my/my",
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (this.source === "login") {
|
||||
this.$u.vuex("vuex_msgList", "");
|
||||
this.$u.vuex("vuex_user", "");
|
||||
this.$u.vuex("vuex_token", "");
|
||||
this.$u.vuex("vuex_userInfo", "");
|
||||
uni.clearStorage();
|
||||
this.$u.route({
|
||||
url: "/pages/login/login/login",
|
||||
});
|
||||
return;
|
||||
}
|
||||
uni.navigateBack();
|
||||
},
|
||||
async goTeacher() {
|
||||
const res = await this.$u.apiList.SelectUserTypeApi();
|
||||
console.log(res, "res---");
|
||||
const jzgFlag = res.jzgFlag;
|
||||
// const studentFlag = res.studentFlag
|
||||
if (jzgFlag === false) {
|
||||
uni.setStorageSync("role", "teacher");
|
||||
uni.navigateTo({
|
||||
url: "/pages/login/teacherCertification",
|
||||
});
|
||||
return;
|
||||
}
|
||||
const req = {
|
||||
userType: 1,
|
||||
};
|
||||
const result = await this.$u.apiList.UpdateUserTypeApi(req);
|
||||
console.log(result, "result---");
|
||||
this.vuex_user.userType = 1;
|
||||
uni.switchTab({
|
||||
url: "/pages/my/my/my",
|
||||
});
|
||||
},
|
||||
async goStudent() {
|
||||
const res = await this.$u.apiList.SelectUserTypeApi();
|
||||
console.log(res, "res---");
|
||||
// const jzgFlag = res.jzgFlag;
|
||||
const studentFlag = res.studentFlag;
|
||||
if (studentFlag === false) {
|
||||
uni.setStorageSync("role", "student");
|
||||
uni.navigateTo({
|
||||
url: "/pages/login/perfect/perfect",
|
||||
});
|
||||
return;
|
||||
}
|
||||
const req = {
|
||||
userType: 0,
|
||||
};
|
||||
const result = await this.$u.apiList.UpdateUserTypeApi(req);
|
||||
console.log(result, "result---");
|
||||
this.vuex_user.userType = 0;
|
||||
uni.switchTab({
|
||||
url: "/pages/my/my/my",
|
||||
});
|
||||
},
|
||||
async goGraduate() {
|
||||
uni.navigateTo({
|
||||
url: "/pages/login/graduateCertification/graduateCertification",
|
||||
});
|
||||
// uni.$u.toast("功能开发中");
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page {
|
||||
background: linear-gradient(
|
||||
0deg,
|
||||
rgba(80, 123, 244, 0) 80%,
|
||||
rgba(95, 147, 238, 0.3) 100%
|
||||
);
|
||||
height: 100%;
|
||||
.button {
|
||||
margin: 0.6rem 0.15rem 0;
|
||||
}
|
||||
}
|
||||
|
||||
.selectList {
|
||||
width: calc(100% - 30rpx);
|
||||
margin: 0 auto;
|
||||
.item {
|
||||
height: 278rpx;
|
||||
padding: 15rpx;
|
||||
margin-bottom: 15rpx;
|
||||
box-shadow: 0rpx 20rpx 40rpx 0rpx rgba(0, 0, 0, 0.05);
|
||||
border-radius: 32rpx;
|
||||
border: 4rpx solid #e7ecf0;
|
||||
.name {
|
||||
width: 60%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
// align-items: center;
|
||||
flex-direction: column;
|
||||
padding-top: 20rpx;
|
||||
padding-left: 100rpx;
|
||||
.text {
|
||||
margin-top: 10rpx;
|
||||
font-size: 48rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
// margin-right: 200rpx;
|
||||
letter-spacing: 2rpx;
|
||||
}
|
||||
.text-en {
|
||||
font-size: 40rpx;
|
||||
color: #666;
|
||||
letter-spacing: 2rpx;
|
||||
font-weight: normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
.item-selected {
|
||||
border: 4rpx solid #8ad3fd;
|
||||
}
|
||||
}
|
||||
.title {
|
||||
width: calc(100% - 60rpx);
|
||||
margin: 70rpx auto 100rpx;
|
||||
h3 {
|
||||
font-weight: 800;
|
||||
font-size: 48rpx;
|
||||
color: #000;
|
||||
line-height: 60rpx;
|
||||
}
|
||||
.tips {
|
||||
font-weight: 500;
|
||||
font-size: 24rpx;
|
||||
color: #666666;
|
||||
}
|
||||
}
|
||||
.teacher {
|
||||
width: 256rpx;
|
||||
height: 256rpx;
|
||||
-moz-background-image: url("/static/common/img/teacher.png");
|
||||
-webkit-background-image: url("/static/common/img/teacher.png");
|
||||
background-image: url("/static/common/img/teacher.png");
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
}
|
||||
.student {
|
||||
width: 256rpx;
|
||||
height: 256rpx;
|
||||
-moz-background-image: url("/static/common/img/student.png");
|
||||
-webkit-background-image: url("/static/common/img/student.png");
|
||||
background-image: url("/static/common/img/student.png");
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
}
|
||||
.graduate {
|
||||
width: 256rpx;
|
||||
height: 256rpx;
|
||||
-moz-background-image: url("/static/common/img/graduate.png");
|
||||
-webkit-background-image: url("/static/common/img/graduate.png");
|
||||
background-image: url("/static/common/img/graduate.png");
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,234 @@
|
|||
<template>
|
||||
<view>
|
||||
<u-navbar title="管理列表" :border-bottom="false"></u-navbar>
|
||||
<scroll-view scroll-y="true" class="scroll">
|
||||
<view class="flex-col list" v-if='list.length'>
|
||||
<view class="flex-row list_item" v-for="(item, i) in list" @click="GoChat(item)" :key="i">
|
||||
<u-avatar class="image" :show-sex="vuex_msgList.indexOf(item.fromUserId+'admin,')>=0" sex-icon=""
|
||||
sex-bg-color="red" :src="$u.http.config.imgUrl+item.fromUserHead"></u-avatar>
|
||||
<view class="right-section flex-col">
|
||||
<view class="top-group justify-between view_1">
|
||||
<view class="flex-row">
|
||||
<text class="text_1">{{item.fromUserName}}</text>
|
||||
<view class="right-text-wrapper flex-col items-end">
|
||||
<text class="text_3">{{item.schoolName}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<text
|
||||
v-if='new Date(item.sendDate) - 0 + (3600000*24)> new Date()&&new Date(item.sendDate).getDate()==new Date().getDate()'
|
||||
class="text_5">{{ item.sendDate.slice(10,16)}}</text>
|
||||
<text v-else class="text_5">{{ item.sendDate.slice(0,10)}}</text>
|
||||
</view>
|
||||
<view class="bottom-group justify-between">
|
||||
<text class="text_7">{{item.message}}</text>
|
||||
<text class="text_9" v-if="item.messageState == 0">未读</text>
|
||||
<text class="text_9" v-if="item.messageState == 1">已读</text>
|
||||
<text class="text_10" v-if="item.messageState == 2">待回复</text>
|
||||
<text class="text_10" v-if="item.messageState == 3">回复中...</text>
|
||||
<text class="text_10" v-if="item.messageState == 4">已回复</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-else style='padding-top:30vh'>
|
||||
<!-- <u-empty text="暂无消息列表" mode="message"></u-empty> -->
|
||||
<no-data text="暂无消息列表"></no-data>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<u-toast ref="uToast" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import NoData from 'components/NoData.vue'
|
||||
export default {
|
||||
components: {
|
||||
NoData
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
list: [],
|
||||
};
|
||||
},
|
||||
onLoad() {},
|
||||
onShow() {
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
// 去聊天
|
||||
GoChat(data) {
|
||||
//管理员聊天绑定
|
||||
this.$u.api.toBind({
|
||||
manageUser: this.vuex_user.id,
|
||||
lockUser: data.fromUserId
|
||||
}).then(res => {
|
||||
uni.navigateTo({
|
||||
url: '../dialogBox/dialogBox?id=admin' + '&shoolid=' + data.schoolId + '&fromid=' + data
|
||||
.fromUserId
|
||||
});
|
||||
}).catch(err=>{
|
||||
/* uni.showToast({
|
||||
title: '已有老师回复',
|
||||
duration: 2000,
|
||||
icon:'none'
|
||||
}); */
|
||||
this.$refs.uToast.show({
|
||||
title: '已有老师回复',
|
||||
type: 'warning',
|
||||
});
|
||||
|
||||
|
||||
})
|
||||
|
||||
},
|
||||
getList() {
|
||||
this.$u.api.getAdminList().then(res => {
|
||||
this.list = res
|
||||
})
|
||||
},
|
||||
//返回上一级
|
||||
router() {
|
||||
uni.switchTab({
|
||||
url: '../../message/msgList/msgList'
|
||||
})
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
::v-deep .u-avatar__sex {
|
||||
width: 0.1rem !important;
|
||||
height: 0.1rem !important;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.scroll {
|
||||
background-color: rgb(246, 247, 250);
|
||||
width: 100%;
|
||||
height: calc(100vh - 0.44rem);
|
||||
}
|
||||
|
||||
.list_item {
|
||||
padding-left: 0.2rem;
|
||||
background: #fff;
|
||||
box-shadow: 0px 0.005rem rgb(234, 234, 234);
|
||||
border-bottom: 1px solid rgb(234, 234, 234);
|
||||
}
|
||||
|
||||
.image {
|
||||
align-self: center;
|
||||
width: 0.4rem;
|
||||
height: 0.4rem;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.right-section {
|
||||
margin-left: 0.14rem;
|
||||
padding: 0.13rem 0.015rem 0.15rem;
|
||||
flex: 1 1 auto;
|
||||
height: 0.66rem;
|
||||
|
||||
}
|
||||
|
||||
.list_item:last-child .right-section {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.top-group {
|
||||
margin-top: 0.09rem;
|
||||
width: 0.4rem;
|
||||
height: 0.4rem;
|
||||
}
|
||||
|
||||
.bottom-group {
|
||||
margin-top: 0.05rem;
|
||||
}
|
||||
|
||||
.text_5 {
|
||||
text-align: right;
|
||||
margin-right: 0.1rem;
|
||||
margin-top: 0.02rem;
|
||||
color: rgb(193, 196, 204);
|
||||
font-size: 0.12rem;
|
||||
line-height: 0.095rem;
|
||||
letter-spacing: 0.012rem;
|
||||
white-space: nowrap;
|
||||
min-width: 0.5rem;
|
||||
}
|
||||
|
||||
.text_7 {
|
||||
margin-top: 0.035rem;
|
||||
color: rgb(177, 179, 182);
|
||||
font-size: 0.12rem;
|
||||
line-height: 0.12rem;
|
||||
letter-spacing: 0.012rem;
|
||||
white-space: nowrap;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.text_9 {
|
||||
margin-right: 0.085rem;
|
||||
margin-bottom: 0.035rem;
|
||||
color: rgb(46, 155, 255);
|
||||
font-size: 0.11rem;
|
||||
line-height: 0.11rem;
|
||||
letter-spacing: 0.011rem;
|
||||
white-space: nowrap;
|
||||
min-width: 0.5rem;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.text_10 {
|
||||
color: rgb(177, 179, 182);
|
||||
font-size: 0.11rem;
|
||||
line-height: 0.11rem;
|
||||
letter-spacing: 0.011rem;
|
||||
white-space: nowrap;
|
||||
min-width: 0.5rem;
|
||||
text-align: right;
|
||||
margin-right: 0.1rem;
|
||||
margin-top: 0.035rem;
|
||||
|
||||
|
||||
}
|
||||
|
||||
.text_1 {
|
||||
margin: 0.02rem 0;
|
||||
color: rgb(2, 2, 2);
|
||||
font-size: 0.15rem;
|
||||
line-height: 0.14rem;
|
||||
letter-spacing: 0.015rem;
|
||||
white-space: nowrap;
|
||||
max-width: 0.65rem;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.right-text-wrapper {
|
||||
margin-left: 0.045rem;
|
||||
padding: 0.035rem 0.08rem;
|
||||
color: rgb(115, 129, 255);
|
||||
font-size: 0.11rem;
|
||||
line-height: 0.11rem;
|
||||
letter-spacing: 0.011rem;
|
||||
white-space: nowrap;
|
||||
background-color: rgba(115, 129, 255, 0.1);
|
||||
border-radius: 0.09rem;
|
||||
height: 0.18rem;
|
||||
}
|
||||
|
||||
.text_3 {
|
||||
margin-right: 0.03rem;
|
||||
}
|
||||
|
||||
.list {
|
||||
padding-top: 0.01rem;
|
||||
}
|
||||
|
||||
.view_1 {
|
||||
margin-top: initial;
|
||||
width: initial;
|
||||
height: initial;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,673 @@
|
|||
<template>
|
||||
<view>
|
||||
<u-navbar back-text="" title="新增关注"></u-navbar>
|
||||
<scroll-view scroll-y="true" class="scroll">
|
||||
<view class="guanzhu">
|
||||
<view class="flex-col renzheng" v-if="!vuex_user.isAttestationXY&& false">
|
||||
<view class="flex-col section_4">
|
||||
<view class="flex-row section_5">
|
||||
<text class="text_3">待认证,请先完成认证~</text>
|
||||
<text class="text_4" @click="onAuto">去认证 >></text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex-col group_3">
|
||||
<view class="flex-col">
|
||||
<image src="/static/common/img/16535374500948048054.png" class="image_1" />
|
||||
</view>
|
||||
<text class="text_5">暂无数据,请尽快认证补充资料~</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex-col group_2" v-else>
|
||||
<view class="flex-col list">
|
||||
<view class="list-item flex-row group_3" v-for="(item, index) in UserFollowList" :key='index'
|
||||
@click='toDetail(item.carewUserId, item.userRole, item.carewUserHead)'>
|
||||
<u-avatar :src="$u.http.config.imgUrl + item.carewUserHead" class="text_3 image_1"></u-avatar>
|
||||
<view class="bottom-text-wrapper justify-between view_1">
|
||||
<view class="">
|
||||
<text class="text_5 text_7"><text>{{ item.carewUserName }}</text><text>{{
|
||||
"(" + item.carewName +
|
||||
")" }}</text></text>
|
||||
<view class="center-text-wrapper flex-col items-end">
|
||||
<text class="text_8">{{ item.school }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if='item.carewType == 2 && item.carewName != "管理员"'
|
||||
class="right-text-wrapper flex-col items-center">
|
||||
<text class="text_10">互相关注</text>
|
||||
</view>
|
||||
<view v-if='item.carewType == 1 && item.carewName != "管理员"'
|
||||
class="right-text-wrapper flex-col items-center view_21">
|
||||
<text class="text_10">已关注</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="!UserFollowList.length"
|
||||
style="margin-top:20vh;display: flex;justify-content: center;align-items: center;flex-direction: column;">
|
||||
<image src="/static/common/img/empty.png" class="image" />
|
||||
<view style="color:grey;margin-top: -5vh;">暂无关注</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import noData from '@/components/NoData.vue';
|
||||
export default {
|
||||
components: {
|
||||
noData
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
list: [],
|
||||
UserFollowList: [],
|
||||
};
|
||||
},
|
||||
onLoad() {
|
||||
// this.getList()
|
||||
//接收系统消息
|
||||
this.$connection.on("SystemMessage", (title, content, time) => {
|
||||
if (this.route.indexOf('sysList') >= 0) {
|
||||
this.list.unshift({
|
||||
messageDate: time,
|
||||
title: title,
|
||||
message: content
|
||||
})
|
||||
}
|
||||
});
|
||||
},
|
||||
onShow() {
|
||||
this.FollowList()
|
||||
|
||||
if (this.vuex_msgList) {
|
||||
var msgList = this.vuex_msgList;
|
||||
msgList = msgList.replace('SystemMessage,', '')
|
||||
this.$u.vuex('vuex_msgList', msgList)
|
||||
if (!msgList) {
|
||||
var tab = this.vuex_tabbar;
|
||||
tab[1].isDot = false;
|
||||
this.$u.vuex('vuex_tabbar', tab);
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
FollowList() {
|
||||
this.$u.api.getFollowList().then(res => {
|
||||
|
||||
this.UserFollowList = res
|
||||
})
|
||||
},
|
||||
toDetail(id, role, head) {
|
||||
if (role == 0) {
|
||||
this.$u.route({
|
||||
url: '/pages/AlumniCircle/userDetail/userDetail?id=' + id + '&type=0'
|
||||
})
|
||||
} else {
|
||||
uni.navigateTo({
|
||||
url: "../dialogBox/dialogBox?id=" + id + '&chatType=1&type=0&head=' + head,
|
||||
});
|
||||
}
|
||||
},
|
||||
getList() {
|
||||
this.$u.api.getSysList().then(res => {
|
||||
this.list = res
|
||||
})
|
||||
},
|
||||
|
||||
//返回上一级
|
||||
router() {
|
||||
uni.switchTab({
|
||||
url: '../../message/msgList/msgList'
|
||||
})
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.scroll {
|
||||
// background-color: rgb(246, 247, 250);
|
||||
background-color: #fff;
|
||||
width: 100%;
|
||||
height: calc(100vh - 0.44rem);
|
||||
}
|
||||
|
||||
.list-item {
|
||||
margin-top: 0.1rem;
|
||||
padding: 20rpx;
|
||||
background-color: rgb(255, 255, 255);
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.items-title {
|
||||
display: flex;
|
||||
padding-bottom: 20rpx;
|
||||
margin-bottom: 20rpx;
|
||||
border-bottom: 2rpx solid #F6F8F9;
|
||||
|
||||
image {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.title-time {
|
||||
margin-left: 0.1rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
padding: 5rpx 0;
|
||||
// align-items: flex-start;
|
||||
}
|
||||
}
|
||||
|
||||
.title-text {
|
||||
font-weight: 600;
|
||||
font-size: 28rpx;
|
||||
color: rgba(0, 0, 0, 0.9);
|
||||
}
|
||||
|
||||
.text_1 {
|
||||
// align-self: center;
|
||||
color: rgb(193, 196, 204);
|
||||
font-size: 0.12rem;
|
||||
line-height: 0.095rem;
|
||||
// letter-spacing: 0.012rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.bottom-section {
|
||||
padding-left: 10rpx;
|
||||
}
|
||||
|
||||
.text_3 {
|
||||
color: rgb(2, 2, 2);
|
||||
font-size: 28rpx;
|
||||
line-height: 0.16rem;
|
||||
// letter-spacing: 0.018rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.text_5 {
|
||||
margin-left: 0.015rem;
|
||||
margin-top: 0.1rem;
|
||||
color: #908a8a;
|
||||
font-size: 28rpx;
|
||||
line-height: 1.5;
|
||||
// letter-spacing: 0.01rem;
|
||||
// text-indent: 0.3rem;
|
||||
}
|
||||
|
||||
.text_6 {
|
||||
margin-top: 0.1rem;
|
||||
font-size: 0.16rem;
|
||||
line-height: 0.16rem;
|
||||
letter-spacing: 0.01rem;
|
||||
|
||||
text {
|
||||
margin-left: 0.015rem;
|
||||
text-indent: 0.3rem;
|
||||
display: block;
|
||||
color: #908a8a;
|
||||
font-size: 0.14rem;
|
||||
margin-top: 0.1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.list {
|
||||
padding: 0rem 0.15rem;
|
||||
flex: 1 1 auto;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.guanzhu {
|
||||
.list-item {
|
||||
padding: 0.14rem 0 0.1rem;
|
||||
align-self: flex-end;
|
||||
box-shadow: 0px 0.005rem rgb(234, 234, 234);
|
||||
width: 3.02rem;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.text_3 {
|
||||
color: rgb(2, 2, 2);
|
||||
font-size: 0.15rem;
|
||||
line-height: 0.14rem;
|
||||
letter-spacing: 0.015rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.bottom-text-wrapper {
|
||||
margin-top: 0.1rem;
|
||||
padding: 0.035rem 0;
|
||||
// color: rgb(115, 129, 255);
|
||||
font-size: 0.11rem;
|
||||
line-height: 0.11rem;
|
||||
letter-spacing: 0.011rem;
|
||||
white-space: nowrap;
|
||||
// background-color: rgba(115, 129, 255, 0.1);
|
||||
border-radius: 0.09rem;
|
||||
color: #3CB5FB;
|
||||
background-color: rgba(60,181,251,0.1);
|
||||
}
|
||||
|
||||
.text_5 {
|
||||
margin-left: 0.1rem;
|
||||
margin-right: 0.03rem;
|
||||
}
|
||||
|
||||
.center-text-wrapper {
|
||||
padding: 0.035rem 0.08rem;
|
||||
color: #3CB5FB;
|
||||
font-size: 0.11rem;
|
||||
line-height: 0.11rem;
|
||||
letter-spacing: 0.011rem;
|
||||
white-space: nowrap;
|
||||
background-color: rgba(60,181,251,0.1);
|
||||
border-radius: 0.09rem;
|
||||
display: inline-block;
|
||||
margin-top: 16rpx;
|
||||
}
|
||||
|
||||
.right-text-wrapper {
|
||||
// margin-right: 0.06rem;
|
||||
// margin-top: 0.03rem;
|
||||
// margin-left: 0.06rem;
|
||||
// padding: 0.085rem 0.08rem;
|
||||
color: #3CB5FB;
|
||||
font-size: 24rpx;
|
||||
line-height: 58rpx;
|
||||
white-space: nowrap;
|
||||
// background-color: rgb(46, 155, 255);
|
||||
border-radius: 0.15rem;
|
||||
border: 2rpx #3CB5FB solid;
|
||||
width: 120rpx;
|
||||
height: 64rpx;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.text_8 {
|
||||
margin-right: 0.03rem;
|
||||
}
|
||||
|
||||
.text_10 {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.text_12 {
|
||||
margin-left: 0.05rem;
|
||||
color: rgb(2, 2, 2);
|
||||
font-size: 0.15rem;
|
||||
line-height: 0.14rem;
|
||||
letter-spacing: 0.015rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.text_14 {
|
||||
margin-left: 0.1rem;
|
||||
margin-right: 0.03rem;
|
||||
}
|
||||
|
||||
.group_2 {
|
||||
// padding: 0.11rem 0 4.94rem;
|
||||
// flex: 1 1 auto;
|
||||
// overflow-y: auto;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.text-wrapper {
|
||||
// margin-left: 0.17rem;
|
||||
padding: 0.11rem 0 0.12rem;
|
||||
color: rgb(255, 255, 255);
|
||||
font-size: 0.18rem;
|
||||
line-height: 0.17rem;
|
||||
letter-spacing: 0.018rem;
|
||||
white-space: nowrap;
|
||||
background-size: 100% 100%;
|
||||
background-repeat: no-repeat;
|
||||
width: 0.4rem;
|
||||
height: 0.4rem;
|
||||
margin-top: 0.08rem;
|
||||
background: #6574fc;
|
||||
border-radius: 50%;
|
||||
|
||||
text {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.list {}
|
||||
|
||||
.text_2 {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.group_3 {
|
||||
padding: initial;
|
||||
align-self: initial;
|
||||
box-shadow: initial;
|
||||
width: initial;
|
||||
position: initial;
|
||||
// box-shadow: 0px 0.005rem #eaeaea;
|
||||
// padding-left: 0.2rem;
|
||||
}
|
||||
|
||||
.group_4 {
|
||||
padding: initial;
|
||||
align-self: initial;
|
||||
box-shadow: initial;
|
||||
width: initial;
|
||||
position: initial;
|
||||
margin-top: 0.015rem;
|
||||
}
|
||||
|
||||
.group_5 {
|
||||
padding: initial;
|
||||
align-self: initial;
|
||||
box-shadow: initial;
|
||||
width: initial;
|
||||
position: initial;
|
||||
}
|
||||
|
||||
.group_6 {
|
||||
padding: initial;
|
||||
align-self: initial;
|
||||
box-shadow: initial;
|
||||
width: initial;
|
||||
position: initial;
|
||||
}
|
||||
|
||||
.group_7 {
|
||||
padding: initial;
|
||||
align-self: initial;
|
||||
box-shadow: initial;
|
||||
width: initial;
|
||||
position: initial;
|
||||
}
|
||||
|
||||
.group_8 {
|
||||
padding: initial;
|
||||
align-self: initial;
|
||||
box-shadow: initial;
|
||||
width: initial;
|
||||
position: initial;
|
||||
}
|
||||
|
||||
.group_9 {
|
||||
padding: initial;
|
||||
align-self: initial;
|
||||
box-shadow: initial;
|
||||
width: initial;
|
||||
position: initial;
|
||||
}
|
||||
|
||||
.image_1 {
|
||||
color: initial;
|
||||
font-size: initial;
|
||||
line-height: initial;
|
||||
letter-spacing: initial;
|
||||
white-space: initial;
|
||||
width: 0.4rem;
|
||||
height: 0.4rem;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
// margin-top: 0.12rem;
|
||||
margin-top: 26rpx;
|
||||
}
|
||||
|
||||
.view_1 {
|
||||
margin-top: initial;
|
||||
// padding: 0.1rem 0;
|
||||
color: initial;
|
||||
font-size: initial;
|
||||
line-height: initial;
|
||||
letter-spacing: initial;
|
||||
white-space: initial;
|
||||
background-color: initial;
|
||||
border-radius: initial;
|
||||
margin-left: 0.08rem;
|
||||
margin-right: 0.04rem;
|
||||
flex: 1 1 auto;
|
||||
position: relative;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.image_2 {
|
||||
color: initial;
|
||||
font-size: initial;
|
||||
line-height: initial;
|
||||
letter-spacing: initial;
|
||||
white-space: initial;
|
||||
align-self: center;
|
||||
width: 0.4rem;
|
||||
height: 0.4rem;
|
||||
}
|
||||
|
||||
.view_4 {
|
||||
margin-top: initial;
|
||||
padding: 0.14rem 0 0.1rem;
|
||||
color: initial;
|
||||
font-size: initial;
|
||||
line-height: initial;
|
||||
letter-spacing: initial;
|
||||
white-space: initial;
|
||||
background-color: initial;
|
||||
border-radius: initial;
|
||||
margin-left: 0.12rem;
|
||||
flex: 1 1 auto;
|
||||
box-shadow: 0px 0.005rem rgb(234, 234, 234);
|
||||
}
|
||||
|
||||
.image_3 {
|
||||
color: initial;
|
||||
font-size: initial;
|
||||
line-height: initial;
|
||||
letter-spacing: initial;
|
||||
white-space: initial;
|
||||
align-self: center;
|
||||
width: 0.4rem;
|
||||
height: 0.4rem;
|
||||
}
|
||||
|
||||
.view_8 {
|
||||
margin-top: initial;
|
||||
padding: 0.15rem 0 0.14rem;
|
||||
color: initial;
|
||||
font-size: initial;
|
||||
line-height: initial;
|
||||
letter-spacing: initial;
|
||||
white-space: initial;
|
||||
background-color: initial;
|
||||
border-radius: initial;
|
||||
margin-left: 0.13rem;
|
||||
flex: 1 1 auto;
|
||||
box-shadow: 0px 0.005rem rgb(234, 234, 234);
|
||||
}
|
||||
|
||||
.image_4 {
|
||||
color: initial;
|
||||
font-size: initial;
|
||||
line-height: initial;
|
||||
letter-spacing: initial;
|
||||
white-space: initial;
|
||||
align-self: center;
|
||||
width: 0.4rem;
|
||||
height: 0.4rem;
|
||||
}
|
||||
|
||||
.view_12 {
|
||||
margin-top: initial;
|
||||
padding: 0.17rem 0 0.08rem;
|
||||
color: initial;
|
||||
font-size: initial;
|
||||
line-height: initial;
|
||||
letter-spacing: initial;
|
||||
white-space: initial;
|
||||
background-color: initial;
|
||||
border-radius: initial;
|
||||
margin-left: 0.12rem;
|
||||
flex: 1 1 auto;
|
||||
box-shadow: 0px 0.005rem rgb(234, 234, 234);
|
||||
}
|
||||
|
||||
.image_5 {
|
||||
color: initial;
|
||||
font-size: initial;
|
||||
line-height: initial;
|
||||
letter-spacing: initial;
|
||||
white-space: initial;
|
||||
align-self: center;
|
||||
width: 0.4rem;
|
||||
height: 0.4rem;
|
||||
}
|
||||
|
||||
.view_16 {
|
||||
margin-top: initial;
|
||||
padding: 0.15rem 0 0.11rem;
|
||||
color: initial;
|
||||
font-size: initial;
|
||||
line-height: initial;
|
||||
letter-spacing: initial;
|
||||
white-space: initial;
|
||||
background-color: initial;
|
||||
border-radius: initial;
|
||||
margin-left: 0.16rem;
|
||||
flex: 1 1 auto;
|
||||
box-shadow: 0px 0.005rem rgb(234, 234, 234);
|
||||
height: 0.67rem;
|
||||
}
|
||||
|
||||
.image_6 {
|
||||
color: initial;
|
||||
font-size: initial;
|
||||
line-height: initial;
|
||||
letter-spacing: initial;
|
||||
white-space: initial;
|
||||
align-self: center;
|
||||
width: 0.4rem;
|
||||
height: 0.4rem;
|
||||
}
|
||||
|
||||
.view_19 {
|
||||
margin-top: initial;
|
||||
padding: 0.18rem 0 0.18rem;
|
||||
color: initial;
|
||||
font-size: initial;
|
||||
line-height: initial;
|
||||
letter-spacing: initial;
|
||||
white-space: initial;
|
||||
background-color: initial;
|
||||
border-radius: initial;
|
||||
margin-left: 0.16rem;
|
||||
flex: 1 1 auto;
|
||||
box-shadow: 0px 0.005rem rgb(234, 234, 234);
|
||||
height: 0.67rem;
|
||||
position: relative;
|
||||
|
||||
}
|
||||
|
||||
.text_7 {
|
||||
margin-left: initial;
|
||||
margin-right: initial;
|
||||
color: rgb(2, 2, 2);
|
||||
font-size: 28rpx;
|
||||
line-height: 0.14rem;
|
||||
// letter-spacing: 0.015rem;
|
||||
white-space: nowrap;
|
||||
display: block;
|
||||
font-weight: bold;
|
||||
|
||||
text:nth-child(1) {
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
max-width: 0.9rem;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
}
|
||||
|
||||
.text_26 {
|
||||
margin-left: initial;
|
||||
margin-right: initial;
|
||||
color: rgb(2, 2, 2);
|
||||
font-size: 0.15rem;
|
||||
line-height: 0.14rem;
|
||||
letter-spacing: 0.015rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.view_20 {
|
||||
left: -0.03rem;
|
||||
bottom: 0.075rem;
|
||||
}
|
||||
|
||||
.view_21 {
|
||||
// margin-right: 0.06rem;
|
||||
// margin-top: initial;
|
||||
// padding: 0.09rem 0 0.06rem;
|
||||
color: rgb(73, 76, 87);
|
||||
background-color: initial;
|
||||
border: solid 0.01rem rgb(185, 185, 185);
|
||||
}
|
||||
}
|
||||
|
||||
.renzheng {
|
||||
padding-bottom: 0rem;
|
||||
|
||||
.section_4 {
|
||||
padding: 0.33rem 0 0.34rem;
|
||||
background-color: rgb(255, 255, 255);
|
||||
|
||||
.section_5 {
|
||||
margin-left: 0.18rem;
|
||||
margin-right: 0.24rem;
|
||||
padding: 0.2rem 0.18rem 0.18rem 0.24rem;
|
||||
background-color: rgb(246, 247, 250);
|
||||
justify-between: space-between;
|
||||
|
||||
.text_3 {
|
||||
color: rgb(160, 162, 172);
|
||||
font-size: 0.15rem;
|
||||
line-height: 0.15rem;
|
||||
letter-spacing: 0.015rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.text_4 {
|
||||
margin-left: 0.05rem;
|
||||
color: rgb(46, 155, 255);
|
||||
font-size: 0.15rem;
|
||||
line-height: 0.15rem;
|
||||
white-space: nowrap;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.group_3 {
|
||||
margin-top: 0.76rem;
|
||||
padding-left: 0.8rem;
|
||||
padding-right: 0.69rem;
|
||||
color: rgb(163, 182, 202);
|
||||
font-size: 0.15rem;
|
||||
line-height: 0.15rem;
|
||||
white-space: nowrap;
|
||||
|
||||
.text_5 {
|
||||
margin-left: 0.02rem;
|
||||
margin-top: 0.13rem;
|
||||
}
|
||||
|
||||
.image_1 {
|
||||
margin-right: 0.14rem;
|
||||
width: 2.12rem;
|
||||
height: 1.89rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
@ -0,0 +1,438 @@
|
|||
<template>
|
||||
<view>
|
||||
<u-navbar title="互动消息" :border-bottom="false"></u-navbar>
|
||||
<u-tabs-swiper ref="uTabs" :list="tabList" :current="current" :is-scroll="false"
|
||||
:active-item-style="{ color: '#3CB5FB', fontSize: '0.15rem' }" :bar-style="{ background: '#3CB5FB' }"
|
||||
@change="tabsChange"></u-tabs-swiper>
|
||||
<scroll-view scroll-y="true" class="scroll">
|
||||
<view class="flex-col list" v-if='list.length'>
|
||||
<template v-for="(item, i) in list">
|
||||
<view v-if='item.interType != 3' class="list-item flex-col section_4" :key="i">
|
||||
<view class="image_2 flex-row view_14">
|
||||
<u-avatar :src="$u.http.config.imgUrl + item.userHead"
|
||||
@click='toDetil(item.interUserId)' class="image_2"></u-avatar>
|
||||
<view class="flex-col group_2">
|
||||
<view class="flex-row group_3">
|
||||
<text class="text_16">{{ item.interUserName }}</text>
|
||||
<text class="text_18">{{ item.interDate }}</text>
|
||||
</view>
|
||||
<view class="right-text-wrapper">
|
||||
<text v-if="item.interType == 0">点赞了你的作品</text>
|
||||
<text v-if="item.interType == 1">收藏了你的作品</text>
|
||||
<text v-if="item.interType == 2">转发了你的作品</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="bottom-section flex-row">
|
||||
<image v-if='item.dynamicHead' :src="$u.http.config.imgUrl + item.dynamicHead.split(',')[0]"
|
||||
class="image_4" />
|
||||
<text v-if="item.interType == 0" class="text_6">{{ item.commentContent }}</text>
|
||||
<text v-if="item.interType == 1" class="text_6">{{ item.dynamicTitle }}</text>
|
||||
<text v-if="item.interType == 2" class="text_6">{{ item.dynamicTitle }}</text>
|
||||
</view>
|
||||
<view class="flex-row group_4">
|
||||
</view>
|
||||
</view>
|
||||
<view v-else class="list-item flex-col section_4">
|
||||
<view class="top-group flex-row view_13">
|
||||
<view class="image_2 flex-row view_14">
|
||||
<u-avatar :src="$u.http.config.imgUrl + item.userHead"
|
||||
@click='toDetil(item.interUserId)' class="image_2"></u-avatar>
|
||||
<view class="flex-col group_2">
|
||||
<view class="flex-row group_3">
|
||||
<text class="text_16">{{ item.interUserName }}</text>
|
||||
<!-- <view class="flex-col items-center text-wrapper_1">
|
||||
<text>{{ item.commentContent == '【我的评论】' ? '评论' : '回复' }}了</text>
|
||||
</view> -->
|
||||
<text class="text_18">{{ item.interDate }}</text>
|
||||
</view>
|
||||
<text class="text_20">{{ item.commentContent == '【我的评论】' ? '评论' :
|
||||
'回复' }}了你:{{ item.content }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- <view class="right-group flex-col items-center view_15">
|
||||
<text class="top-group_2">回复</text>
|
||||
</view> -->
|
||||
</view>
|
||||
|
||||
<view class="bottom-section flex-row">
|
||||
<text v-if="item.commentContent == '【我的评论】'" class="text_6">{{ item.dynamicTitle }}</text>
|
||||
<text v-else class="text_6">{{ item.commentContent }}</text>
|
||||
</view>
|
||||
<view class="flex-row group_4">
|
||||
<!-- <image
|
||||
src="https://codefun-proj-user-res-1256085488.cos.ap-guangzhou.myqcloud.com/6216dee45a7e3f031061d0f1/621c59e162a7d90011002985/16460348611151830106.png"
|
||||
class="image_11" />
|
||||
<text class="text_22">还有10条评论 ></text> -->
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
<view v-else style='padding-top:30vh'>
|
||||
<!-- <u-empty text="暂无消息列表" mode="message"></u-empty> -->
|
||||
<no-data text="暂无消息列表"></no-data>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import NoData from 'components/NoData.vue'
|
||||
export default {
|
||||
components: {
|
||||
NoData
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
list: [],
|
||||
tabList: [
|
||||
{
|
||||
name: "全部",
|
||||
},
|
||||
{
|
||||
name: "评论",
|
||||
},
|
||||
{
|
||||
name: "点赞",
|
||||
},
|
||||
{
|
||||
name: "收藏",
|
||||
},
|
||||
{
|
||||
name: "转发",
|
||||
},
|
||||
],
|
||||
current:0,
|
||||
};
|
||||
},
|
||||
onLoad() {
|
||||
this.getList(-1)
|
||||
//接收互动消息
|
||||
this.$connection.on("InteractMessage", (data, type) => {
|
||||
if (this.route.indexOf('interactionList') >= 0) {
|
||||
this.list.unshift(data.data)
|
||||
}
|
||||
});
|
||||
},
|
||||
onShow() {
|
||||
if (this.vuex_msgList) {
|
||||
var msgList = this.vuex_msgList;
|
||||
msgList = msgList.replace('InteractMessage,', '')
|
||||
this.$u.vuex('vuex_msgList', msgList)
|
||||
if (!msgList) {
|
||||
var tab = this.vuex_tabbar;
|
||||
tab[1].isDot = false;
|
||||
this.$u.vuex('vuex_tabbar', tab);
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// tabschange
|
||||
tabsChange(i) {
|
||||
// this.current 0=全部 1=评论 2=点赞 3=收藏 4=转发
|
||||
if (this.current !== i) {
|
||||
this.current = i;
|
||||
if (this.current == 0) {
|
||||
this.getList(-1)
|
||||
} else if (this.current == 1) {
|
||||
this.getList(3)
|
||||
} else {
|
||||
this.getList(this.current - 2);
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
//type 0=点赞 1=收藏 2=转发 3=评论
|
||||
getList(type) {
|
||||
this.$u.api.getinteractionList(type).then(res => {
|
||||
this.list = res
|
||||
})
|
||||
},
|
||||
//返回上一级
|
||||
router() {
|
||||
uni.switchTab({
|
||||
url: '../../message/msgList/msgList'
|
||||
})
|
||||
},
|
||||
toDetil(id) {
|
||||
this.$u.route({
|
||||
url: '/pages/AlumniCircle/userDetail/userDetail?id=' + id
|
||||
})
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.scroll {
|
||||
background-color: rgb(246, 247, 250);
|
||||
width: 100%;
|
||||
height: calc(100vh - 0.44rem);
|
||||
}
|
||||
|
||||
.list-item {
|
||||
padding: 0 0.14rem 0.17rem;
|
||||
background-color: rgb(255, 255, 255);
|
||||
border-radius: 0.1rem;
|
||||
margin-top: 0.1rem;
|
||||
}
|
||||
|
||||
.list-item:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.top-group {
|
||||
padding: 0.12rem 0 0.085rem;
|
||||
}
|
||||
|
||||
.bottom-section {
|
||||
margin-top: 10rpx;
|
||||
margin-right: 0.055rem;
|
||||
padding: 0.07rem 0.025rem 0.08rem 0.14rem;
|
||||
color: rgb(54, 54, 54);
|
||||
font-size: 0.12rem;
|
||||
// letter-spacing: 0.012rem;
|
||||
white-space: nowrap;
|
||||
background-color:#F6F8F9;
|
||||
border-radius: 24rpx;
|
||||
// margin-left: 0.5rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.image_2 {
|
||||
margin-bottom: 0.025rem;
|
||||
width: 0.4rem;
|
||||
height: 0.4rem;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.right-group {
|
||||
// margin-left: 0.12rem;
|
||||
// margin-top: 0.05rem;
|
||||
}
|
||||
|
||||
.image_4 {
|
||||
width: 0.35rem;
|
||||
height: 0.35rem;
|
||||
}
|
||||
|
||||
.text_6 {
|
||||
margin-left: 0.025rem;
|
||||
align-self: center;
|
||||
overflow: hidden;
|
||||
max-width: 84%;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.top-group_1 {
|
||||
color: rgb(2, 2, 2);
|
||||
font-size: 0.15rem;
|
||||
line-height: 0.14rem;
|
||||
letter-spacing: 0.015rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.text_4 {
|
||||
margin-left: 0.02rem;
|
||||
margin-top: 0.085rem;
|
||||
color: rgb(177, 179, 182);
|
||||
font-size: 0.12rem;
|
||||
line-height: 0.12rem;
|
||||
letter-spacing: 0.012rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.text_1 {
|
||||
// margin: 0.02rem 0;
|
||||
color: rgb(2, 2, 2);
|
||||
font-size: 0.15rem;
|
||||
// line-height: 0.14rem;
|
||||
letter-spacing: 0.015rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.right-text-wrapper {
|
||||
// margin-left: 0.015rem;
|
||||
padding: 0.03rem 0 0.04rem;
|
||||
// color: rgb(46, 155, 255);
|
||||
font-size: 0.12rem;
|
||||
// line-height: 0.12rem;
|
||||
// letter-spacing: 0.012rem;
|
||||
white-space: nowrap;
|
||||
// background-color: rgba(46, 155, 255, 0.1);
|
||||
border-radius: 0.09rem;
|
||||
// width: 0.65rem;
|
||||
height: 0.18rem;
|
||||
color: #000;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.list {
|
||||
padding: 0.14rem 0.14rem 0.14rem 0.15rem;
|
||||
}
|
||||
|
||||
.view_2 {
|
||||
color: initial;
|
||||
font-size: initial;
|
||||
line-height: initial;
|
||||
letter-spacing: initial;
|
||||
white-space: initial;
|
||||
}
|
||||
|
||||
.top-group {
|
||||
padding: 0.12rem 0 0.085rem;
|
||||
}
|
||||
|
||||
.image_2 {
|
||||
margin-bottom: 0.025rem;
|
||||
width: 0.4rem;
|
||||
height: 0.4rem;
|
||||
}
|
||||
|
||||
.right-group {
|
||||
// margin-left: 0.12rem;
|
||||
// margin-top: 0.05rem;
|
||||
}
|
||||
|
||||
.section_4 {
|
||||
padding: 0.15rem 0.16rem 0;
|
||||
margin-top: 0.1rem;
|
||||
}
|
||||
|
||||
.view_13 {
|
||||
padding: initial;
|
||||
}
|
||||
|
||||
.text_20 {
|
||||
margin-right: initial;
|
||||
padding: initial;
|
||||
align-self: initial;
|
||||
background-color: initial;
|
||||
// margin-left: 0.53rem;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
width: 80%;
|
||||
font-size: 24rpx;
|
||||
color: rgba(0, 0, 0, 0.9);
|
||||
|
||||
}
|
||||
|
||||
.text-wrapper_2 {
|
||||
margin-right: 0.05rem;
|
||||
margin-top: 0.1rem;
|
||||
padding: 0.18rem 0 0.2rem;
|
||||
color: rgb(54, 54, 54);
|
||||
font-size: 0.12rem;
|
||||
line-height: 0.12rem;
|
||||
letter-spacing: 0.012rem;
|
||||
white-space: nowrap;
|
||||
background-color: rgb(246, 247, 250);
|
||||
max-width: 84%;
|
||||
min-width: 84%;
|
||||
margin-left: 0.53rem;
|
||||
}
|
||||
|
||||
.group_4 {
|
||||
padding: 0.1rem 0.52rem 0.1rem;
|
||||
color: rgb(177, 179, 182);
|
||||
font-size: 0.12rem;
|
||||
line-height: 0.12rem;
|
||||
letter-spacing: 0.012rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.view_14 {
|
||||
margin-bottom: initial;
|
||||
width: initial;
|
||||
height: initial;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.view_15 {
|
||||
margin-left: 0.2rem;
|
||||
margin-top: initial;
|
||||
margin-right: 0.07rem;
|
||||
padding: 0.07rem 0;
|
||||
color: rgb(255, 255, 255);
|
||||
font-size: 0.12rem;
|
||||
line-height: 0.12rem;
|
||||
white-space: nowrap;
|
||||
background-color: rgb(46, 155, 255);
|
||||
border-radius: 0.13rem;
|
||||
width: 0.56rem;
|
||||
height: 0.25rem;
|
||||
}
|
||||
|
||||
.view_15:active {
|
||||
background: #fff;
|
||||
color: rgb(46, 155, 255);
|
||||
border: 1px solid rgb(46, 155, 255);
|
||||
}
|
||||
|
||||
.text_21 {
|
||||
margin-left: 0.14rem;
|
||||
margin-right: 0.12rem;
|
||||
max-width: 100%;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.image_11 {
|
||||
width: 0.2rem;
|
||||
height: 0.2rem;
|
||||
}
|
||||
|
||||
.text_22 {
|
||||
margin: 0.05rem 0 0.04rem 0.09rem;
|
||||
}
|
||||
|
||||
.image_10 {
|
||||
width: 0.4rem;
|
||||
height: 0.4rem;
|
||||
}
|
||||
|
||||
.group_2 {
|
||||
margin-left: 0.11rem;
|
||||
margin-bottom: 0.045rem;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.group_3 {
|
||||
padding-left: 0.01rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.text_18 {
|
||||
// margin-top: 0.055rem;
|
||||
color: rgb(177, 179, 182);
|
||||
font-size: 0.12rem;
|
||||
// line-height: 0.12rem;
|
||||
// letter-spacing: 0.012rem;
|
||||
white-space: nowrap;
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
|
||||
.text_16 {
|
||||
margin-bottom: 0.03rem;
|
||||
color: rgb(2, 2, 2);
|
||||
font-size:28rpx;
|
||||
// line-height: 0.14rem;
|
||||
// letter-spacing: 0.015rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.text-wrapper_1 {
|
||||
margin-left: 0.04rem;
|
||||
padding: 0.03rem 0 0.04rem;
|
||||
color: rgb(46, 155, 255);
|
||||
font-size: 0.12rem;
|
||||
line-height: 0.12rem;
|
||||
letter-spacing: 0.012rem;
|
||||
white-space: nowrap;
|
||||
background-color: rgba(46, 155, 255, 0.1);
|
||||
border-radius: 0.09rem;
|
||||
width: 0.65rem;
|
||||
height: 0.18rem;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,938 @@
|
|||
<template>
|
||||
<view>
|
||||
<u-navbar :is-back="false" title="">
|
||||
<view class="slot-wrap">
|
||||
<u-tabs-swiper ref="uTabs" :list="navList" :current="current" :is-scroll="false"
|
||||
:active-item-style="{ color: '#3CB5FB', fontSize: '0.18rem' }"
|
||||
:bar-style="{ background: '#3CB5FB' }" @change="tabsChange"></u-tabs-swiper>
|
||||
</view>
|
||||
</u-navbar>
|
||||
<swiper :current="swiperCurrent" @transition="transition" @animationfinish="animationfinish"
|
||||
style="height: calc(100vh - 0.95rem); width: 100%">
|
||||
<swiper-item class="swiper-item" v-for="(item, index) in navList" :key="index"
|
||||
style="height: calc(100vh - 0.95rem); width: 100%">
|
||||
<scroll-view scroll-y="true" style="height: calc(100vh - 0.95rem); width: 100%"
|
||||
@scrolltolower="onreachBottom">
|
||||
<!-- 消息 -->
|
||||
<view class="msg" v-if="index == 0">
|
||||
<view class="flex-col renzheng" v-if="!vuex_user.isAttestationXY&&false">
|
||||
<view class="flex-col section_4">
|
||||
<view class="flex-row section_5">
|
||||
<text class="text_3">待认证,请先完成认证~</text>
|
||||
<text class="text_4" @click="onAuto">去认证 >></text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex-col group_3">
|
||||
<view class="flex-col">
|
||||
<image src="/static/common/img/16535374500948048054.png" class="image_1" />
|
||||
</view>
|
||||
<text class="text_5">暂无数据,请尽快认证补充资料~</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex-col group_2">
|
||||
<view class="flex-col list">
|
||||
<navigator url="../adminList/adminList" class="list-item flex-row"
|
||||
style='box-shadow: 0px 0.005rem #eaeaea;' v-if='vuex_user.isAttestationGLY'>
|
||||
<u-avatar class="image_1" :show-sex="vuex_msgList.indexOf('admin')>=0" sex-icon=""
|
||||
size="0.4rem" sex-bg-color="red" mode="circle"
|
||||
src="/static/common/img/adminHeaderImg.png">
|
||||
</u-avatar>
|
||||
<view class="right-section flex-col">
|
||||
<view class="top-group justify-between">
|
||||
<text class="text_2">管理列表</text>
|
||||
<!-- <text class="text_4">8:52</text> -->
|
||||
</view>
|
||||
<text class="text_6" v-if="vuex_msgList.indexOf('admin')>=0">你有新通知</text>
|
||||
<text class="text_6" v-else>暂无新通知</text>
|
||||
</view>
|
||||
</navigator>
|
||||
<navigator v-if='interInfo' url="../interactionList/interactionList"
|
||||
class="list-item flex-row" style='box-shadow: 0px 0.005rem #eaeaea;'>
|
||||
<u-avatar class="image_1" :show-sex="vuex_msgList.indexOf('InteractMessage')>=0"
|
||||
sex-icon="" size="0.4rem" sex-bg-color="red" mode="circle"
|
||||
src="/static/common/img/interactionhiderimg.png"></u-avatar>
|
||||
<view class="right-section flex-col">
|
||||
<view class="top-group justify-between">
|
||||
<text class="text_2">互动消息</text>
|
||||
<view style='display:none'>
|
||||
{{interInfo.interDate?interInfo.interDate = interInfo.interDate.replace(/-/g, "/"):''}}
|
||||
</view>
|
||||
<text
|
||||
v-if='new Date(interInfo.interDate) - 0 + (3600000*24)> new Date()&&new Date(interInfo.interDate).getDate()==new Date().getDate()'
|
||||
class="text_4">{{interInfo.interDate.slice(10,16)}}</text>
|
||||
<text v-else class="text_4">{{ interInfo.interDate.slice(5,10)}}</text>
|
||||
<!-- <text class="text_4">{{interInfo.interDate}}</text> -->
|
||||
</view>
|
||||
<text v-if='interInfo.interType==0'
|
||||
class="text_4 text_15">{{interInfo.interUserName+' 点赞了 '+interInfo.dynamicTitle}}</text>
|
||||
<text v-if='interInfo.interType==1'
|
||||
class="text_4 text_15">{{interInfo.interUserName+' 收藏了 '+interInfo.dynamicTitle}}</text>
|
||||
<text v-if='interInfo.interType==2'
|
||||
class="text_4 text_15">{{interInfo.interUserName+' 转发了 '+interInfo.dynamicTitle}}</text>
|
||||
<text v-if='interInfo.interType==3'
|
||||
class="text_4 text_15">{{interInfo.interUserName+' 评论了 '+interInfo.dynamicTitle}}</text>
|
||||
</view>
|
||||
</navigator>
|
||||
<navigator v-if='sysInfo' url="../sysList/sysList" class="list-item flex-row group_4">
|
||||
<u-avatar class="image_1" :show-sex="vuex_msgList.indexOf('SystemMessage')>=0"
|
||||
sex-icon="" size="0.4rem" sex-bg-color="red" mode="circle"
|
||||
src="/static/common/img/systemHeaderimg.png">
|
||||
</u-avatar>
|
||||
<view class="right-section flex-col view_2">
|
||||
<view class="top-group justify-between view_3">
|
||||
<text class="text_2 text_8">系统消息</text>
|
||||
<view style='display:none'>
|
||||
{{sysInfo.messageDate?sysInfo.messageDate = sysInfo.messageDate.replace(/-/g, "/"):''}}
|
||||
</view>
|
||||
<text
|
||||
v-if='new Date(sysInfo.messageDate) - 0 + (3600000*24)> new Date()&&new Date(sysInfo.messageDate).getDate()==new Date().getDate()'
|
||||
class="text_6 text_16">{{ sysInfo.messageDate.slice(10,16)}}</text>
|
||||
<text v-else class="text_6 text_16">{{
|
||||
sysInfo.messageDate.slice(5,10)}}</text>
|
||||
</view>
|
||||
<text class="text_4 text_15">{{sysInfo.title}} </text>
|
||||
</view>
|
||||
</navigator>
|
||||
<view v-if="!sysInfo" style="margin-top:20vh;display: flex;justify-content: center;align-items: center;flex-direction: column;" >
|
||||
<image src="/static/common/img/empty.png" class="image" />
|
||||
<view style="color:grey;margin-top: -5vh;">暂无消息</view>
|
||||
</view>
|
||||
<template v-for="(v, i) in UserMsgList">
|
||||
<view class="list-item flex-row group_5" :key="i"
|
||||
@click="GoChat(v.userId,v.chatType,v.userHead)">
|
||||
<u-avatar v-if='v.chatType==0' class="image_1"
|
||||
:show-sex="vuex_msgList.indexOf(v.userId+',')>=0" sex-icon="" size="0.4rem"
|
||||
sex-bg-color="red" mode="circle" :src="$u.http.config.imgUrl+v.userHead">
|
||||
</u-avatar>
|
||||
<u-avatar v-else class="image_1" :show-sex="vuex_msgList.indexOf('admin,')>=0"
|
||||
sex-icon="" size="0.4rem" sex-bg-color="red" mode="circle"
|
||||
:src="$u.http.config.imgUrl+v.userHead">
|
||||
</u-avatar>
|
||||
<view class="right-section justify-between view_4">
|
||||
<view class="top-group flex-col view_5">
|
||||
<view class="text_2 flex-row view_6">
|
||||
<text class="text_11">{{v.userNetName}}</text>
|
||||
<view class="right-text-wrapper flex-col items-end">
|
||||
<text class="text_13">{{ v.userSchoolName }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<text class="text_4 text_15">{{v.message}}</text>
|
||||
</view>
|
||||
<view style='display:none'>
|
||||
{{v.sendDate?v.sendDate = v.sendDate.replace(/-/g, "/"):''}}</view>
|
||||
<text
|
||||
v-if='new Date(v.sendDate) - 0 + (3600000*24)> new Date()&&new Date(v.sendDate).getDate()==new Date().getDate()'
|
||||
class="text_6 text_16">{{ v.sendDate.slice(10,16)}}</text>
|
||||
<text v-else class="text_6 text_16">{{ v.sendDate.slice(5,10)}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
<!-- 关注 -->
|
||||
<view class="guanzhu" v-else>
|
||||
<view class="flex-col renzheng" v-if="!vuex_user.isAttestationXY&&false">
|
||||
<view class="flex-col section_4">
|
||||
<view class="flex-row section_5">
|
||||
<text class="text_3">待认证,请先完成认证~</text>
|
||||
<text class="text_4" @click="onAuto">去认证 >></text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex-col group_3">
|
||||
<view class="flex-col">
|
||||
<image src="/static/common/img/16535374500948048054.png" class="image_1" />
|
||||
</view>
|
||||
<text class="text_5">暂无数据,请尽快认证补充资料~</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex-col group_2">
|
||||
<view class="flex-col list">
|
||||
<!-- <view class="list-item flex-row group_3">
|
||||
<view class="flex-col items-end text-wrapper text_3">
|
||||
<text class="text_2">浙</text>
|
||||
</view>
|
||||
<view class="bottom-text-wrapper justify-between view_1">
|
||||
<text class="text_5 text_7">学校管理员</text>
|
||||
<view class="center-text-wrapper flex-col items-end">
|
||||
<text class="text_8">浙江大学</text>
|
||||
</view>
|
||||
</view>
|
||||
</view> -->
|
||||
<view class="list-item flex-row group_3" v-for="(item,index) in UserFollowList"
|
||||
:key='index' @click='toDetail(item.carewUserId,item.userRole,item.carewUserHead)'>
|
||||
<u-avatar :src="$u.http.config.imgUrl+item.carewUserHead" class="text_3 image_1"></u-avatar>
|
||||
<view class="bottom-text-wrapper justify-between view_1">
|
||||
<view class="">
|
||||
<text
|
||||
class="text_5 text_7"><text>{{item.carewUserName}}</text><text>{{"("+item.carewName+")"}}</text></text>
|
||||
<view class="center-text-wrapper flex-col items-end">
|
||||
<text class="text_8">{{item.school}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if='item.carewType==2&&item.carewName!="管理员"'
|
||||
class="right-text-wrapper flex-col items-center">
|
||||
<text class="text_10">互相关注</text>
|
||||
</view>
|
||||
<view v-if='item.carewType==1&&item.carewName!="管理员"'
|
||||
class="right-text-wrapper flex-col items-center view_21">
|
||||
<text class="text_10">已关注</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="!UserFollowList.length" style="margin-top:20vh;display: flex;justify-content: center;align-items: center;flex-direction: column;" >
|
||||
<image src="/static/common/img/empty.png" class="image" />
|
||||
<view style="color:grey;margin-top: -5vh;">暂无关注</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
<u-tabbar :list="vuex_tabbar" :class="{phone:vuex_iPhone}"></u-tabbar>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
tabbar: "",
|
||||
swiperCurrent: 0,
|
||||
current: 0,
|
||||
UserMsgList: [],
|
||||
UserFollowList: [],
|
||||
navList: [{
|
||||
name: "消息",
|
||||
},
|
||||
{
|
||||
name: "关注",
|
||||
},
|
||||
],
|
||||
interInfo: '',
|
||||
sysInfo: '',
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
current() {
|
||||
this.getList();
|
||||
},
|
||||
},
|
||||
created() {
|
||||
// 和onShow 重复
|
||||
// this.getList()
|
||||
},
|
||||
onLoad() {
|
||||
//接收数据
|
||||
this.$connection.on("ReceiveMessage", (user, message) => {
|
||||
this.getList()
|
||||
});
|
||||
this.$connection.on("InteractMessage", (data, type) => {
|
||||
this.getList()
|
||||
});
|
||||
this.$connection.on("SystemMessage", (title, content, time) => {
|
||||
this.getList()
|
||||
});
|
||||
},
|
||||
onShow() {
|
||||
this.getList()
|
||||
|
||||
},
|
||||
methods: {
|
||||
toDetail(id, role, head) {
|
||||
if (role == 0) {
|
||||
this.$u.route({
|
||||
url: '/pages/AlumniCircle/userDetail/userDetail?id=' + id + '&type=0'
|
||||
})
|
||||
} else {
|
||||
uni.navigateTo({
|
||||
url: "../dialogBox/dialogBox?id=" + id + '&chatType=1&type=0&head=' + head,
|
||||
});
|
||||
}
|
||||
},
|
||||
getList() {
|
||||
if (this.current == 0) {
|
||||
this.charList();
|
||||
} else {
|
||||
this.FollowList();
|
||||
}
|
||||
},
|
||||
onAuto() {
|
||||
this.$u.route({
|
||||
url: "pages/my/ShoolList/ShoolList"
|
||||
})
|
||||
},
|
||||
charList() {
|
||||
const data = {
|
||||
id: this.vuex_user.id,
|
||||
userRole: this.vuex_user.isAttestationGLY ? 1 : 0
|
||||
}
|
||||
this.$u.api.getcharList(data).then(res => {
|
||||
this.UserMsgList = res
|
||||
})
|
||||
this.$u.api.getinteractionList().then(res => {
|
||||
this.interInfo = res[0]
|
||||
})
|
||||
this.$u.api.getSysList().then(res => {
|
||||
this.sysInfo = res[0]
|
||||
})
|
||||
},
|
||||
FollowList() {
|
||||
this.$u.api.getFollowList().then(res => {
|
||||
|
||||
this.UserFollowList = res
|
||||
})
|
||||
},
|
||||
// 去聊天
|
||||
GoChat(id, chatType, head) {
|
||||
uni.navigateTo({
|
||||
url: "../dialogBox/dialogBox?id=" + id + '&chatType=' + chatType + '&type=0&head=' + head,
|
||||
});
|
||||
},
|
||||
// tabs通知swiper切换
|
||||
tabsChange(index) {
|
||||
this.swiperCurrent = index;
|
||||
},
|
||||
// swiper-item左右移动,通知tabs的滑块跟随移动
|
||||
transition(e) {
|
||||
let dx = e.detail.dx;
|
||||
this.$refs.uTabs.setDx(dx);
|
||||
},
|
||||
// 由于swiper的内部机制问速切题,快换swiper不会触发dx的连续变化,需要在结束时重置状态
|
||||
// swiper滑动结束,分别设置tabs和swiper的状态
|
||||
animationfinish(e) {
|
||||
let current = e.detail.current;
|
||||
this.$refs.uTabs.setFinishCurrent(current);
|
||||
this.swiperCurrent = current;
|
||||
this.current = current;
|
||||
},
|
||||
// scroll-view到底部加载更多
|
||||
onreachBottom() {},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
::v-deep .u-avatar__sex {
|
||||
width: 0.1rem !important;
|
||||
height: 0.1rem !important;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.msg {
|
||||
.list-item {
|
||||
padding-left: 0.2rem;
|
||||
}
|
||||
|
||||
.image_1 {
|
||||
align-self: center;
|
||||
width: 0.4rem;
|
||||
height: 0.4rem;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.right-section {
|
||||
margin-left: 0.15rem;
|
||||
padding: 0.14rem 0 0.18rem;
|
||||
flex: 1 1 auto;
|
||||
height: 0.66rem;
|
||||
}
|
||||
|
||||
.top-group {
|
||||
margin-right: 0.1rem;
|
||||
}
|
||||
|
||||
.text_6 {
|
||||
margin-top: 0.09rem;
|
||||
color: rgb(180, 182, 189);
|
||||
font-size: 0.12rem;
|
||||
line-height: 0.12rem;
|
||||
letter-spacing: 0.012rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.text_2 {
|
||||
color: rgb(2, 2, 2);
|
||||
font-size: 0.15rem;
|
||||
line-height: 0.14rem;
|
||||
letter-spacing: 0.015rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.text_4 {
|
||||
margin-bottom: 0.05rem;
|
||||
color: rgb(193, 196, 204);
|
||||
font-size: 0.12rem;
|
||||
line-height: 0.095rem;
|
||||
letter-spacing: 0.012rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.text_11 {
|
||||
margin-bottom: 0.03rem;
|
||||
color: rgb(2, 2, 2);
|
||||
font-size: 0.15rem;
|
||||
line-height: 0.14rem;
|
||||
letter-spacing: 0.015rem;
|
||||
white-space: nowrap;
|
||||
max-width: 1rem;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.right-text-wrapper {
|
||||
padding: 0.035rem 0.08rem;
|
||||
color: rgb(115, 129, 255);
|
||||
margin-left: 0.1rem;
|
||||
font-size: 0.11rem;
|
||||
line-height: 0.11rem;
|
||||
letter-spacing: 0.011rem;
|
||||
white-space: nowrap;
|
||||
background-color: rgba(115, 129, 255, 0.1);
|
||||
border-radius: 0.09rem;
|
||||
height: 0.18rem;
|
||||
}
|
||||
|
||||
.text_13 {
|
||||
margin-right: 0.03rem;
|
||||
}
|
||||
|
||||
// .group_2 {
|
||||
// padding-bottom: 0.15rem;
|
||||
// flex: 1 1 auto;
|
||||
// overflow-y: auto;
|
||||
// }
|
||||
|
||||
.group_4 {
|
||||
padding: 0 0.01rem;
|
||||
padding-left: 0.2rem;
|
||||
box-shadow: 0px 0.005rem #eaeaea;
|
||||
}
|
||||
|
||||
.group_5 {
|
||||
padding-left: 0.2rem;
|
||||
margin-top: 0.015rem;
|
||||
box-shadow: 0px 0.005rem #eaeaea;
|
||||
}
|
||||
|
||||
.group_4:active,
|
||||
.group_5:active {
|
||||
background: #efefef;
|
||||
}
|
||||
|
||||
.group_8 {
|
||||
padding-left: initial;
|
||||
}
|
||||
|
||||
.view_2 {
|
||||
margin-left: 0.15rem;
|
||||
padding: 0.15rem 0 0.14rem;
|
||||
height: 0.67rem;
|
||||
}
|
||||
|
||||
.view_4 {
|
||||
margin-left: 0.16rem;
|
||||
padding: 0.15rem 0 0.14rem;
|
||||
height: 0.67rem;
|
||||
}
|
||||
|
||||
.view_3 {
|
||||
margin-right: initial;
|
||||
}
|
||||
|
||||
.view_5 {
|
||||
margin-right: initial;
|
||||
}
|
||||
|
||||
.text_16 {
|
||||
margin-top: 0.0rem;
|
||||
color: rgb(193, 196, 204);
|
||||
line-height: 0.095rem;
|
||||
margin-right: 0.095rem;
|
||||
}
|
||||
|
||||
.text_28 {
|
||||
margin-top: initial;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0.17rem;
|
||||
}
|
||||
|
||||
.text_8 {
|
||||
line-height: 0.14rem;
|
||||
}
|
||||
|
||||
.text_9 {
|
||||
margin-right: 0.025rem;
|
||||
}
|
||||
|
||||
.view_6 {
|
||||
color: initial;
|
||||
font-size: initial;
|
||||
line-height: initial;
|
||||
letter-spacing: initial;
|
||||
white-space: initial;
|
||||
}
|
||||
|
||||
.text_15 {
|
||||
margin-bottom: initial;
|
||||
color: rgb(180, 182, 189);
|
||||
line-height: 1.2;
|
||||
margin-top: 0.08rem;
|
||||
width: 50%;
|
||||
overflow: hidden;
|
||||
display: block;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.view_19 {
|
||||
margin-left: 0.045rem;
|
||||
}
|
||||
}
|
||||
|
||||
.guanzhu {
|
||||
.list-item {
|
||||
padding: 0.14rem 0 0.1rem;
|
||||
align-self: flex-end;
|
||||
box-shadow: 0px 0.005rem rgb(234, 234, 234);
|
||||
width: 3.02rem;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.text_3 {
|
||||
color: rgb(2, 2, 2);
|
||||
font-size: 0.15rem;
|
||||
line-height: 0.14rem;
|
||||
letter-spacing: 0.015rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.bottom-text-wrapper {
|
||||
margin-top: 0.1rem;
|
||||
padding: 0.035rem 0;
|
||||
color: rgb(115, 129, 255);
|
||||
font-size: 0.11rem;
|
||||
line-height: 0.11rem;
|
||||
letter-spacing: 0.011rem;
|
||||
white-space: nowrap;
|
||||
background-color: rgba(115, 129, 255, 0.1);
|
||||
border-radius: 0.09rem;
|
||||
}
|
||||
|
||||
.text_5 {
|
||||
margin-left: 0.1rem;
|
||||
margin-right: 0.03rem;
|
||||
}
|
||||
|
||||
.center-text-wrapper {
|
||||
padding: 0.035rem 0.08rem;
|
||||
color: rgb(115, 129, 255);
|
||||
font-size: 0.11rem;
|
||||
line-height: 0.11rem;
|
||||
letter-spacing: 0.011rem;
|
||||
white-space: nowrap;
|
||||
background-color: rgba(115, 129, 255, 0.1);
|
||||
border-radius: 0.09rem;
|
||||
display: inline-block;
|
||||
margin-top: 0.1rem;
|
||||
}
|
||||
|
||||
.right-text-wrapper {
|
||||
margin-right: 0.06rem;
|
||||
margin-top: 0.03rem;
|
||||
margin-left: 0.06rem;
|
||||
padding: 0.085rem 0.08rem;
|
||||
color: rgb(255, 255, 255);
|
||||
font-size: 0.14rem;
|
||||
line-height: 0.13rem;
|
||||
white-space: nowrap;
|
||||
background-color: rgb(46, 155, 255);
|
||||
border-radius: 0.15rem;
|
||||
width: 0.85rem;
|
||||
height: 0.3rem;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.text_8 {
|
||||
margin-right: 0.03rem;
|
||||
}
|
||||
|
||||
.text_10 {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.text_12 {
|
||||
margin-left: 0.05rem;
|
||||
color: rgb(2, 2, 2);
|
||||
font-size: 0.15rem;
|
||||
line-height: 0.14rem;
|
||||
letter-spacing: 0.015rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.text_14 {
|
||||
margin-left: 0.1rem;
|
||||
margin-right: 0.03rem;
|
||||
}
|
||||
|
||||
.group_2 {
|
||||
// padding: 0.11rem 0 4.94rem;
|
||||
// flex: 1 1 auto;
|
||||
// overflow-y: auto;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.text-wrapper {
|
||||
// margin-left: 0.17rem;
|
||||
padding: 0.11rem 0 0.12rem;
|
||||
color: rgb(255, 255, 255);
|
||||
font-size: 0.18rem;
|
||||
line-height: 0.17rem;
|
||||
letter-spacing: 0.018rem;
|
||||
white-space: nowrap;
|
||||
background-size: 100% 100%;
|
||||
background-repeat: no-repeat;
|
||||
width: 0.4rem;
|
||||
height: 0.4rem;
|
||||
margin-top: 0.08rem;
|
||||
background: #6574fc;
|
||||
border-radius: 50%;
|
||||
|
||||
text {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.list {}
|
||||
|
||||
.text_2 {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.group_3 {
|
||||
padding: initial;
|
||||
align-self: initial;
|
||||
box-shadow: initial;
|
||||
width: initial;
|
||||
position: initial;
|
||||
box-shadow: 0px 0.005rem #eaeaea;
|
||||
padding-left: 0.2rem;
|
||||
}
|
||||
|
||||
.group_4 {
|
||||
padding: initial;
|
||||
align-self: initial;
|
||||
box-shadow: initial;
|
||||
width: initial;
|
||||
position: initial;
|
||||
margin-top: 0.015rem;
|
||||
}
|
||||
|
||||
.group_5 {
|
||||
padding: initial;
|
||||
align-self: initial;
|
||||
box-shadow: initial;
|
||||
width: initial;
|
||||
position: initial;
|
||||
}
|
||||
|
||||
.group_6 {
|
||||
padding: initial;
|
||||
align-self: initial;
|
||||
box-shadow: initial;
|
||||
width: initial;
|
||||
position: initial;
|
||||
}
|
||||
|
||||
.group_7 {
|
||||
padding: initial;
|
||||
align-self: initial;
|
||||
box-shadow: initial;
|
||||
width: initial;
|
||||
position: initial;
|
||||
}
|
||||
|
||||
.group_8 {
|
||||
padding: initial;
|
||||
align-self: initial;
|
||||
box-shadow: initial;
|
||||
width: initial;
|
||||
position: initial;
|
||||
}
|
||||
|
||||
.group_9 {
|
||||
padding: initial;
|
||||
align-self: initial;
|
||||
box-shadow: initial;
|
||||
width: initial;
|
||||
position: initial;
|
||||
}
|
||||
|
||||
.image_1 {
|
||||
color: initial;
|
||||
font-size: initial;
|
||||
line-height: initial;
|
||||
letter-spacing: initial;
|
||||
white-space: initial;
|
||||
width: 0.4rem;
|
||||
height: 0.4rem;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
margin-top: 0.12rem;
|
||||
}
|
||||
|
||||
.view_1 {
|
||||
margin-top: initial;
|
||||
padding: 0.1rem 0;
|
||||
color: initial;
|
||||
font-size: initial;
|
||||
line-height: initial;
|
||||
letter-spacing: initial;
|
||||
white-space: initial;
|
||||
background-color: initial;
|
||||
border-radius: initial;
|
||||
margin-left: 0.12rem;
|
||||
margin-right: 0.04rem;
|
||||
flex: 1 1 auto;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.image_2 {
|
||||
color: initial;
|
||||
font-size: initial;
|
||||
line-height: initial;
|
||||
letter-spacing: initial;
|
||||
white-space: initial;
|
||||
align-self: center;
|
||||
width: 0.4rem;
|
||||
height: 0.4rem;
|
||||
}
|
||||
|
||||
.view_4 {
|
||||
margin-top: initial;
|
||||
padding: 0.14rem 0 0.1rem;
|
||||
color: initial;
|
||||
font-size: initial;
|
||||
line-height: initial;
|
||||
letter-spacing: initial;
|
||||
white-space: initial;
|
||||
background-color: initial;
|
||||
border-radius: initial;
|
||||
margin-left: 0.12rem;
|
||||
flex: 1 1 auto;
|
||||
box-shadow: 0px 0.005rem rgb(234, 234, 234);
|
||||
}
|
||||
|
||||
.image_3 {
|
||||
color: initial;
|
||||
font-size: initial;
|
||||
line-height: initial;
|
||||
letter-spacing: initial;
|
||||
white-space: initial;
|
||||
align-self: center;
|
||||
width: 0.4rem;
|
||||
height: 0.4rem;
|
||||
}
|
||||
|
||||
.view_8 {
|
||||
margin-top: initial;
|
||||
padding: 0.15rem 0 0.14rem;
|
||||
color: initial;
|
||||
font-size: initial;
|
||||
line-height: initial;
|
||||
letter-spacing: initial;
|
||||
white-space: initial;
|
||||
background-color: initial;
|
||||
border-radius: initial;
|
||||
margin-left: 0.13rem;
|
||||
flex: 1 1 auto;
|
||||
box-shadow: 0px 0.005rem rgb(234, 234, 234);
|
||||
}
|
||||
|
||||
.image_4 {
|
||||
color: initial;
|
||||
font-size: initial;
|
||||
line-height: initial;
|
||||
letter-spacing: initial;
|
||||
white-space: initial;
|
||||
align-self: center;
|
||||
width: 0.4rem;
|
||||
height: 0.4rem;
|
||||
}
|
||||
|
||||
.view_12 {
|
||||
margin-top: initial;
|
||||
padding: 0.17rem 0 0.08rem;
|
||||
color: initial;
|
||||
font-size: initial;
|
||||
line-height: initial;
|
||||
letter-spacing: initial;
|
||||
white-space: initial;
|
||||
background-color: initial;
|
||||
border-radius: initial;
|
||||
margin-left: 0.12rem;
|
||||
flex: 1 1 auto;
|
||||
box-shadow: 0px 0.005rem rgb(234, 234, 234);
|
||||
}
|
||||
|
||||
.image_5 {
|
||||
color: initial;
|
||||
font-size: initial;
|
||||
line-height: initial;
|
||||
letter-spacing: initial;
|
||||
white-space: initial;
|
||||
align-self: center;
|
||||
width: 0.4rem;
|
||||
height: 0.4rem;
|
||||
}
|
||||
|
||||
.view_16 {
|
||||
margin-top: initial;
|
||||
padding: 0.15rem 0 0.11rem;
|
||||
color: initial;
|
||||
font-size: initial;
|
||||
line-height: initial;
|
||||
letter-spacing: initial;
|
||||
white-space: initial;
|
||||
background-color: initial;
|
||||
border-radius: initial;
|
||||
margin-left: 0.16rem;
|
||||
flex: 1 1 auto;
|
||||
box-shadow: 0px 0.005rem rgb(234, 234, 234);
|
||||
height: 0.67rem;
|
||||
}
|
||||
|
||||
.image_6 {
|
||||
color: initial;
|
||||
font-size: initial;
|
||||
line-height: initial;
|
||||
letter-spacing: initial;
|
||||
white-space: initial;
|
||||
align-self: center;
|
||||
width: 0.4rem;
|
||||
height: 0.4rem;
|
||||
}
|
||||
|
||||
.view_19 {
|
||||
margin-top: initial;
|
||||
padding: 0.18rem 0 0.18rem;
|
||||
color: initial;
|
||||
font-size: initial;
|
||||
line-height: initial;
|
||||
letter-spacing: initial;
|
||||
white-space: initial;
|
||||
background-color: initial;
|
||||
border-radius: initial;
|
||||
margin-left: 0.16rem;
|
||||
flex: 1 1 auto;
|
||||
box-shadow: 0px 0.005rem rgb(234, 234, 234);
|
||||
height: 0.67rem;
|
||||
position: relative;
|
||||
|
||||
}
|
||||
|
||||
.text_7 {
|
||||
margin-left: initial;
|
||||
margin-right: initial;
|
||||
color: rgb(2, 2, 2);
|
||||
font-size: 0.15rem;
|
||||
line-height: 0.14rem;
|
||||
letter-spacing: 0.015rem;
|
||||
white-space: nowrap;
|
||||
display: block;
|
||||
|
||||
text:nth-child(1) {
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
max-width: 0.9rem;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
}
|
||||
|
||||
.text_26 {
|
||||
margin-left: initial;
|
||||
margin-right: initial;
|
||||
color: rgb(2, 2, 2);
|
||||
font-size: 0.15rem;
|
||||
line-height: 0.14rem;
|
||||
letter-spacing: 0.015rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.view_20 {
|
||||
left: -0.03rem;
|
||||
bottom: 0.075rem;
|
||||
}
|
||||
|
||||
.view_21 {
|
||||
margin-right: 0.06rem;
|
||||
margin-top: initial;
|
||||
padding: 0.09rem 0 0.06rem;
|
||||
color: rgb(73, 76, 87);
|
||||
background-color: initial;
|
||||
border: solid 0.01rem rgb(185, 185, 185);
|
||||
}
|
||||
}
|
||||
|
||||
.renzheng {
|
||||
padding-bottom: 0rem;
|
||||
|
||||
.section_4 {
|
||||
padding: 0.33rem 0 0.34rem;
|
||||
background-color: rgb(255, 255, 255);
|
||||
|
||||
.section_5 {
|
||||
margin-left: 0.18rem;
|
||||
margin-right: 0.24rem;
|
||||
padding: 0.2rem 0.18rem 0.18rem 0.24rem;
|
||||
background-color: rgb(246, 247, 250);
|
||||
justify-between: space-between;
|
||||
|
||||
.text_3 {
|
||||
color: rgb(160, 162, 172);
|
||||
font-size: 0.15rem;
|
||||
line-height: 0.15rem;
|
||||
letter-spacing: 0.015rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.text_4 {
|
||||
margin-left: 0.05rem;
|
||||
color: rgb(46, 155, 255);
|
||||
font-size: 0.15rem;
|
||||
line-height: 0.15rem;
|
||||
white-space: nowrap;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.group_3 {
|
||||
margin-top: 0.76rem;
|
||||
padding-left: 0.8rem;
|
||||
padding-right: 0.69rem;
|
||||
color: rgb(163, 182, 202);
|
||||
font-size: 0.15rem;
|
||||
line-height: 0.15rem;
|
||||
white-space: nowrap;
|
||||
|
||||
.text_5 {
|
||||
margin-left: 0.02rem;
|
||||
margin-top: 0.13rem;
|
||||
}
|
||||
|
||||
.image_1 {
|
||||
margin-right: 0.14rem;
|
||||
width: 2.12rem;
|
||||
height: 1.89rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,908 @@
|
|||
<template>
|
||||
<view>
|
||||
<view class="page-title">消息</view>
|
||||
<view class="slot-wrap">
|
||||
<!-- <u-tabs-swiper ref="uTabs" :list="navList" :current="current" :is-scroll="false"
|
||||
:active-item-style="{ color: '#3CB5FB', fontSize: '0.18rem' }"
|
||||
:bar-style="{ background: '#3CB5FB' }" @change="tabsChange"></u-tabs-swiper> -->
|
||||
|
||||
<view class="tabs-item" v-for="(item, index) in navList" :key="index" @click="tabsClick(item.type)">
|
||||
<image :src="item.image"></image>
|
||||
<text>{{ item.name }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- <swiper :current="swiperCurrent" @transition="transition" @animationfinish="animationfinish"
|
||||
style="height: calc(100vh - 2.1rem); width: 100%">
|
||||
<swiper-item class="swiper-item" v-for="(item, index) in navList" :key="index"
|
||||
style="height: calc(100vh - 2.1rem); width: 100%"> -->
|
||||
<scroll-view scroll-y="true" style="height: calc(100vh - 2.5rem - 56px); width: 100%"
|
||||
@scrolltolower="onreachBottom">
|
||||
<!-- 消息 -->
|
||||
<view class="msg" >
|
||||
<view class="flex-col renzheng" v-if="!vuex_user.isAttestationXY && false">
|
||||
<view class="flex-col section_4">
|
||||
<view class="flex-row section_5">
|
||||
<text class="text_3">待认证,请先完成认证~</text>
|
||||
<text class="text_4" @click="onAuto">去认证 >></text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex-col group_3">
|
||||
<view class="flex-col">
|
||||
<image src="/static/common/img/16535374500948048054.png" class="image_1" />
|
||||
</view>
|
||||
<text class="text_5">暂无数据,请尽快认证补充资料~</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex-col group_2">
|
||||
<view class="flex-col list">
|
||||
<navigator url="../adminList/adminList" class="list-item flex-row"
|
||||
style='box-shadow: 0px 0.005rem #eaeaea;' v-if='vuex_user.isAttestationGLY'>
|
||||
<u-avatar class="image_1" :show-sex="vuex_msgList.indexOf('admin') >= 0" sex-icon=""
|
||||
size="0.4rem" sex-bg-color="red" mode="circle"
|
||||
src="/static/common/img/adminHeaderImg.png">
|
||||
</u-avatar>
|
||||
<view class="right-section flex-col">
|
||||
<view class="top-group justify-between">
|
||||
<text class="text_2">管理列表</text>
|
||||
<!-- <text class="text_4">8:52</text> -->
|
||||
</view>
|
||||
<text class="text_6" v-if="vuex_msgList.indexOf('admin') >= 0">你有新通知</text>
|
||||
<text class="text_6" v-else>暂无管理消息</text>
|
||||
</view>
|
||||
</navigator>
|
||||
<!-- <view v-if="!sysInfo"
|
||||
style="margin-top:20vh;display: flex;justify-content: center;align-items: center;flex-direction: column;">
|
||||
<image src="/static/common/img/empty.png" class="image" />
|
||||
<view style="color:grey;margin-top: -5vh;">暂无消息</view>
|
||||
</view> -->
|
||||
<view v-if="UserMsgList.length">
|
||||
<view v-for="(v, i) in UserMsgList" :key="i" class="list-item flex-row group_5"
|
||||
@click="GoChat(v.userId, v.chatType, v.userHead)">
|
||||
<u-avatar v-if='v.chatType == 0' class="image_1"
|
||||
:show-sex="vuex_msgList.indexOf(v.userId + ',') >= 0" sex-icon=""
|
||||
size="0.4rem" sex-bg-color="red" mode="circle"
|
||||
:src="$u.http.config.imgUrl + v.userHead">
|
||||
</u-avatar>
|
||||
<u-avatar v-else class="image_1" :show-sex="vuex_msgList.indexOf('admin,') >= 0"
|
||||
sex-icon="" size="0.4rem" sex-bg-color="red" mode="circle"
|
||||
:src="$u.http.config.imgUrl + v.userHead">
|
||||
</u-avatar>
|
||||
<view class="right-section justify-between view_4">
|
||||
<view class="top-group flex-col view_5">
|
||||
<view class="text_2 flex-row view_6">
|
||||
<text class="text_11">{{ v.userNetName }}</text>
|
||||
<view class="right-text-wrapper flex-col items-end">
|
||||
<text class="text_13">{{ v.userSchoolName }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<text class="text_4 text_15">{{ v.message }}</text>
|
||||
</view>
|
||||
<view style='display:none'>
|
||||
{{ v.sendDate ? v.sendDate = v.sendDate.replace(/-/g, "/") : '' }}
|
||||
</view>
|
||||
<text
|
||||
v-if='new Date(v.sendDate) - 0 + (3600000 * 24) > new Date() && new Date(v.sendDate).getDate() == new Date().getDate()'
|
||||
class="text_6 text_16">{{ v.sendDate.slice(10, 16) }}</text>
|
||||
<text v-else class="text_6 text_16">{{ v.sendDate.slice(5, 10) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<no-data v-else type="message"></no-data>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<!-- </swiper-item>
|
||||
</swiper> -->
|
||||
|
||||
<!-- 使用自定义TabBar -->
|
||||
<custom-tab-bar></custom-tab-bar>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import noData from '@/components/NoData.vue'
|
||||
import CustomTabBar from '@/components/custom-tab-bar/custom-tab-bar.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
noData,
|
||||
CustomTabBar
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
tabbar: "",
|
||||
swiperCurrent: 0,
|
||||
current: 0,
|
||||
UserMsgList: [],
|
||||
UserFollowList: [],
|
||||
navList: [{
|
||||
name: "互动消息",
|
||||
image: "/static/common/img/message/interactive.png",
|
||||
type: 0
|
||||
},
|
||||
{
|
||||
name: "系统消息",
|
||||
image: "/static/common/img/message/system.png",
|
||||
type: 1
|
||||
},
|
||||
{
|
||||
name: "新增关注",
|
||||
image: "/static/common/img/message/attention.png",
|
||||
type: 2
|
||||
},
|
||||
],
|
||||
interInfo: '',
|
||||
sysInfo: '',
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
current() {
|
||||
this.getList();
|
||||
},
|
||||
},
|
||||
created() {
|
||||
// 和onShow 重复
|
||||
// this.getList()
|
||||
},
|
||||
onLoad() {
|
||||
//接收数据
|
||||
this.$connection.on("ReceiveMessage", (user, message) => {
|
||||
this.getList()
|
||||
});
|
||||
this.$connection.on("InteractMessage", (data, type) => {
|
||||
this.getList()
|
||||
});
|
||||
this.$connection.on("SystemMessage", (title, content, time) => {
|
||||
this.getList()
|
||||
});
|
||||
},
|
||||
onShow() {
|
||||
this.getList()
|
||||
|
||||
},
|
||||
methods: {
|
||||
tabsClick(type) {
|
||||
switch (type) {
|
||||
case 0:
|
||||
this.$u.route({url:'/pages/message/interactionList/interactionList'})
|
||||
break;
|
||||
case 1:
|
||||
this.$u.route({url:'/pages/message/sysList/sysList'})
|
||||
break;
|
||||
case 2:
|
||||
this.$u.route({url:'/pages/message/attentionList/attentionList'})
|
||||
break;
|
||||
|
||||
}
|
||||
},
|
||||
toDetail(id, role, head) {
|
||||
if (role == 0) {
|
||||
this.$u.route({
|
||||
url: '/pages/AlumniCircle/userDetail/userDetail?id=' + id + '&type=0'
|
||||
})
|
||||
} else {
|
||||
uni.navigateTo({
|
||||
url: "../dialogBox/dialogBox?id=" + id + '&chatType=1&type=0&head=' + head,
|
||||
});
|
||||
}
|
||||
},
|
||||
getList() {
|
||||
if (this.current == 0) {
|
||||
this.charList();
|
||||
} else {
|
||||
this.FollowList();
|
||||
}
|
||||
},
|
||||
onAuto() {
|
||||
this.$u.route({
|
||||
url: "pages/my/ShoolList/ShoolList"
|
||||
})
|
||||
},
|
||||
charList() {
|
||||
const data = {
|
||||
id: this.vuex_user.id,
|
||||
userRole: this.vuex_user.isAttestationGLY ? 1 : 0
|
||||
}
|
||||
this.$u.api.getcharList(data).then(res => {
|
||||
this.UserMsgList = res
|
||||
})
|
||||
this.$u.api.getinteractionList(-1).then(res => {
|
||||
this.interInfo = res[0]
|
||||
})
|
||||
this.$u.api.getSysList().then(res => {
|
||||
this.sysInfo = res[0]
|
||||
})
|
||||
},
|
||||
FollowList() {
|
||||
this.$u.api.getFollowList().then(res => {
|
||||
|
||||
this.UserFollowList = res
|
||||
})
|
||||
},
|
||||
// 去聊天
|
||||
GoChat(id, chatType, head) {
|
||||
uni.navigateTo({
|
||||
url: "../dialogBox/dialogBox?id=" + id + '&chatType=' + chatType + '&type=0&head=' + head,
|
||||
});
|
||||
},
|
||||
// tabs通知swiper切换
|
||||
tabsChange(index) {
|
||||
this.swiperCurrent = index;
|
||||
},
|
||||
// swiper-item左右移动,通知tabs的滑块跟随移动
|
||||
transition(e) {
|
||||
let dx = e.detail.dx;
|
||||
this.$refs.uTabs.setDx(dx);
|
||||
},
|
||||
// 由于swiper的内部机制问速切题,快换swiper不会触发dx的连续变化,需要在结束时重置状态
|
||||
// swiper滑动结束,分别设置tabs和swiper的状态
|
||||
animationfinish(e) {
|
||||
let current = e.detail.current;
|
||||
this.$refs.uTabs.setFinishCurrent(current);
|
||||
this.swiperCurrent = current;
|
||||
this.current = current;
|
||||
},
|
||||
// scroll-view到底部加载更多
|
||||
onreachBottom() { },
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
::v-deep .u-avatar__sex {
|
||||
width: 0.1rem !important;
|
||||
height: 0.1rem !important;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.msg {
|
||||
.list-item {
|
||||
padding-left: 0.2rem;
|
||||
}
|
||||
|
||||
.image_1 {
|
||||
align-self: center;
|
||||
width: 0.4rem;
|
||||
height: 0.4rem;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.right-section {
|
||||
margin-left: 0.15rem;
|
||||
padding: 0.14rem 0 0.18rem;
|
||||
flex: 1 1 auto;
|
||||
height: 0.66rem;
|
||||
}
|
||||
|
||||
.top-group {
|
||||
margin-right: 0.1rem;
|
||||
}
|
||||
|
||||
.text_6 {
|
||||
margin-top: 0.09rem;
|
||||
color: rgb(180, 182, 189);
|
||||
font-size: 0.12rem;
|
||||
line-height: 0.12rem;
|
||||
letter-spacing: 0.012rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.text_2 {
|
||||
color: rgb(2, 2, 2);
|
||||
font-size: 0.15rem;
|
||||
line-height: 0.14rem;
|
||||
letter-spacing: 0.015rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.text_4 {
|
||||
margin-bottom: 0.05rem;
|
||||
color: rgb(193, 196, 204);
|
||||
font-size: 0.12rem;
|
||||
line-height: 0.095rem;
|
||||
letter-spacing: 0.012rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.text_11 {
|
||||
// margin-bottom: 0.03rem;
|
||||
color: rgb(2, 2, 2);
|
||||
font-size: 0.15rem;
|
||||
line-height: 36rpx;
|
||||
// letter-spacing: 0.015rem;
|
||||
white-space: nowrap;
|
||||
max-width: 1rem;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.right-text-wrapper {
|
||||
padding: 0.035rem 0.08rem;
|
||||
color: #3CB5FB;
|
||||
margin-left: 0.1rem;
|
||||
font-size: 0.11rem;
|
||||
line-height: 0.11rem;
|
||||
letter-spacing: 0.011rem;
|
||||
white-space: nowrap;
|
||||
background-color: rgba(60,181,251,0.1);
|
||||
border-radius: 0.09rem;
|
||||
height: 0.18rem;
|
||||
}
|
||||
|
||||
.text_13 {
|
||||
margin-right: 0.03rem;
|
||||
}
|
||||
|
||||
// .group_2 {
|
||||
// padding-bottom: 0.15rem;
|
||||
// flex: 1 1 auto;
|
||||
// overflow-y: auto;
|
||||
// }
|
||||
|
||||
.group_4 {
|
||||
padding: 0 0.01rem;
|
||||
padding-left: 0.2rem;
|
||||
box-shadow: 0px 0.005rem #eaeaea;
|
||||
}
|
||||
|
||||
.group_5 {
|
||||
padding-left: 0.2rem;
|
||||
margin-top: 0.015rem;
|
||||
box-shadow: 0px 0.005rem #eaeaea;
|
||||
}
|
||||
|
||||
.group_4:active,
|
||||
.group_5:active {
|
||||
background: #efefef;
|
||||
}
|
||||
|
||||
.group_8 {
|
||||
padding-left: initial;
|
||||
}
|
||||
|
||||
.view_2 {
|
||||
margin-left: 0.15rem;
|
||||
padding: 0.15rem 0 0.14rem;
|
||||
height: 0.67rem;
|
||||
}
|
||||
|
||||
.view_4 {
|
||||
margin-left: 0.16rem;
|
||||
padding: 0.15rem 0 0.14rem;
|
||||
height: 0.67rem;
|
||||
}
|
||||
|
||||
.view_3 {
|
||||
margin-right: initial;
|
||||
}
|
||||
|
||||
.view_5 {
|
||||
margin-right: initial;
|
||||
}
|
||||
|
||||
.text_16 {
|
||||
margin-top: 0.0rem;
|
||||
color: rgb(193, 196, 204);
|
||||
line-height: 0.095rem;
|
||||
margin-right: 0.095rem;
|
||||
}
|
||||
|
||||
.text_28 {
|
||||
margin-top: initial;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0.17rem;
|
||||
}
|
||||
|
||||
.text_8 {
|
||||
line-height: 0.14rem;
|
||||
}
|
||||
|
||||
.text_9 {
|
||||
margin-right: 0.025rem;
|
||||
}
|
||||
|
||||
.view_6 {
|
||||
color: initial;
|
||||
font-size: initial;
|
||||
line-height: initial;
|
||||
letter-spacing: initial;
|
||||
white-space: initial;
|
||||
}
|
||||
|
||||
.text_15 {
|
||||
margin-bottom: initial;
|
||||
color: rgb(180, 182, 189);
|
||||
line-height: 1.2;
|
||||
margin-top: 0.08rem;
|
||||
width: 50%;
|
||||
overflow: hidden;
|
||||
display: block;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.view_19 {
|
||||
margin-left: 0.045rem;
|
||||
}
|
||||
}
|
||||
|
||||
.guanzhu {
|
||||
.list-item {
|
||||
padding: 0.14rem 0 0.1rem;
|
||||
align-self: flex-end;
|
||||
box-shadow: 0px 0.005rem rgb(234, 234, 234);
|
||||
width: 3.02rem;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.text_3 {
|
||||
color: rgb(2, 2, 2);
|
||||
font-size: 0.15rem;
|
||||
line-height: 0.14rem;
|
||||
letter-spacing: 0.015rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.bottom-text-wrapper {
|
||||
margin-top: 0.1rem;
|
||||
padding: 0.035rem 0;
|
||||
color: rgb(115, 129, 255);
|
||||
font-size: 0.11rem;
|
||||
line-height: 0.11rem;
|
||||
letter-spacing: 0.011rem;
|
||||
white-space: nowrap;
|
||||
background-color: rgba(115, 129, 255, 0.1);
|
||||
border-radius: 0.09rem;
|
||||
}
|
||||
|
||||
.text_5 {
|
||||
margin-left: 0.1rem;
|
||||
margin-right: 0.03rem;
|
||||
}
|
||||
|
||||
.center-text-wrapper {
|
||||
padding: 0.035rem 0.08rem;
|
||||
color: rgb(115, 129, 255);
|
||||
font-size: 0.11rem;
|
||||
line-height: 0.11rem;
|
||||
letter-spacing: 0.011rem;
|
||||
white-space: nowrap;
|
||||
background-color: rgba(115, 129, 255, 0.1);
|
||||
border-radius: 0.09rem;
|
||||
display: inline-block;
|
||||
margin-top: 0.1rem;
|
||||
}
|
||||
|
||||
.right-text-wrapper {
|
||||
margin-right: 0.06rem;
|
||||
margin-top: 0.03rem;
|
||||
margin-left: 0.06rem;
|
||||
padding: 0.085rem 0.08rem;
|
||||
color: rgb(255, 255, 255);
|
||||
font-size: 0.14rem;
|
||||
line-height: 0.13rem;
|
||||
white-space: nowrap;
|
||||
background-color: rgb(46, 155, 255);
|
||||
border-radius: 0.15rem;
|
||||
width: 0.85rem;
|
||||
height: 0.3rem;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.text_8 {
|
||||
margin-right: 0.03rem;
|
||||
}
|
||||
|
||||
.text_10 {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.text_12 {
|
||||
margin-left: 0.05rem;
|
||||
color: rgb(2, 2, 2);
|
||||
font-size: 0.15rem;
|
||||
line-height: 0.14rem;
|
||||
letter-spacing: 0.015rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.text_14 {
|
||||
margin-left: 0.1rem;
|
||||
margin-right: 0.03rem;
|
||||
}
|
||||
|
||||
.group_2 {
|
||||
// padding: 0.11rem 0 4.94rem;
|
||||
// flex: 1 1 auto;
|
||||
// overflow-y: auto;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.text-wrapper {
|
||||
// margin-left: 0.17rem;
|
||||
padding: 0.11rem 0 0.12rem;
|
||||
color: rgb(255, 255, 255);
|
||||
font-size: 0.18rem;
|
||||
line-height: 0.17rem;
|
||||
letter-spacing: 0.018rem;
|
||||
white-space: nowrap;
|
||||
background-size: 100% 100%;
|
||||
background-repeat: no-repeat;
|
||||
width: 0.4rem;
|
||||
height: 0.4rem;
|
||||
margin-top: 0.08rem;
|
||||
background: #6574fc;
|
||||
border-radius: 50%;
|
||||
|
||||
text {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.list {}
|
||||
|
||||
.text_2 {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.group_3 {
|
||||
padding: initial;
|
||||
align-self: initial;
|
||||
box-shadow: initial;
|
||||
width: initial;
|
||||
position: initial;
|
||||
box-shadow: 0px 0.005rem #eaeaea;
|
||||
padding-left: 0.2rem;
|
||||
}
|
||||
|
||||
.group_4 {
|
||||
padding: initial;
|
||||
align-self: initial;
|
||||
box-shadow: initial;
|
||||
width: initial;
|
||||
position: initial;
|
||||
margin-top: 0.015rem;
|
||||
}
|
||||
|
||||
.group_5 {
|
||||
padding: initial;
|
||||
align-self: initial;
|
||||
box-shadow: initial;
|
||||
width: initial;
|
||||
position: initial;
|
||||
}
|
||||
|
||||
.group_6 {
|
||||
padding: initial;
|
||||
align-self: initial;
|
||||
box-shadow: initial;
|
||||
width: initial;
|
||||
position: initial;
|
||||
}
|
||||
|
||||
.group_7 {
|
||||
padding: initial;
|
||||
align-self: initial;
|
||||
box-shadow: initial;
|
||||
width: initial;
|
||||
position: initial;
|
||||
}
|
||||
|
||||
.group_8 {
|
||||
padding: initial;
|
||||
align-self: initial;
|
||||
box-shadow: initial;
|
||||
width: initial;
|
||||
position: initial;
|
||||
}
|
||||
|
||||
.group_9 {
|
||||
padding: initial;
|
||||
align-self: initial;
|
||||
box-shadow: initial;
|
||||
width: initial;
|
||||
position: initial;
|
||||
}
|
||||
|
||||
.image_1 {
|
||||
color: initial;
|
||||
font-size: initial;
|
||||
line-height: initial;
|
||||
letter-spacing: initial;
|
||||
white-space: initial;
|
||||
width: 0.4rem;
|
||||
height: 0.4rem;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
margin-top: 0.12rem;
|
||||
}
|
||||
|
||||
.view_1 {
|
||||
margin-top: initial;
|
||||
padding: 0.1rem 0;
|
||||
color: initial;
|
||||
font-size: initial;
|
||||
line-height: initial;
|
||||
letter-spacing: initial;
|
||||
white-space: initial;
|
||||
background-color: initial;
|
||||
border-radius: initial;
|
||||
margin-left: 0.12rem;
|
||||
margin-right: 0.04rem;
|
||||
flex: 1 1 auto;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.image_2 {
|
||||
color: initial;
|
||||
font-size: initial;
|
||||
line-height: initial;
|
||||
letter-spacing: initial;
|
||||
white-space: initial;
|
||||
align-self: center;
|
||||
width: 0.4rem;
|
||||
height: 0.4rem;
|
||||
}
|
||||
|
||||
.view_4 {
|
||||
margin-top: initial;
|
||||
padding: 0.14rem 0 0.1rem;
|
||||
color: initial;
|
||||
font-size: initial;
|
||||
line-height: initial;
|
||||
letter-spacing: initial;
|
||||
white-space: initial;
|
||||
background-color: initial;
|
||||
border-radius: initial;
|
||||
margin-left: 0.12rem;
|
||||
flex: 1 1 auto;
|
||||
box-shadow: 0px 0.005rem rgb(234, 234, 234);
|
||||
}
|
||||
|
||||
.image_3 {
|
||||
color: initial;
|
||||
font-size: initial;
|
||||
line-height: initial;
|
||||
letter-spacing: initial;
|
||||
white-space: initial;
|
||||
align-self: center;
|
||||
width: 0.4rem;
|
||||
height: 0.4rem;
|
||||
}
|
||||
|
||||
.view_8 {
|
||||
margin-top: initial;
|
||||
padding: 0.15rem 0 0.14rem;
|
||||
color: initial;
|
||||
font-size: initial;
|
||||
line-height: initial;
|
||||
letter-spacing: initial;
|
||||
white-space: initial;
|
||||
background-color: initial;
|
||||
border-radius: initial;
|
||||
margin-left: 0.13rem;
|
||||
flex: 1 1 auto;
|
||||
box-shadow: 0px 0.005rem rgb(234, 234, 234);
|
||||
}
|
||||
|
||||
.image_4 {
|
||||
color: initial;
|
||||
font-size: initial;
|
||||
line-height: initial;
|
||||
letter-spacing: initial;
|
||||
white-space: initial;
|
||||
align-self: center;
|
||||
width: 0.4rem;
|
||||
height: 0.4rem;
|
||||
}
|
||||
|
||||
.view_12 {
|
||||
margin-top: initial;
|
||||
padding: 0.17rem 0 0.08rem;
|
||||
color: initial;
|
||||
font-size: initial;
|
||||
line-height: initial;
|
||||
letter-spacing: initial;
|
||||
white-space: initial;
|
||||
background-color: initial;
|
||||
border-radius: initial;
|
||||
margin-left: 0.12rem;
|
||||
flex: 1 1 auto;
|
||||
box-shadow: 0px 0.005rem rgb(234, 234, 234);
|
||||
}
|
||||
|
||||
.image_5 {
|
||||
color: initial;
|
||||
font-size: initial;
|
||||
line-height: initial;
|
||||
letter-spacing: initial;
|
||||
white-space: initial;
|
||||
align-self: center;
|
||||
width: 0.4rem;
|
||||
height: 0.4rem;
|
||||
}
|
||||
|
||||
.view_16 {
|
||||
margin-top: initial;
|
||||
padding: 0.15rem 0 0.11rem;
|
||||
color: initial;
|
||||
font-size: initial;
|
||||
line-height: initial;
|
||||
letter-spacing: initial;
|
||||
white-space: initial;
|
||||
background-color: initial;
|
||||
border-radius: initial;
|
||||
margin-left: 0.16rem;
|
||||
flex: 1 1 auto;
|
||||
box-shadow: 0px 0.005rem rgb(234, 234, 234);
|
||||
height: 0.67rem;
|
||||
}
|
||||
|
||||
.image_6 {
|
||||
color: initial;
|
||||
font-size: initial;
|
||||
line-height: initial;
|
||||
letter-spacing: initial;
|
||||
white-space: initial;
|
||||
align-self: center;
|
||||
width: 0.4rem;
|
||||
height: 0.4rem;
|
||||
}
|
||||
|
||||
.view_19 {
|
||||
margin-top: initial;
|
||||
padding: 0.18rem 0 0.18rem;
|
||||
color: initial;
|
||||
font-size: initial;
|
||||
line-height: initial;
|
||||
letter-spacing: initial;
|
||||
white-space: initial;
|
||||
background-color: initial;
|
||||
border-radius: initial;
|
||||
margin-left: 0.16rem;
|
||||
flex: 1 1 auto;
|
||||
box-shadow: 0px 0.005rem rgb(234, 234, 234);
|
||||
height: 0.67rem;
|
||||
position: relative;
|
||||
|
||||
}
|
||||
|
||||
.text_7 {
|
||||
margin-left: initial;
|
||||
margin-right: initial;
|
||||
color: rgb(2, 2, 2);
|
||||
font-size: 0.15rem;
|
||||
line-height: 0.14rem;
|
||||
letter-spacing: 0.015rem;
|
||||
white-space: nowrap;
|
||||
display: block;
|
||||
|
||||
text:nth-child(1) {
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
max-width: 0.9rem;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
}
|
||||
|
||||
.text_26 {
|
||||
margin-left: initial;
|
||||
margin-right: initial;
|
||||
color: rgb(2, 2, 2);
|
||||
font-size: 0.15rem;
|
||||
line-height: 0.14rem;
|
||||
letter-spacing: 0.015rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.view_20 {
|
||||
left: -0.03rem;
|
||||
bottom: 0.075rem;
|
||||
}
|
||||
|
||||
.view_21 {
|
||||
margin-right: 0.06rem;
|
||||
margin-top: initial;
|
||||
padding: 0.09rem 0 0.06rem;
|
||||
color: rgb(73, 76, 87);
|
||||
background-color: initial;
|
||||
border: solid 0.01rem rgb(185, 185, 185);
|
||||
}
|
||||
}
|
||||
|
||||
.renzheng {
|
||||
padding-bottom: 0rem;
|
||||
|
||||
.section_4 {
|
||||
padding: 0.33rem 0 0.34rem;
|
||||
background-color: rgb(255, 255, 255);
|
||||
|
||||
.section_5 {
|
||||
margin-left: 0.18rem;
|
||||
margin-right: 0.24rem;
|
||||
padding: 0.2rem 0.18rem 0.18rem 0.24rem;
|
||||
background-color: rgb(246, 247, 250);
|
||||
justify-between: space-between;
|
||||
|
||||
.text_3 {
|
||||
color: rgb(160, 162, 172);
|
||||
font-size: 0.15rem;
|
||||
line-height: 0.15rem;
|
||||
letter-spacing: 0.015rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.text_4 {
|
||||
margin-left: 0.05rem;
|
||||
color: rgb(46, 155, 255);
|
||||
font-size: 0.15rem;
|
||||
line-height: 0.15rem;
|
||||
white-space: nowrap;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.group_3 {
|
||||
margin-top: 0.76rem;
|
||||
padding-left: 0.8rem;
|
||||
padding-right: 0.69rem;
|
||||
color: rgb(163, 182, 202);
|
||||
font-size: 0.15rem;
|
||||
line-height: 0.15rem;
|
||||
white-space: nowrap;
|
||||
|
||||
.text_5 {
|
||||
margin-left: 0.02rem;
|
||||
margin-top: 0.13rem;
|
||||
}
|
||||
|
||||
.image_1 {
|
||||
margin-right: 0.14rem;
|
||||
width: 2.12rem;
|
||||
height: 1.89rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
.page-title{
|
||||
padding: 50rpx ;
|
||||
color: #000;
|
||||
font-size: 36rpx;
|
||||
font-weight: 800;
|
||||
background: #ceedff; /* fallback for old browsers */
|
||||
background: -webkit-linear-gradient(to top,#f6f7fa, #ceedff); /* Chrome 10-25, Safari 5.1-6 */
|
||||
background: linear-gradient(to top,#f6f7fa, #ceedff); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
|
||||
|
||||
}
|
||||
|
||||
.slot-wrap {
|
||||
// height: 220rpx;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
padding: 0 60rpx;
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.tabs-item {
|
||||
width: 112rpx;
|
||||
height: 168rpx;
|
||||
// padding-top: 50rpx;
|
||||
// margin-bottom: 50rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
image {
|
||||
width: 104rpx;
|
||||
height: 104rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,175 @@
|
|||
<template>
|
||||
<view>
|
||||
<u-navbar back-text="" title="系统消息"></u-navbar>
|
||||
<scroll-view scroll-y="true" class="scroll">
|
||||
<view class="flex-col list" v-if='list.length'>
|
||||
<view class="list-item flex-col group_1" :key="i" v-for="(item, i) in list">
|
||||
<view class="items-title">
|
||||
<image src="/static/common/img/message/system.png" mode=""></image>
|
||||
<view class="title-time">
|
||||
<text class="title-text">系统消息</text>
|
||||
<text class="text_1">{{ item.messageDate }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="bottom-section flex-col">
|
||||
<text class="text_3">{{ item.title }}</text>
|
||||
<text class="text_5">{{ item.message.split(',未通过原因:')[0] }}</text>
|
||||
<text v-if="item.message.split(',未通过原因:').length >= 2" class="text_6">驳回理由:<text>{{
|
||||
item.message.split(',未通过原因:')[1] }}</text></text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-else style='padding-top:30vh'>
|
||||
<no-data text="暂无系统消息"></no-data>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import noData from '@/components/NoData.vue';
|
||||
export default {
|
||||
components: {
|
||||
noData
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
list: []
|
||||
};
|
||||
},
|
||||
onLoad() {
|
||||
this.getList()
|
||||
//接收系统消息
|
||||
this.$connection.on("SystemMessage", (title, content, time) => {
|
||||
if (this.route.indexOf('sysList') >= 0) {
|
||||
this.list.unshift({
|
||||
messageDate: time,
|
||||
title: title,
|
||||
message: content
|
||||
})
|
||||
}
|
||||
});
|
||||
},
|
||||
onShow() {
|
||||
if (this.vuex_msgList) {
|
||||
var msgList = this.vuex_msgList;
|
||||
msgList = msgList.replace('SystemMessage,', '')
|
||||
this.$u.vuex('vuex_msgList', msgList)
|
||||
if (!msgList) {
|
||||
var tab = this.vuex_tabbar;
|
||||
tab[1].isDot = false;
|
||||
this.$u.vuex('vuex_tabbar', tab);
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getList() {
|
||||
this.$u.api.getSysList().then(res => {
|
||||
this.list = res
|
||||
})
|
||||
},
|
||||
//返回上一级
|
||||
router() {
|
||||
uni.switchTab({
|
||||
url: '../../message/msgList/msgList'
|
||||
})
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.scroll {
|
||||
background-color: rgb(246, 247, 250);
|
||||
width: 100%;
|
||||
height: calc(100vh - 0.44rem);
|
||||
}
|
||||
|
||||
.list-item {
|
||||
margin-top: 0.1rem;
|
||||
padding: 20rpx;
|
||||
background-color: rgb(255, 255, 255);
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.items-title {
|
||||
display: flex;
|
||||
padding-bottom: 20rpx;
|
||||
margin-bottom: 20rpx;
|
||||
border-bottom: 2rpx solid #F6F8F9;
|
||||
|
||||
image {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.title-time {
|
||||
margin-left: 0.1rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
padding: 5rpx 0;
|
||||
// align-items: flex-start;
|
||||
}
|
||||
}
|
||||
|
||||
.title-text {
|
||||
font-weight: 600;
|
||||
font-size: 28rpx;
|
||||
color: rgba(0, 0, 0, 0.9);
|
||||
}
|
||||
|
||||
.text_1 {
|
||||
// align-self: center;
|
||||
color: rgb(193, 196, 204);
|
||||
font-size: 0.12rem;
|
||||
line-height: 0.095rem;
|
||||
// letter-spacing: 0.012rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.bottom-section {
|
||||
padding-left: 10rpx;
|
||||
}
|
||||
|
||||
.text_3 {
|
||||
color: rgb(2, 2, 2);
|
||||
font-size: 28rpx;
|
||||
line-height: 0.16rem;
|
||||
// letter-spacing: 0.018rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.text_5 {
|
||||
margin-left: 0.015rem;
|
||||
margin-top: 0.1rem;
|
||||
color: #908a8a;
|
||||
font-size: 28rpx;
|
||||
line-height: 1.5;
|
||||
// letter-spacing: 0.01rem;
|
||||
// text-indent: 0.3rem;
|
||||
}
|
||||
|
||||
.text_6 {
|
||||
margin-top: 0.1rem;
|
||||
font-size: 0.16rem;
|
||||
line-height: 0.16rem;
|
||||
letter-spacing: 0.01rem;
|
||||
|
||||
text {
|
||||
margin-left: 0.015rem;
|
||||
text-indent: 0.3rem;
|
||||
display: block;
|
||||
color: #908a8a;
|
||||
font-size: 0.14rem;
|
||||
margin-top: 0.1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.list {
|
||||
padding: 0.18rem 0.15rem;
|
||||
flex: 1 1 auto;
|
||||
overflow-y: auto;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,84 +1,89 @@
|
|||
<template>
|
||||
<view class="page-container">
|
||||
<view class="page-header">
|
||||
<PageHeader
|
||||
title="我的"
|
||||
:is-back="false"
|
||||
:border-bottom="false"
|
||||
:background="headerBackground"
|
||||
/>
|
||||
</view>
|
||||
<div class="my-page">
|
||||
<PageHeader
|
||||
title="我的"
|
||||
:is-back="false"
|
||||
:border-bottom="false"
|
||||
:background="headerBackground"
|
||||
/>
|
||||
|
||||
<scroll-view
|
||||
class="page-main"
|
||||
scroll-y
|
||||
enable-back-to-top
|
||||
>
|
||||
<view class="main-content">
|
||||
<div class="user-info">
|
||||
<div class="avatar">
|
||||
<image :src="teacherInfo.avatar" class="avatar-img"></image>
|
||||
<div class="content-wrapper">
|
||||
<div class="user-info">
|
||||
<div class="avatar">
|
||||
<!-- <img src="" alt="用户头像" /> -->
|
||||
</div>
|
||||
<div class="info">
|
||||
<div class="name">{{ teacherInfo.name }}</div>
|
||||
<div class="tag">
|
||||
<image
|
||||
class="tag-icon"
|
||||
src="@/static/notes/collage-icon.png"
|
||||
></image>
|
||||
{{ teacherInfo.collegeName }}
|
||||
</div>
|
||||
<div class="info">
|
||||
<div class="name">{{ teacherInfo.name }}</div>
|
||||
<div class="tag">
|
||||
<image
|
||||
class="tag-icon"
|
||||
src="@/static/notes/collage-icon.png"
|
||||
></image>
|
||||
{{ teacherInfo.collegeName }}
|
||||
</div>
|
||||
<div class="tag">
|
||||
<image class="tag-icon" src="@/static/notes/major-icon.png"></image>
|
||||
{{ teacherInfo.professionalName }}
|
||||
</div>
|
||||
<div class="tag">
|
||||
<image class="tag-icon" src="@/static/notes/major-icon.png"></image>
|
||||
{{ teacherInfo.professionalName }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="banner">
|
||||
<img src="@/static/notes/banner.png" alt="banner" />
|
||||
<div class="statistics">
|
||||
<div class="stat-item">
|
||||
<div class="stat-num">36</div>
|
||||
<div class="stat-label">总答题</div>
|
||||
</div>
|
||||
|
||||
<div class="menu-list">
|
||||
<div class="menu-item" @click="navigateTo('personal-info')">
|
||||
<div class="menu-icon">
|
||||
<image src="@/static/notes/menu1.png" class="menu-icon-img"></image>
|
||||
</div>
|
||||
<div class="menu-text">个人信息</div>
|
||||
<view class="arrow-icon">
|
||||
<u-icon name="arrow-right" color="#999" size="24"></u-icon>
|
||||
</view>
|
||||
</div>
|
||||
<div class="menu-item" @click="navigateTo('change-password')">
|
||||
<div class="menu-icon">
|
||||
<image src="@/static/notes/menu2.png" class="menu-icon-img"></image>
|
||||
</div>
|
||||
<div class="menu-text">修改密码</div>
|
||||
<view class="arrow-icon">
|
||||
<u-icon name="arrow-right" color="#999" size="24"></u-icon>
|
||||
</view>
|
||||
</div>
|
||||
<div class="menu-item" @click="navigateTo('logout-records')">
|
||||
<div class="menu-icon">
|
||||
<image src="@/static/notes/menu3.png" class="menu-icon-img"></image>
|
||||
</div>
|
||||
<div class="menu-text">退出登录</div>
|
||||
<view class="arrow-icon">
|
||||
<u-icon name="arrow-right" color="#999" size="24"></u-icon>
|
||||
</view>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<div class="stat-num">10</div>
|
||||
<div class="stat-label">已完成</div>
|
||||
</div>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<div class="stat-item">
|
||||
<div class="stat-num">26</div>
|
||||
<div class="stat-label">未回复</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<view class="page-tabbar">
|
||||
<TabBar :currentPath="'/pages/my/index'" @change="handleTabChange" />
|
||||
</view>
|
||||
</view>
|
||||
<div class="banner">
|
||||
<img src="@/static/notes/banner.png" alt="banner" />
|
||||
</div>
|
||||
|
||||
<div class="menu-list">
|
||||
<div class="menu-item" @click="navigateTo('personal-info')">
|
||||
<div class="menu-icon">
|
||||
<image src="@/static/notes/menu1.png" class="menu-icon-img"></image>
|
||||
</div>
|
||||
<div class="menu-text">个人信息</div>
|
||||
<view class="arrow-icon">
|
||||
<u-icon name="arrow-right" color="#999" size="24"></u-icon>
|
||||
</view>
|
||||
</div>
|
||||
<div class="menu-item" @click="navigateTo('change-password')">
|
||||
<div class="menu-icon">
|
||||
<image src="@/static/notes/menu2.png" class="menu-icon-img"></image>
|
||||
</div>
|
||||
<div class="menu-text">修改密码</div>
|
||||
<view class="arrow-icon">
|
||||
<u-icon name="arrow-right" color="#999" size="24"></u-icon>
|
||||
</view>
|
||||
</div>
|
||||
<div class="menu-item" @click="navigateTo('logout-records')">
|
||||
<div class="menu-icon">
|
||||
<image src="@/static/notes/menu3.png" class="menu-icon-img"></image>
|
||||
</div>
|
||||
<div class="menu-text">退出登录</div>
|
||||
<view class="arrow-icon">
|
||||
<u-icon name="arrow-right" color="#999" size="24"></u-icon>
|
||||
</view>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<TabBar :currentPath="'/pages/my/index'" @change="handleTabChange" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import TabBar from "@/components/TabBar-optimized.vue";
|
||||
import TabBar from "@/components/TabBar.vue";
|
||||
import PageHeader from "@/components/PageHeader.vue";
|
||||
|
||||
export default {
|
||||
|
|
@ -92,12 +97,7 @@ export default {
|
|||
headerBackground: {
|
||||
background: "transparent",
|
||||
},
|
||||
teacherInfo: {
|
||||
name:'孙老师',
|
||||
collegeName:'生命科学与工程学院·生物工程专业',
|
||||
professionalName:'生物工程专业',
|
||||
avatar:'/static/common/images/avatar_default.jpg',
|
||||
},
|
||||
teacherInfo: {},
|
||||
};
|
||||
},
|
||||
onLoad() {
|
||||
|
|
@ -149,69 +149,24 @@ export default {
|
|||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* ===== 页面容器 - 主流三段式布局 ===== */
|
||||
.page-container {
|
||||
/* 固定定位,占满整个视口 */
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
|
||||
/* Flex 布局 */
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
/* 背景图片(保留特色) */
|
||||
.my-page {
|
||||
height: 100vh;
|
||||
/* background-color: #f5f6fa; */
|
||||
background-image: url("@/static/notes/bg.png");
|
||||
background-position: center top;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% auto;
|
||||
|
||||
/* 防止溢出 */
|
||||
overflow: hidden;
|
||||
background-size: 100% auto; /* 以宽度为基准等比例缩放 */
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* ===== 头部导航 ===== */
|
||||
.page-header {
|
||||
/* 不收缩,固定高度 */
|
||||
flex-shrink: 0;
|
||||
|
||||
/* 层级 */
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
/* ===== 内容区域 ===== */
|
||||
.page-main {
|
||||
/* 占据剩余空间 */
|
||||
.content-wrapper {
|
||||
flex: 1;
|
||||
|
||||
/* 重要:防止 flex 子元素溢出 */
|
||||
height: 0;
|
||||
|
||||
/* 允许滚动 */
|
||||
overflow-y: auto;
|
||||
|
||||
/* iOS 滚动优化 */
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
/* ===== 内容内层 ===== */
|
||||
.main-content {
|
||||
/* 底部留出 TabBar 空间 + 安全区域 */
|
||||
padding-bottom: calc(50px + env(safe-area-inset-bottom));
|
||||
|
||||
/* 最小高度(确保可以滚动) */
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
/* ===== 底部导航 ===== */
|
||||
.page-tabbar {
|
||||
/* 不收缩,固定高度 */
|
||||
flex-shrink: 0;
|
||||
|
||||
/* 层级 */
|
||||
z-index: 100;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding-bottom: 60px; /* 为底部导航栏预留空间 */
|
||||
overflow: hidden; /* 防止滚动条出现 */
|
||||
}
|
||||
|
||||
.user-info {
|
||||
|
|
@ -255,6 +210,13 @@ export default {
|
|||
align-items: center;
|
||||
}
|
||||
|
||||
.statistics {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
/* margin-top: 5px;
|
||||
padding: 15px 0; */
|
||||
}
|
||||
|
||||
.stat-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,466 @@
|
|||
<template>
|
||||
<view class="notes-page">
|
||||
<PageHeader title="留言板" :is-back="false" :border-bottom="false" />
|
||||
<view class="custom-tabs-box">
|
||||
<u-tabs
|
||||
:list="tabList"
|
||||
:current="tabCurrent"
|
||||
@change="onTabChange"
|
||||
:is-scroll="false"
|
||||
:height="80"
|
||||
:font-size="28"
|
||||
active-color="#4A6CF7"
|
||||
inactive-color="#333333"
|
||||
:bar-width="120"
|
||||
:bar-height="4"
|
||||
bg-color="#ffffff"
|
||||
:item-width="200"
|
||||
></u-tabs>
|
||||
<view class="space"></view>
|
||||
</view>
|
||||
|
||||
<!-- 内容区域包装器 -->
|
||||
<view class="content-wrapper">
|
||||
<!-- 留言列表 -->
|
||||
<scroll-view class="message-list" scroll-y>
|
||||
<view v-for="(item, index) in currentMessages" :key="index">
|
||||
<u-swipe-action
|
||||
:options="swipeOptions"
|
||||
:show="item.show"
|
||||
:index="index"
|
||||
@click="handleSwipeClick"
|
||||
@open="(e) => handleSwipeOpen(e, index)"
|
||||
@close="(e) => handleSwipeClose(e, index)"
|
||||
@content-click="() => closeOther(index)"
|
||||
:btn-width="80"
|
||||
:disabled="false"
|
||||
>
|
||||
<view class="message-item">
|
||||
<view class="message-header">
|
||||
<view class="user-info">
|
||||
<image
|
||||
class="avatar"
|
||||
:src="item.avatar || defaultAvatar"
|
||||
></image>
|
||||
<text class="username">{{ item.username }}</text>
|
||||
</view>
|
||||
<view class="message-time">{{ item.time }}</view>
|
||||
</view>
|
||||
|
||||
<view class="message-content">
|
||||
<view class="question">
|
||||
<view class="question-icon">问</view>
|
||||
<view class="question-text">{{ item.question }}</view>
|
||||
</view>
|
||||
|
||||
<view
|
||||
class="reply-button"
|
||||
@click.stop="handleReply(item)"
|
||||
v-if="!item.reply"
|
||||
>
|
||||
<u-icon name="chat" color="#4a6cf7" size="16"></u-icon>
|
||||
<text>回复</text>
|
||||
</view>
|
||||
|
||||
<view class="reply-content" v-if="item.reply">
|
||||
<view class="reply-header">
|
||||
<view class="reply-icon">答</view>
|
||||
<view class="reply-info">
|
||||
<text>{{ item.replyUser }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
class="reply-text"
|
||||
:class="{ expanded: item.expanded }"
|
||||
>{{ item.reply }}</view
|
||||
>
|
||||
<view
|
||||
class="expand-button"
|
||||
v-if="item.reply.length > 100"
|
||||
@click.stop="toggleExpand(item)"
|
||||
>
|
||||
{{ item.expanded ? "收起" : "展开" }}
|
||||
<u-icon
|
||||
:name="item.expanded ? 'arrow-up' : 'arrow-down'"
|
||||
size="12"
|
||||
></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view
|
||||
class="reply-button"
|
||||
@click.stop="handleReply(item)"
|
||||
v-if="item.reply"
|
||||
>
|
||||
<u-icon name="chat" color="#4a6cf7" size="16"></u-icon>
|
||||
<text>回复</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</u-swipe-action>
|
||||
</view>
|
||||
|
||||
<!-- 无数据提示 -->
|
||||
<view class="empty-tip" v-if="currentMessages.length === 0">
|
||||
暂无留言数据
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
||||
<!-- 使用TabBar组件 -->
|
||||
<TabBar :currentPath="'/pages/notes/index'" @change="handleTabChange" />
|
||||
|
||||
<!-- 开发中提示弹窗 -->
|
||||
<u-modal
|
||||
v-model="showDevModal"
|
||||
:show-cancel-button="false"
|
||||
title="提示"
|
||||
content="该功能正在开发中,敬请期待!"
|
||||
@confirm="showDevModal = false"
|
||||
></u-modal>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import TabBar from "@/components/TabBar.vue";
|
||||
import PageHeader from "@/components/PageHeader.vue";
|
||||
|
||||
export default {
|
||||
name: "NotesPage",
|
||||
components: {
|
||||
TabBar,
|
||||
PageHeader,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
tabList: [{ name: "未回复" }, { name: "已回复" }],
|
||||
tabCurrent: 0,
|
||||
activeTab: "unread",
|
||||
showDevModal: false,
|
||||
defaultAvatar: "/static/avatar/default-avatar.png",
|
||||
unreadMessages: [
|
||||
{
|
||||
id: 1,
|
||||
avatar: "",
|
||||
username: "浙江理工生13024",
|
||||
time: "2023/6/26 15:45:12",
|
||||
question: "学校在录取时有没有一些专业会有特殊要求?",
|
||||
reply: "",
|
||||
expanded: false,
|
||||
show: false,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
avatar: "",
|
||||
username: "理工13024",
|
||||
time: "2023/6/26 15:45:12",
|
||||
question: "在录取时有没有一些专业会有特殊要求?",
|
||||
reply: "",
|
||||
expanded: false,
|
||||
show: false,
|
||||
},
|
||||
],
|
||||
repliedMessages: [
|
||||
{
|
||||
id: 3,
|
||||
avatar: "",
|
||||
username: "浙江理工生13024",
|
||||
time: "2023/6/26 15:45:12",
|
||||
question: "学校在录取时有没有一些专业会有特殊要求?",
|
||||
reply:
|
||||
"学生与体健康状况必须符合教育部、卫生部、中国残疾人联合会印发的《普通高等学校招生体检工作指导意见》和人力资源社会保障部、原卫生部、原教育部、原公安部、原国家人口计划生育委员会制定的有关规定。原卫生部、原教育部、原公安部、原国家人口计划生育委员会制定的有关规定。",
|
||||
replyUser: "系统回复",
|
||||
expanded: false,
|
||||
show: false,
|
||||
},
|
||||
],
|
||||
swipeOptions: [
|
||||
{
|
||||
text: "删除",
|
||||
style: {
|
||||
backgroundColor: "#fa3534",
|
||||
color: "#ffffff",
|
||||
fontSize: "15px",
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
currentMessages() {
|
||||
return this.activeTab === "unread"
|
||||
? this.unreadMessages
|
||||
: this.repliedMessages;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onTabChange(index) {
|
||||
this.tabCurrent = index;
|
||||
// 根据索引设置activeTab值
|
||||
this.activeTab = index === 0 ? "unread" : "replied";
|
||||
// 切换选项卡时关闭所有打开的滑动按钮
|
||||
this.closeAllSwipe();
|
||||
},
|
||||
switchTab(tab) {
|
||||
this.activeTab = tab;
|
||||
// 更新tabCurrent以匹配activeTab
|
||||
this.tabCurrent = tab === "unread" ? 0 : 1;
|
||||
// 切换选项卡时关闭所有打开的滑动按钮
|
||||
this.closeAllSwipe();
|
||||
},
|
||||
handleTabChange(path, index) {
|
||||
console.log("切换到标签页:", path, index);
|
||||
},
|
||||
handleReply(item) {
|
||||
this.showDevModal = true;
|
||||
},
|
||||
toggleExpand(item) {
|
||||
item.expanded = !item.expanded;
|
||||
},
|
||||
handleSwipeClick(e) {
|
||||
const { index } = e; // 当前点击的滑动单元格索引
|
||||
const btnIndex = e.index; // 点击的按钮索引
|
||||
|
||||
if (btnIndex === 0) {
|
||||
// 删除按钮
|
||||
// 删除当前消息
|
||||
if (this.activeTab === "unread") {
|
||||
this.unreadMessages.splice(index, 1);
|
||||
} else {
|
||||
this.repliedMessages.splice(index, 1);
|
||||
}
|
||||
}
|
||||
},
|
||||
handleSwipeOpen(e, index) {
|
||||
// 打开滑动按钮时,关闭其他打开的滑动按钮
|
||||
this.closeOther(index);
|
||||
},
|
||||
handleSwipeClose(e, index) {
|
||||
// 处理滑动关闭事件
|
||||
if (this.activeTab === "unread") {
|
||||
this.unreadMessages[index].show = false;
|
||||
} else {
|
||||
this.repliedMessages[index].show = false;
|
||||
}
|
||||
},
|
||||
closeOther(index) {
|
||||
// 关闭除当前外的所有滑动按钮
|
||||
if (this.activeTab === "unread") {
|
||||
this.unreadMessages.forEach((item, idx) => {
|
||||
if (idx !== index) {
|
||||
item.show = false;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.repliedMessages.forEach((item, idx) => {
|
||||
if (idx !== index) {
|
||||
item.show = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
closeAllSwipe() {
|
||||
// 关闭所有滑动按钮
|
||||
this.unreadMessages.forEach((item) => {
|
||||
item.show = false;
|
||||
});
|
||||
this.repliedMessages.forEach((item) => {
|
||||
item.show = false;
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.notes-page {
|
||||
height: 100vh;
|
||||
background-color: #f5f6fa;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
|
||||
.custom-tabs-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.space {
|
||||
flex: 1;
|
||||
background: #fff;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.custom-tabs-box >>> .u-tabs__wrapper__nav__item {
|
||||
padding: 0 20px 0 0 !important; /* 调整标签项的padding */
|
||||
}
|
||||
|
||||
.custom-tabs-box >>> .u-tabs__wrapper__nav__line {
|
||||
bottom: 0 !important; /* 确保下划线位于底部 */
|
||||
height: 4px !important; /* 设置下划线高度 */
|
||||
border-radius: 2px !important; /* 圆角 */
|
||||
}
|
||||
|
||||
.content-wrapper {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding-bottom: 60px; /* 为底部导航栏预留空间 */
|
||||
overflow-y: auto; /* 允许内容滚动 */
|
||||
}
|
||||
|
||||
/* 留言列表样式 */
|
||||
.message-list {
|
||||
flex: 1;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.message-item {
|
||||
background-color: #fff;
|
||||
padding: 15px;
|
||||
margin-bottom: 10px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.message-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 50%;
|
||||
margin-right: 8px;
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
.username {
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.message-time {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.message-content {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.question {
|
||||
display: flex;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.question-icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 50%;
|
||||
background-color: #4a6cf7;
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-right: 8px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.question-text {
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.reply-button {
|
||||
height: 32px;
|
||||
background-color: #f0f2fd;
|
||||
color: #4a6cf7;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
margin-top: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.reply-button text {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.reply-content {
|
||||
background-color: #f8f8f8;
|
||||
border-radius: 4px;
|
||||
padding: 10px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.reply-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.reply-icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 50%;
|
||||
background-color: #ff9500;
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.reply-info {
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.reply-text {
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
color: #333;
|
||||
margin-left: 28px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 3;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
|
||||
.reply-text.expanded {
|
||||
-webkit-line-clamp: unset;
|
||||
}
|
||||
|
||||
.expand-button {
|
||||
text-align: right;
|
||||
font-size: 12px;
|
||||
color: #4a6cf7;
|
||||
margin-top: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.empty-tip {
|
||||
text-align: center;
|
||||
padding: 20px;
|
||||
color: #999;
|
||||
font-size: 14px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,533 +0,0 @@
|
|||
<template>
|
||||
<view class="test-page">
|
||||
<view class="test-header">
|
||||
<text class="title">WebSocket 测试工具</text>
|
||||
<text class="subtitle">实时测试 WebSocket 连接和消息</text>
|
||||
</view>
|
||||
|
||||
<!-- 连接状态 -->
|
||||
<view class="status-card">
|
||||
<view class="status-item">
|
||||
<text class="label">连接状态:</text>
|
||||
<text :class="['value', connectionStatus.class]">{{ connectionStatus.text }}</text>
|
||||
</view>
|
||||
<view class="status-item">
|
||||
<text class="label">队列消息:</text>
|
||||
<text class="value">{{ queueLength }} 条</text>
|
||||
</view>
|
||||
<view class="status-item">
|
||||
<text class="label">重连次数:</text>
|
||||
<text class="value">{{ reconnectAttempts }} 次</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 连接控制 -->
|
||||
<view class="control-card">
|
||||
<view class="control-title">连接控制</view>
|
||||
<input
|
||||
class="url-input"
|
||||
v-model="wsUrl"
|
||||
placeholder="输入 WebSocket 地址"
|
||||
/>
|
||||
<view class="button-group">
|
||||
<button class="btn btn-primary" @click="handleConnect" :disabled="isConnected">
|
||||
连接
|
||||
</button>
|
||||
<button class="btn btn-danger" @click="handleDisconnect" :disabled="!isConnected">
|
||||
断开
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 消息发送 -->
|
||||
<view class="message-card">
|
||||
<view class="control-title">发送消息</view>
|
||||
<textarea
|
||||
class="message-input"
|
||||
v-model="messageToSend"
|
||||
placeholder="输入消息内容(JSON 格式)"
|
||||
:rows="5"
|
||||
></textarea>
|
||||
<view class="button-group">
|
||||
<button class="btn btn-success" @click="handleSendMessage" :disabled="!isConnected">
|
||||
发送消息
|
||||
</button>
|
||||
<button class="btn btn-secondary" @click="handleSendPing" :disabled="!isConnected">
|
||||
发送心跳
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 快速测试 -->
|
||||
<view class="quick-test-card">
|
||||
<view class="control-title">快速测试</view>
|
||||
<view class="button-group">
|
||||
<button class="btn btn-info" @click="testEcho">
|
||||
Echo 服务测试
|
||||
</button>
|
||||
<button class="btn btn-info" @click="testLocalServer">
|
||||
本地服务器测试
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 日志显示 -->
|
||||
<view class="log-card">
|
||||
<view class="log-header">
|
||||
<text class="control-title">日志 ({{ logs.length }})</text>
|
||||
<button class="btn-clear" @click="clearLogs">清空</button>
|
||||
</view>
|
||||
<scroll-view class="log-content" scroll-y>
|
||||
<view
|
||||
v-for="(log, index) in logs"
|
||||
:key="index"
|
||||
:class="['log-item', `log-${log.type}`]"
|
||||
>
|
||||
<text class="log-time">{{ log.time }}</text>
|
||||
<text class="log-type">{{ log.typeText }}</text>
|
||||
<text class="log-message">{{ log.message }}</text>
|
||||
</view>
|
||||
<view v-if="logs.length === 0" class="empty-log">
|
||||
暂无日志
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import wsManager from '@/utils/websocket-manager.js'
|
||||
|
||||
export default {
|
||||
name: 'WebSocketTest',
|
||||
data() {
|
||||
return {
|
||||
// WebSocket URL
|
||||
wsUrl: 'wss://echo.websocket.org',
|
||||
|
||||
// 连接状态
|
||||
isConnected: false,
|
||||
reconnectAttempts: 0,
|
||||
queueLength: 0,
|
||||
|
||||
// 消息
|
||||
messageToSend: JSON.stringify({
|
||||
type: 'test',
|
||||
content: 'Hello WebSocket!',
|
||||
timestamp: Date.now()
|
||||
}, null, 2),
|
||||
|
||||
// 日志
|
||||
logs: [],
|
||||
|
||||
// 计时器
|
||||
startTime: 0
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
connectionStatus() {
|
||||
if (this.isConnected) {
|
||||
return { text: '已连接', class: 'status-connected' }
|
||||
} else if (this.reconnectAttempts > 0) {
|
||||
return { text: '重连中...', class: 'status-reconnecting' }
|
||||
} else {
|
||||
return { text: '未连接', class: 'status-disconnected' }
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
this.setupEventListeners()
|
||||
this.addLog('info', '测试工具已加载')
|
||||
},
|
||||
|
||||
onUnload() {
|
||||
// 清理事件监听
|
||||
wsManager.off('open', this.handleOpen)
|
||||
wsManager.off('close', this.handleClose)
|
||||
wsManager.off('error', this.handleError)
|
||||
wsManager.off('message', this.handleMessage)
|
||||
wsManager.off('reconnect', this.handleReconnect)
|
||||
},
|
||||
|
||||
methods: {
|
||||
// 设置事件监听
|
||||
setupEventListeners() {
|
||||
this.handleOpen = () => {
|
||||
this.isConnected = true
|
||||
this.reconnectAttempts = 0
|
||||
const duration = Date.now() - this.startTime
|
||||
this.addLog('success', `连接成功 (耗时 ${duration}ms)`)
|
||||
}
|
||||
|
||||
this.handleClose = (res) => {
|
||||
this.isConnected = false
|
||||
this.addLog('warning', `连接关闭 (code: ${res.code})`)
|
||||
}
|
||||
|
||||
this.handleError = (err) => {
|
||||
this.addLog('error', `连接错误: ${JSON.stringify(err)}`)
|
||||
}
|
||||
|
||||
this.handleMessage = (data) => {
|
||||
this.addLog('message', `收到消息: ${JSON.stringify(data, null, 2)}`)
|
||||
}
|
||||
|
||||
this.handleReconnect = (attempts) => {
|
||||
this.reconnectAttempts = attempts
|
||||
this.addLog('info', `正在重连 (第 ${attempts} 次)`)
|
||||
}
|
||||
|
||||
wsManager.on('open', this.handleOpen)
|
||||
wsManager.on('close', this.handleClose)
|
||||
wsManager.on('error', this.handleError)
|
||||
wsManager.on('message', this.handleMessage)
|
||||
wsManager.on('reconnect', this.handleReconnect)
|
||||
},
|
||||
|
||||
// 连接
|
||||
handleConnect() {
|
||||
if (!this.wsUrl) {
|
||||
uni.showToast({ title: '请输入 WebSocket 地址', icon: 'none' })
|
||||
return
|
||||
}
|
||||
|
||||
this.addLog('info', `开始连接: ${this.wsUrl}`)
|
||||
this.startTime = Date.now()
|
||||
|
||||
wsManager.connect(this.wsUrl, {
|
||||
reconnectInterval: 3000,
|
||||
maxReconnectAttempts: 5,
|
||||
heartbeatInterval: 30000
|
||||
})
|
||||
|
||||
this.updateState()
|
||||
},
|
||||
|
||||
// 断开连接
|
||||
handleDisconnect() {
|
||||
this.addLog('info', '手动断开连接')
|
||||
wsManager.close(true)
|
||||
this.isConnected = false
|
||||
this.reconnectAttempts = 0
|
||||
},
|
||||
|
||||
// 发送消息
|
||||
handleSendMessage() {
|
||||
try {
|
||||
const message = JSON.parse(this.messageToSend)
|
||||
this.addLog('send', `发送消息: ${JSON.stringify(message)}`)
|
||||
wsManager.send(message)
|
||||
} catch (e) {
|
||||
this.addLog('error', `消息格式错误: ${e.message}`)
|
||||
uni.showToast({ title: 'JSON 格式错误', icon: 'none' })
|
||||
}
|
||||
},
|
||||
|
||||
// 发送心跳
|
||||
handleSendPing() {
|
||||
const ping = {
|
||||
type: 'ping',
|
||||
timestamp: Date.now()
|
||||
}
|
||||
this.addLog('send', `发送心跳: ${JSON.stringify(ping)}`)
|
||||
wsManager.send(ping)
|
||||
},
|
||||
|
||||
// Echo 服务测试
|
||||
testEcho() {
|
||||
this.wsUrl = 'wss://echo.websocket.org'
|
||||
this.messageToSend = JSON.stringify({
|
||||
type: 'test',
|
||||
content: 'Echo 测试消息',
|
||||
timestamp: Date.now()
|
||||
}, null, 2)
|
||||
|
||||
this.addLog('info', '开始 Echo 服务测试')
|
||||
uni.showToast({ title: '点击"连接"开始测试', icon: 'none' })
|
||||
},
|
||||
|
||||
// 本地服务器测试
|
||||
testLocalServer() {
|
||||
this.wsUrl = 'ws://localhost:8082/ws/chat?token=test-token'
|
||||
this.messageToSend = JSON.stringify({
|
||||
type: 'message',
|
||||
fromUserId: 'test_user',
|
||||
toUserId: 'admin',
|
||||
content: '本地服务器测试',
|
||||
timestamp: Date.now()
|
||||
}, null, 2)
|
||||
|
||||
this.addLog('info', '开始本地服务器测试')
|
||||
uni.showToast({ title: '点击"连接"开始测试', icon: 'none' })
|
||||
},
|
||||
|
||||
// 更新状态
|
||||
updateState() {
|
||||
const state = wsManager.getState()
|
||||
this.isConnected = state.isConnected
|
||||
this.reconnectAttempts = state.reconnectAttempts
|
||||
this.queueLength = state.queueLength
|
||||
},
|
||||
|
||||
// 添加日志
|
||||
addLog(type, message) {
|
||||
const typeMap = {
|
||||
info: 'ℹ️ 信息',
|
||||
success: '✅ 成功',
|
||||
warning: '⚠️ 警告',
|
||||
error: '❌ 错误',
|
||||
send: '📤 发送',
|
||||
message: '📩 接收'
|
||||
}
|
||||
|
||||
const now = new Date()
|
||||
const time = `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}:${now.getSeconds().toString().padStart(2, '0')}`
|
||||
|
||||
this.logs.unshift({
|
||||
type,
|
||||
typeText: typeMap[type] || type,
|
||||
message,
|
||||
time
|
||||
})
|
||||
|
||||
// 最多保留 100 条日志
|
||||
if (this.logs.length > 100) {
|
||||
this.logs.pop()
|
||||
}
|
||||
},
|
||||
|
||||
// 清空日志
|
||||
clearLogs() {
|
||||
this.logs = []
|
||||
this.addLog('info', '日志已清空')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.test-page {
|
||||
padding: 20rpx;
|
||||
background-color: #f5f6fa;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.test-header {
|
||||
text-align: center;
|
||||
padding: 40rpx 0;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
margin-top: 10rpx;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.status-card,
|
||||
.control-card,
|
||||
.message-card,
|
||||
.quick-test-card,
|
||||
.log-card {
|
||||
background: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.status-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 20rpx 0;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.status-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.label {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.value {
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.status-connected {
|
||||
color: #52c41a;
|
||||
}
|
||||
|
||||
.status-reconnecting {
|
||||
color: #faad14;
|
||||
}
|
||||
|
||||
.status-disconnected {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.control-title {
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.url-input,
|
||||
.message-input {
|
||||
width: 100%;
|
||||
padding: 20rpx;
|
||||
border: 1rpx solid #d9d9d9;
|
||||
border-radius: 8rpx;
|
||||
font-size: 26rpx;
|
||||
margin-bottom: 20rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.message-input {
|
||||
min-height: 200rpx;
|
||||
font-family: 'Courier New', monospace;
|
||||
}
|
||||
|
||||
.button-group {
|
||||
display: flex;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.btn {
|
||||
flex: 1;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
text-align: center;
|
||||
border-radius: 8rpx;
|
||||
font-size: 28rpx;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: #1890ff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.btn-danger {
|
||||
background: #ff4d4f;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.btn-success {
|
||||
background: #52c41a;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background: #d9d9d9;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.btn-info {
|
||||
background: #722ed1;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.btn:disabled {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.log-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.btn-clear {
|
||||
padding: 10rpx 20rpx;
|
||||
background: #f0f0f0;
|
||||
border: none;
|
||||
border-radius: 8rpx;
|
||||
font-size: 24rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.log-content {
|
||||
height: 600rpx;
|
||||
border: 1rpx solid #f0f0f0;
|
||||
border-radius: 8rpx;
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
.log-item {
|
||||
padding: 20rpx;
|
||||
margin-bottom: 10rpx;
|
||||
border-radius: 8rpx;
|
||||
font-size: 24rpx;
|
||||
line-height: 1.6;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.log-info {
|
||||
background: #e6f7ff;
|
||||
border-left: 4rpx solid #1890ff;
|
||||
}
|
||||
|
||||
.log-success {
|
||||
background: #f6ffed;
|
||||
border-left: 4rpx solid #52c41a;
|
||||
}
|
||||
|
||||
.log-warning {
|
||||
background: #fffbe6;
|
||||
border-left: 4rpx solid #faad14;
|
||||
}
|
||||
|
||||
.log-error {
|
||||
background: #fff2f0;
|
||||
border-left: 4rpx solid #ff4d4f;
|
||||
}
|
||||
|
||||
.log-send {
|
||||
background: #f9f0ff;
|
||||
border-left: 4rpx solid #722ed1;
|
||||
}
|
||||
|
||||
.log-message {
|
||||
background: #fff0f6;
|
||||
border-left: 4rpx solid #eb2f96;
|
||||
}
|
||||
|
||||
.log-time {
|
||||
color: #999;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.log-type {
|
||||
font-weight: 500;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.log-message {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.empty-log {
|
||||
text-align: center;
|
||||
padding: 100rpx 0;
|
||||
color: #999;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
|
@ -1,310 +0,0 @@
|
|||
<template>
|
||||
<view class="page-container">
|
||||
<view class="page-header">
|
||||
<PageHeader title="人工转接" :is-back="false" :border-bottom="false" />
|
||||
</view>
|
||||
|
||||
<scroll-view
|
||||
class="page-main"
|
||||
scroll-y
|
||||
enable-back-to-top
|
||||
>
|
||||
<view class="main-content">
|
||||
<!-- 服务状态卡片 -->
|
||||
<view class="status-card">
|
||||
<view class="status-title">人工服务</view>
|
||||
<view class="status-content">
|
||||
<view class="status-badge" :class="isOnline ? 'online' : 'offline'">
|
||||
{{ isOnline ? '在线' : '离线' }}
|
||||
</view>
|
||||
<view class="status-desc">
|
||||
{{ isOnline ? '客服正在为您服务' : '当前暂无客服在线' }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 人工客服列表 -->
|
||||
<view class="section-title">在线客服</view>
|
||||
<view class="agent-list">
|
||||
<view class="agent-item" v-for="(agent, index) in agentList" :key="index" @click="handleTransfer(agent)">
|
||||
<view class="agent-avatar-wrapper">
|
||||
<image class="agent-avatar" :src="agent.avatar || defaultAvatar"></image>
|
||||
<view class="online-dot" v-if="agent.online"></view>
|
||||
</view>
|
||||
<view class="agent-info">
|
||||
<view class="agent-name">{{ agent.name }}</view>
|
||||
<view class="agent-status">{{ agent.statusText }}</view>
|
||||
</view>
|
||||
<view class="agent-action">
|
||||
<u-button
|
||||
size="mini"
|
||||
type="primary"
|
||||
:disabled="!agent.online"
|
||||
@click.stop="handleTransfer(agent)"
|
||||
>
|
||||
{{ agent.online ? '转接' : '离线' }}
|
||||
</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 无数据提示 -->
|
||||
<view class="empty-tip" v-if="agentList.length === 0">
|
||||
暂无客服在线
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<view class="page-tabbar">
|
||||
<TabBar :currentPath="'/pages/manual-transfer/index'" @change="handleTabChange" />
|
||||
</view>
|
||||
|
||||
<u-modal
|
||||
v-model="showModal"
|
||||
:show-cancel-button="true"
|
||||
title="人工转接"
|
||||
:content="modalContent"
|
||||
@confirm="confirmTransfer"
|
||||
@cancel="showModal = false"
|
||||
></u-modal>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import TabBar from "@/components/TabBar-optimized.vue";
|
||||
import PageHeader from "@/components/PageHeader.vue";
|
||||
|
||||
export default {
|
||||
name: "TransferPage",
|
||||
components: {
|
||||
TabBar,
|
||||
PageHeader,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showModal: false,
|
||||
modalContent: '',
|
||||
selectedAgent: null,
|
||||
defaultAvatar: "/static/avatar/default-avatar.png",
|
||||
isOnline: true,
|
||||
agentList: [
|
||||
{
|
||||
id: 1,
|
||||
name: "客服小王",
|
||||
avatar: "",
|
||||
online: true,
|
||||
statusText: "空闲中",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "客服小李",
|
||||
avatar: "",
|
||||
online: true,
|
||||
statusText: "忙碌中",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: "客服小张",
|
||||
avatar: "",
|
||||
online: false,
|
||||
statusText: "离线",
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
handleTabChange(path, index) {
|
||||
console.log("切换到标签页:", path, index);
|
||||
},
|
||||
handleTransfer(agent) {
|
||||
if (!agent.online) {
|
||||
uni.showToast({
|
||||
title: '该客服当前离线',
|
||||
icon: 'none'
|
||||
});
|
||||
return;
|
||||
}
|
||||
this.selectedAgent = agent;
|
||||
this.modalContent = `确认转接到${agent.name}吗?`;
|
||||
this.showModal = true;
|
||||
},
|
||||
confirmTransfer() {
|
||||
// 这里可以执行实际的转接逻辑
|
||||
uni.showToast({
|
||||
title: '正在为您转接...',
|
||||
icon: 'none'
|
||||
});
|
||||
this.showModal = false;
|
||||
|
||||
// 模拟跳转到聊天页面
|
||||
setTimeout(() => {
|
||||
// uni.navigateTo({
|
||||
// url: '/pages/message/dialogBox/dialogBox?agentId=' + this.selectedAgent.id
|
||||
// });
|
||||
}, 1000);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* ===== 页面容器 - 主流三段式布局 ===== */
|
||||
.page-container {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #f5f6fa;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* ===== 头部导航 ===== */
|
||||
.page-header {
|
||||
flex-shrink: 0;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
/* ===== 内容区域 ===== */
|
||||
.page-main {
|
||||
flex: 1;
|
||||
height: 0;
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
/* ===== 内容内层 ===== */
|
||||
.main-content {
|
||||
padding: 10px;
|
||||
padding-bottom: calc(50px + env(safe-area-inset-bottom) + 10px);
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
/* ===== 底部导航 ===== */
|
||||
.page-tabbar {
|
||||
flex-shrink: 0;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.status-card {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
padding: 20px;
|
||||
margin-bottom: 15px;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
|
||||
}
|
||||
|
||||
.status-title {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #fff;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.status-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.status-badge {
|
||||
padding: 4px 12px;
|
||||
border-radius: 20px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.status-badge.online {
|
||||
background-color: #52c41a;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.status-badge.offline {
|
||||
background-color: #999;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.status-desc {
|
||||
font-size: 13px;
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
margin: 15px 0 10px 0;
|
||||
}
|
||||
|
||||
.agent-list {
|
||||
background-color: #fff;
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.agent-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 15px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.agent-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.agent-avatar-wrapper {
|
||||
position: relative;
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
.agent-avatar {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border-radius: 50%;
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
.online-dot {
|
||||
position: absolute;
|
||||
bottom: 2px;
|
||||
right: 2px;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background-color: #52c41a;
|
||||
border-radius: 50%;
|
||||
border: 2px solid #fff;
|
||||
}
|
||||
|
||||
.agent-info {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.agent-name {
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.agent-status {
|
||||
font-size: 13px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.agent-action {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.empty-tip {
|
||||
text-align: center;
|
||||
padding: 50px 20px;
|
||||
color: #999;
|
||||
font-size: 14px;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
|
@ -0,0 +1 @@
|
|||
<!-- 图标文件内容,这是二进制文件,实际使用时需要上传真实图片 -->
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
|
|
@ -0,0 +1 @@
|
|||
|
||||
|
|
@ -0,0 +1 @@
|
|||
|
||||
|
|
@ -0,0 +1 @@
|
|||
// 这是一个占位文件,需要替换为实际的AI头像图标
|
||||
|
|
@ -0,0 +1 @@
|
|||
|
||||
|
|
@ -0,0 +1 @@
|
|||
// 这是一个占位文件,需要替换为实际的聊天图标
|
||||
|
After Width: | Height: | Size: 541 B |
|
After Width: | Height: | Size: 654 B |
|
After Width: | Height: | Size: 703 B |
|
After Width: | Height: | Size: 637 B |
|
After Width: | Height: | Size: 745 B |
|
After Width: | Height: | Size: 749 B |
|
After Width: | Height: | Size: 574 B |
|
After Width: | Height: | Size: 707 B |
|
After Width: | Height: | Size: 742 B |
|
After Width: | Height: | Size: 565 B |
|
After Width: | Height: | Size: 597 B |
|
After Width: | Height: | Size: 662 B |
|
After Width: | Height: | Size: 659 B |
|
After Width: | Height: | Size: 761 B |
|
|
@ -0,0 +1 @@
|
|||
|
||||
|
After Width: | Height: | Size: 789 B |
|
After Width: | Height: | Size: 375 B |
|
After Width: | Height: | Size: 352 B |
|
After Width: | Height: | Size: 364 B |
|
After Width: | Height: | Size: 405 B |
|
After Width: | Height: | Size: 404 B |
|
After Width: | Height: | Size: 338 B |
|
After Width: | Height: | Size: 382 B |
|
After Width: | Height: | Size: 389 B |
|
After Width: | Height: | Size: 313 B |
|
After Width: | Height: | Size: 358 B |
|
After Width: | Height: | Size: 384 B |
|
After Width: | Height: | Size: 377 B |
|
After Width: | Height: | Size: 399 B |
|
|
@ -0,0 +1 @@
|
|||
|
||||
|
|
@ -0,0 +1 @@
|
|||
|
||||
|
|
@ -0,0 +1 @@
|
|||
|
||||
|
Before Width: | Height: | Size: 310 B |
|
Before Width: | Height: | Size: 262 B |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 8.1 KiB |
|
After Width: | Height: | Size: 412 B |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 679 B |
|
After Width: | Height: | Size: 615 B |
|
After Width: | Height: | Size: 511 B |
|
After Width: | Height: | Size: 796 B |
|
After Width: | Height: | Size: 419 B |
|
After Width: | Height: | Size: 743 B |
|
After Width: | Height: | Size: 524 B |
|
After Width: | Height: | Size: 206 B |
|
After Width: | Height: | Size: 514 B |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 212 B |
|
After Width: | Height: | Size: 212 B |
|
After Width: | Height: | Size: 239 B |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 402 B |
|
After Width: | Height: | Size: 18 KiB |