Signed-off-by: kevin <kevin@lmve.net>
This commit is contained in:
2025-06-05 11:04:12 +08:00
parent 9b63e88da8
commit 9d3eb0cea9
1675 changed files with 357271 additions and 1 deletions
+750
View File
@@ -0,0 +1,750 @@
<template>
<tabler-header v-if="!fulldis" @updatedcount="get_user"></tabler-header>
<FullCalendar ref="fullCalendar" :options='calendarOptions' >
<!-- <template v-slot:eventContent='arg'>
<b>{{ arg.timeText }}</b>
<i>{{ arg.event.title }}</i>
</template> -->
</FullCalendar>
<tabler-footer v-if="!fulldis"></tabler-footer>
<div v-if="set_item_flag" class="modal modal-blur fade show" style="display: block;" >
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">{{event_id==0?"正在添加日程":"正在修改 "+event_username+" 创建的日程"}}</h5>
<button type="button" class="btn-close" @click="set_item_close"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<view class="date-seles">
<!-- <datetime-picker v-model="range" type="daterange" /> -->
<datatime-picker-for-fullCalendar :value="range" :title="title" :color_sele="color_sele" @update="update_date"></datatime-picker-for-fullCalendar>
</view>
<div>
<uni-easyinput class="input" type="text" placeholder="输入日程内容" v-model="title" ></uni-easyinput>
</div>
<div>
<radio-group class="color_box" @change="change_color">
<div class="color_box_item" v-for="(item, index) in radio_colors" :key="item">
<label class="form-colorinput">
<radio :value="item.color" :checked="item.color === this.color_sele" :color="item.color" :background-color="item.color"/>
{{item.text}}
</label>
</div>
</radio-group>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn me-auto" @click="set_item_close">Close</button>
<button type="button" class="btn" @click="copy_item">复制</button>
<button type="button" class="btn" :disabled="!copy_color" @click="pise_item">粘贴</button>
<button v-if="event_id==0" type="button" class="btn btn-primary" @click="add_even">添加日程</button>
<button v-if="event_id!=0" type="button" class="btn btn-danger" @click="del_even">删除日程</button>
<button v-if="event_id!=0" type="button" class="btn btn-primary" @click="change_even">修改日程</button>
</div>
</div>
</div>
</div>
<view>
<!-- 提示信息弹窗 -->
<uni-popup ref="message" type="message">
<uni-popup-message :type="msgType" :message="messageText" :duration="2000"></uni-popup-message>
</uni-popup>
</view>
</template>
<script>
import { public_func } from '@/public_js.js';
import FullCalendar from '@fullcalendar/vue3'
import dayGridPlugin from '@fullcalendar/daygrid'
import timeGridPlugin from '@fullcalendar/timegrid'
import interactionPlugin from "@fullcalendar/interaction"//拖动插件 需要用npm安装
import screenfull from 'screenfull'
export default {
components: {
FullCalendar // make the <FullCalendar> tag available
},
onReady() {
console.log("onReady")
},
mounted() {
console.log("mounted")
//实例被创建
//console.log(FullCalendar)
this.get_evensts();
//
},
onLoad() {
console.log("onLoad");
clearTimeout(this.auto_get_event_time);
this.auto_get_event_time=null;
this.auto_get_event_time=setInterval(this.get_evensts, 5000);
},
onUnload() {
console.log("onUnload");
clearTimeout(this.auto_get_event_time);
this.auto_get_event_time=null;
},
onHide() {
console.log("onHide");
},
onShow() {
console.log("onshow")
},
methods:{
// 进入全屏
enterFullscreen(element)
{
screenfull.request();
},
// 退出全屏
exitFullscreen()
{
screenfull.exit();
},
test(){
},
handleDatesRender(arg)
{
console.log(arg.currentStart)
console.log(arg.currentEnd)
},
pise_item(){
this.color_sele=this.copy_color;
this.title=this.copy_title;
},
copy_item(){
this.copy_color=this.color_sele;
this.copy_title=this.title;
},
change_even(){
var that = this;
uni.request({
header: {'Content-Type': 'application/x-www-form-urlencoded'},
url:public_func.baseUrl+"api/?ac=ma&do=change",
method:'POST',
data:{
user_id:this.user.id,
user_pass:this.user.pass,
id:this.event_id,
stad_date:this.range[0],
end_date:this.range[1],
title:this.title,
color_sele:this.color_sele,
type:"events",
allday:1,
},
timeout:10000,
success(res) {
console.log(res.data);
if(res.data['error_code']==0)
{
that.set_item_close();
that.messageToggle('success',"已修改加日程");
that.get_evensts();
}else
{
that.messageToggle('error',res.data['error_msg']);
return ;
}
},
fail() {
that.messageToggle('error',"网络错误");
}
});
},
del_even(){
var that = this;
uni.request({
header: {'Content-Type': 'application/x-www-form-urlencoded'},
url:public_func.baseUrl+"api/?ac=ma&do=del",
method:'POST',
data:{
user_id:this.user.id,
user_pass:this.user.pass,
id:this.event_id,
},
timeout:10000,
success(res) {
console.log(res.data);
if(res.data['error_code']==0)
{
that.set_item_close();
that.messageToggle('success',"已删除");
that.get_evensts();
}else
{
that.messageToggle('error',res.data['error_msg']);
return ;
}
},
fail() {
that.messageToggle('error',"网络错误");
}
});
},
get_evensts(){
//console.log("get_evensts");
var user=this.user;
if(user==null)
{
user={
id:"0",
pass:"0"
};
}
var that = this;
uni.request({
header: {'Content-Type': 'application/x-www-form-urlencoded'},
url:public_func.baseUrl+"api/?ac=ma&do=show",
method:'POST',
data:{
user_id:user.id,
user_pass:user.pass,
},
timeout:10000,
success(res) {
console.log(res.data);
if(res.data['error_code']==0)
{
/* var events=res.data['events'].map(item => {
return { ...item, recurrence: ['RRULE:FREQ=DAILY'] };//给每一项插入一个标签 不过好像没什么用
});
that.calendarOptions.events=events; */
that.calendarOptions.events=res.data['events'];
}else
{
that.messageToggle('error',res.data['error_msg']);
return ;
}
},
fail() {
that.messageToggle('error',"网络错误");
}
});
},
updateCurrentMonth(info) {
const currentDate = info.start;
const currentMonth = currentDate.getMonth() + 1; // 月份从0开始,所以需要加1
const currentYear = currentDate.getFullYear();
this.currentMonth = `当前显示的月份是: ${currentYear}${currentMonth}`;
},
messageToggle(type,msg) {
this.msgType=type;
this.messageText=msg;
this.$refs.message.open();
},
add_even()
{
var that = this;
uni.request({
header: {'Content-Type': 'application/x-www-form-urlencoded'},
url:public_func.baseUrl+"api/?ac=ma&do=add",
method:'POST',
data:{
user_id:this.user.id,
user_pass:this.user.pass,
stad_date:this.range[0],
end_date:this.range[1],
title:this.title,
color_sele:this.color_sele,
type:"events",
allday:1,
},
timeout:10000,
success(res) {
console.log(res.data);
if(res.data['error_code']==0)
{
that.set_item_close();
that.messageToggle('success',"已添加日程");
that.get_evensts();
}else
{
that.messageToggle('error',res.data['error_msg']);
return ;
}
},
fail() {
that.messageToggle('error',"网络错误");
}
});
},
edit_item(e){
},
set_item_show(){
this.set_item_flag=true;
},
set_item_close(){
this.set_item_flag=false;
},
change_color(ev)
{
console.log(ev.detail.value)
this.color_sele=ev.detail.value;
},
get_user(user)
{
console.log(user)
this.user=user;
},
update_date(date)
{
console.log(date)
this.range[0]=date[0];
this.range[1]=date[1];
}
},
data() {
var that=this;
return {
fulldis:false,
click_time:0,
set_item_flag:false,
color_sele:"#066FD1",
user:null,
range:[0,0],
range2:[0,0],
stad_date:null,
end_date:null,
title:"",
event_username:"",
event_id:0,
msgType:"success",
message:"这是一条成功提示",
messageText:"",
show_mon:0,
auto_get_event_time:null,
copy_title:"",
copy_color:null,
radio_colors:[
{color:"#066FD1",text:"工作"},
{color:"#09d119",text:"值班"},
{color:"#ff00ff",text:"考试"},
{color:"#ffff00",text:"备用"},
{color:"#d16c13",text:"个人假期"},
{color:"#d10d21",text:"公众假期"},
],
this_mon_fastday:null,
this_mon_endday:null,
show_switch_flag:true,
calendarOptions: {
height:"auto",
plugins: [
dayGridPlugin,
timeGridPlugin,
interactionPlugin//导入拖动插件
],
initialView: 'dayGridMonth',
headerToolbar: {
left: 'prevYearCustom,prevMonthCustom,todayCustom,nextMonthCustom,nextYearCustom',
center: 'title',
right: 'quanping,dayGridMonth'//,timeGridWeek,timeGridDay'
},
fixedWeekCount:false,
weekNumbers:true,
businessHours: {
dow: [ 1, 2, 3, 4 ,5], // 周一 - 周四
start: '9:00', // 上午10点开始
end: '18:00', // 下午18点结束
},
//weekNumbersWithinDays:true,
weekends: true,//是否显示周末
// 自定义按钮
customButtons: {
prevYearCustom: {
text: '上一年',
click: function() {
that.show_switch_flag=true;
that.$refs.fullCalendar.getApi().prevYear();
}
},
nextYearCustom: {
text: '下一年',
click: function() {
that.show_switch_flag=true;
that.$refs.fullCalendar.getApi().nextYear();
}
},
prevMonthCustom: {
text: '上月',
click: function() {
that.show_switch_flag=true;
that.$refs.fullCalendar.getApi().prev(); // 将日历后退一步(例如,一个月或一周)。
}
},
nextMonthCustom: {
text: '下月',
click: function() {
that.show_switch_flag=true;
that.$refs.fullCalendar.getApi().next(); // 将日历向前移动一步(例如,一个月或一周)。
}
},
todayCustom: {
text: '今天',
click: function() {
that.show_switch_flag=true;
that.$refs.fullCalendar.getApi().today();
}
},
quanping: {
text: '全屏',
click: function() {
if(that.fulldis)
{
that.fulldis=false;
that.exitFullscreen();
}else
{
that.fulldis=true;
that.enterFullscreen();
}
}
}
},
datesSet(info)
{
//console.log(info);
that.this_mon_fastday=info.start;
that.this_mon_endday=info.end;
},
dayCellDidMount(info)
{
switch(info.dow)
{
case 0:
info.el.style.backgroundColor = '#ffb5b5';
break;
case 6:
info.el.style.backgroundColor = '#ffb5b5';
break;
}
if(info.isToday)
{
//info.el.style.backgroundColor = '#ffff7f';
}
info.el.style.border = '1px solid #4b4b4b'; // 浅蓝色边框
},
selectable: true,
dateClick(info) {
var click_time;
const now = new Date();
const nextime=now.getTime()-that.click_time
if(nextime<400)
{
console.log(nextime)//双击时间
var click_date={
date:info.date,
datestr:info.dateStr,
}
console.log(click_date)
if(that.user==null)
{
uni.redirectTo({
url:'/pages/login/login'
});
}else
{
that.event_id=0;
that.title="";
that.color_sele=that.radio_colors[0].color;
that.range[0]=click_date.datestr;
var next_day=new Date(click_date.datestr);
next_day.setDate(next_day.getDate() + 1);
that.range[1]=public_func.formatDate(next_day);
that.set_item_show();
}
}
that.click_time=now.getTime()
},
select(info) {
if((info.end-info.start)>86400000)
{
var select_date={
start:info.start,
end:info.end,
startStr:info.startStr,
endStr:info.endStr,
}
console.log(select_date)
if(that.user!=null)
{
that.event_id=0;
that.title="";
that.color_sele=that.radio_colors[0].color;
that.range[0]=public_func.formatDate(select_date.start);
that.range[1]=public_func.formatDate(select_date.end);
that.set_item_show();
}
}
},
//placeholder:true,
eventClick(info) {
console.log(info)
const now = new Date();
const nextime=now.getTime()-this.click_time
if(nextime<400)
{
console.log(nextime)//双击时间
var ev={
id:info.el.fcSeg.eventRange.def.publicId,
title:info.el.fcSeg.eventRange.def.title,
allDay:info.el.fcSeg.eventRange.def.allDay,
start:info.el.fcSeg.eventRange.range.start,
end:info.el.fcSeg.eventRange.range.end,
bg_color:info.el.fcSeg.eventRange.ui.backgroundColor,
edit:info.el.fcSeg.eventRange.ui.startEditable,
username:info.el.fcSeg.eventRange.def.extendedProps.event_username,
}
if(that.user==null)
{
uni.redirectTo({
url:'/pages/login/login'
});
}else
{
if(ev.edit)
{
that.event_id=ev.id;
that.title=ev.title;
that.color_sele=ev.bg_color;
that.range[0]=public_func.formatDate(ev.start);
that.range[1]=public_func.formatDate(ev.end);
that.event_username=ev.username;
that.set_item_show();
}else
{
that.messageToggle('warn',"这个不是您的日程");
}
}
}
this.click_time=now.getTime()
// change the border color just for fun
//info.el.style.borderColor = 'red';
},
eventDrop(info){
var olo_ev={
id:info.oldEvent._def.publicId,
title:info.oldEvent._def.title,
allDay:info.oldEvent._def.allDay,
start:info.oldEvent._instance.range.start,
end:info.oldEvent._instance.range.end,
}
var ev={
id:info.event._def.publicId,
title:info.event._def.title,
allDay:info.event._def.allDay,
start:info.event._instance.range.start,
end:info.event._instance.range.end,
}
//console.log(info)
//console.log(olo_ev)
console.log(info.event)
//var user=that.user;
//var that2 = this;
uni.request({
header: {'Content-Type': 'application/x-www-form-urlencoded'},
url:public_func.baseUrl+"api/?ac=ma&do=event_droup",
method:'POST',
data:{
user_id:that.user.id,
user_pass:that.user.pass,
id:ev.id,
start:public_func.formatDate(ev.start),
end:public_func.formatDate(ev.end),
},
timeout:10000,
success(res) {
console.log(res.data);
if(res.data['error_code']==0)
{
//that.messageToggle('success', public_func.formatDate(ev.start));
that.get_evensts();
}else
{
that.messageToggle('error',res.data['error_msg']);
return ;
}
},
fail() {
that.messageToggle('error',"网络错误");
}
});
},
//weekNumbers:true,//是否在日历中显示周次(一年中的第几周)
firstDay:1,
events: [],
}
}
},
}
</script>
<style lang="scss">
.color_box
{
display: flex;
//justify-content: space-between; /* 调整子元素之间的间距 */
.color_box_item
{
border-radius: 5px;
box-shadow: 0 0 10px 5px rgba(207, 207, 207, 0.5); /* 外部阴影效果 */
margin-left: 20rpx;
}
}
.input{
padding-bottom: 30rpx;
}
.date-seles{
display: flex;
flex-wrap: wrap; /* 允许换行 */
padding-bottom: 10rpx;
}
// 相应的CSS样式
.fc-event-centered {
display: flex;
align-items: center;
justify-content: center;
text-align: center;
height: 100%;
}
.fc-highlight {
background: #55aaff !important;
}
</style>
+32
View File
@@ -0,0 +1,32 @@
<template>
<tabler-header></tabler-header>
<h1>信息整合</h1>
<tabler-footer></tabler-footer>
</template>
<script>
export default {
data() {
return {
}
},
methods: {
}
}
</script>
<style lang="scss">
</style>
+188
View File
@@ -0,0 +1,188 @@
<template>
<view>
<!-- <tabler-header></tabler-header> -->
<body class=" d-flex flex-column">
<div class="page page-center">
<div class="container container-normal py-4">
<div class="row align-items-center g-4">
<div class="col-lg">
<div class="container-tight">
<div class="text-center mb-4">
</div>
<div class="card card-md">
<div class="card-body">
<button class="btn" @click="goto_home">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-reply" viewBox="0 0 16 16">
<path d="M6.598 5.013a.144.144 0 0 1 .202.134V6.3a.5.5 0 0 0 .5.5c.667 0 2.013.005 3.3.822.984.624 1.99 1.76 2.595 3.876-1.02-.983-2.185-1.516-3.205-1.799a8.74 8.74 0 0 0-1.921-.306 7.404 7.404 0 0 0-.798.008h-.013l-.005.001h-.001L7.3 9.9l-.05-.498a.5.5 0 0 0-.45.498v1.153c0 .108-.11.176-.202.134L2.614 8.254a.503.503 0 0 0-.042-.028.147.147 0 0 1 0-.252.499.499 0 0 0 .042-.028l3.984-2.933zM7.8 10.386c.068 0 .143.003.223.006.434.02 1.034.086 1.7.271 1.326.368 2.896 1.202 3.94 3.08a.5.5 0 0 0 .933-.305c-.464-3.71-1.886-5.662-3.46-6.66-1.245-.79-2.527-.942-3.336-.971v-.66a1.144 1.144 0 0 0-1.767-.96l-3.994 2.94a1.147 1.147 0 0 0 0 1.946l3.994 2.94a1.144 1.144 0 0 0 1.767-.96v-.667z"/>
</svg>
返回
</button>
<h2 class="h2 text-center mb-4">登录您的账号</h2>
<div class="mb-3">
<label class="form-label">
用户名
</label>
<uni-easyinput v-model="username" class="input" type="text" placeholder="输入用户名" maxlength="24"></uni-easyinput>
</div>
<div class="mb-2">
<label class="form-label">
密码
</label>
<uni-easyinput v-model="password" class="input_pass" type="password" placeholder="输入密码" maxlength="64" @confirm="login"></uni-easyinput>
</div>
<div class="mb-2">
<uni-fav :checked="autologin" :star="false" class="favBtn" @click="autologin_change" :content-text="contentText"/>
</div>
<div class="form-footer">
<button @click="login" class="btn btn-primary w-100">注册或登录</button>
</div>
</div>
</div>
<div class="text-center text-secondary mt-3">
注意如果账号未注册将会自动注册后自动登录
</div>
</div>
</div>
<div class="col-lg d-none d-lg-block">
<img src="/static/illustrations/undraw_secure_login_pdn4.svg" height="300" class="d-block mx-auto" alt="">
</div>
</div>
</div>
</div>
<view>
<!-- 提示信息弹窗 -->
<uni-popup ref="message" type="message">
<uni-popup-message :type="msgType" :message="messageText" :duration="2000"></uni-popup-message>
</uni-popup>
</view>
</body>
</view>
<tabler-footer></tabler-footer>
</template>
<script>
import { public_func } from '@/public_js.js';
export default {
data() {
return {
username:"",
password:"",
autologin: false,
msgType:"success",
message:"这是一条成功提示",
messageText:"",
contentText: {
contentDefault: '自动登录',
contentFav: '自动登录'
}
}
},
methods: {
messageToggle(type,msg) {
this.msgType=type;
this.messageText=msg;
this.$refs.message.open();
},
goto_home(){
uni.redirectTo({
url:"/pages/index/index"
});
},
login(){
console.log("try login")
if(this.username==""||this.password=="")
{
//console.log(baseUrl);
this.messageToggle('error',"账号或密码为空");
return ;
}
if(this.username.length<5)
{
this.messageToggle('error',"账号少于5位");
return ;
}
//let user=public_func.login_user(this.username,this.password);
//console.log(public_func.login_user(this.username,this.password));
var that = this;
uni.request({
header: {'Content-Type': 'application/x-www-form-urlencoded'},
url:public_func.baseUrl+"api/?ac=login&do=login",
method:'POST',
data:{
acc:this.username,
pass:this.password,
},
timeout:10000,
success(res) {
console.log(res.data);
if(res.data['error_code']==0)
{
//login ok
sessionStorage.setItem('user',JSON.stringify(res.data['user']));
if(that.autologin)
{
localStorage.setItem('user',JSON.stringify(res.data['user']));
}
that.messageToggle('success',"登录成功");
setTimeout(function(){
that.goto_home();
}, 1000);
}else
{
that.messageToggle('error',res.data['error_msg']);
return ;
}
},
fail() {
that.messageToggle('error',"网络错误");
}
});
},
autologin_change(){
if(this.autologin)
{
this.autologin=false;
}else
{
this.autologin=true;
}
}
}
}
</script>
<style lang="scss">
.input{
}
.input_pass{
}
</style>
+23
View File
@@ -0,0 +1,23 @@
<template>
<view>
<tabler-header @updatedcount="get_user"></tabler-header>
<tabler-footer></tabler-footer>
</view>
</template>
<script>
export default {
data() {
return {
}
},
methods: {
}
}
</script>
<style>
</style>
+23
View File
@@ -0,0 +1,23 @@
<template>
<view>
<tabler-header @updatedcount="get_user"></tabler-header>
</view>
</template>
<script>
export default {
data() {
return {
}
},
methods: {
}
}
</script>
<style>
</style>
+247
View File
@@ -0,0 +1,247 @@
<template>
<tabler-header @updatedcount="get_user"></tabler-header>
<view class="container">
<!-- 导航栏 -->
<uni-nav-bar title="题库列表" :border="false" />
<div class="qa_ye_box">
<div class="qa_ye">
<ul class="pagination ">
<li class="page-item disabled">
<a class="page-link" tabindex="-1" aria-disabled="true">
<!-- Download SVG icon from http://tabler-icons.io/i/chevron-left -->
<svg xmlns="http://www.w3.org/2000/svg" class="icon" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M15 6l-6 6l6 6" /></svg>
prev
</a>
</li>
<li class="page-item active"><a class="page-link" >1</a></li>
<li class="page-item"><a class="page-link" >2</a></li>
<li class="page-item"><a class="page-link" >3</a></li>
<li class="page-item"><a class="page-link" >4</a></li>
<li class="page-item"><a class="page-link" >5</a></li>
<li class="page-item">
<a class="page-link" >
next <!-- Download SVG icon from http://tabler-icons.io/i/chevron-right -->
<svg xmlns="http://www.w3.org/2000/svg" class="icon" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M9 6l6 6l-6 6" /></svg>
</a>
</li>
</ul>
</div>
<div class="qa_ye_but">
<a class="btn btn-primary w-100">添加题库</a>
</div>
</div>
<!-- 内容区域 -->
<scroll-view scroll-y class="content">
<view class="qbank-list">
<view
v-for="qbank in qbanks"
:key="qbank.qbank_id"
class="qbank-card"
@click="navigateToDetail(qbank.qbank_id)"
>
<!-- 卡片内容 -->
<view class="card-content">
<!-- 左侧图标 -->
<image
:src="qbank.logo_path || '/static/logo-placeholder.png'"
class="logo"
mode="aspectFit"
/>
<!-- 右侧信息 -->
<view class="info">
<text class="title">{{ qbank.name }}</text>
<text class="description">{{ qbank.description }}</text>
<view class="meta">
<uni-icons type="calendar" size="14" color="#666" />
<text class="time">{{ formatDate(qbank.created_at) }}</text>
</view>
</view>
</view>
<!-- 右侧箭头 -->
<uni-icons type="arrowright" size="20" color="#999" />
</view>
</view>
<!-- 空状态 -->
<view v-if="qbanks.length === 0" class="empty">
<image src="/static/empty.png" class="empty-img" />
<text class="empty-text">暂无题库数据</text>
</view>
</scroll-view>
</view>
<tabler-footer></tabler-footer>
</template>
<script setup>
import { ref } from 'vue';
// 本地测试数据
const qbanks = ref([
{
qbank_id: 1,
name: '前端开发题库',
description: '涵盖HTML/CSS/JavaScript等前端核心知识',
logo_path: '/static/fe-logo.png',
created_at: '2024-03-15 09:00:00'
},
{
qbank_id: 2,
name: 'Java面试宝典',
description: 'Java基础、框架与分布式系统面试题',
logo_path: '',
created_at: '2024-03-10 14:30:00'
},
{
qbank_id: 3,
name: '数据库专项练习',
description: 'MySQL、Redis等数据库实战题库',
logo_path: '/static/db-logo.png',
created_at: '2024-03-05 16:45:00'
}
]);
// 日期格式化
const formatDate = (dateStr) => {
return dateStr.split(' ')[0].replace(/-/g, '/');
};
// 跳转详情页
const navigateToDetail = (id) => {
uni.navigateTo({
url: `/pages/qbank/detail?id=${id}`
});
};
</script>
<style lang="scss" scoped>
.qa_ye_box{
display: flex; /* 启用弹性布局 */
gap: 10px; /* 子元素间距(可选) */
justify-content: start; /* 水平对齐方式 */
.qa_ye{
width: 90%;
}
.qa_ye_but{
//width: 10%;
}
}
.container {
height: 100vh;
display: flex;
flex-direction: column;
background-color: #f5f6f8;
}
.content {
flex: 1;
padding: 20rpx 24rpx;
}
.qbank-list {
display: flex;
flex-direction: column;
gap: 24rpx;
}
.qbank-card {
background: #fff;
border-radius: 16rpx;
padding: 32rpx;
display: flex;
align-items: center;
justify-content: space-between;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
transition: all 0.2s;
&:active {
transform: scale(0.98);
background: #f8f9fa;
}
}
.card-content {
flex: 1;
display: flex;
align-items: center;
gap: 24rpx;
}
.logo {
width: 120rpx;
height: 120rpx;
border-radius: 12rpx;
background-color: #f1f2f3;
}
.info {
flex: 1;
display: flex;
flex-direction: column;
gap: 12rpx;
}
.title {
font-size: 32rpx;
font-weight: 600;
color: #333;
line-height: 1.4;
}
.description {
font-size: 26rpx;
color: #666;
line-height: 1.4;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
}
.meta {
display: flex;
align-items: center;
gap: 8rpx;
margin-top: 8rpx;
}
.time {
font-size: 24rpx;
color: #999;
}
.empty {
display: flex;
flex-direction: column;
align-items: center;
padding: 100rpx 0;
&-img {
width: 300rpx;
height: 300rpx;
opacity: 0.6;
}
&-text {
font-size: 28rpx;
color: #999;
margin-top: 24rpx;
}
}
</style>
+291
View File
@@ -0,0 +1,291 @@
<template>
<tabler-header ref="the_heard" @updatedcount="get_user" :user_updata="user"></tabler-header>
<div class="page-wrapper">
<!-- Page header -->
<div class="page-header d-print-none">
<div class="container-xl">
<div class="row g-2 align-items-center">
<div class="col">
<h2 class="page-title">
设置
</h2>
</div>
</div>
</div>
</div>
<!-- Page body -->
<div class="page-body">
<div class="container-xl">
<div class="card">
<div class="row g-0">
<div class="col-12 col-md-3 border-end">
<business-settings />
</div>
<div class="col-12 col-md-9 d-flex flex-column">
<div class="card-body">
<h2 class="mb-4">我的账号</h2>
<div class="row g-3">
<div class="col-md">
<div class="form-label">ID: {{user_id}}</div>
</div>
<div class="col-md">
<div class="form-label">账号: {{user_acc}}</div>
</div>
</div>
<h3 class="card-title">Profile Details</h3>
<div class="row align-items-center">
<div class="col-auto"><span class="avatar avatar-xl" style="background-image: url(./static/avatars/000m.jpg)"></span>
</div>
<div class="col-auto"><a class="btn">
Change avatar
</a></div>
<div class="col-auto"><a class="btn btn-ghost-danger">
Delete avatar
</a></div>
</div>
<h3 class="card-title mt-4">Business Profile</h3>
<h3 class="card-title mt-4">Email</h3>
<p class="card-subtitle">This contact will be shown to others publicly, so choose it carefully.</p>
<div>
<div class="row g-2">
<div class="col-auto">
<uni-easyinput v-model="input_email" class="input" type="text" placeholder="输入邮箱" maxlength="128"></uni-easyinput>
</div>
<div class="col-auto">
<a class="btn" @click="change_email">Change</a></div>
</div>
</div>
<h3 class="card-title mt-4">Password</h3>
<p class="card-subtitle">You can set a permanent password if you don't want to use temporary login codes.</p>
<div>
<div class="col-auto">
<uni-easyinput v-model="input_oldpass" class="input mb-3" type="password" placeholder="输入旧密码" maxlength="64"></uni-easyinput>
<uni-easyinput v-model="input_newpass" class="input mb-3" type="password" placeholder="输入新密码" maxlength="64"></uni-easyinput>
<uni-easyinput v-model="input_cofpass" class="input mb-3" type="password" placeholder="确认新密码" maxlength="64"></uni-easyinput>
</div>
<a class="btn" @click="change_pass">Set new password</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<footer class="footer footer-transparent d-print-none">
<div class="container-xl">
<div class="row text-center align-items-center flex-row-reverse">
<div class="col-lg-auto ms-lg-auto">
<ul class="list-inline list-inline-dots mb-0">
<li class="list-inline-item"><a href="https://tabler.io/docs" target="_blank" class="link-secondary" rel="noopener">Documentation</a></li>
<li class="list-inline-item"><a href="./license.html" class="link-secondary">License</a></li>
<li class="list-inline-item"><a href="https://github.com/tabler/tabler" target="_blank" class="link-secondary" rel="noopener">Source code</a></li>
<li class="list-inline-item">
<a href="https://github.com/sponsors/codecalm" target="_blank" class="link-secondary" rel="noopener">
<!-- Download SVG icon from http://tabler-icons.io/i/heart -->
<svg xmlns="http://www.w3.org/2000/svg" class="icon text-pink icon-filled icon-inline" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M19.5 12.572l-7.5 7.428l-7.5 -7.428a5 5 0 1 1 7.5 -6.566a5 5 0 1 1 7.5 6.572"></path></svg>
Sponsor
</a>
</li>
</ul>
</div>
<div class="col-12 col-lg-auto mt-3 mt-lg-0">
<ul class="list-inline list-inline-dots mb-0">
<li class="list-inline-item">
Copyright © 2023
<a href="." class="link-secondary">Tabler</a>.
All rights reserved.
</li>
<li class="list-inline-item">
<a href="./changelog.html" class="link-secondary" rel="noopener">
v1.0.0-beta20
</a>
</li>
</ul>
</div>
</div>
</div>
</footer>
</div>
<view>
<!-- 提示信息弹窗 -->
<uni-popup ref="message" type="message">
<uni-popup-message :type="msgType" :message="messageText" :duration="2000"></uni-popup-message>
</uni-popup>
</view>
</template>
<script>
import { public_func } from '@/public_js.js';
export default {
data() {
return {
msgType:"success",
message:"这是一条成功提示",
messageText:"",
user:null,
user_id:0,
user_acc:"",
input_email:"",
input_oldpass:"",
input_newpass:"",
input_cofpass:"",
}
},
onReady() {
console.log("onready")
},
mounted() {
console.log("mounted")
},
methods: {
messageToggle(type,msg) {
this.msgType=type;
this.messageText=msg;
this.$refs.message.open();
},
get_user(user)
{
//console.log(user)
if(user==null)//如果还没登录 跳转到登录
{
uni.redirectTo({
url:'/pages/login/login'
});
}else
{
this.user=user;
this.user_id=user.id;
this.user_acc=user.acc;
if(user.email!=null)
{
this.input_email=user.email;
}
}
},
change_email()
{
if(this.input_email=="")
{
this.messageToggle("error","请输入email");
return;
}
if(public_func.isValidEmail(this.input_email))
{
//try change email
var that = this;
uni.request({
header: {'Content-Type': 'application/x-www-form-urlencoded'},
url:public_func.baseUrl+"api/?ac=users&do=change_email",
method:'POST',
data:{
id:that.user.id,
acc:that.user.acc,
pass:that.user.pass,
email:that.input_email,
},
timeout:10000,
success(res) {
console.log(res.data);
if(res.data['error_code']==0)
{
that.user=res.data['user'];
that.messageToggle('success',"邮箱修改成功");
return ;
}else
{
that.messageToggle('error',res.data['error_msg']);
return ;
}
},
fail() {
that.messageToggle('error',"网络错误");
}
});
}else
{
this.messageToggle("error","邮箱格式不正确");
}
},
change_pass()
{
if(this.input_oldpass=="")
{
this.messageToggle("error","请输入旧密码");
return;
}
if(this.input_newpass=="")
{
this.messageToggle("error","请输入新密码");
return;
}
if(this.input_cofpass!=this.input_newpass)
{
this.messageToggle("error","确认密码错误");
return;
}
var that = this;
uni.request({
header: {'Content-Type': 'application/x-www-form-urlencoded'},
url:public_func.baseUrl+"api/?ac=users&do=change_pass",
method:'POST',
data:{
id:that.user.id,
acc:that.user.acc,
pass:that.input_oldpass,
newpass:that.input_cofpass
},
timeout:10000,
success(res) {
console.log(res.data);
if(res.data['error_code']==0)
{
that.user=res.data['user'];
that.messageToggle('success',"密码修改成功");
that.input_oldpass="";
that.input_newpass="";
that.input_cofpass="";
setTimeout(function() {
that.$refs.the_heard.login_out();
}, 1000);
return ;
}else
{
that.messageToggle('error',res.data['error_msg']);
return ;
}
},
fail() {
that.messageToggle('error',"网络错误");
}
});
}
}
}
</script>
<style>
</style>
File diff suppressed because one or more lines are too long
+377
View File
@@ -0,0 +1,377 @@
<template>
<view class="container p-4">
<!-- 新增悬浮导航 -->
<view class="floating-nav">
<button class="nav-toggle" @click="showNav = !showNav">
<text class="icon">📖</text>
</button>
<view v-if="showNav" class="nav-panel">
<view class="panel-header">
<text>题目导航</text>
<button @click="showNav = false" class="close-btn">×</button>
</view>
<view class="question-grid">
<view
v-for="(q, index) in questions"
:key="index"
class="grid-item"
:class="{
'current': current === index,
'answered': answers[index] !== undefined
}"
@click="jumpTo(index)"
>
{{ index + 1 }}
</view>
</view>
</view>
</view>
<!-- 进度条 -->
<view class="card mb-4">
<view class="card-body">
<view class="d-flex align-items-center">
<view class="flex-grow-1 me-3 position-relative">
<progress
class="progress w-100"
:value="current + 1"
:max="questions.length"
style="height: 8px;"
></progress>
</view>
<text class="text-muted">{{ current + 1 }}/{{ questions.length }}</text>
</view>
</view>
</view>
<!-- 题目区域 -->
<view class="card mb-4">
<view class="card-body">
<h2 class="card-title mb-4 text-primary">{{ currentQuestion.question }}</h2>
<view class="list-group list-group-flush">
<view
v-for="(option, index) in currentQuestion.options"
:key="index"
class="list-group-item list-group-item-action cursor-pointer"
:class="{ 'active': selectedAnswer === index }"
@click="handleAnswer(index)"
>
<view class="form-check">
<view class="form-check-input" :class="{ 'checked': selectedAnswer === index }"></view>
<span class="form-check-label">{{ option }}</span>
</view>
</view>
</view>
</view>
</view>
<!-- 操作按钮 -->
<view class="row g-2">
<view class="col">
<button
class="btn btn-outline-primary w-100"
@click="prevQuestion"
:disabled="current === 0"
>
上一题
</button>
</view>
<view class="col">
<button
v-if="current < questions.length - 1"
class="btn btn-primary w-100"
@click="nextQuestion"
:disabled="selectedAnswer === null"
>
下一题
</button>
<button
v-else
class="btn btn-success w-100"
@click="submit"
>
提交答卷
</button>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
showNav: false,
current: 0,
selectedAnswer: null,
answers: [],
questions: [
{
question: "uniapp的全局样式文件是?",
options: ["App.vue", "main.js", "uni.css", "global.sass"],
correct: 0
},
{
question: "下列哪个API可以跳转页面?",
options: ["uni.request", "uni.navigateTo", "uni.showToast", "uni.getStorage"],
correct: 1
},
{
question: "uniapp支持哪种小程序语法?",
options: ["微信小程序", "支付宝小程序", "百度小程序", "全部支持"],
correct: 3
},
{
question: "如何获取设备信息?",
options: ["uni.getSystemInfo", "wx.getDeviceInfo", "device.platform", "navigator.userAgent"],
correct: 0
},
{
question: "下列哪个不是uniapp项目类型?",
options: ["HBuilderX", "微信开发者工具", "Visual Studio Code", "Android Studio"],
correct: 3
}
],
};
},
computed: {
currentQuestion() {
return this.questions[this.current];
}
},
methods: {
jumpTo(index) {
if(index >=0 && index < this.questions.length) {
this.current = index
this.selectedAnswer = this.answers[index] ?? null
this.showNav = false
}
},
handleAnswer(index) {
this.selectedAnswer = index;
// 震动反馈(真机生效)
uni.vibrateShort();
},
prevQuestion() {
if (this.current > 0) {
this.current--;
this.selectedAnswer = this.answers[this.current] ?? null;
}
},
nextQuestion() {
if (this.selectedAnswer !== null) {
this.answers[this.current] = this.selectedAnswer;
this.current++;
this.selectedAnswer = this.answers[this.current] ?? null;
}
},
submit() {
const score = this.questions.reduce((acc, q, index) => {
return acc + (this.answers[index] === q.correct ? 1 : 0);
}, 0);
uni.showModal({
title: '答题完成',
content: `正确率:${ ((score / this.questions.length) * 100).toFixed(0) }%`,
showCancel: false
});
}
}
};
</script>
<style>
/* 引入Tabler核心样式 */
.container {
background-color: var(--tblr-bg-surface);
min-height: 100vh;
}
.card {
box-shadow: var(--tblr-box-shadow-sm);
border-radius: var(--tblr-border-radius);
}
.list-group-item {
transition: all 0.2s ease;
border-left: 0;
border-right: 0;
cursor: pointer;
-webkit-tap-highlight-color: transparent;
}
.list-group-item.active {
background-color: var(--tblr-primary-bg-subtle);
border-color: var(--tblr-primary);
z-index: 2;
}
.form-check {
display: flex;
align-items: center;
}
.form-check-input {
position: relative;
width: 1.2em;
height: 1.2em;
border: 2px solid var(--tblr-border-color);
border-radius: 50%;
margin-right: 0.5em;
transition: all 0.2s ease;
}
.form-check-input.checked {
border-color: var(--tblr-primary);
}
.form-check-input.checked::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 0.6em;
height: 0.6em;
background: var(--tblr-primary);
border-radius: 50%;
transform: translate(-50%, -50%);
}
.btn-success {
background-color: var(--tblr-success);
border-color: var(--tblr-success);
}
.card-title {
font-size: 1.25rem;
font-weight: 600;
}
/* 添加进度条样式 */
progress {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
overflow: hidden;
background: var(--tblr-bg-surface-secondary);
}
progress::-webkit-progress-bar {
background: var(--tblr-bg-surface-secondary);
}
progress::-webkit-progress-value {
background: var(--tblr-primary);
transition: all 0.3s ease;
}
progress::-moz-progress-bar {
background: var(--tblr-primary);
}
/* 新增的进度条样式 */
progress {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
border-radius: 8px;
height: 8px !important;
}
progress::-webkit-progress-bar {
background: #f3f3f3;
border-radius: 8px;
}
progress::-webkit-progress-value {
background: var(--tblr-primary);
border-radius: 8px;
transition: width 0.3s ease;
}
progress::-moz-progress-bar {
background: var(--tblr-primary);
border-radius: 8px;
}
/* 悬浮导航样式 */
.floating-nav {
position: fixed;
right: 20rpx;
bottom: 120rpx;
z-index: 999;
}
.nav-toggle {
width: 100rpx;
height: 100rpx;
border-radius: 50%;
background: #007AFF;
box-shadow: 0 5rpx 20rpx rgba(0,0,0,0.2);
}
.icon {
font-size: 50rpx;
color: white;
}
.nav-panel {
position: absolute;
right: 0;
bottom: 120rpx;
width: 600rpx;
background: white;
border-radius: 20rpx;
box-shadow: 0 10rpx 40rpx rgba(0,0,0,0.15);
padding: 20rpx;
}
.panel-header {
display: flex;
justify-content: space-between;
align-items: center;
padding-bottom: 20rpx;
border-bottom: 1rpx solid #eee;
}
.close-btn {
font-size: 40rpx;
color: #999;
padding: 0 20rpx;
}
.question-grid {
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 15rpx;
margin-top: 20rpx;
}
.grid-item {
width: 100rpx;
height: 100rpx;
border-radius: 15rpx;
background: #f5f5f5;
display: flex;
align-items: center;
justify-content: center;
font-size: 34rpx;
transition: all 0.2s;
}
.grid-item.answered {
background: #e3f2fd;
color: #007AFF;
}
.grid-item.current {
transform: scale(1.1);
border: 2rpx solid #007AFF;
box-shadow: 0 5rpx 15rpx rgba(0,122,255,0.3);
}
</style>