提交 9f0dc82d authored 作者: 刘旭's avatar 刘旭

更新ui设计

上级 9ec04e56
<script setup lang="ts"> <script setup lang="ts">
import { onLaunch, onShow, onHide } from "@dcloudio/uni-app" import { onLaunch, onShow, onHide } from "@dcloudio/uni-app";
</script> </script>
<style lang="scss"> <style lang="scss">
@import "./static/iconfont/iconfont.css"; @import "./static/iconfont/iconfont.css";
@import "./scss/common.scss"; @import "./scss/common.scss";
@import "vk-uview-ui/index.scss"; @import "vk-uview-ui/index.scss";
.uni-tabbar {
max-width: 420px;
margin: 0 auto;
border-left: #f6f6f6 solid 1px;
border-right: #f6f6f6 solid 1px;
}
page { page {
background: #f5f5f5; background: #fbfcff;
font-family: PingFang SC-Medium, PingFang SC;
} }
</style> </style>
import request from "@/utils/request";
/**
* @brief 查询讲师列表
* @param data
* @return
*/
export const getLecturerList = (data: any) =>
request(
"/LQKJ.K3.PeiXunSystem.WebApi.WebApiService.TeacList,LQKJ.K3.PeiXunSystem.WebApi.common.kdsvc",
"POST",
data
);
...@@ -115,6 +115,20 @@ ...@@ -115,6 +115,20 @@
"navigationBarTitleText": "现场教学点", "navigationBarTitleText": "现场教学点",
"onReachBottomDistance": 50 "onReachBottomDistance": 50
} }
},
{
"path": "pages/lecturer/index",
"style": {
"navigationBarTitleText": "讲师列表",
"onReachBottomDistance": 50
}
},
{
"path": "pages/trainingEvaluation/index",
"style": {
"navigationBarTitleText": "培训评价",
"onReachBottomDistance": 50
}
} }
], ],
"globalStyle": { "globalStyle": {
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
<!-- <headers title="班级通讯录" /> --> <!-- <headers title="班级通讯录" /> -->
<view class="address-book-item-container"> <view class="address-book-item-container">
<uni-search-bar <uni-search-bar
v-show="addressBookList.length"
placeholder="姓名/单位/电话" placeholder="姓名/单位/电话"
bgColor="#ffffff" bgColor="#ffffff"
clearButton="auto" clearButton="auto"
...@@ -10,14 +11,12 @@ ...@@ -10,14 +11,12 @@
@clear="clear" @clear="clear"
/> />
<view v-if="addressBookList.length"> <view v-if="addressBookList.length">
<text style="margin-bottom: 20rpx; display: block" <text class="fund">为您找到{{ listQuery.total }}位同学</text>
>为你找到{{ listQuery.total }}个的同学</text
>
<block v-for="(item, i) in addressBookList" :key="i"> <block v-for="(item, i) in addressBookList" :key="i">
<addressBookItem <addressBookItem
:addressBookItem="item" :addressBookItem="item"
buttonTitle="联系TA" buttonTitle=""
@tapButton="tapButton" @tapButton="tapButton"
/> />
</block> </block>
...@@ -25,19 +24,23 @@ ...@@ -25,19 +24,23 @@
<u-loadmore :status="status" icon-type="flower" /> <u-loadmore :status="status" icon-type="flower" />
</view> </view>
</view> </view>
<view v-else class="empty"> <u-empty
<u-empty text="暂无数据" mode="list"></u-empty> v-else
</view> text="暂无数据~"
icon-size="506"
:margin-top="220"
src="../../static/img/noData.png"
></u-empty>
</view> </view>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
// import headers from "@/components/header/index.vue" // import headers from "@/components/header/index.vue"
import addressBookItem from "./components/addressBookItem.vue" import addressBookItem from "./components/addressBookItem.vue";
import { getClassBook } from "@/api/class" import { getClassBook } from "@/api/class";
import { useGlobalStore } from "@/store/useStore" import { useGlobalStore } from "@/store/useStore";
const globalStore = useGlobalStore() const globalStore = useGlobalStore();
const listQuery = reactive({ const listQuery = reactive({
Phone: globalStore.Phone, Phone: globalStore.Phone,
classId: "", classId: "",
...@@ -46,60 +49,55 @@ const listQuery = reactive({ ...@@ -46,60 +49,55 @@ const listQuery = reactive({
total: 0, total: 0,
type: 2, type: 2,
Name: "", Name: "",
}) });
const status = ref("loadmore") const status = ref("loadmore");
const addressBookList = ref([] as any) const addressBookList = ref([] as any);
onLoad((options: any) => { onLoad((options: any) => {
listQuery.classId = options.classId listQuery.classId = options.classId;
init() init();
}) });
const search = (val: any) => { const search = (val: any) => {
listQuery.Name = val.value listQuery.Name = val.value;
init() init();
} };
const clear = () => { const clear = () => {
addressBookList.value = [] addressBookList.value = [];
listQuery.Name = "" listQuery.Name = "";
init() init();
} };
const tapButton = (phone: string) => { const tapButton = (phone: string) => {
location.href = "tel:" + phone location.href = "tel:" + phone;
} };
const init = async () => { const init = async () => {
status.value = "loading" status.value = "loading";
const { data: res } = await getClassBook(listQuery) const { data: res } = await getClassBook(listQuery);
if (res.code == 200) { if (res.code == 200) {
if (res.total > 10) status.value = "loadmore" if (res.total > 10) status.value = "loadmore";
else status.value = "nomore" else status.value = "nomore";
addressBookList.value = [...addressBookList.value, ...res.data] addressBookList.value = [...addressBookList.value, ...res.data];
listQuery.total = res.total listQuery.total = res.total;
} }
} };
// 上拉加载数据 // 上拉加载数据
onReachBottom(() => { onReachBottom(() => {
// 判断是否还有下一页数据 // 判断是否还有下一页数据
if (listQuery.pageIndex * listQuery.pageSize >= listQuery.total) if (listQuery.pageIndex * listQuery.pageSize >= listQuery.total)
return (status.value = "nomore") return (status.value = "nomore");
// // 判断是否正在请求其它数据,如果是,则不发起额外的请求 // // 判断是否正在请求其它数据,如果是,则不发起额外的请求
if (status.value === "loading") return if (status.value === "loading") return;
listQuery.pageIndex += 1 listQuery.pageIndex += 1;
init() init();
}) });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.address-book-item-container { .address-book-item-container {
padding: 0 30rpx; padding: 0 30rpx;
box-sizing: border-box; box-sizing: border-box;
.uni-searchbar {
padding: 0;
margin: 20rpx 0;
}
} }
</style> </style>
<template> <template>
<!-- <headers title="我的班级" /> --> <!-- <headers title="我的班级" /> -->
<u-tabs <view style="padding: 0 32rpx 168rpx">
:list="tabsState.list" <u-tabs
:is-scroll="false" :list="tabsState.list"
v-model="tabsState.current" :is-scroll="false"
bg-color="#f5f5f5" v-model="tabsState.current"
@change="tabsChange" :active-item-style="{ fontSize: '34rpx', color: '#000000' }"
/> font-size="28"
<uni-search-bar bar-width="72"
placeholder="姓名/单位/电话" bar-height="6"
bgColor="#ffffff" bg-color="#fbfcff"
clearButton="auto" inactive-color="#cecfcf"
cancelButton="none" active-color="#05a8ff"
@confirm="search" @change="tabsChange"
@clear="clear" />
/> <uni-search-bar
<view v-if="addressBookList.length" class="address-book-item-container"> placeholder="姓名/单位/电话"
<text style="margin-bottom: 20rpx; display: block" bgColor="#ffffff"
>为你找到{{ listQuery.total }}个的同学</text clearButton="auto"
> cancelButton="none"
<block v-for="(item, i) in addressBookList" :key="i"> @confirm="search"
<addressBookItem @clear="clear"
:addressBookItem="item" />
:buttonTitle="tabsState.current ? '' : '查看评价'" <view v-if="addressBookList.length">
@tapButton="tapButton" <text class="fund">为您找到{{ listQuery.total }}位同学</text>
/> <block v-for="(item, i) in addressBookList" :key="i">
</block> <addressBookItem
<view style="padding: 20rpx"> :addressBookItem="item"
<u-loadmore :status="status" icon-type="flower" /> :buttonTitle="tabsState.current ? '' : '查看评价'"
@tapButton="tapButton"
/>
</block>
<view style="padding: 20rpx">
<u-loadmore :status="status" icon-type="flower" />
</view>
</view> </view>
</view> <u-empty
<view v-else class="empty"> v-else
<u-empty text="暂无数据" mode="list"></u-empty> text="暂无数据~"
icon-size="506"
:margin-top="220"
src="../../static/img/noData.png"
></u-empty>
</view> </view>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
// import headers from "@/components/header/index.vue" // import headers from "@/components/header/index.vue"
import addressBookItem from "./components/addressBookItem.vue" import addressBookItem from "./components/addressBookItem.vue";
import { getClassBook } from "@/api/class" import { getClassBook } from "@/api/class";
import { useGlobalStore } from "@/store/useStore" import { useGlobalStore } from "@/store/useStore";
const globalStore = useGlobalStore() const globalStore = useGlobalStore();
const listQuery = reactive({ const listQuery = reactive({
Phone: globalStore.Phone, Phone: globalStore.Phone,
classId: "", classId: "",
courseId: '', courseId: "",
pageIndex: 1, pageIndex: 1,
pageSize: 10, pageSize: 10,
total: 0, total: 0,
type: 0, type: 0,
Name: "", Name: "",
}) });
const tabsState = reactive({ const tabsState = reactive({
list: [ list: [
...@@ -64,70 +74,59 @@ const tabsState = reactive({ ...@@ -64,70 +74,59 @@ const tabsState = reactive({
}, },
], ],
current: 0, current: 0,
}) });
const status = ref("loadmore") const status = ref("loadmore");
const addressBookList = ref([] as any) const addressBookList = ref([] as any);
onLoad((options: any) => { onLoad((options: any) => {
listQuery.classId = options.classId listQuery.classId = options.classId;
init() init();
}) });
const search = (val: any) => { const search = (val: any) => {
listQuery.Name = val.value listQuery.Name = val.value;
tabsChange(tabsState.current) tabsChange(tabsState.current);
} };
const clear = () => { const clear = () => {
listQuery.Name = "" listQuery.Name = "";
tabsChange(tabsState.current) tabsChange(tabsState.current);
} };
const tabsChange = (index: number) => { const tabsChange = (index: number) => {
addressBookList.value = [] addressBookList.value = [];
listQuery.pageIndex = 1 listQuery.pageIndex = 1;
listQuery.pageSize = 10 listQuery.pageSize = 10;
if (index) { if (index) {
listQuery.type = 1 listQuery.type = 1;
} else listQuery.type = 0 } else listQuery.type = 0;
init() init();
} };
const tapButton = (classId: string, studentId: string) => { const tapButton = (classId: string, studentId: string) => {
uni.navigateTo({ uni.navigateTo({
url: "/pages/class/evaluate?classId=" + classId + "&studentId=" + studentId, url: "/pages/class/evaluate?classId=" + classId + "&studentId=" + studentId,
}) });
} };
const init = async () => { const init = async () => {
status.value = "loading" status.value = "loading";
const { data: res } = await getClassBook(listQuery) const { data: res } = await getClassBook(listQuery);
if (res.code == 200) { if (res.code == 200) {
if (res.total > 10) status.value = "loadmore" if (res.total > 10) status.value = "loadmore";
else status.value = "nomore" else status.value = "nomore";
addressBookList.value = res.data addressBookList.value = res.data;
listQuery.total = res.total listQuery.total = res.total;
} }
} };
// 上拉加载数据 // 上拉加载数据
onReachBottom(() => { onReachBottom(() => {
// 判断是否还有下一页数据 // 判断是否还有下一页数据
if (listQuery.pageIndex * listQuery.pageSize >= listQuery.total) if (listQuery.pageIndex * listQuery.pageSize >= listQuery.total)
return (status.value = "nomore") return (status.value = "nomore");
// // 判断是否正在请求其它数据,如果是,则不发起额外的请求 // // 判断是否正在请求其它数据,如果是,则不发起额外的请求
if (status.value === "loading") return if (status.value === "loading") return;
listQuery.pageIndex += 1 listQuery.pageIndex += 1;
init() init();
}) });
</script> </script>
<style lang="scss" scoped>
.address-book-item-container {
padding: 0 30rpx;
.uni-searchbar {
padding: 0;
margin: 20rpx 0;
}
}
</style>
...@@ -5,22 +5,30 @@ ...@@ -5,22 +5,30 @@
<view class="address-book-content"> <view class="address-book-content">
<view class="left"> <view class="left">
<u-image <u-image
width="160rpx" width="92rpx"
height="160rpx" height="92rpx"
shape="circle"
:src="baseUrl + '/' + addressBookItem.proPhoto" :src="baseUrl + '/' + addressBookItem.proPhoto"
></u-image> ></u-image>
<view class="content"> <view class="content">
<h4>{{ addressBookItem.stuName }}</h4> <view class="stu-name">{{ addressBookItem.stuName }}</view>
<text class="tel">{{ addressBookItem.Phone }}</text> <text class="tel">{{ addressBookItem.Phone }}</text>
<text>单位: {{ addressBookItem.stuUnit }}</text> <text class="tel">单位:{{ addressBookItem.stuUnit }}</text>
</view> </view>
</view> </view>
<u-image
v-if="!buttonTitle"
width="96rpx"
height="52rpx"
src="../../../static/img/phone2.png"
@tap="tapButton"
></u-image>
<u-button <u-button
v-show="buttonTitle" v-else
size="mini" hover-class="background-color: #04a7ff; color: #ffffff"
type="primary"
@tap="tapButton" @tap="tapButton"
>{{ buttonTitle }} >
<view>{{ buttonTitle }}</view>
</u-button> </u-button>
</view> </view>
</template> </template>
...@@ -29,8 +37,7 @@ ...@@ -29,8 +37,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { src } from "@/utils/example" import { baseUrl } from "@/utils/request";
import { baseUrl } from "@/utils/request"
const props = defineProps({ const props = defineProps({
addressBookItem: { addressBookItem: {
...@@ -38,26 +45,33 @@ const props = defineProps({ ...@@ -38,26 +45,33 @@ const props = defineProps({
default: () => [], default: () => [],
} as any, } as any,
buttonTitle: String, buttonTitle: String,
}) });
const emits = defineEmits(["tapButton"]) const emits = defineEmits(["tapButton"]);
const tapButton = () => { const tapButton = () => {
if (props.buttonTitle === "联系TA") console.log(props.buttonTitle);
emits("tapButton", props.addressBookItem.Phone) if (props.buttonTitle) {
else
emits( emits(
"tapButton", "tapButton",
props.addressBookItem.FCLASS, props.addressBookItem.FCLASS,
props.addressBookItem.studentId props.addressBookItem.studentId
) );
} } else {
location.href = "tel:" + props.addressBookItem.Phone;
// emits("tapButton", props.addressBookItem.Phone);
}
};
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.address-book-container { .address-book-container {
margin-bottom: 32rpx; margin-bottom: 32rpx;
height: 200rpx; height: 152rpx;
:deep(.u-card__body) {
padding: 16rpx 32rpx !important;
}
.address-book-content { .address-book-content {
display: flex; display: flex;
...@@ -66,21 +80,42 @@ const tapButton = () => { ...@@ -66,21 +80,42 @@ const tapButton = () => {
.left { .left {
display: flex; display: flex;
align-items: center;
.content { .content {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: flex-end; justify-content: flex-end;
margin-left: 20rpx; margin-left: 20rpx;
color: #909399;
font-size: 26rpx;
.stu-name {
font-size: 28rpx;
font-weight: 500;
color: #000000;
margin-bottom: 8rpx;
}
.tel { .tel {
margin: 20rpx 0; margin-bottom: 4rpx;
font-size: 24rpx;
font-weight: 400;
color: rgba(34, 34, 34, 0.5);
height: 34rpx;
line-height: 28rpx;
} }
} }
} }
uni-button { .u-btn {
margin: 0; margin: 0;
width: 160rpx;
height: 72rpx;
background: #05a8ff;
border-radius: 8rpx;
font-size: 28rpx;
color: #ffffff;
} }
} }
} }
......
<template> <template>
<view class="arrange-item-container"> <view class="arrange-item-container">
<h3> <view class="opening-time">
&nbsp;{{ dayjs(arrangeItem.startDate).format("YYYY-MM-DD") }}&nbsp;&nbsp; &nbsp;{{ dayjs(arrangeItem.startDate).format("YYYY-MM-DD") }}&nbsp;&nbsp;
{{ {{
dateFormat(arrangeItem.startDate) + dateFormat(arrangeItem.startDate) +
"~" + "~" +
dateFormat(arrangeItem.endDate) dateFormat(arrangeItem.endDate)
}} }}
</h3> </view>
<u-card :show-head="false" margin="0"> <u-card :show-head="false" margin="0">
<template #body> <template #body>
<view class="arrange-header"> <view class="body">
<h3>{{ arrangeItem.courseName }}</h3> <view>
<u-button size="mini" plain :type="arrangeStatus.type">{{ <view class="arrange-header">
arrangeStatus.detail <h3>{{ arrangeItem.courseName }}</h3>
}}</u-button> </view>
</view> <view class="item" style="margin: 32rpx 0 24rpx">
<view class="item"> <u-icon size="32" name="account" />
<u-icon name="account" /> <text v-for="(item, i) in arrangeItem.Teachs" :key="i">
<text>&nbsp;{{ arrangeItem.teachName }}</text> &nbsp;{{ item.teachName }}&nbsp;
</view> </text>
<view class="item"> </view>
<u-icon name="map" /> <view class="item">
<text>&nbsp;{{ arrangeItem.classArea }}&nbsp;</text> <u-icon size="32" name="map" />
</view> <text>&nbsp;{{ arrangeItem.classArea }}&nbsp;</text>
</template> </view>
<template #foot> </view>
<view class="arrange-footer" @tap="openInfo"> <view class="courseware">
<u-icon name="order" /> <view>
<text>课件资料</text> <u-badge
type="error"
size="mini"
:count="6"
:offset="[-4, -4]"
></u-badge>
<u-icon
name="file-text-fill"
color="#05a8ff"
size="40"
class="courseware-icon"
@tap="openInfo"
></u-icon>
</view>
<view class="desc">课程资料{{ arrangeItem.FileCount }}</view>
</view>
<view
:type="arrangeStatus.type"
:class="arrangeStatus.type"
class="body-right"
>
{{ arrangeStatus.detail }}
</view>
</view> </view>
</template> </template>
</u-card> </u-card>
...@@ -41,87 +63,116 @@ ...@@ -41,87 +63,116 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import infoPopup from "@/pages/course/components/infoPopup.vue" import infoPopup from "@/pages/course/components/infoPopup.vue";
import dayjs from "dayjs" import dayjs from "dayjs";
const props = defineProps({ const props = defineProps({
arrangeItem: { arrangeItem: {
type: Array, type: Array,
default: () => [], default: () => [],
} as any, } as any,
}) });
const show = ref(false) const show = ref(false);
const infoRef = ref() const infoRef = ref();
const arrangeDetail = ["未开始", "上课中", "已下课"] const arrangeDetail = ["未开始", "上课中", "已下课"];
const arrangeStatus = computed(() => { const arrangeStatus = computed(() => {
const statusObj = { const statusObj = {
type: "", type: "",
detail: "", detail: "",
} };
switch (props.arrangeItem.courseType) { switch (props.arrangeItem.courseType) {
case 0: case 0:
statusObj.type = "warning" statusObj.type = "warning";
break break;
case 1: case 1:
statusObj.type = "primary" statusObj.type = "primary";
break break;
case 2: case 2:
statusObj.type = "info" statusObj.type = "info";
break break;
} }
statusObj.detail = arrangeDetail[props.arrangeItem.courseType] statusObj.detail = arrangeDetail[props.arrangeItem.courseType];
return statusObj return statusObj;
}) });
const dateFormat = (dateStr: string) => { const dateFormat = (dateStr: string) => {
// 创建一个日期对象,传入特定日期和时间 // 创建一个日期对象,传入特定日期和时间
const date = new Date(dateStr) const date = new Date(dateStr);
// 获取小时和分钟 // 获取小时和分钟
const hours = ("0" + date.getHours()).slice(-2) const hours = ("0" + date.getHours()).slice(-2);
const minutes = ("0" + date.getMinutes()).slice(-2) const minutes = ("0" + date.getMinutes()).slice(-2);
// 构建时间字符串 // 构建时间字符串
const time = hours + ":" + minutes const time = hours + ":" + minutes;
return time return time;
} };
const openInfo = () => { const openInfo = () => {
show.value = true show.value = true;
infoRef.value.init() infoRef.value.init();
} };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.arrange-item-container { .arrange-item-container {
h3 { // :deep(.u-card__body) {
margin-bottom: 32rpx; // padding: 40rpx 32rpx !important;
// }
.opening-time {
margin-bottom: 24rpx;
font-size: 28rpx;
font-weight: 400;
color: rgba(0, 0, 0, 0.6);
} }
.body {
.arrange-header { position: relative;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center;
h3 { .arrange-header {
margin: 0; display: flex;
justify-content: space-between;
align-items: center;
h3 {
margin: 0;
font-size: 34rpx;
font-weight: 500;
color: #222222;
}
uni-button {
margin: 0;
}
} }
uni-button { .body-right {
margin: 0; position: absolute;
bottom: -29rpx;
right: -29rpx;
text-align: center;
font-size: 24rpx;
color: #2979ff;
background: #e4e4e4;
border-radius: 24rpx 0rpx 24rpx 0rpx;
padding: 4rpx 16rpx;
}
.info {
color: #82848a;
background-color: #e4e4e4;
}
.success {
color: #19be6b;
background-color: #deffd9;
} }
} }
.item { .item {
margin: 20rpx 0; font-size: 28rpx;
} font-weight: 400;
color: rgba(34, 34, 34, 0.9);
.arrange-footer {
text-align: end;
text {
color: #2979ff;
}
} }
} }
</style> </style>
<template> <template>
<view class="class-item-container"> <view class="class-item-container">
<u-card :show-head="false" margin="0" border-radius="20"> <u-card :show-head="false" margin="0" border-radius="24">
<template #body> <template #body>
<view class="calss-header"> <view class="calss-header">
<h3>{{ classItem.className }}</h3> <h3>{{ classItem.className }}</h3>
<u-button <!-- <u-button
v-show="current == 2" v-show="current == 2"
size="mini" size="mini"
type="primary" type="primary"
@tap="toEvaluate" @tap="toEvaluate"
>查看评价</u-button >查看评价</u-button
> > -->
</view> </view>
<view class="item"> <view class="item">
<text>课程时间:</text> <text>课程时间:</text>
...@@ -20,31 +20,55 @@ ...@@ -20,31 +20,55 @@
<text>教室地点:</text> <text>教室地点:</text>
<text>{{ classItem.classArea }}</text> <text>{{ classItem.classArea }}</text>
</view> </view>
<view> </view> <view class="class-progress item">
<view class="progress item">
<text>课程进度:</text> <text>课程进度:</text>
<u-line-progress <u-line-progress
active-color="#2979ff" active-color="#5363ff"
:percent="percent ? percent : 0" :percent="percent ? percent : 0"
:height="25" :show-percent="false"
:height="20"
style="margin-top: 10rpx"
/> />
<view class="progress">
{{
(props.classItem.coursePro[0]?.SumPro
? props.classItem.coursePro[0]?.SumPro
: "0") +
"/" +
props.classItem.courseSum[0]?.Sum
}}
</view>
</view> </view>
<view class="class-teacher item"> <view class="class-teacher item">
<text>班主任:</text> <text>班主任:</text>
<u-tag <view>
v-for="(item, index) in classItem.Management" <view
:key="index" v-for="(item, index) in classItem.Management"
:text="item.teachName" :key="index"
shape="circle" class="btn"
/> @tap="contact(item.teacPhone)"
>
<u-image src="../../../static/img/phone.png" />
<view>{{ item.teachName }}</view>
</view>
</view>
</view> </view>
</template> </template>
<template #foot> <template #foot>
<view class="class-footer"> <view class="class-footer">
<u-button size="mini" plain @tap="toAddressBook">班级通讯录</u-button> <!-- @tap="toAddressBook" -->
<u-button size="mini" plain @tap="classQrCode">班级二维码</u-button> <u-button size="mini" shape="circle" @tap="toEvaluate"
<u-button type="primary" size="mini" plain @tap="toCourseArrange" >班级通讯录</u-button
>
<u-button size="mini" shape="circle" @tap="classQrCode"
>班级二维码</u-button
>
<u-button
size="mini"
shape="circle"
hover-class="background-color: #04a7ff; color: #ffffff"
style="background-color: #04a7ff; color: #ffffff"
@tap="toCourseArrange"
>课程安排</u-button >课程安排</u-button
> >
</view> </view>
...@@ -61,7 +85,7 @@ ...@@ -61,7 +85,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import saveQrCode from "./saveQrCode.vue" import saveQrCode from "./saveQrCode.vue";
const props = defineProps({ const props = defineProps({
classItem: { classItem: {
...@@ -72,52 +96,61 @@ const props = defineProps({ ...@@ -72,52 +96,61 @@ const props = defineProps({
type: Number, type: Number,
default: 0, default: 0,
}, },
}) });
const emits = defineEmits(["init"]) const emits = defineEmits(["init"]);
const show = ref(false) const show = ref(false);
const percent = computed( const percent = computed(
() => () =>
(props.classItem.coursePro[0]?.SumPro / props.classItem.courseSum[0].Sum) * (props.classItem.coursePro[0]?.SumPro / props.classItem.courseSum[0].Sum) *
100 100
) );
const classQrCode = () => { const classQrCode = () => {
show.value = true show.value = true;
} };
const toAddressBook = () => { const toAddressBook = () => {
uni.navigateTo({ uni.navigateTo({
url: "/pages/class/addressBook?classId=" + props.classItem.classId, url: "/pages/class/addressBook?classId=" + props.classItem.classId,
}) });
} };
const toCourseArrange = () => { const toCourseArrange = () => {
uni.navigateTo({ uni.navigateTo({
url: "/pages/class/courseArrange?classId=" + props.classItem.classId, url: "/pages/class/courseArrange?classId=" + props.classItem.classId,
}) });
} };
const toEvaluate = () => { const toEvaluate = () => {
uni.navigateTo({ uni.navigateTo({
url: "/pages/class/classEvaluate?classId=" + props.classItem.classId, url: "/pages/class/classEvaluate?classId=" + props.classItem.classId,
}) });
} };
const contact = (tel: string) => {
location.href = "tel:" + tel;
};
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.class-item-container { .class-item-container {
margin-bottom: 20rpx; margin-bottom: 32rpx;
:deep(.u-card__body) {
padding: 40rpx 32rpx 18rpx !important;
}
.calss-header { .calss-header {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
margin-bottom: 16rpx; margin-bottom: 32rpx;
h3 { h3 {
margin: 0; margin: 0;
font-size: 34rpx;
font-weight: 500;
color: #222222;
} }
uni-button { uni-button {
...@@ -128,11 +161,13 @@ const toEvaluate = () => { ...@@ -128,11 +161,13 @@ const toEvaluate = () => {
.item { .item {
display: flex; display: flex;
align-items: flex-start; align-items: flex-start;
margin-bottom: 24rpx;
text { text {
display: block; display: block;
padding: 12rpx 0;
font-size: 28rpx; font-size: 28rpx;
font-weight: 400;
color: rgba(34, 34, 34, 0.9);
} }
text:first-child { text:first-child {
...@@ -144,10 +179,19 @@ const toEvaluate = () => { ...@@ -144,10 +179,19 @@ const toEvaluate = () => {
} }
} }
.progress { .class-progress {
display: flex; display: flex;
align-items: center; align-items: center;
.progress {
margin-left: 10px;
margin-top: 8rpx;
}
.u-progress {
margin-left: 20rpx;
}
text { text {
white-space: nowrap; white-space: nowrap;
} }
...@@ -162,8 +206,21 @@ const toEvaluate = () => { ...@@ -162,8 +206,21 @@ const toEvaluate = () => {
display: flex; display: flex;
align-items: center; align-items: center;
.u-tag { .btn {
margin-right: 20rpx; height: 56rpx;
padding: 14rpx 36rpx 14rpx 14rpx;
background: #04a7ff;
border-radius: 112rpx;
color: #ffffff;
display: flex;
align-items: center;
justify-content: center;
.u-image {
margin-right: 6rpx;
width: 50rpx !important;
height: 46rpx !important;
}
} }
} }
...@@ -172,9 +229,9 @@ const toEvaluate = () => { ...@@ -172,9 +229,9 @@ const toEvaluate = () => {
display: flex; display: flex;
justify-content: flex-end; justify-content: flex-end;
uni-button { .u-btn {
margin-left: 30rpx; height: 56rpx;
margin-right: 0; margin: 0 16rpx 0 0;
} }
} }
} }
......
...@@ -3,50 +3,51 @@ ...@@ -3,50 +3,51 @@
v-model="props.show" v-model="props.show"
mode="center" mode="center"
closeable closeable
border-radius="15" border-radius="40"
width="80%" @close="handleClose"
> >
<view class="qrcode"> <view class="qrcode">
<view class="title">班级二维码</view> <view class="title">班级二维码</view>
<view class="image"> <view class="image">
<u-image <u-image width="100%" height="100%" :src="baseUrl + '/' + Url" />
width="100%" <view class="refresh" @tap="updateImage">
height="500rpx" <u-icon name="reload" color="#000000" size="32"></u-icon>
:src="baseUrl + '/' + Url" </view>
ref="canvasRef"
/>
</view> </view>
<view class="detail"
><text
>扫描二维码快速进入班级群或截图保存二维码微信识别进入班级群</text
></view
>
</view> </view>
<view class="footer"> <!-- <view class="footer">
<u-button type="primary" size="medium" @tap="updateImage" <u-button type="primary" size="medium" @tap="updateImage"
>更新二维码</u-button >更新二维码</u-button
> >
<!-- <u-button type="success" size="medium" @tap="saveImage" <u-button type="primary" size="medium" @tap="saveImage"
>保存二维码</u-button >保存二维码</u-button
> --> >
</view> </view> -->
</u-popup> </u-popup>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { baseUrl } from "@/utils/request" import { baseUrl } from "@/utils/request";
import { toast } from "@/utils/util" import { toast } from "@/utils/util";
const props = defineProps({ const props = defineProps({
show: Boolean, show: Boolean,
classId: Number, classId: Number,
Url: String, Url: String,
}) });
const emits = defineEmits(["init", "update:modelValue"])
const canvasRef = ref() const emits = defineEmits(["init", "update:modelValue"]);
const updateImage = () => { const updateImage = () => {
uni.chooseImage({ uni.chooseImage({
count: 1, count: 1,
success: (chooseImageRes) => { success: (chooseImageRes) => {
const tempFilePaths = chooseImageRes.tempFilePaths const tempFilePaths = chooseImageRes.tempFilePaths;
uni.uploadFile({ uni.uploadFile({
url: url:
baseUrl + baseUrl +
...@@ -57,64 +58,110 @@ const updateImage = () => { ...@@ -57,64 +58,110 @@ const updateImage = () => {
classId: props.classId, classId: props.classId,
}, },
success: ({ data }: any) => { success: ({ data }: any) => {
const res = JSON.parse(data) const res = JSON.parse(data);
if (res.code == 200) { if (res.code == 200) {
emits("init") emits("init");
emits("update:modelValue", false) emits("update:modelValue", false);
toast("更新成功") toast("更新成功");
} }
}, },
}) });
}, },
}) });
} };
const saveImage = () => { const saveImage = () => {
downloadImage(baseUrl + "/" + props.Url) downloadImage(baseUrl + "/" + props.Url);
// downloadFile(baseUrl + "/" + props.Url, "image.jpg") // downloadFile(baseUrl + "/" + props.Url, "image.jpg");
} };
function downloadFile(fileURL: string, fileName: string) { function downloadFile(fileURL: string, fileName: string) {
fetch(fileURL) fetch(fileURL)
.then((response) => response.blob()) .then((response) => response.blob())
.then((blob) => { .then((blob) => {
const downloadUrl = URL.createObjectURL(blob) const downloadUrl = URL.createObjectURL(blob);
const link = document.createElement("a") const link = document.createElement("a");
link.href = downloadUrl link.href = downloadUrl;
link.download = fileName link.download = fileName;
link.click() link.click();
URL.revokeObjectURL(downloadUrl) URL.revokeObjectURL(downloadUrl);
}) });
} }
function downloadImage(url: string) { function downloadImage(url: string) {
const link = document.createElement("a") const link = document.createElement("a");
link.href = url link.href = url;
link.download = "image.jpg" link.download = "image.jpg";
link.style.display = "none" link.style.display = "none";
document.body.appendChild(link) document.body.appendChild(link);
link.click() link.click();
document.body.removeChild(link) document.body.removeChild(link);
} }
const handleClose = () => emits("update:modelValue", false);
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
:deep(.u-mode-center-box) { :deep(.u-mode-center-box) {
background-color: transparent; background-color: transparent;
} }
:deep(.u-iconfont::before) {
margin-top: 50rpx;
}
.qrcode { .qrcode {
padding: 24rpx; background-image: url("../../../static/img/bg2.png");
background-repeat: no-repeat;
background-size: cover;
padding: 24rpx 32rpx;
background-color: #fff; background-color: #fff;
border-bottom-right-radius: 15rpx; border-bottom-right-radius: 15rpx;
border-bottom-left-radius: 15rpx; border-bottom-left-radius: 15rpx;
.title { .title {
font-size: larger; font-size: 34rpx;
font-weight: bolder; font-weight: 500;
color: #000000;
margin-top: 50rpx;
} }
.image { .image {
padding: 46rpx; position: relative;
width: 350rpx;
height: 330rpx;
margin-top: 44rpx;
margin: 44rpx 125rpx;
.refresh {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
background-color: #ffffff;
width: 48rpx;
height: 48rpx;
display: flex;
align-items: center;
justify-content: center;
}
:deep(.u-iconfont::before) {
margin-top: 0;
}
}
.detail {
text-align: center;
margin-bottom: 60rpx;
text {
display: block;
width: 520rpx;
height: 68rpx;
margin: 0 40rpx;
font-size: 24rpx;
font-weight: 400;
color: #bcbcbc;
line-height: 28rpx;
}
} }
} }
.footer { .footer {
......
<template> <template>
<!-- <headers title="课程安排" /> -->
<view class="course-arrange-container"> <view class="course-arrange-container">
<view class="progress"> <view class="course-arrange-progress">
<text>课程进</text> <text>课程进</text>
<u-line-progress <u-line-progress
active-color="#2979ff" active-color="#5363ff"
:percent="percent ? percent : 0" :percent="percent ? percent : 0"
:height="25" :show-percent="false"
:height="20"
style="margin-top: 10rpx"
/> />
<view class="progress">
{{
(totalPercentage ? totalPercentage : "0") + "/" + arrangeList.length
}}
</view>
</view> </view>
<view v-if="arrangeList.length"> <view v-if="arrangeList.length">
<u-time-line> <u-time-line>
<u-time-line-item v-for="(item, index) in arrangeList" :key="index"> <u-time-line-item v-for="(item, index) in arrangeList" :key="index">
<template #node> <template #node>
<view class="u-node"> <u-icon name="clock-fill" color="#909399" />
<view class="u-dot"></view>
</view>
</template> </template>
<template #content> <template #content>
<arrangeItem :arrangeItem="item" /> <arrangeItem :arrangeItem="item" />
...@@ -33,70 +37,77 @@ ...@@ -33,70 +37,77 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
// import headers from "@/components/header/index.vue" import arrangeItem from "./components/arrangeItem.vue";
import arrangeItem from "./components/arrangeItem.vue" import { getTeachCourse } from "@/api/course";
import { getTeachCourse } from "@/api/course"
const arrangeList = ref([] as any) const arrangeList = ref([] as any);
const percent = ref() const percent = ref();
const totalPercentage = ref();
const listQuery = reactive({ const listQuery = reactive({
pageIndex: 1, pageIndex: 1,
pageSize: 10, pageSize: 999,
total: 0, total: 0,
classId: "", classId: "",
Name: "", Name: "",
}) });
const status = ref("loadmore") const status = ref("loadmore");
onLoad((options: any) => { onLoad((options: any) => {
listQuery.classId = options.classId listQuery.classId = options.classId;
init() init();
}) });
// 上拉加载数据 // 上拉加载数据
onReachBottom(() => { onReachBottom(() => {
// 判断是否还有下一页数据 // 判断是否还有下一页数据
if (listQuery.pageIndex * listQuery.pageSize >= listQuery.total) if (listQuery.pageIndex * listQuery.pageSize >= listQuery.total)
return (status.value = "nomore") return (status.value = "nomore");
// 判断是否正在请求其它数据,如果是,则不发起额外的请求 // 判断是否正在请求其它数据,如果是,则不发起额外的请求
if (status.value === "loading") return if (status.value === "loading") return;
listQuery.pageIndex += 1 listQuery.pageIndex += 1;
init() init();
}) });
const init = async () => { const init = async () => {
status.value = "loading" status.value = "loading";
const { data: res } = await getTeachCourse(listQuery) const { data: res } = await getTeachCourse(listQuery);
if (res.code == 200) { if (res.code == 200) {
if (res.total > 10) status.value = "loadmore" if (res.total > 10) status.value = "loadmore";
else status.value = "nomore" else status.value = "nomore";
arrangeList.value = [...arrangeList.value, ...res.data] arrangeList.value = [...arrangeList.value, ...res.data];
listQuery.total = res.total listQuery.total = res.total;
let num: number = res.data.filter( totalPercentage.value = res.data.filter(
(item: any) => item.courseType === 2 (item: any) => item.courseType === 2
).length ).length;
percent.value = (num / res.total) * 100 percent.value = (totalPercentage.value / res.total) * 100;
// console.log(arrangeList.value) // console.log(arrangeList.value)
} }
} };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.course-arrange-container { .course-arrange-container {
padding: 0 20rpx; padding-right: 32rpx;
margin-left: 32rpx;
.progress { .course-arrange-progress {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
padding: 26rpx 10rpx 50rpx 30rpx; padding: 32rpx 0 56rpx;
width: 90%;
.progress {
margin-left: 10px;
margin-top: 8rpx;
}
text { text {
display: block; display: block;
padding: 12rpx 0;
font-size: 32rpx;
white-space: nowrap; white-space: nowrap;
font-size: 28rpx;
font-weight: 400;
color: rgba(34, 34, 34, 0.9);
margin-top: 6rpx;
} }
.registered { .registered {
...@@ -104,14 +115,6 @@ const init = async () => { ...@@ -104,14 +115,6 @@ const init = async () => {
color: #3b99fc; color: #3b99fc;
} }
} }
.u-dot {
height: 22rpx;
width: 22rpx;
border-radius: 3.125rem;
background: #2979ff;
box-shadow: 0 0 10px rgba(0, 0, 0.6, 0.412);
}
} }
:deep(uni-modal) { :deep(uni-modal) {
z-index: 99999 !important; z-index: 99999 !important;
......
...@@ -5,7 +5,13 @@ ...@@ -5,7 +5,13 @@
:list="tabsState.list" :list="tabsState.list"
:is-scroll="false" :is-scroll="false"
v-model="tabsState.current" v-model="tabsState.current"
bg-color="#f5f5f5" :active-item-style="{ fontSize: '34rpx', color: '#000000' }"
font-size="28"
bar-width="72"
bar-height="6"
bg-color="#fbfcff"
inactive-color="#cecfcf"
active-color="#05a8ff"
@change="tabsChange" @change="tabsChange"
/> />
<!-- 搜索 --> <!-- 搜索 -->
...@@ -19,9 +25,7 @@ ...@@ -19,9 +25,7 @@
/> />
<!-- 内容 --> <!-- 内容 -->
<view v-if="classList.length"> <view v-if="classList.length">
<text style="margin-bottom: 20rpx; display: block" <text class="fund">为您找到{{ listQuery.total }}个班级</text>
>为你找到{{ listQuery.total }}个的班级</text
>
<block v-for="(item, index) in classList" :key="index"> <block v-for="(item, index) in classList" :key="index">
<classItem <classItem
...@@ -34,19 +38,23 @@ ...@@ -34,19 +38,23 @@
<u-loadmore :status="status" icon-type="flower" /> <u-loadmore :status="status" icon-type="flower" />
</view> </view>
</view> </view>
<view v-else class="empty"> <u-empty
<u-empty text="暂无数据" mode="list"></u-empty> v-else
</view> text="暂无数据~"
icon-size="506"
:margin-top="220"
src="../../static/img/noData.png"
></u-empty>
</view> </view>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
// import headers from "@/components/header/index.vue" // import headers from "@/components/header/index.vue"
import classItem from "./components/classItem.vue" import classItem from "./components/classItem.vue";
import { getClassList } from "@/api/class" import { getClassList } from "@/api/class";
import { useGlobalStore } from "@/store/useStore" import { useGlobalStore } from "@/store/useStore";
const globalStore = useGlobalStore() const globalStore = useGlobalStore();
const tabsState = reactive({ const tabsState = reactive({
list: [ list: [
...@@ -61,9 +69,9 @@ const tabsState = reactive({ ...@@ -61,9 +69,9 @@ const tabsState = reactive({
}, },
], ],
current: 0, current: 0,
}) });
const classList = ref([] as any) const classList = ref([] as any);
const listQuery = reactive({ const listQuery = reactive({
Phone: globalStore.Phone, Phone: globalStore.Phone,
...@@ -72,70 +80,65 @@ const listQuery = reactive({ ...@@ -72,70 +80,65 @@ const listQuery = reactive({
pageSize: 10, pageSize: 10,
total: 0, total: 0,
Name: "", Name: "",
}) });
const status = ref("loadmore") const status = ref("loadmore");
const tabsChange = (index: number) => { const tabsChange = (index: number) => {
classList.value = [] classList.value = [];
listQuery.pageIndex = 1 listQuery.pageIndex = 1;
listQuery.pageSize = 10 listQuery.pageSize = 10;
switch (index) { switch (index) {
case 0: case 0:
listQuery.type = 1 listQuery.type = 1;
break break;
case 1: case 1:
listQuery.type = 0 listQuery.type = 0;
break break;
default: default:
listQuery.type = 2 listQuery.type = 2;
break break;
} }
init() init();
} };
const search = (val: any) => { const search = (val: any) => {
listQuery.Name = val.value listQuery.Name = val.value;
tabsChange(tabsState.current) tabsChange(tabsState.current);
} };
const clear = () => { const clear = () => {
listQuery.Name = "" listQuery.Name = "";
tabsChange(tabsState.current) tabsChange(tabsState.current);
} };
// 上拉加载数据 // 上拉加载数据
onReachBottom(() => { onReachBottom(() => {
// 判断是否还有下一页数据 // 判断是否还有下一页数据
if (listQuery.pageIndex * listQuery.pageSize >= listQuery.total) if (listQuery.pageIndex * listQuery.pageSize >= listQuery.total)
return (status.value = "nomore") return (status.value = "nomore");
// // 判断是否正在请求其它数据,如果是,则不发起额外的请求 // // 判断是否正在请求其它数据,如果是,则不发起额外的请求
if (status.value === "loading") return if (status.value === "loading") return;
listQuery.pageIndex += 1 listQuery.pageIndex += 1;
init() init();
}) });
const init = async () => { const init = async () => {
status.value = "loading" status.value = "loading";
const { data: res } = await getClassList(listQuery) const { data: res } = await getClassList(listQuery);
if (res.code == 200) { if (res.code == 200) {
if (res.total > 10) status.value = "loadmore" if (res.total > 10) status.value = "loadmore";
else status.value = "nomore" else status.value = "nomore";
classList.value = [...classList.value, ...res.data] classList.value = [...classList.value, ...res.data];
listQuery.total = res.total listQuery.total = res.total;
} }
} };
tabsChange(tabsState.current) tabsChange(tabsState.current);
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.class-container { .class-container {
padding: 0 30rpx 30rpx; padding: 0 32rpx 168rpx;
.uni-searchbar {
padding: 0;
margin: 20rpx 0;
}
} }
</style> </style>
...@@ -21,9 +21,7 @@ ...@@ -21,9 +21,7 @@
/> />
</view> --> </view> -->
<view v-if="detailList.length"> <view v-if="detailList.length">
<text style="margin-bottom: 20rpx; display: block" <text class="fund">为您找到{{ listQuery.total }}位同学</text>
>为你找到{{ listQuery.total }}个的班级</text
>
<block v-for="(item, index) in detailList" :key="index"> <block v-for="(item, index) in detailList" :key="index">
<detailsItem :detailItem="item" @init="refresh" /> <detailsItem :detailItem="item" @init="refresh" />
...@@ -39,8 +37,8 @@ ...@@ -39,8 +37,8 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { getStateList } from "@/api/course" import { getStateList } from "@/api/course";
import detailsItem from "./components/detailsItem.vue" import detailsItem from "./components/detailsItem.vue";
const tagList = ref([ const tagList = ref([
{ type: "primary", name: "全部" }, { type: "primary", name: "全部" },
...@@ -48,9 +46,9 @@ const tagList = ref([ ...@@ -48,9 +46,9 @@ const tagList = ref([
{ type: "info", name: "缺勤" }, { type: "info", name: "缺勤" },
{ type: "info", name: "请假" }, { type: "info", name: "请假" },
{ type: "info", name: "补签" }, { type: "info", name: "补签" },
]) ]);
const detailList = ref([] as any) const detailList = ref([] as any);
const listQuery = reactive({ const listQuery = reactive({
courseId: "", courseId: "",
...@@ -58,58 +56,58 @@ const listQuery = reactive({ ...@@ -58,58 +56,58 @@ const listQuery = reactive({
pageSize: 10, pageSize: 10,
total: 0, total: 0,
Name: "", Name: "",
}) });
const status = ref("loadmore") const status = ref("loadmore");
// 上拉加载数据 // 上拉加载数据
onReachBottom(() => { onReachBottom(() => {
// 判断是否还有下一页数据 // 判断是否还有下一页数据
if (listQuery.pageIndex * listQuery.pageSize >= listQuery.total) if (listQuery.pageIndex * listQuery.pageSize >= listQuery.total)
return (status.value = "nomore") return (status.value = "nomore");
// // 判断是否正在请求其它数据,如果是,则不发起额外的请求 // // 判断是否正在请求其它数据,如果是,则不发起额外的请求
if (status.value === "loading") return if (status.value === "loading") return;
listQuery.pageIndex += 1 listQuery.pageIndex += 1;
init() init();
}) });
const changeTagType = (index: number) => { const changeTagType = (index: number) => {
tagList.value.map((item: any, i: number) => { tagList.value.map((item: any, i: number) => {
if (index === i) item.type = "primary" if (index === i) item.type = "primary";
else item.type = "info" else item.type = "info";
}) });
} };
const search = (val: any) => { const search = (val: any) => {
listQuery.Name = val.value listQuery.Name = val.value;
init() init();
} };
const clear = () => { const clear = () => {
listQuery.Name = "" listQuery.Name = "";
init() init();
} };
const init = async () => { const init = async () => {
status.value = "loading" status.value = "loading";
const { data: res } = await getStateList(listQuery) const { data: res } = await getStateList(listQuery);
if (res.code == 200) { if (res.code == 200) {
if (res.total > 10) status.value = "loadmore" if (res.total > 10) status.value = "loadmore";
else status.value = "nomore" else status.value = "nomore";
detailList.value = [...detailList.value, ...res.data] detailList.value = [...detailList.value, ...res.data];
listQuery.total = res.total listQuery.total = res.total;
} }
} };
const refresh = () => { const refresh = () => {
detailList.value = [] detailList.value = [];
init() init();
} };
onLoad((options: any) => { onLoad((options: any) => {
listQuery.courseId = options.courseId listQuery.courseId = options.courseId;
init() init();
}) });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
......
...@@ -5,22 +5,30 @@ ...@@ -5,22 +5,30 @@
<view class="address-book-content"> <view class="address-book-content">
<view class="left"> <view class="left">
<u-image <u-image
width="160rpx" width="92rpx"
height="160rpx" height="92rpx"
shape="circle"
:src="baseUrl + '/' + addressBookItem.proPhoto" :src="baseUrl + '/' + addressBookItem.proPhoto"
></u-image> ></u-image>
<view class="content"> <view class="content">
<h4>{{ addressBookItem.stuName }}</h4> <view class="stu-name">{{ addressBookItem.stuName }}</view>
<text class="tel">{{ addressBookItem.Phone }}</text> <text class="tel">{{ addressBookItem.Phone }}</text>
<text>单位: {{ addressBookItem.stuUnit }}</text> <text class="tel">单位:{{ addressBookItem.stuUnit }}</text>
</view> </view>
</view> </view>
<u-image
v-if="!buttonTitle"
width="96rpx"
height="52rpx"
src="../../../static/img/phone2.png"
@tap="tapButton"
></u-image>
<u-button <u-button
v-show="buttonTitle" v-else
size="mini" hover-class="background-color: #04a7ff; color: #ffffff"
type="primary"
@tap="tapButton" @tap="tapButton"
>{{ buttonTitle }} >
<view>{{ buttonTitle }}</view>
</u-button> </u-button>
</view> </view>
</template> </template>
...@@ -29,8 +37,7 @@ ...@@ -29,8 +37,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { src } from "@/utils/example" import { baseUrl } from "@/utils/request";
import { baseUrl } from "@/utils/request"
const props = defineProps({ const props = defineProps({
addressBookItem: { addressBookItem: {
...@@ -38,27 +45,31 @@ const props = defineProps({ ...@@ -38,27 +45,31 @@ const props = defineProps({
default: () => [], default: () => [],
} as any, } as any,
buttonTitle: String, buttonTitle: String,
}) });
const emits = defineEmits(["tapButton"]) const emits = defineEmits(["tapButton"]);
const tapButton = () => { const tapButton = () => {
if (props.buttonTitle === "联系TA") if (!props.buttonTitle) location.href = "tel:" + props.addressBookItem.Phone;
emits("tapButton", props.addressBookItem.Phone) // emits("tapButton", props.addressBookItem.Phone)
else else
emits( emits(
"tapButton", "tapButton",
props.addressBookItem.FCLASS, props.addressBookItem.FCLASS,
props.addressBookItem.studentId, props.addressBookItem.studentId,
props.addressBookItem.courseId props.addressBookItem.courseId
) );
} };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.address-book-container { .address-book-container {
margin-bottom: 32rpx; margin-bottom: 32rpx;
height: 200rpx; height: 152rpx;
:deep(.u-card__body) {
padding: 16rpx 32rpx !important;
}
.address-book-content { .address-book-content {
display: flex; display: flex;
...@@ -67,21 +78,42 @@ const tapButton = () => { ...@@ -67,21 +78,42 @@ const tapButton = () => {
.left { .left {
display: flex; display: flex;
align-items: center;
.content { .content {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: flex-end; justify-content: flex-end;
margin-left: 20rpx; margin-left: 20rpx;
color: #909399;
font-size: 26rpx;
.stu-name {
font-size: 28rpx;
font-weight: 500;
color: #000000;
margin-bottom: 8rpx;
}
.tel { .tel {
margin: 20rpx 0; margin-bottom: 4rpx;
font-size: 24rpx;
font-weight: 400;
color: rgba(34, 34, 34, 0.5);
height: 34rpx;
line-height: 28rpx;
} }
} }
} }
uni-button { .u-btn {
margin: 0; margin: 0;
width: 160rpx;
height: 72rpx;
background: #05a8ff;
border-radius: 8rpx;
font-size: 28rpx;
color: #ffffff;
} }
} }
} }
......
...@@ -7,7 +7,12 @@ ...@@ -7,7 +7,12 @@
@close="close" @close="close"
> >
<view class="u_card"> <view class="u_card">
<u-card :title="'学员' + label"> <u-card
:title="'学员' + label"
:show-head="false"
margin="0"
border-radius="20"
>
<template #body> <template #body>
<view>学员姓名:{{ name }}</view> <view>学员姓名:{{ name }}</view>
<u-form :model="formData" label-position="top"> <u-form :model="formData" label-position="top">
...@@ -48,37 +53,37 @@ ...@@ -48,37 +53,37 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { toast } from "@/utils/util" import { toast } from "@/utils/util";
const props = defineProps({ const props = defineProps({
show: Boolean, show: Boolean,
name: String, name: String,
label: String, label: String,
radio: String, radio: String,
}) });
const emits = defineEmits(["update:modelValue", "submit"]) const emits = defineEmits(["update:modelValue", "submit"]);
const formData = reactive({ const formData = reactive({
radio: "", radio: "",
reason: "", reason: "",
}) });
const submit = () => { const submit = () => {
if (!formData.reason) return toast("请输入" + props.label) if (!formData.reason) return toast("请输入" + props.label);
emits("submit", formData.reason) emits("submit", formData.reason);
} };
const close = () => { const close = () => {
formData.reason = "" formData.reason = "";
} };
const init = (radio: string) => { const init = (radio: string) => {
formData.radio = radio formData.radio = radio;
} };
defineExpose({ defineExpose({
init, init,
}) });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
......
...@@ -3,40 +3,58 @@ ...@@ -3,40 +3,58 @@
v-model="props.show" v-model="props.show"
mode="bottom" mode="bottom"
closeable closeable
safe-area-inset-bottom
height="40%" height="40%"
border-radius="30" border-radius="30"
@close="handeClose" @close="handeClose"
> >
<view class="info"> <view class="info">
<block v-if="infoList.length"> <view style="width: 100%">
<text class="title">课件资料</text> <view class="title">课程资料</view>
<view v-for="(item, i) in infoList" :key="i" class="item"> <view v-if="infoList.length">
<view> <view v-for="(item, i) in infoList" :key="i" class="item">
<u-icon name="order" size="50"></u-icon> <view>
<text>{{ item.name }}</text> <!-- <u-icon name="order" size="50"></u-icon> -->
</view> <u-image
<view> src="../../../static/img/PDF.png"
<u-icon width="35"
name="eye-fill" height="40"
size="50" ></u-image>
style="margin-right: 30rpx" <view class="pdf-name">{{ item.name }}</view>
@tap="pdfView(item)" </view>
></u-icon> <view>
<u-icon name="download" size="50" @tap="downLoadPdf(item)"></u-icon> <u-image
src="../../../static/img/Check.png"
width="35"
height="40"
style="margin-right: 30rpx"
@tap="pdfView(item)"
></u-image>
<u-image
src="../../../static/img/download.png"
width="35"
height="40"
@tap="downLoadPdf(item)"
></u-image>
</view>
</view> </view>
</view> </view>
</block> <u-empty
<view v-else class="empty"> v-else
<u-empty text="暂无资料" mode="list" /> text="暂无数据~"
icon-size="300"
:margin-top="100"
src="../../static/img/noData.png"
></u-empty>
</view> </view>
</view> </view>
</u-popup> </u-popup>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { zconfirm } from "@/utils/util" import { zconfirm } from "@/utils/util";
import { getFileList } from "@/api/course" import { getFileList } from "@/api/course";
import { baseUrl } from "@/utils/request" import { baseUrl } from "@/utils/request";
const props = defineProps({ const props = defineProps({
show: { show: {
...@@ -47,9 +65,9 @@ const props = defineProps({ ...@@ -47,9 +65,9 @@ const props = defineProps({
type: String, type: String,
default: "", default: "",
}, },
}) });
const emits = defineEmits(["update:show"]) const emits = defineEmits(["update:show"]);
const pdfView = (item: any) => { const pdfView = (item: any) => {
uni.navigateTo({ uni.navigateTo({
...@@ -58,38 +76,41 @@ const pdfView = (item: any) => { ...@@ -58,38 +76,41 @@ const pdfView = (item: any) => {
item.name + item.name +
"&url=" + "&url=" +
encodeURIComponent(baseUrl + "/" + item.url), encodeURIComponent(baseUrl + "/" + item.url),
}) success: () => {
} handeClose();
},
});
};
const infoList = ref([] as any) const infoList = ref([] as any);
const downLoadPdf = (item: any) => { const downLoadPdf = (item: any) => {
zconfirm("确定下载课资料?", (result: boolean) => { zconfirm("确定下载课资料?", (result: boolean) => {
if (result) { if (result) {
const url = baseUrl + "/" + item.url const url = baseUrl + "/" + item.url;
const a = document.createElement("a") const a = document.createElement("a");
a.href = url a.href = url;
a.download = item.name a.download = item.name;
a.click() a.click();
} }
}) });
} };
const handeClose = () => { const handeClose = () => {
emits("update:show", false) emits("update:show", false);
} };
const init = async () => { const init = async () => {
const { data: res } = await getFileList({ courseNumber: props.courseNumber }) const { data: res } = await getFileList({ courseNumber: props.courseNumber });
if (res.code == 200) { if (res.code == 200) {
console.log(res) // console.log(res)
infoList.value = res.data infoList.value = res.data;
} }
} };
defineExpose({ defineExpose({
init, init,
}) });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
...@@ -97,19 +118,18 @@ defineExpose({ ...@@ -97,19 +118,18 @@ defineExpose({
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
padding: 0 30rpx; padding: 0 32rpx;
.title { .title {
// position: sticky;
// top: 0;
// left: 0;
height: 90rpx;
line-height: 90rpx;
font-size: 32rpx;
font-weight: bolder;
color: $u-main-color;
text-align: center; text-align: center;
width: 100%; width: 100%;
margin-bottom: 48rpx;
margin-top: 30rpx;
height: 48rpx;
font-size: 34rpx;
font-weight: 500;
color: #222222;
line-height: 40rpx;
} }
.item { .item {
...@@ -117,30 +137,37 @@ defineExpose({ ...@@ -117,30 +137,37 @@ defineExpose({
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
background-color: $u-type-info-light;
width: 100%; width: 100%;
height: 100rpx; padding: 20rpx 40rpx;
padding: 30rpx;
border-radius: 10rpx; border-radius: 10rpx;
margin-bottom: 20rpx; margin-bottom: 20rpx;
// height: 88rpx;
background: #ffffff;
box-shadow: 0rpx 8rpx 60rpx 0rpx rgba(0, 0, 0, 0.05);
border-radius: 16rpx;
view { view {
display: flex; display: flex;
align-items: center; align-items: center;
text { .pdf-name {
margin-left: 10rpx; margin-left: 22rpx;
display: block; font-size: 28rpx;
font-size: 32rpx; font-weight: 400;
color: #000000; color: rgba(34, 34, 34, 0.9);
} }
} }
} }
} }
</style> </style>
<style> <style lang="scss" scoped>
:deep(uni-modal) { :deep(uni-modal) {
z-index: 19999 !important; z-index: 19999 !important;
} }
:deep(.uni-scroll-view-content) {
background-color: #fbfcff;
}
</style> </style>
<template> <template>
<!-- <headers title="我的班级" /> --> <view style="padding: 0 32rpx 168rpx">
<u-tabs <u-tabs
:list="tabsState.list" :list="tabsState.list"
:is-scroll="false" :is-scroll="false"
v-model="tabsState.current" v-model="tabsState.current"
bg-color="#f5f5f5" :active-item-style="{ fontSize: '34rpx', color: '#000000' }"
@change="tabsChange" font-size="28"
/> bar-width="72"
<uni-search-bar bar-height="6"
placeholder="姓名/单位/电话" bg-color="#fbfcff"
bgColor="#ffffff" inactive-color="#cecfcf"
clearButton="auto" active-color="#05a8ff"
cancelButton="none" @change="tabsChange"
@confirm="search" />
@clear="clear" <uni-search-bar
/> placeholder="姓名/单位/电话"
<view v-if="addressBookList.length" class="address-book-item-container"> bgColor="#ffffff"
<text style="margin-bottom: 20rpx; display: block" clearButton="auto"
>为你找到{{ listQuery.total }}个的同学</text cancelButton="none"
> @confirm="search"
<block v-for="(item, i) in addressBookList" :key="i"> @clear="clear"
<addressBookItem />
:addressBookItem="item" <view v-if="addressBookList.length">
:buttonTitle="tabsState.current ? '' : '查看评价'" <text class="fund">为您找到{{ listQuery.total }}位同学</text>
@tapButton="tapButton" <block v-for="(item, i) in addressBookList" :key="i">
/> <addressBookItem
</block> :addressBookItem="item"
<view style="padding: 20rpx"> :buttonTitle="tabsState.current ? '' : '查看评价'"
<u-loadmore :status="status" icon-type="flower" /> @tapButton="tapButton"
/>
</block>
<view style="padding: 20rpx">
<u-loadmore :status="status" icon-type="flower" />
</view>
</view> </view>
</view> <u-empty
<view v-else class="empty"> v-else
<u-empty text="暂无数据" mode="list"></u-empty> text="暂无数据~"
icon-size="506"
:margin-top="220"
src="../../static/img/noData.png"
></u-empty>
</view> </view>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
// import headers from "@/components/header/index.vue" // import headers from "@/components/header/index.vue"
import addressBookItem from "./components/addressBookItem.vue" import addressBookItem from "./components/addressBookItem.vue";
import { getClassBook } from "@/api/class" import { getClassBook } from "@/api/class";
import { useGlobalStore } from "@/store/useStore" import { useGlobalStore } from "@/store/useStore";
const globalStore = useGlobalStore() const globalStore = useGlobalStore();
const listQuery = reactive({ const listQuery = reactive({
Phone: globalStore.Phone, Phone: globalStore.Phone,
...@@ -52,7 +61,7 @@ const listQuery = reactive({ ...@@ -52,7 +61,7 @@ const listQuery = reactive({
total: 0, total: 0,
type: 0, type: 0,
Name: "", Name: "",
}) });
const tabsState = reactive({ const tabsState = reactive({
list: [ list: [
...@@ -64,35 +73,35 @@ const tabsState = reactive({ ...@@ -64,35 +73,35 @@ const tabsState = reactive({
}, },
], ],
current: 0, current: 0,
}) });
const status = ref("loadmore") const status = ref("loadmore");
const addressBookList = ref([] as any) const addressBookList = ref([] as any);
onLoad((options: any) => { onLoad((options: any) => {
listQuery.classId = options.classId listQuery.classId = options.classId;
listQuery.courseId = options.courseId listQuery.courseId = options.courseId;
init() init();
}) });
const search = (val: any) => { const search = (val: any) => {
listQuery.Name = val.value listQuery.Name = val.value;
tabsChange(tabsState.current) tabsChange(tabsState.current);
} };
const clear = () => { const clear = () => {
listQuery.Name = "" listQuery.Name = "";
tabsChange(tabsState.current) tabsChange(tabsState.current);
} };
const tabsChange = (index: number) => { const tabsChange = (index: number) => {
addressBookList.value = [] addressBookList.value = [];
listQuery.pageIndex = 1 listQuery.pageIndex = 1;
listQuery.pageSize = 10 listQuery.pageSize = 10;
if (index) { if (index) {
listQuery.type = 1 listQuery.type = 1;
} else listQuery.type = 0 } else listQuery.type = 0;
init() init();
} };
const tapButton = (classId: string, studentId: string, courseId: string) => { const tapButton = (classId: string, studentId: string, courseId: string) => {
uni.navigateTo({ uni.navigateTo({
...@@ -103,38 +112,33 @@ const tapButton = (classId: string, studentId: string, courseId: string) => { ...@@ -103,38 +112,33 @@ const tapButton = (classId: string, studentId: string, courseId: string) => {
courseId + courseId +
"&studentId=" + "&studentId=" +
studentId, studentId,
}) });
} };
const init = async () => { const init = async () => {
status.value = "loading" status.value = "loading";
const { data: res } = await getClassBook(listQuery) const { data: res } = await getClassBook(listQuery);
if (res.code == 200) { if (res.code == 200) {
if (res.total > 10) status.value = "loadmore" if (res.total > 10) status.value = "loadmore";
else status.value = "nomore" else status.value = "nomore";
addressBookList.value = res.data addressBookList.value = res.data;
listQuery.total = res.total listQuery.total = res.total;
} }
} };
// 上拉加载数据 // 上拉加载数据
onReachBottom(() => { onReachBottom(() => {
// 判断是否还有下一页数据 // 判断是否还有下一页数据
if (listQuery.pageIndex * listQuery.pageSize >= listQuery.total) if (listQuery.pageIndex * listQuery.pageSize >= listQuery.total)
return (status.value = "nomore") return (status.value = "nomore");
// // 判断是否正在请求其它数据,如果是,则不发起额外的请求 // // 判断是否正在请求其它数据,如果是,则不发起额外的请求
if (status.value === "loading") return if (status.value === "loading") return;
listQuery.pageIndex += 1 listQuery.pageIndex += 1;
init() init();
}) });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.address-book-item-container { .address-book-item-container {
padding: 0 30rpx; padding: 0 30rpx;
.uni-searchbar {
padding: 0;
margin: 20rpx 0;
}
} }
</style> </style>
<template> <template>
<!-- <headers title="培训评价" /> -->
<view class="evaluate-container"> <view class="evaluate-container">
<u-card :show-head="false" :show-foot="false" margin="0" border-radius="20"> <u-card :show-head="false" :show-foot="false" margin="0" border-radius="24">
<template #body> <template #body>
<h4>尊敬的各位学员:</h4> <h4 style="font-weight: bolder; color: #000000; font-size: 28rpx">
尊敬的各位学员:
</h4>
<text class="detail"> <text class="detail">
感谢您参加本次培训班!请各位学员对此次授课老师及教学安排进行满意度评价,同时我们也欢迎您提出意见和建议,您的感受及观点对我们非常重要谢谢! 感谢您参加本次培训班!请各位学员对此次授课老师及教学安排进行满意度评价,同时我们也欢迎您提出意见和建议,您的感受及观点对我们非常重要谢谢!
</text> </text>
</template> </template>
</u-card> </u-card>
<u-card :show-head="false" :show-foot="false" margin="0" border-radius="20"> <view class="courseEvaluation">
<view class="half-circle"></view>
课程评价
</view>
<u-card :show-head="false" :show-foot="false" margin="0" border-radius="24">
<template #body> <template #body>
<view> <view>
<view class="rateItem"> <view class="rateItem">
...@@ -17,56 +22,64 @@ ...@@ -17,56 +22,64 @@
<u-rate <u-rate
:count="5" :count="5"
v-model="evaluateData.parmeters.Model.FContent" v-model="evaluateData.parmeters.Model.FContent"
size="42" size="44"
active-color="#F7BA2A" active-color="#F7BA2A"
:disabled="disabled" :disabled="disabled"
/> />
<view class="rate">
{{ evaluateStr(evaluateData.parmeters.Model.FContent) }}
</view>
</view> </view>
<view class="rateItem"> <view class="rateItem">
<h4>授课讲师</h4> <h4>授课讲师</h4>
<u-rate <u-rate
:count="5" :count="5"
v-model="evaluateData.parmeters.Model.FLecturer" v-model="evaluateData.parmeters.Model.FClassService"
size="42" size="44"
active-color="#F7BA2A" active-color="#F7BA2A"
:disabled="disabled" :disabled="disabled"
/> />
<view class="rate">
{{ evaluateStr(evaluateData.parmeters.Model.FClassService) }}
</view>
</view> </view>
</view> </view>
</template> </template>
</u-card> </u-card>
<u-card :show-head="false" :show-foot="false" margin="0" border-radius="20"> <view class="evaluate-item">
<template #body> <view class="title">您的培训收获与意见建议:</view>
<text style="margin-top: 40rpx"> 您的培训收获与意见建议: </text> <u-card
<view class="evaluate-textarea last"> :show-head="false"
:show-foot="false"
margin="0"
border-radius="24"
>
<template #body>
<u-input <u-input
v-model="evaluateData.parmeters.Model.FOpinion" v-model="evaluateData.parmeters.Model.FOpinion"
type="textarea" type="textarea"
placeholder-style="background-color: #f5f5f5;font-size: 24rpx;overflow-y: auto;" placeholder-style="font-size: 24rpx;font-weight: 400;color: #BCBCBC;"
height="160"
maxlength="1400" maxlength="1400"
:auto-height="false"
placeholder="快来说说您的想法~" placeholder="快来说说您的想法~"
:disabled="disabled" :disabled="disabled"
/> />
</view> </template>
</template> </u-card>
</u-card> </view>
<view class="submit" v-show="!disabled"> <view class="submit" v-show="!disabled">
<u-button type="primary" @tap="submit">确定提交</u-button> <u-button @tap="submit">确定提交</u-button>
</view> </view>
</view> </view>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
// import headers from "@/components/header/index.vue" // import headers from "@/components/header/index.vue"
import { remarkOn, remarkDetail } from "@/api/class" import { remarkOn, remarkDetail } from "@/api/class";
import { useGlobalStore } from "@/store/useStore" import { useGlobalStore } from "@/store/useStore";
import { toast, zconfirm } from "@/utils/util" import { toast, zconfirm, evaluateStr } from "@/utils/util";
const globalStore = useGlobalStore() const globalStore = useGlobalStore();
const disabled = ref(false) const disabled = ref(false);
const evaluateData = reactive({ const evaluateData = reactive({
parmeters: { parmeters: {
NeedReturnFields: ["FID"], NeedReturnFields: ["FID"],
...@@ -95,11 +108,11 @@ const evaluateData = reactive({ ...@@ -95,11 +108,11 @@ const evaluateData = reactive({
FClassService: 0, //班主任服务 FClassService: 0, //班主任服务
}, },
}, },
}) });
onLoad(async (options: any) => { onLoad(async (options: any) => {
evaluateData.parmeters.Model.FClass.FNUMBER = options.classNumber evaluateData.parmeters.Model.FClass.FNUMBER = options.classNumber;
evaluateData.parmeters.Model.FTrainingPro.FNUMBER = options.ItemNumber evaluateData.parmeters.Model.FTrainingPro.FNUMBER = options.ItemNumber;
if (options.iEvaluate != "false") { if (options.iEvaluate != "false") {
let data = { let data = {
classId: "", classId: "",
...@@ -107,37 +120,37 @@ onLoad(async (options: any) => { ...@@ -107,37 +120,37 @@ onLoad(async (options: any) => {
studentId: options.studentId, studentId: options.studentId,
pageIndex: 1, pageIndex: 1,
pageSize: 10, pageSize: 10,
} };
const { data: res } = await remarkDetail(data) const { data: res } = await remarkDetail(data);
if (res.code == 200) { if (res.code == 200) {
evaluateData.parmeters.Model.FClassService = res.data[0].FCLASSSERVICE evaluateData.parmeters.Model.FClassService = res.data[0].FCLASSSERVICE;
evaluateData.parmeters.Model.FContent = res.data[0].FCONTENT evaluateData.parmeters.Model.FContent = res.data[0].FCONTENT;
evaluateData.parmeters.Model.FLecturer = res.data[0].LECTURER evaluateData.parmeters.Model.FLecturer = res.data[0].LECTURER;
evaluateData.parmeters.Model.FPostService = res.data[0].FPOSTSERVICE evaluateData.parmeters.Model.FPostService = res.data[0].FPOSTSERVICE;
evaluateData.parmeters.Model.FHighlights = res.data[0].FHIGHLIGHTS evaluateData.parmeters.Model.FHighlights = res.data[0].FHIGHLIGHTS;
evaluateData.parmeters.Model.FSupplement = res.data[0].FSUPPLEMENT evaluateData.parmeters.Model.FSupplement = res.data[0].FSUPPLEMENT;
evaluateData.parmeters.Model.FOpinion = res.data[0].FOPINION evaluateData.parmeters.Model.FOpinion = res.data[0].FOPINION;
disabled.value = true disabled.value = true;
} }
} }
}) });
const submit = () => { const submit = () => {
zconfirm("确定提交评价?", async (result: boolean) => { zconfirm("确定提交评价?", async (result: boolean) => {
if (result) { if (result) {
const { data: res } = await remarkOn(evaluateData) const { data: res } = await remarkOn(evaluateData);
if (res.code == 200) { if (res.code == 200) {
uni.navigateBack() uni.navigateBack();
toast("评价成功") toast("评价成功");
} }
} }
}) });
} };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.evaluate-container { .evaluate-container {
padding: 30rpx; padding: 30rpx 30rpx 110rpx 30rpx;
.u-card { .u-card {
margin-bottom: 10rpx !important; margin-bottom: 10rpx !important;
...@@ -150,7 +163,9 @@ const submit = () => { ...@@ -150,7 +163,9 @@ const submit = () => {
text-indent: 2em; text-indent: 2em;
display: block; display: block;
font-size: 28rpx; font-size: 28rpx;
margin-top: 10rpx; margin-top: 20rpx;
font-weight: 400;
color: rgba(34, 34, 34, 0.8);
} }
.rateItem { .rateItem {
...@@ -166,23 +181,45 @@ const submit = () => { ...@@ -166,23 +181,45 @@ const submit = () => {
h4 { h4 {
width: 140rpx; width: 140rpx;
margin-right: 20rpx; margin-right: 20rpx;
font-size: 28rpx;
font-weight: 500;
color: rgba(34, 34, 34, 0.9);
} }
} }
}
.evaluate-textarea { .evaluate-item {
background-color: #f5f5f5; margin-top: 40rpx;
padding: 0 10rpx; .title {
box-sizing: border-box; font-size: 28rpx;
margin: 20rpx 0; font-weight: 400;
color: rgba(0, 0, 0, 0.9);
margin-bottom: 24rpx;
} }
:deep(.u-card__body) {
.last { padding: 20rpx 24rpx !important;
margin-bottom: 0; }
:deep(.uni-textarea-placeholder, .u-input__textarea) {
background-color: #ffffff !important;
}
:deep(.uni-textarea-compute) {
font-size: 24rpx;
font-weight: 400;
color: rgba(0, 0, 0, 0.6);
}
:deep(.uni-textarea-textarea) {
overflow-y: auto !important;
} }
} }
} }
.submit { .submit {
margin: 40rpx 40rpx 0; margin: 64rpx 184rpx 0;
.u-btn {
width: 320rpx;
height: 96rpx;
background: #05a8ff;
border-radius: 12rpx;
color: #ffffff;
}
} }
</style> </style>
...@@ -5,7 +5,13 @@ ...@@ -5,7 +5,13 @@
:list="tabsState.list" :list="tabsState.list"
:is-scroll="false" :is-scroll="false"
v-model="tabsState.current" v-model="tabsState.current"
bg-color="#f5f5f5" :active-item-style="{ fontSize: '34rpx', color: '#000000' }"
font-size="28"
bar-width="72"
bar-height="6"
bg-color="#fbfcff"
inactive-color="#cecfcf"
active-color="#05a8ff"
@change="tabsChange" @change="tabsChange"
/> />
<!-- 搜索 --> <!-- 搜索 -->
...@@ -19,9 +25,7 @@ ...@@ -19,9 +25,7 @@
/> />
<!-- 内容 --> <!-- 内容 -->
<view v-if="courseList.length"> <view v-if="courseList.length">
<text style="margin-bottom: 20rpx; display: block" <text class="fund">为您找到{{ listQuery.total }}个课程</text>
>为你找到{{ listQuery.total }}个的班级</text
>
<block v-for="(item, index) in courseList" :key="index"> <block v-for="(item, index) in courseList" :key="index">
<courseItem :courseItem="item" :current="tabsState.current" /> <courseItem :courseItem="item" :current="tabsState.current" />
...@@ -30,19 +34,23 @@ ...@@ -30,19 +34,23 @@
<u-loadmore :status="status" icon-type="flower" /> <u-loadmore :status="status" icon-type="flower" />
</view> </view>
</view> </view>
<view v-else class="empty"> <u-empty
<u-empty text="暂无数据" mode="list" /> v-else
</view> text="暂无数据~"
icon-size="506"
:margin-top="220"
src="../../static/img/noData.png"
></u-empty>
</view> </view>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
// import headers from "@/components/header/index.vue" // import headers from "@/components/header/index.vue"
import courseItem from "./components/courseItem.vue" import courseItem from "./components/courseItem.vue";
import { getCourseList } from "@/api/course" import { getCourseList } from "@/api/course";
import { useGlobalStore } from "@/store/useStore" import { useGlobalStore } from "@/store/useStore";
const globalStore = useGlobalStore() const globalStore = useGlobalStore();
const tabsState = reactive({ const tabsState = reactive({
list: [ list: [
...@@ -57,9 +65,9 @@ const tabsState = reactive({ ...@@ -57,9 +65,9 @@ const tabsState = reactive({
}, },
], ],
current: 0, current: 0,
}) });
const courseList = ref([] as any) const courseList = ref([] as any);
const listQuery = reactive({ const listQuery = reactive({
Phone: globalStore.Phone, Phone: globalStore.Phone,
...@@ -68,61 +76,61 @@ const listQuery = reactive({ ...@@ -68,61 +76,61 @@ const listQuery = reactive({
total: 0, total: 0,
type: 0, type: 0,
Name: "", Name: "",
}) });
const status = ref("loadmore") const status = ref("loadmore");
const tabsChange = (index: number) => { const tabsChange = (index: number) => {
courseList.value = [] courseList.value = [];
listQuery.pageIndex = 1 listQuery.pageIndex = 1;
listQuery.pageSize = 10 listQuery.pageSize = 10;
switch (index) { switch (index) {
case 0: case 0:
listQuery.type = 0 listQuery.type = 0;
break break;
case 1: case 1:
listQuery.type = 1 listQuery.type = 1;
break break;
default: default:
listQuery.type = 2 listQuery.type = 2;
break break;
} }
init() init();
} };
const search = (val: any) => { const search = (val: any) => {
listQuery.Name = val.value listQuery.Name = val.value;
tabsChange(tabsState.current) tabsChange(tabsState.current);
} };
const clear = () => { const clear = () => {
listQuery.Name = "" listQuery.Name = "";
tabsChange(tabsState.current) tabsChange(tabsState.current);
} };
// 上拉加载数据 // 上拉加载数据
onReachBottom(() => { onReachBottom(() => {
// 判断是否还有下一页数据 // 判断是否还有下一页数据
if (listQuery.pageIndex * listQuery.pageSize >= listQuery.total) if (listQuery.pageIndex * listQuery.pageSize >= listQuery.total)
return (status.value = "nomore") return (status.value = "nomore");
// // 判断是否正在请求其它数据,如果是,则不发起额外的请求 // // 判断是否正在请求其它数据,如果是,则不发起额外的请求
if (status.value === "loading") return if (status.value === "loading") return;
listQuery.pageIndex += 1 listQuery.pageIndex += 1;
init() init();
}) });
const init = async () => { const init = async () => {
status.value = "loading" status.value = "loading";
const { data: res } = await getCourseList(listQuery) const { data: res } = await getCourseList(listQuery);
if (res.code == 200) { if (res.code == 200) {
if (res.total > 10) status.value = "loadmore" if (res.total > 10) status.value = "loadmore";
else status.value = "nomore" else status.value = "nomore";
courseList.value = [...courseList.value, ...res.data] courseList.value = [...courseList.value, ...res.data];
listQuery.total = res.total listQuery.total = res.total;
} }
} };
init() init();
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
...@@ -130,11 +138,6 @@ init() ...@@ -130,11 +138,6 @@ init()
padding: 0 30rpx 30rpx; padding: 0 30rpx 30rpx;
padding-top: 20rpx; padding-top: 20rpx;
.uni-searchbar {
padding: 0;
margin: 20rpx 0;
}
.tag .u-tag { .tag .u-tag {
margin-right: 20rpx; margin-right: 20rpx;
} }
......
<template> <template>
<!-- <headers :title="pdfState.title" /> -->
<view class="pdf-container"> <view class="pdf-container">
<web-view class="webview" :src="pdfState.pdfUrl"></web-view> <web-view class="webview" :src="pdfState.pdfUrl"></web-view>
<view class="down" @tap="downLoadPdf">
<u-image
src="../../static/img/download.png"
width="50"
height="50"
></u-image>
<view style="margin-left: 10rpx">点击下载</view>
</view>
</view> </view>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
// import headers from "@/components/header/index.vue" import { zconfirm } from "@/utils/util";
const pdfState = reactive({ const pdfState = reactive({
title: "", title: "",
pdfUrl: "", pdfUrl: "",
viewerUrl: "/static/pdf/web/viewer.html", viewerUrl: "/static/pdf/web/viewer.html",
}) url: "",
});
const downLoadPdf = () => {
zconfirm("确定下载课程资料?", (result: boolean) => {
if (result) {
const a = document.createElement("a");
a.href = pdfState.url;
a.download = pdfState.title;
a.click();
}
});
};
onLoad((options: any) => { onLoad((options: any) => {
pdfState.title = options.name pdfState.title = options.name;
pdfState.url = options.url;
pdfState.pdfUrl = pdfState.pdfUrl =
pdfState.viewerUrl + "?file=" + encodeURIComponent(options.url) pdfState.viewerUrl + "?file=" + encodeURIComponent(options.url);
}) });
onReady(() => { onReady(() => {
uni.setNavigationBarTitle({ uni.setNavigationBarTitle({
title: pdfState.title, title: pdfState.title,
}) });
}) });
onBackPress(() => {
uni.$emit("refresh", { refresh: true });
});
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.pdf-container { .pdf-container {
width: 100vw; width: 100vw;
height: 100vh; height: 100vh;
position: relative;
.webview { .webview {
height: 90%; height: 90%;
} }
.down {
position: absolute;
bottom: 15%;
z-index: 999;
right: 0;
background-color: #ffffff;
padding: 10rpx;
display: flex;
align-items: center;
border-radius: 10rpx 0 0 10rpx;
color: #04a7ff;
}
} }
</style> </style>
<template> <template>
<view class="see-more-container"> <view style="position: relative">
<block v-for="(item, index) in Teachs"> <u-image
width="100%"
height="824rpx"
:src="baseUrl + '/' + Teachs[0].Url"
/>
<view class="teach-name">
{{ Teachs[0].teachName }}
</view>
<view class="see-more-container">
<view class="menu-title">
<view class="half-circle"></view>
<view class="title">讲师简介</view>
</view>
<view class="detail">
{{ Teachs[0].teachMsg }}
</view>
</view>
<!-- <block v-for="(item, index) in Teachs">
<u-card :show-head="false" :show-foot="false" margin="0"> <u-card :show-head="false" :show-foot="false" margin="0">
<template #body> <template #body>
<u-section <u-section
...@@ -41,51 +58,96 @@ ...@@ -41,51 +58,96 @@
</view> </view>
</template> </template>
</u-card> </u-card>
</block> </block> -->
</view> </view>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { useCourseStore } from "@/store/modules/courseStore" import { useCourseStore } from "@/store/modules/courseStore";
import { baseUrl } from "@/utils/request" import { baseUrl } from "@/utils/request";
const courseStore = useCourseStore() const courseStore = useCourseStore();
const Teachs = computed(() => courseStore.getTeachs) const Teachs = computed(() => courseStore.getTeachs);
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.see-more-container { .see-more-container {
padding: 20rpx 30rpx; padding: 52rpx 32rpx 0;
box-sizing: border-box;
position: fixed;
bottom: 0;
width: 100%;
height: 830rpx;
background: #fbfcff;
border-radius: 90rpx 90rpx 0rpx 0rpx;
border-radius: 90rpx;
.u-card { .menu-title {
margin-bottom: 24rpx !important; width: 100%;
display: flex;
margin-bottom: 30rpx;
.info { .title {
display: flex; font-size: 34rpx;
margin-top: 20rpx; font-weight: 600;
color: #222222;
.info-text { line-height: 40rpx;
display: flex;
flex-direction: column;
margin-left: 20rpx;
justify-content: space-around;
text:nth-child(1) {
font-size: 34rpx;
font-weight: bold;
color: #303133;
}
}
} }
}
.detail { .detail {
text-indent: 1em; text-indent: 2em;
margin-top: 30rpx; font-size: 28rpx;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-weight: 400;
font-size: 28rpx; color: rgba(34, 34, 34, 0.8);
line-height: 1.25; height: 630rpx;
} overflow-y: auto;
} }
// .u-card {
// margin-bottom: 24rpx !important;
// .info {
// display: flex;
// margin-top: 20rpx;
// .info-text {
// display: flex;
// flex-direction: column;
// margin-left: 20rpx;
// justify-content: space-around;
// text:nth-child(1) {
// font-size: 34rpx;
// font-weight: bold;
// color: #303133;
// }
// }
// }
// .detail {
// text-indent: 1em;
// margin-top: 30rpx;
// font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
// font-size: 28rpx;
// line-height: 1.25;
// }
// }
}
.teach-name {
position: absolute;
top: 594rpx;
left: 50%;
transform: translateX(-50%);
width: 184rpx;
height: 68rpx;
background: rgba(4, 167, 255, 0.3);
border-radius: 16rpx;
line-height: 68rpx;
font-size: 34rpx;
font-weight: 600;
color: #ffffff;
text-align: center;
} }
</style> </style>
<template> <template>
<!-- <headers title='西部人力培训中心' backIconName="close" /> --> <view class="bg-header">
<u-image src="../../static/img/background.png" width="100%" height="100%" />
</view>
<view class="home-container"> <view class="home-container">
<!-- 用户信息部分 --> <!-- 用户信息部分 -->
<view class="user-info"> <view class="user-info">
<u-image <u-image
width="260rpx" width="240rpx"
height="260rpx" height="240rpx"
:src="baseUrl + '/' + globalStore.infoData.Image" :src="baseUrl + '/' + globalStore.infoData?.Image"
border-radius="30" border-radius="24"
/> />
<text class="name">{{ globalStore.infoData.Name }}</text> <text class="name">{{ globalStore.infoData?.Name }}</text>
<view v-if="globalStore.Phone" class="info"> <view v-if="globalStore.Phone" class="info">
<text>{{ <text>{{
globalStore.infoData.Type == "BZR" ? "班主任" : "讲师" globalStore.infoData.Type == "BZR" ? "班主任" : "讲师"
...@@ -17,12 +19,15 @@ ...@@ -17,12 +19,15 @@
</view> </view>
</view> </view>
<view class="user-menu"> <view class="menu-title">
<text class="menu-title">服务功能</text> <view class="half-circle"></view>
<view class="title">服务功能</view>
</view>
<!-- <view class="user-menu">
<view class="content"> <view class="content">
<u-grid :col="3"> <u-grid :col="3">
<u-grid-item @tap="toClass"> <u-grid-item @tap="toClass">
<!-- <u-badge count="2" :offset="[20, 20]"></u-badge> -->
<u-icon name="man-add-fill" :size="53"></u-icon> <u-icon name="man-add-fill" :size="53"></u-icon>
<view class="grid-text">管理班级</view> <view class="grid-text">管理班级</view>
</u-grid-item> </u-grid-item>
...@@ -31,7 +36,6 @@ ...@@ -31,7 +36,6 @@
<view class="grid-text">我的课程</view> <view class="grid-text">我的课程</view>
</u-grid-item> </u-grid-item>
<u-grid-item @tap="toSetPositioning"> <u-grid-item @tap="toSetPositioning">
<!-- <u-badge count="3" :offset="[20, 20]"></u-badge> -->
<u-icon name="list-dot" :size="53"></u-icon> <u-icon name="list-dot" :size="53"></u-icon>
<view class="grid-text">设置考勤定位</view> <view class="grid-text">设置考勤定位</view>
</u-grid-item> </u-grid-item>
...@@ -41,54 +45,132 @@ ...@@ -41,54 +45,132 @@
</u-grid-item> </u-grid-item>
</u-grid> </u-grid>
</view> </view>
</view> -->
<view class="user-menu">
<view
class="menu-item"
v-for="item in menuList"
:key="item.id"
@tap="gridChange(item.id)"
>
<!-- Ribbon2 Ribbon5 -->
<u-image :src="item.src" width="120rpx" height="120rpx" />
<text>{{ item.name }}</text>
</view>
</view>
<view class="bg-footer">
<u-image
src="../../static/img/mask_group.png"
width="100%"
height="100%"
/>
</view> </view>
</view> </view>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
// import headers from '@/components/header/index.vue' import { useGlobalStore } from "@/store/useStore";
import { useGlobalStore } from "@/store/useStore" import { baseUrl } from "@/utils/request";
import { baseUrl } from "@/utils/request"
const globalStore = useGlobalStore();
const globalStore = useGlobalStore() const menuList = [
{
id: 0,
src: "../../static/img/Ribbon1.png",
name: "班级管理",
},
{
id: 1,
src: "../../static/img/Ribbon2.png",
name: "我的课程",
},
{
id: 2,
src: "../../static/img/Ribbon3.png",
name: "考勤定位",
},
{
id: 3,
src: "../../static/img/Ribbon4.png",
name: "讲师列表",
},
{
id: 4,
src: "../../static/img/Ribbon5.png",
name: "现场教学",
},
{
id: 5,
src: "../../static/img/Ribbon6.png",
name: "培训评价",
},
];
const toClass = () => { const toClass = () => {
uni.navigateTo({ uni.navigateTo({
url: "/pages/class/index", url: "/pages/class/index",
}) });
} };
const toCourse = () => { const toCourse = () => {
uni.navigateTo({ uni.navigateTo({
url: "/pages/course/index", url: "/pages/course/index",
}) });
} };
const toSetPositioning = () => { const toSetPositioning = () => {
uni.navigateTo({ uni.navigateTo({
url: "/pages/setPositioning/index", url: "/pages/setPositioning/index",
}) });
} };
const toTeachPoints = () => { const toTeachPoints = () => {
uni.navigateTo({ uni.navigateTo({
url: "/pages/teachPoints/index", url: "/pages/teachPoints/index",
}) });
} };
const gridChange = (type: number) => {
switch (type) {
case 0:
toClass();
break;
case 1:
toCourse();
break;
case 2:
toSetPositioning();
break;
case 3:
uni.navigateTo({
url: "/pages/lecturer/index",
});
break;
case 4:
toTeachPoints();
break;
case 5:
uni.navigateTo({
url: "/pages/trainingEvaluation/index",
});
break;
}
};
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
page { page {
background-image: url("https://img2.baidu.com/it/u=460732253,1892860896&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=888"); background-color: #ffffff;
background-size: cover; }
/* 背景图片自适应屏幕大小 */ .bg-header {
/* 其他样式设置 */ position: relative;
} }
.home-container { .home-container {
position: absolute;
top: 3%;
width: 100%; width: 100%;
height: calc(100% - 48px);
.user-info { .user-info {
margin: 40rpx 0 100rpx 0; margin: 40rpx 0 40rpx 0;
width: 100%; width: 100%;
height: 30%; height: 30%;
display: flex; display: flex;
...@@ -110,31 +192,48 @@ page { ...@@ -110,31 +192,48 @@ page {
} }
} }
.menu-title {
margin: 0 32rpx;
width: 100%;
display: flex;
margin-bottom: 32rpx;
.title {
font-size: 34rpx;
font-weight: 600;
color: #222222;
line-height: 40rpx;
}
}
.user-menu { .user-menu {
// height: 238rpx;
margin: 0 32rpx;
padding: 48rpx;
background: #ffffff;
box-shadow: 0rpx 8rpx 60rpx 0rpx rgba(0, 0, 0, 0.05);
border-radius: 24rpx;
display: flex; display: flex;
flex-direction: column; flex-wrap: wrap;
box-sizing: border-box; box-sizing: border-box;
margin: 16rpx;
border-radius: 8rpx; .menu-item {
// border: 1px solid #e4e7ed; text-align: center;
background-color: #ffffff; flex-basis: calc((100% - 96rpx) / 3);
overflow: hidden; // height: 200rpx;
color: #303133; display: flex;
transition: 0.3s; flex-direction: column;
box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.05); align-items: center;
margin-right: 48rpx;
.menu-title { margin-bottom: 24rpx;
box-sizing: border-box;
width: 100%;
font-size: 36rpx;
font-weight: bold;
padding: 32rpx 0 32rpx 50rpx;
background: linear-gradient(to right, #f4f8ff, #cce3fe);
} }
.content { & .menu-item:nth-child(3n) {
padding: 30rpx 0 80rpx 0; margin-right: 0;
} }
} }
} }
.bg-footer {
// z-index: -99;
}
</style> </style>
<template>
<view class="lecturer-item">
<u-card :show-head="false" margin="0" border-radius="24">
<template #body>
<view class="body">
<view class="body-left">
<view class="body-left-header">
<u-image
width="112rpx"
height="112rpx"
border-radius="8"
:src="baseUrl + '/' + lecturerItem.FPHOTO"
></u-image>
<view class="body-left-header-right">
<view class="body-left-header-right-top">
<text>{{ lecturerItem.FNAME }}</text>
<text class="line"></text>
<text>{{ lecturerItem.FTITLE }}</text>
</view>
<view class="body-left-header-right-bottom"
>党性学习第一节</view
>
</view>
</view>
<view class="body-left-bottom">
<view class="item"
>可授课程:{{ lecturerItem.FCANCOURSE }}
<view class="item-sub">查看全部可授课程</view>
</view>
<view class="item">课酬参考:{{ lecturerItem.FSALARY }}</view>
<view class="item"
>联系电话:{{
hidePhoneNumber(lecturerItem.FPHONENUMBER)
}}</view
>
</view>
</view>
<view class="body-right">
<view class="body-right-title">职称证明</view>
<u-image
width="182rpx"
height="250rpx"
:src="baseUrl + '/' + lecturerItem.FTITLEPROVE"
></u-image>
<view class="body-right-down" @tap="downTitleImage">点击下载</view>
</view>
</view>
</template>
<template #foot>
<view class="foot">
<text>{{ lecturerItem.FINTRODUCE }}</text>
</view>
</template>
</u-card>
</view>
</template>
<script setup lang="ts">
import { baseUrl } from "@/utils/request";
import { hidePhoneNumber, toast } from "@/utils/util";
const props = defineProps({
lecturerItem: {
type: Object,
} as any,
});
const downTitleImage = () => {
try {
uni.downloadFile({
url: baseUrl + "/" + props.lecturerItem.FTITLEPROVE, // 这里是你接口地址 若要传参 直接 url拼接参数即可
success: (res) => {
console.log(res, "res");
var tempFilePath = res.tempFilePath; // 这里拿到后端返回的图片路径
const url = tempFilePath;
const a = document.createElement("a");
a.href = url;
a.download = props.lecturerItem.FNAME + ".jpg";
a.click();
},
fail: () => {
uni.hideLoading();
},
});
} catch (error) {
toast("下载失败");
}
};
</script>
<style lang="scss" scoped>
.lecturer-item {
margin-bottom: 32rpx;
:deep(.u-card__body) {
padding: 40rpx 32rpx 32rpx !important;
}
:deep(.u-card__foot) {
padding: 32rpx 32rpx 40rpx !important;
}
.body {
display: flex;
height: 348rpx;
justify-content: space-between;
.body-left {
.body-left-header {
display: flex;
margin-bottom: 24rpx;
.body-left-header-right {
margin-left: 16rpx;
height: 112rpx;
display: flex;
flex-direction: column;
justify-content: space-between;
.body-left-header-right-top {
display: flex;
align-items: center;
font-size: 32rpx;
font-weight: 500;
color: #000000;
.line {
width: 0rpx;
height: 24rpx;
border: 2rpx solid rgba(0, 0, 0, 0.1);
margin: 0 8rpx;
}
& text:last-child {
font-size: 24rpx;
font-weight: 500;
color: rgba(0, 0, 0, 0.5);
line-height: 28rpx;
}
}
.body-left-header-right-bottom {
font-size: 28rpx;
font-weight: 400;
color: #666666;
}
}
}
.body-left-bottom {
.item {
font-size: 28rpx;
font-weight: 400;
color: #222222;
margin-bottom: 24rpx;
.item-sub {
font-size: 24rpx;
font-weight: 400;
color: #05a8ff;
margin-top: 4rpx;
}
}
& .item:last-child {
margin-bottom: 8rpx;
}
}
}
.body-right {
display: flex;
flex-direction: column;
align-items: center;
.body-right-title {
margin-bottom: 16rpx;
font-size: 28rpx;
font-weight: 400;
color: #222222;
}
.body-right-down {
font-size: 24rpx;
font-weight: 400;
color: #05a8ff;
margin-top: 8rpx;
}
}
}
.foot {
max-height: 102rpx;
font-size: 24rpx;
font-weight: 400;
color: rgba(34, 34, 34, 0.7);
text {
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
}
}
}
</style>
<template>
<view class="lecturer-container">
<!-- 搜索 -->
<uni-search-bar
placeholder="班级名称"
bgColor="#ffffff"
clearButton="auto"
cancelButton="none"
@confirm="search"
@clear="clear"
/>
<view v-if="lecturerList.length">
<block v-for="(item, index) in lecturerList" :key="index">
<lecturerItem :lecturerItem="item" @init="initLecturerItem" />
</block>
<view style="padding: 20rpx">
<u-loadmore :status="status" icon-type="flower" />
</view>
</view>
<u-empty
v-else
text="暂无数据~"
icon-size="506"
:margin-top="220"
src="../../static/img/noData.png"
></u-empty>
</view>
</template>
<script setup lang="ts">
import { getLecturerList } from "@/api/lecturer";
import lecturerItem from "./components/lecturerItem.vue";
const listQuery = reactive({
PageIndex: 1,
PageSize: 10,
total: 0,
KeyWords: "",
});
const lecturerList = ref([] as any);
const status = ref("loadmore");
const search = (val: any) => {
listQuery.KeyWords = val.value;
};
const clear = () => {
listQuery.KeyWords = "";
};
const initLecturerItem = () => {};
// 上拉加载数据
onReachBottom(() => {
// 判断是否还有下一页数据
if (listQuery.PageIndex * listQuery.PageSize >= listQuery.total)
return (status.value = "nomore");
// // 判断是否正在请求其它数据,如果是,则不发起额外的请求
if (status.value === "loading") return;
listQuery.PageIndex += 1;
init();
});
const init = async () => {
status.value = "loading";
const { data: res } = await getLecturerList(listQuery);
if (res.code == 200) {
if (res.total > 10) status.value = "loadmore";
else status.value = "nomore";
lecturerList.value = [...lecturerList.value, ...res.data];
listQuery.total = res.total;
}
};
init();
</script>
<style lang="scss" scoped>
.lecturer-container {
padding: 0 32rpx 64rpx;
}
</style>
<template> <template>
<view class="login-container"> <view style="position: relative">
<u-form :model="data.formData" ref="form" label-width="150"> <view class="bg-header">
<u-form-item label="手机号" prop="Phone" <u-image
><u-input v-model="data.formData.Phone" placeholder="请出输入手机号" src="../../static/img/background.png"
/></u-form-item> width="100%"
<u-form-item label="密码" prop="Password" height="100%"
><u-input />
v-model="data.formData.Password" </view>
type="password" <view class="logo">
placeholder="请输入密码" <u-image src="../../static/img/logo.png" width="100%" height="240rpx" />
/></u-form-item> <view class="logo-detail">培训系统</view>
</u-form> </view>
<view class="footer"> <view class="container">
<u-button @click="submit" size="medium" type="primary">登录</u-button> <view class="content">
<u-form :model="data.formData" ref="form" label-width="150">
<u-form-item
prop="Phone"
left-icon="../../static/img/icon_user.png"
:left-icon-style="data.leftIconStyle"
>
<u-input v-model="data.formData.Phone" placeholder="请输入手机号"
/></u-form-item>
<u-form-item
prop="Password"
left-icon="../../static/img/icon_yanzhenma.png"
:left-icon-style="data.leftIconStyle"
style="margin-top: 48rpx"
>
<u-input
v-model="data.formData.Password"
type="password"
placeholder="请输入密码"
/></u-form-item>
</u-form>
<view class="footer">
<u-button @click="submit" type="primary">登录</u-button>
</view>
</view>
</view>
<view v-if="hideshow" class="bg-footer">
<u-image
src="../../static/img/mask_group.png"
width="100%"
height="100%"
/>
</view> </view>
</view> </view>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { useGlobalStore } from "@/store/useStore" import { useGlobalStore } from "@/store/useStore";
import { Login } from "./interface/index" import { Login } from "./interface/index";
import { teachLogin } from "@/api/login" import { teachLogin } from "@/api/login";
import { toast } from "@/utils/util"; import { toast } from "@/utils/util";
const globalStore = useGlobalStore() const globalStore = useGlobalStore();
const form = ref() const form = ref();
const uniA: any = uni const uniA: any = uni;
const showHeight = ref();
const hideshow = ref(true);
const docmHeight = document.documentElement.clientHeight;
const data = reactive({ const data = reactive({
formData: { formData: {
Phone: "", Phone: "15077060245",
Password: "", Password: "123456",
} as Login.LoginForm, } as Login.LoginForm,
rules: { rules: {
Phone: [ Phone: [
...@@ -39,15 +73,15 @@ const data = reactive({ ...@@ -39,15 +73,15 @@ const data = reactive({
message: "请输入手机号", message: "请输入手机号",
trigger: ["change", "blur"], trigger: ["change", "blur"],
}, },
// { {
// // 自定义验证函数,见上说明 // 自定义验证函数,见上说明
// validator: (rule: any, value: any, callback: any) => { validator: (rule: any, value: any, callback: any) => {
// return uniA.$u.test.mobile(value) return uniA.$u.test.mobile(value);
// }, },
// message: "手机号码不正确", message: "手机号码不正确",
// // 触发器可以同时用blur和change // 触发器可以同时用blur和change
// trigger: ["change", "blur"], trigger: ["change", "blur"],
// }, },
], ],
Password: [ Password: [
{ {
...@@ -57,49 +91,101 @@ const data = reactive({ ...@@ -57,49 +91,101 @@ const data = reactive({
}, },
], ],
}, },
}) leftIconStyle: {
width: "40rpx",
height: "40rpx",
display: "flex",
},
});
onReady(() => { onReady(() => {
form.value.setRules(data.rules) form.value.setRules(data.rules);
}) });
onMounted(() => {
window.onresize = () => {
return (() => {
showHeight.value = document.body.clientHeight;
})();
};
});
watch(
() => showHeight.value,
() => {
if (docmHeight > showHeight.value) {
hideshow.value = false;
} else {
hideshow.value = true;
}
}
);
const submit = () => { const submit = () => {
form.value.validate(async (valid: boolean) => { form.value.validate(async (valid: boolean) => {
if (valid) { if (valid) {
const { data: res } = await teachLogin(data.formData) const { data: res } = await teachLogin(data.formData);
if (res.code == 200) { if (res.code == 200) {
globalStore.setPhone(data.formData.Phone) globalStore.setPhone(data.formData.Phone);
globalStore.setInfoData(res.data[0]) globalStore.setInfoData(res.data[0]);
uni.reLaunch({ url: "/pages/home/index" }) uni.reLaunch({ url: "/pages/home/index" });
toast('登录成功') toast("登录成功");
} }
} else { } else {
console.log("验证失败") console.log("验证失败");
} }
}) });
} };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
page { .container {
background-image: url("https://img2.baidu.com/it/u=460732253,1892860896&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=888");
background-size: cover;
/* 背景图片自适应屏幕大小 */
/* 其他样式设置 */
}
.login-container {
padding: 30rpx;
position: absolute; position: absolute;
top: 25%; top: 500rpx;
left: 5%; left: 12%;
width: 90vw; z-index: 99;
background-color: #fff; width: 568rpx;
border-radius: 15rpx; .content {
width: 568rpx;
height: 372rpx;
.yanzhenma {
display: flex;
align-items: center;
margin-top: 48rpx;
.u-form-item {
width: 392rpx;
}
}
.footer { :deep(.u-form-item) {
display: flex; position: relative;
margin-top: 30rpx; box-sizing: border-box;
background: #ffffff;
padding: 10rpx 36rpx 10rpx;
box-shadow: 0rpx 8rpx 100rpx 0rpx rgba(0, 0, 0, 0.05);
border-radius: 16rpx;
height: 90rpx;
}
:deep(.u-form-item__message) {
padding-left: 0 !important;
margin-top: 20rpx;
}
.footer {
height: 84rpx;
margin-top: 64rpx;
.u-btn {
width: 100%;
height: 100%;
background-color: #04a7ff;
}
.register {
text-align: center;
font-size: 26rpx;
margin: 20rpx 0;
color: #07a9ff;
}
}
} }
} }
</style> </style>
<template>
<u-popup
v-model="props.show"
mode="center"
closeable
width="600rpx"
border-radius="24"
@close="handleClose"
>
<view class="position">
<view class="title">请设置定位的应用范围</view>
<u-form :model="data.parmeters" ref="formRef" label-position="top">
<!-- <u-form-item label="考勤地址名称" prop="F_LQKJ_HITAREA"
><u-input v-model="data.parmeters.F_LQKJ_HITAREA" clearable
/></u-form-item> -->
<u-form-item prop="F_LQKJ_SCOPE" :border-bottom="false">
<u-radio-group v-model="num" shape="square">
<u-radio name="0"
>距离范围{{
data.parmeters.F_LQKJ_SCOPE ? data.parmeters.F_LQKJ_SCOPE : 0
}}</u-radio
>
</u-radio-group>
</u-form-item>
<u-form-item
prop="F_LQKJ_SCOPE"
:border-bottom="false"
style="margin-left: 48rpx"
>
<u-radio-group
v-model="data.parmeters.F_LQKJ_SCOPE"
shape="square"
@change="change"
>
<u-radio name="50">50</u-radio>
<u-radio name="100">100</u-radio>
<u-radio name="200">200</u-radio>
</u-radio-group>
</u-form-item>
<u-form-item
prop="type"
:border-bottom="false"
style="margin-bottom: 24rpx"
>
<u-radio-group v-model="data.parmeters.type" shape="square">
<u-radio name="0">仅当前课程考勤定位 </u-radio>
<u-radio name="1">同步班级所有课程的考勤定位 </u-radio>
</u-radio-group>
</u-form-item>
</u-form>
<view class="footer">
<u-button @tap="handleClose" size="medium">拒绝</u-button>
<u-button type="success" size="medium" @tap="submit">确认</u-button>
</view>
</view>
</u-popup>
</template>
<script setup lang="ts">
import { setAddr } from "@/api/position";
import { toast } from "@/utils/util";
import { useMapStore } from "@/store/modules/mapStore";
const mapStore = useMapStore();
const props = defineProps({
show: {
type: Boolean,
default: false,
},
});
const emits = defineEmits(["update:show"]);
const data = reactive({
parmeters: {
F_LQKJ_LONGITUDE: "",
F_LQKJ_SCOPE: "",
FCOURSEID: 0,
type: "0",
F_LQKJ_HITAREA: "",
classId: "",
},
rules: {
F_LQKJ_HITAREA: [
{
required: true,
message: "请输入考勤地址名称",
trigger: ["change", "blur"],
},
],
F_LQKJ_SCOPE: [
{
required: true,
message: "请设置有效范围",
trigger: "blur",
},
],
},
});
const num = ref();
const formRef = ref();
const change = () => {
num.value = "0";
};
const submit = () => {
formRef.value.validate(async (valid: any) => {
if (valid) {
const { data: res } = await setAddr({ parmeters: data.parmeters });
if (res.code == 200) {
uni.navigateBack();
handleClose();
toast("设置成功");
}
} else {
}
});
};
const init = () => {
data.parmeters.F_LQKJ_HITAREA = mapStore.mapData.hitArea;
data.parmeters.F_LQKJ_LONGITUDE = mapStore.mapData.Longitude;
data.parmeters.F_LQKJ_SCOPE = mapStore.mapData.Scope;
data.parmeters.FCOURSEID = mapStore.mapData.courseId;
data.parmeters.type = mapStore.mapData.type;
data.parmeters.classId = mapStore.mapData.classId;
if (data.parmeters.F_LQKJ_SCOPE) num.value = "0";
formRef.value.setRules(data.rules);
};
const handleClose = () => {
formRef.value?.resetFields();
emits("update:show", false);
};
const resetFields = () => {};
defineExpose({
init,
});
</script>
<style lang="scss" scoped>
:deep(.u-iconfont::before) {
margin-top: 24rpx;
}
.u-form-item {
padding: 0;
}
.position {
padding: 40rpx 32rpx;
.title {
font-size: 34rpx;
font-weight: 500;
color: #000000;
margin-bottom: 32rpx;
}
:deep(.u-iconfont::before) {
margin-top: 0;
}
.footer {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 8rpx;
.u-btn {
width: 176rpx;
height: 66rpx;
background: #04a7ff;
border-radius: 12rpx;
}
:deep(.u-hairline-border:after) {
border: 0;
}
& .u-btn:first-child {
color: #04a7ff;
background: rgba(0, 0, 0, 0.1);
}
}
}
</style>
<template> <template>
<div class="position-container"> <view class="position-container">
<u-card :show-head="false" margin="0"> <u-card :show-head="false" margin="0">
<template #body> <template #body>
<view class="position-header"> <view class="position-header">
<h3>{{ positionItem.courseName }}</h3> {{ positionItem.courseName }}
</view> </view>
<view class="item"> <view class="item">
<text>上课地点:{{ positionItem.classArea }}</text> <text>上课地点:{{ positionItem.classArea }}</text>
...@@ -30,17 +30,17 @@ ...@@ -30,17 +30,17 @@
<template #foot> <template #foot>
<view class="position-footer"> <view class="position-footer">
<text>所属班级:{{ positionItem.className }}</text> <text>所属班级:{{ positionItem.className }}</text>
<u-button type="primary" size="mini" @tap="openMap">{{ <u-button type="primary" @tap="openMap">{{
current ? "修改定位" : "设置定位" current ? "修改定位" : "设置定位"
}}</u-button> }}</u-button>
</view> </view>
</template> </template>
</u-card> </u-card>
</div> </view>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { useMapStore } from "@/store/modules/mapStore" import { useMapStore } from "@/store/modules/mapStore";
const props = defineProps({ const props = defineProps({
positionItem: { positionItem: {
...@@ -51,35 +51,56 @@ const props = defineProps({ ...@@ -51,35 +51,56 @@ const props = defineProps({
type: Number, type: Number,
default: 0, default: 0,
}, },
}) });
const mapStore = useMapStore() const mapStore = useMapStore();
const openMap = () => { const openMap = () => {
mapStore.setMapData(props.positionItem) mapStore.setMapData(props.positionItem);
uni.navigateTo({ uni.navigateTo({
url: "/pages/setPositioning/map", url: "/pages/setPositioning/map",
}) });
} };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.position-container { .position-container {
margin-bottom: 20rpx; margin-bottom: 20rpx;
:deep(.u-card__body) {
padding: 40rpx 32rpx 8rpx !important;
}
.position-header { .position-header {
margin-bottom: 30rpx; margin-bottom: 32rpx;
height: 48rpx;
font-size: 34rpx;
font-weight: 500;
color: #222222;
line-height: 40rpx;
} }
.item { .item {
margin-bottom: 20rpx; margin-bottom: 24rpx;
font-size: 28rpx;
font-weight: 400;
color: rgba(34, 34, 34, 0.9);
} }
.position-footer { .position-footer {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center;
font-size: 24rpx;
font-weight: 400;
color: rgba(34, 34, 34, 0.5);
line-height: 28rpx;
.u-btn { .u-btn {
margin: 0; margin: 0;
height: 58rpx;
background: #04a7ff;
border-radius: 12rpx;
font-size: 24rpx;
} }
} }
} }
......
...@@ -5,7 +5,13 @@ ...@@ -5,7 +5,13 @@
:list="tabsState.list" :list="tabsState.list"
:is-scroll="false" :is-scroll="false"
v-model="tabsState.current" v-model="tabsState.current"
bg-color="#f5f5f5" :active-item-style="{ fontSize: '34rpx', color: '#000000' }"
font-size="28"
bar-width="72"
bar-height="6"
bg-color="#fbfcff"
inactive-color="#cecfcf"
active-color="#05a8ff"
@change="tabsChange" @change="tabsChange"
/> />
<!-- 搜索 --> <!-- 搜索 -->
...@@ -19,9 +25,7 @@ ...@@ -19,9 +25,7 @@
/> />
<!-- 内容 --> <!-- 内容 -->
<view v-if="positionList.length"> <view v-if="positionList.length">
<text style="margin-bottom: 20rpx; display: block" <text class="fund">为您找到{{ listQuery.total }} 个课程</text>
>为你找到{{ listQuery.total }} 个的课程</text
>
<block v-for="(item, index) in positionList" :key="index"> <block v-for="(item, index) in positionList" :key="index">
<setPositionItem :positionItem="item" :current="tabsState.current" /> <setPositionItem :positionItem="item" :current="tabsState.current" />
...@@ -30,19 +34,23 @@ ...@@ -30,19 +34,23 @@
<u-loadmore :status="status" icon-type="flower" /> <u-loadmore :status="status" icon-type="flower" />
</view> </view>
</view> </view>
<view v-else class="empty"> <u-empty
<u-empty text="暂无数据" mode="list" /> v-else
</view> text="暂无数据~"
icon-size="506"
:margin-top="220"
src="../../static/img/noData.png"
></u-empty>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
// import headers from "@/components/header/index.vue" // import headers from "@/components/header/index.vue"
import setPositionItem from "./components/setPositionItem.vue" import setPositionItem from "./components/setPositionItem.vue";
import { getLocationList } from "@/api/position" import { getLocationList } from "@/api/position";
import { useGlobalStore } from "@/store/useStore" import { useGlobalStore } from "@/store/useStore";
const globalStore = useGlobalStore() const globalStore = useGlobalStore();
const tabsState = reactive({ const tabsState = reactive({
list: [ list: [
...@@ -54,9 +62,9 @@ const tabsState = reactive({ ...@@ -54,9 +62,9 @@ const tabsState = reactive({
}, },
], ],
current: 0, current: 0,
}) });
const positionList: any = ref([] as any) const positionList: any = ref([] as any);
const listQuery = reactive({ const listQuery = reactive({
Phone: globalStore.Phone, Phone: globalStore.Phone,
pageIndex: 1, pageIndex: 1,
...@@ -64,54 +72,54 @@ const listQuery = reactive({ ...@@ -64,54 +72,54 @@ const listQuery = reactive({
total: 0, total: 0,
type: 0, type: 0,
Name: "", Name: "",
}) });
const status = ref("loadmore") const status = ref("loadmore");
const tabsChange = (index: number) => { const tabsChange = (index: number) => {
positionList.value = [] positionList.value = [];
if (index) { if (index) {
listQuery.type = 1 listQuery.type = 1;
} else { } else {
listQuery.type = 0 listQuery.type = 0;
} }
init() init();
} };
const search = (val: any) => { const search = (val: any) => {
listQuery.Name = val.value listQuery.Name = val.value;
init() init();
} };
const clear = () => { const clear = () => {
listQuery.Name = "" listQuery.Name = "";
init() init();
} };
// 上拉加载数据 // 上拉加载数据
onReachBottom(() => { onReachBottom(() => {
// 判断是否还有下一页数据 // 判断是否还有下一页数据
if (listQuery.pageIndex * listQuery.pageSize >= listQuery.total) if (listQuery.pageIndex * listQuery.pageSize >= listQuery.total)
return (status.value = "nomore") return (status.value = "nomore");
// // 判断是否正在请求其它数据,如果是,则不发起额外的请求 // // 判断是否正在请求其它数据,如果是,则不发起额外的请求
if (status.value === "loading") return if (status.value === "loading") return;
listQuery.pageIndex += 1 listQuery.pageIndex += 1;
init() init();
}) });
const init = async () => { const init = async () => {
status.value = "loading" status.value = "loading";
const { data: res } = await getLocationList(listQuery) const { data: res } = await getLocationList(listQuery);
if (res.code == 200) { if (res.code == 200) {
if (res.total > 10) status.value = "loadmore" if (res.total > 10) status.value = "loadmore";
else status.value = "nomore" else status.value = "nomore";
positionList.value = [...positionList.value, ...res.data] positionList.value = [...positionList.value, ...res.data];
listQuery.total = res.total listQuery.total = res.total;
// console.log(positionList.value) // console.log(positionList.value)
} }
} };
onShow(() => { onShow(() => {
tabsChange(tabsState.current) tabsChange(tabsState.current);
}) });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
......
<template> <template>
<!-- <headers title="考勤地点设置" :is-button="false" @submit="submit" /> -->
<view v-if="flag" class="map"> <view v-if="flag" class="map">
<iframe id="mapPage" width="100%" height="100%" frameborder="0" :src="src"> <iframe id="mapPage" width="100%" height="100%" frameborder="0" :src="src">
</iframe> </iframe>
<view class="complete"> <view class="complete">
<u-button <u-button type="primary" @tap="submit" style="margin-right: 30rpx"
type="primary" >完成</u-button
size="mini"
@tap="submit"
style="margin-right: 30rpx"
>下一步</u-button
> >
</view> </view>
</view> </view>
<positionPopup ref="positionRef" v-model:show="show" />
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import headers from "@/components/header/index.vue" import { toast, zconfirm } from "@/utils/util";
import { toast, zconfirm } from "@/utils/util" import { useMapStore } from "@/store/modules/mapStore";
import { useMapStore } from "@/store/modules/mapStore" import positionPopup from "./components/positionPopup.vue";
const mapStore = useMapStore() const mapStore = useMapStore();
const state = reactive({ const state = reactive({
key: "3M5BZ-SFCRJ-AHSF7-XRA5Q-Y6NIJ-DXBH4", key: "3M5BZ-SFCRJ-AHSF7-XRA5Q-Y6NIJ-DXBH4",
coord: "", coord: "",
}) });
const src = ref() const src = ref();
const flag = ref(false) const flag = ref(false);
const addrDetail = ref() const show = ref(false);
const addrDetail = ref();
window.addEventListener( const positionRef = ref();
"message",
function (event) {
// 接收位置信息,用户选择确认位置点后选点组件会触发该事件,回传用户的位置信息
var loc = event.data
if (loc && loc.module == "locationPicker") {
//防止其他应用也会向该页面post信息,需判断module是否为'locationPicker'
addrDetail.value = loc
}
},
false
)
const submit = () => { const submit = () => {
if (!addrDetail.value) return toast("请选择地址") if (!addrDetail.value) return toast("请选择地址");
console.log("location", addrDetail.value) const Longitude =
uni.navigateTo({ addrDetail.value.latlng.lat + "," + addrDetail.value.latlng.lng;
url: "/pages/setPositioning/setAttendance", mapStore.setMapData({
success() { ...mapStore.mapData,
const Longitude = ...{ hitArea: addrDetail.value.poiaddress, Longitude },
addrDetail.value.latlng.lat + "," + addrDetail.value.latlng.lng });
mapStore.setMapData({ show.value = true;
...mapStore.mapData, setTimeout(() => {
...{ hitArea: addrDetail.value.poiaddress, Longitude }, positionRef.value.init();
}) // console.log("location", addrDetail.value);
}, }, 100);
}) // uni.navigateTo({
setTimeout(function () { // url: "/pages/setPositioning/setAttendance",
console.log(mapStore.mapData, "mapStore.mapData") // success() {
}, 10) // const Longitude =
} // addrDetail.value.latlng.lat + "," + addrDetail.value.latlng.lng;
// mapStore.setMapData({
// ...mapStore.mapData,
// ...{ hitArea: addrDetail.value.poiaddress, Longitude },
// });
// },
// });
};
const setPosition = (event: any) => {
// 接收位置信息,用户选择确认位置点后选点组件会触发该事件,回传用户的位置信息
var loc = event.data;
if (loc && loc.module == "locationPicker") {
//防止其他应用也会向该页面post信息,需判断module是否为'locationPicker'
addrDetail.value = loc;
}
};
onReady(() => {
// positionRef.value.initRules();
});
onMounted(() => { onMounted(() => {
if (mapStore.mapData.StateType) { if (mapStore.mapData.StateType) {
state.coord = mapStore.mapData.Longitude state.coord = mapStore.mapData.Longitude;
console.log(mapStore.mapData, state.coord , 'state.coord ') console.log(mapStore.mapData, state.coord, "state.coord ");
src.value = `https://apis.map.qq.com/tools/locpicker?search=1&type=1&key=${state.key}&referer=XBRLPX&coord=${state.coord}&zoom=18` src.value = `https://apis.map.qq.com/tools/locpicker?search=1&type=1&key=${state.key}&referer=XBRLPX&coord=${state.coord}&zoom=18`;
setTimeout(() => { setTimeout(() => {
flag.value = true flag.value = true;
}, 300) }, 300);
} else { } else {
uni.getLocation({ uni.getLocation({
type: "gcj02", type: "gcj02",
success(res: any) { success(res: any) {
console.log(res) // console.log(res);
state.coord = res.latitude + "," + res.longitude state.coord = res.latitude + "," + res.longitude;
src.value = `https://apis.map.qq.com/tools/locpicker?search=1&type=1&key=${state.key}&referer=XBRLPX&coord=${state.coord}&zoom=18` src.value = `https://apis.map.qq.com/tools/locpicker?search=1&type=1&key=${state.key}&referer=XBRLPX&coord=${state.coord}&zoom=18`;
setTimeout(() => { setTimeout(() => {
flag.value = true flag.value = true;
}, 300) }, 300);
}, },
}) });
} }
}) window.addEventListener("message", setPosition, false);
});
onBackPress(() => {
window.removeEventListener("message", setPosition, false);
flag.value = false;
});
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
...@@ -95,8 +106,15 @@ onMounted(() => { ...@@ -95,8 +106,15 @@ onMounted(() => {
.complete { .complete {
position: absolute; position: absolute;
top: 5.5%; top: 46%;
right: -3%; right: -2%;
.u-btn {
padding: 12rpx;
height: 58rpx;
background: #04a7ff;
border-radius: 12rpx 12rpx 12rpx 12rpx;
opacity: 1;
}
} }
} }
</style> </style>
...@@ -35,13 +35,13 @@ ...@@ -35,13 +35,13 @@
<script setup lang="ts"> <script setup lang="ts">
// import headers from "@/components/header/index.vue" // import headers from "@/components/header/index.vue"
import { setAddr } from "@/api/position" import { setAddr } from "@/api/position";
import { toast } from "@/utils/util" import { toast } from "@/utils/util";
import { useMapStore } from "@/store/modules/mapStore" import { useMapStore } from "@/store/modules/mapStore";
const mapStore = useMapStore() const mapStore = useMapStore();
const formRef = ref() const formRef = ref();
const data = reactive({ const data = reactive({
parmeters: { parmeters: {
...@@ -103,41 +103,41 @@ const data = reactive({ ...@@ -103,41 +103,41 @@ const data = reactive({
label: "800米", label: "800米",
}, },
], ],
}) });
const back = () => { const back = () => {
uni.navigateBack() uni.navigateBack();
} };
const submit = () => { const submit = () => {
formRef.value.validate(async (valid: any) => { formRef.value.validate(async (valid: any) => {
if (valid) { if (valid) {
const { data: res } = await setAddr({ parmeters: data.parmeters }) const { data: res } = await setAddr({ parmeters: data.parmeters });
if (res.code == 200) { if (res.code == 200) {
uni.navigateBack({ delta: 2 }) uni.navigateBack({ delta: 2 });
toast("设置成功") toast("设置成功");
} }
} else { } else {
} }
}) });
} };
const onConfirm = (item: any) => { const onConfirm = (item: any) => {
data.parmeters.F_LQKJ_SCOPE = item[0].value data.parmeters.F_LQKJ_SCOPE = item[0].value;
} };
onReady(() => { onReady(() => {
formRef.value.setRules(data.rules) formRef.value.setRules(data.rules);
setTimeout(() => { setTimeout(() => {
data.parmeters.F_LQKJ_HITAREA = mapStore.mapData.hitArea data.parmeters.F_LQKJ_HITAREA = mapStore.mapData.hitArea;
data.parmeters.F_LQKJ_LONGITUDE = mapStore.mapData.Longitude data.parmeters.F_LQKJ_LONGITUDE = mapStore.mapData.Longitude;
data.parmeters.F_LQKJ_SCOPE = mapStore.mapData.Scope data.parmeters.F_LQKJ_SCOPE = mapStore.mapData.Scope;
data.parmeters.FCOURSEID = mapStore.mapData.courseId data.parmeters.FCOURSEID = mapStore.mapData.courseId;
data.parmeters.type = mapStore.mapData.type data.parmeters.type = mapStore.mapData.type;
data.parmeters.classId = mapStore.mapData.classId data.parmeters.classId = mapStore.mapData.classId;
console.log(mapStore.mapData) console.log(mapStore.mapData);
}, 100) }, 100);
}) });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
......
...@@ -2,17 +2,56 @@ ...@@ -2,17 +2,56 @@
<div class="teach-points-container"> <div class="teach-points-container">
<u-card :show-head="false" margin="0"> <u-card :show-head="false" margin="0">
<template #body> <template #body>
<view class="teach-points-header"> <view class="body">
<h3>{{ teachPointsItem.FTERRITORIALITY }}</h3> <view>
<!-- <view class="teach-points-header">
<h3>{{ teachPointsItem.FTERRITORIALITY }}</h3>
</view> -->
<view class="item">
<text>现场教学点:{{ teachPointsItem.FTEACHINGPOINTS }}</text>
</view>
<view class="item">
<text>属地:{{ teachPointsItem.FTEACHINGPOINTS }}</text>
</view>
<view class="item">
<text>讲解员:{{ teachPointsItem.FTEACHINGPOINTS }}</text>
</view>
<view class="item">
<text>联系人:{{ teachPointsItem.FCONTACTS }}</text>
<u-icon
name="phone"
size="32"
color="#05A8FF"
style="margin-left: 32rpx"
@tap="tapButton(teachPointsItem.FPHONE)"
></u-icon>
</view>
<view class="item">
<text>票价/门票:{{ teachPointsItem.FTEACHINGPOINTS }}</text>
</view>
<view class="item">
<text>预约方式:{{ teachPointsItem.FTEACHINGPOINTS }}</text>
</view>
<view class="item">
<text>备注:{{ teachPointsItem.FTEACHINGPOINTS }}</text>
</view>
</view>
<u-image
src=""
width="220rpx"
height="296rpx"
border-radius="8"
style="margin-bottom: 24rpx"
/>
</view> </view>
<view class="item"> </template>
<text>现场教学点:{{ teachPointsItem.FTEACHINGPOINTS }}</text> <template #foot>
</view> <view class="foot">
<view class="item"> <text
<text>联系人:{{ teachPointsItem.FCONTACTS }}</text> >深圳市南山区西丽街道办公室位于圳地处中国华南地区、广东南部、珠江口东岸,东临大亚湾和大鹏湾,西濒珠江口和伶仃洋;南隔深圳河与香港相连,
</view> 北部与东莞、惠州两城市接深圳市南山区西丽街道办公室位于圳地处中国华南地区、广东南部、珠江口东岸,东临大亚湾和大鹏湾,西濒珠江口和伶仃洋;
<view class="item"> 南隔深圳河与香港相连,北部与东莞、惠州两城市接
<text>联系电话:{{ teachPointsItem.FPHONE }}</text> </text>
</view> </view>
</template> </template>
</u-card> </u-card>
...@@ -25,18 +64,53 @@ defineProps({ ...@@ -25,18 +64,53 @@ defineProps({
type: Array, type: Array,
default: () => [], default: () => [],
} as any, } as any,
}) });
const tapButton = (phone: string) => {
location.href = "tel:" + phone;
};
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.teach-points-container { .teach-points-container {
margin-bottom: 20rpx; margin-bottom: 20rpx;
:deep(.u-card__body) {
padding: 40rpx 32rpx 6rpx !important;
}
:deep(.u-card__foot) {
padding: 32rpx 32rpx 40rpx !important;
}
.teach-points-header { .teach-points-header {
margin-bottom: 30rpx; margin-bottom: 30rpx;
} }
.body {
display: flex;
justify-content: space-between;
align-items: flex-end;
.item {
display: flex;
margin-bottom: 24rpx;
font-size: 28rpx;
font-weight: 400;
color: rgba(34, 34, 34, 0.9);
}
}
.foot {
max-height: 102rpx;
font-size: 24rpx;
font-weight: 400;
color: rgba(34, 34, 34, 0.7);
.item { text {
margin-bottom: 20rpx; display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
}
} }
} }
</style> </style>
...@@ -2,16 +2,23 @@ ...@@ -2,16 +2,23 @@
<view class="teach-container"> <view class="teach-container">
<view v-if="teachPointsList.length"> <view v-if="teachPointsList.length">
<!-- 搜索 --> <!-- 搜索 -->
<uni-search-bar <view class="search">
placeholder="现场教学点" <view class="search-btn">属地</view>
bgColor="#ffffff" <u-input
clearButton="auto" v-model="listQuery.territoriality"
cancelButton="none" placeholder=""
@confirm="search" border
/> border-color="#F8F8F8"
<text style="margin-bottom: 20rpx; display: block" />
>为你找到{{ listQuery.total }}个的现场教学点</text <uni-search-bar
> placeholder="关键词"
bgColor="#ffffff"
clearButton="auto"
cancelButton="none"
@confirm="search"
/>
</view>
<!-- <text class="fund">为您找到{{ listQuery.total }}个现场教学点</text> -->
<block v-for="(item, index) in teachPointsList" :key="index"> <block v-for="(item, index) in teachPointsList" :key="index">
<teachPointsItem :teachPointsItem="item" /> <teachPointsItem :teachPointsItem="item" />
...@@ -27,53 +34,99 @@ ...@@ -27,53 +34,99 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import teachPointsItem from "./components/teachPointsItem.vue" import teachPointsItem from "./components/teachPointsItem.vue";
import { getTeachPointsList } from "@/api/teachPoints" import { getTeachPointsList } from "@/api/teachPoints";
const teachPointsList = ref([] as any) const teachPointsList = ref([] as any);
const status = ref("loadmore") const status = ref("loadmore");
const listQuery = reactive({ const listQuery = reactive({
pageIndex: 1, pageIndex: 1,
pageSize: 10, pageSize: 10,
total: 0, total: 0,
Area: "", Area: "",
}) territoriality: "",
});
const search = (val: any) => { const search = (val: any) => {
teachPointsList.value = [] teachPointsList.value = [];
listQuery.Area = val.value listQuery.Area = val.value;
init() init();
} };
// 上拉加载数据 // 上拉加载数据
onReachBottom(() => { onReachBottom(() => {
// 判断是否还有下一页数据 // 判断是否还有下一页数据
if (listQuery.pageIndex * listQuery.pageSize >= listQuery.total) if (listQuery.pageIndex * listQuery.pageSize >= listQuery.total)
return (status.value = "nomore") return (status.value = "nomore");
// // 判断是否正在请求其它数据,如果是,则不发起额外的请求 // // 判断是否正在请求其它数据,如果是,则不发起额外的请求
if (status.value === "loading") return if (status.value === "loading") return;
listQuery.pageIndex += 1 listQuery.pageIndex += 1;
init() init();
}) });
const init = async () => { const init = async () => {
status.value = "loading" status.value = "loading";
const { data: res } = await getTeachPointsList(listQuery) const { data: res } = await getTeachPointsList(listQuery);
if (res.code == 200) { if (res.code == 200) {
if (res.total > 10) status.value = "loadmore" if (res.total > 10) status.value = "loadmore";
else status.value = "nomore" else status.value = "nomore";
teachPointsList.value = [...teachPointsList.value, ...res.data] teachPointsList.value = [...teachPointsList.value, ...res.data];
listQuery.total = res.total listQuery.total = res.total;
console.log(teachPointsList.value) console.log(teachPointsList.value);
} else status.value = "nomore" } else status.value = "nomore";
} };
init() init();
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.teach-container { .teach-container {
padding: 0 30rpx 30rpx; padding: 0 32rpx 64rpx;
padding-top: 20rpx; padding-top: 20rpx;
.search {
width: 100%;
display: flex;
align-items: center;
height: 72rpx;
margin: 32rpx 0 48rpx;
.search-btn {
width: 72rpx;
background: #05a8ff;
border-radius: 24rpx 0rpx 0rpx 24rpx;
line-height: 72rpx;
text-align: center;
color: #ffffff;
font-size: 24rpx;
}
.u-input {
flex: 1;
height: 100%;
// margin-right: 1rpx;
background-color: #ffffff;
:deep(.u-input__input) {
background-color: #ffffff;
}
}
.uni-searchbar {
margin: 0;
padding: 0 !important;
width: 446rpx;
height: 100%;
// box-shadow: 0rpx 8rpx 60rpx 0rpx rgba(0, 0, 0, 0.05) !important;
border-radius: 0 24rpx 24rpx 0;
border: 1rpx solid #f8f8f8;
:deep(.uni-searchbar__box) {
border-radius: 0 24rpx 24rpx 0 !important;
padding: 0;
background-color: #ffffff;
}
}
}
} }
</style> </style>
<template>
<!-- <headers title="我的班级" /> -->
<view class="class-container">
<u-tabs
:list="tabsState.list"
:is-scroll="false"
v-model="tabsState.current"
:active-item-style="{ fontSize: '34rpx', color: '#000000' }"
font-size="28"
bar-width="72"
bar-height="6"
bg-color="#fbfcff"
inactive-color="#cecfcf"
active-color="#05a8ff"
@change="tabsChange"
/>
<!-- 搜索 -->
<uni-search-bar
placeholder="班级名称"
bgColor="#ffffff"
clearButton="auto"
cancelButton="none"
@confirm="search"
@clear="clear"
/>
<!-- 内容 -->
<view v-if="evaluateList.length">
<text class="fund">为您找到{{ listQuery.total }}个班级</text>
<view v-if="!tabsState.current">
<block v-for="(item, index) in evaluateList" :key="index">
<classItem :classItem="item" :current="2" @init="tabsChange" />
</block>
</view>
<view v-else>
<block v-for="(item, index) in evaluateList" :key="index">
<courseItem :courseItem="item" :current="2" />
</block>
</view>
<view style="padding: 20rpx">
<u-loadmore :status="status" icon-type="flower" />
</view>
</view>
<u-empty
v-else
text="暂无数据~"
icon-size="506"
:margin-top="220"
src="../../static/img/noData.png"
></u-empty>
</view>
</template>
<script setup lang="ts">
// import headers from "@/components/header/index.vue"
import classItem from "@/pages/class/components/classItem.vue";
import courseItem from "@/pages/course/components/courseItem.vue";
import { getClassList } from "@/api/class";
import { getCourseList } from "@/api/course";
import { useGlobalStore } from "@/store/useStore";
const globalStore = useGlobalStore();
const tabsState = reactive({
list: [
{
name: "培训评价",
},
{
name: "课程评价",
},
],
current: 0,
});
const evaluateList = ref([] as any);
const listQuery = reactive({
Phone: globalStore.Phone,
type: 2,
pageIndex: 1,
pageSize: 10,
total: 0,
Name: "",
});
const status = ref("loadmore");
const tabsChange = (index: number) => {
evaluateList.value = [];
listQuery.pageIndex = 1;
listQuery.pageSize = 10;
if (index) initCourse();
else initClass();
};
const search = (val: any) => {
listQuery.Name = val.value;
tabsChange(tabsState.current);
};
const clear = () => {
listQuery.Name = "";
tabsChange(tabsState.current);
};
// 上拉加载数据
onReachBottom(() => {
// 判断是否还有下一页数据
if (listQuery.pageIndex * listQuery.pageSize >= listQuery.total)
return (status.value = "nomore");
// // 判断是否正在请求其它数据,如果是,则不发起额外的请求
if (status.value === "loading") return;
listQuery.pageIndex += 1;
if (tabsState.current) initCourse();
else initClass();
});
const initClass = async () => {
status.value = "loading";
const { data: res } = await getClassList(listQuery);
if (res.code == 200) {
if (res.total > 10) status.value = "loadmore";
else status.value = "nomore";
evaluateList.value = [...evaluateList.value, ...res.data];
listQuery.total = res.total;
}
};
const initCourse = async () => {
status.value = "loading";
const { data: res } = await getCourseList(listQuery);
if (res.code == 200) {
if (res.total > 10) status.value = "loadmore";
else status.value = "nomore";
evaluateList.value = [...evaluateList.value, ...res.data];
listQuery.total = res.total;
}
};
tabsChange(tabsState.current);
</script>
<style lang="scss" scoped>
.class-container {
padding: 0 32rpx 168rpx;
}
</style>
.card { .uni-tabbar {
box-sizing: border-box; max-width: 420px;
margin: 16rpx; margin: 0 auto;
padding: 16rpx; border-left: #f6f6f6 solid 1px;
border-radius: 8rpx; border-right: #f6f6f6 solid 1px;
border: 1px solid #e4e7ed; }
.uni-searchbar {
padding: 0 !important;
margin: 32rpx 0 48rpx;
width: 686rpx;
height: 72rpx;
background: #ffffff;
box-shadow: 0rpx 8rpx 60rpx 0rpx rgba(0, 0, 0, 0.05) !important;
border-radius: 24rpx;
:deep(.uni-searchbar__box) {
border-radius: 30rpx !important;
}
}
.u-card {
border-radius: 20rpx;
background-color: #ffffff; background-color: #ffffff;
overflow: hidden; box-shadow: 0rpx 8rpx 60rpx 0rpx rgba(0, 0, 0, 0.05) !important;
color: #303133; border-radius: 24rpx;
transition: 0.3s; }
box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.05);
.card-text { .logo {
position: absolute;
top: 128rpx;
left: 270rpx;
width: 212rpx;
height: 316rpx;
.logo-detail {
width: 100%;
height: 44rpx;
font-size: 34rpx;
font-family: PingFang SC-Medium, PingFang SC;
font-weight: 500;
color: #222222;
line-height: 44rpx;
margin-top: 32rpx;
text-align: center;
}
}
.half-circle {
width: 20rpx;
height: 40rpx;
border-radius: 0 20rpx 20rpx 0;
background-color: #04a7ff;
line-height: 40rpx;
margin-right: 20rpx;
}
.fund {
margin-bottom: 32rpx;
display: block;
}
.courseEvaluation {
margin: 48rpx 0 32rpx;
font-weight: bolder;
display: flex;
align-items: center;
font-size: 34rpx;
color: #222222;
}
.rate {
margin-left: 30rpx;
color: #c8c9cc;
font-size: 24rpx;
}
.code {
color: #07a9ff;
font-size: 28rpx;
}
.courseware {
display: flex;
flex-direction: column;
align-items: center;
.courseware-icon {
padding: 20rpx; padding: 20rpx;
border-radius: 50%;
background-color: #ddf3ff;
} }
.grid-text { .desc {
font-size: 28rpx; margin-top: 10rpx;
margin-top: 4rpx; font-size: 24rpx;
color: #303133; font-weight: 400;
padding: 0 10rpx; color: rgba(34, 34, 34, 0.5);
white-space: "nowrap";
text-overflow: "ellipsis";
overflow: "hidden";
} }
} }
.card {
// height: 730rpx;
background: #ffffff;
box-shadow: 0rpx 8rpx 38rpx 0rpx rgba(0, 0, 0, 0.05);
border-radius: 24rpx;
padding: 18rpx 32rpx 48rpx;
}
.empty { .empty {
margin-top: 40rpx; margin-top: 220rpx;
}
.bg-header {
position: absolute;
top: 0;
width: 100%;
height: 624rpx;
}
.bg-footer {
position: fixed;
bottom: 0;
width: 100%;
height: 29.68%;
z-index: -99;
}
.prompt {
width: 100%;
margin-top: 28rpx;
.prompt-title {
height: 44rpx;
font-size: 32rpx;
font-weight: 400;
color: #222222;
line-height: 38rpx;
margin-bottom: 16rpx;
}
.prompt-detail {
height: 152rpx;
font-size: 28rpx;
font-weight: 400;
color: #999999;
line-height: 48rpx;
}
}
.active {
color: #ffffff !important;
background: #05a8ff !important;
}
.code {
width: 190rpx;
height: 40rpx;
font-size: 28rpx;
font-family: PingFang SC-Regular, PingFang SC;
text-align: right;
font-weight: 400;
color: #05a8ff;
line-height: 33rpx;
} }
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论