-
12App.vue
-
20index.html
-
22main.js
-
72manifest.json
-
73pages.json
-
256pages/expense/expense.vue
-
214pages/index/index.vue
-
131pages/login/login.vue
-
193pages/payment/payment.vue
-
187pages/userInfo/userInfo.vue
-
BINstatic/bar/原始黄其振.jpg
-
BINstatic/bar/我小点声哭.jpg
-
BINstatic/bar/无腿黄其振.jpg
-
BINstatic/bar/爱莉1.jpg
-
BINstatic/bar/真我光锥.jpg
-
BINstatic/bar/证件照黄其振.jpg
-
BINstatic/bar/赵文康竖中指.jpg
-
BINstatic/logo.png
-
13uni.promisify.adaptor.js
-
76uni.scss
-
8unpackage/dist/cache/.vite/deps/_metadata.json
-
3unpackage/dist/cache/.vite/deps/package.json
@ -0,0 +1,12 @@ |
|||
<template> |
|||
<view class="app"> |
|||
<router-view /> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
|
|||
</script> |
|||
|
|||
<style> |
|||
</style> |
@ -0,0 +1,20 @@ |
|||
<!DOCTYPE html> |
|||
<html lang="en"> |
|||
<head> |
|||
<meta charset="UTF-8" /> |
|||
<script> |
|||
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') || |
|||
CSS.supports('top: constant(a)')) |
|||
document.write( |
|||
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' + |
|||
(coverSupport ? ', viewport-fit=cover' : '') + '" />') |
|||
</script> |
|||
<title></title> |
|||
<!--preload-links--> |
|||
<!--app-context--> |
|||
</head> |
|||
<body> |
|||
<div id="app"><!--app-html--></div> |
|||
<script type="module" src="/main.js"></script> |
|||
</body> |
|||
</html> |
@ -0,0 +1,22 @@ |
|||
import App from './App' |
|||
|
|||
// #ifndef VUE3
|
|||
import Vue from 'vue' |
|||
import './uni.promisify.adaptor' |
|||
Vue.config.productionTip = false |
|||
App.mpType = 'app' |
|||
const app = new Vue({ |
|||
...App |
|||
}) |
|||
app.$mount() |
|||
// #endif
|
|||
|
|||
// #ifdef VUE3
|
|||
import { createSSRApp } from 'vue' |
|||
export function createApp() { |
|||
const app = createSSRApp(App) |
|||
return { |
|||
app |
|||
} |
|||
} |
|||
// #endif
|
@ -0,0 +1,72 @@ |
|||
{ |
|||
"name" : "Q3ex", |
|||
"appid" : "__UNI__B16A5B2", |
|||
"description" : "", |
|||
"versionName" : "1.0.0", |
|||
"versionCode" : "100", |
|||
"transformPx" : false, |
|||
/* 5+App特有相关 */ |
|||
"app-plus" : { |
|||
"usingComponents" : true, |
|||
"nvueStyleCompiler" : "uni-app", |
|||
"compilerVersion" : 3, |
|||
"splashscreen" : { |
|||
"alwaysShowBeforeRender" : true, |
|||
"waiting" : true, |
|||
"autoclose" : true, |
|||
"delay" : 0 |
|||
}, |
|||
/* 模块配置 */ |
|||
"modules" : {}, |
|||
/* 应用发布信息 */ |
|||
"distribute" : { |
|||
/* android打包配置 */ |
|||
"android" : { |
|||
"permissions" : [ |
|||
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>", |
|||
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>", |
|||
"<uses-permission android:name=\"android.permission.VIBRATE\"/>", |
|||
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>", |
|||
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>", |
|||
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>", |
|||
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>", |
|||
"<uses-permission android:name=\"android.permission.CAMERA\"/>", |
|||
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>", |
|||
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>", |
|||
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>", |
|||
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>", |
|||
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>", |
|||
"<uses-feature android:name=\"android.hardware.camera\"/>", |
|||
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>" |
|||
] |
|||
}, |
|||
/* ios打包配置 */ |
|||
"ios" : {}, |
|||
/* SDK配置 */ |
|||
"sdkConfigs" : {} |
|||
} |
|||
}, |
|||
/* 快应用特有相关 */ |
|||
"quickapp" : {}, |
|||
/* 小程序特有相关 */ |
|||
"mp-weixin" : { |
|||
"appid" : "", |
|||
"setting" : { |
|||
"urlCheck" : false |
|||
}, |
|||
"usingComponents" : true |
|||
}, |
|||
"mp-alipay" : { |
|||
"usingComponents" : true |
|||
}, |
|||
"mp-baidu" : { |
|||
"usingComponents" : true |
|||
}, |
|||
"mp-toutiao" : { |
|||
"usingComponents" : true |
|||
}, |
|||
"uniStatistics" : { |
|||
"enable" : false |
|||
}, |
|||
"vueVersion" : "3" |
|||
} |
@ -0,0 +1,73 @@ |
|||
{ |
|||
"pages": [ |
|||
{ |
|||
"path": "pages/login/login", |
|||
"style": { |
|||
"navigationBarTitleText": "登录", |
|||
"navigationStyle": "custom" |
|||
} |
|||
}, |
|||
{ |
|||
"path": "pages/index/index", |
|||
"style": { |
|||
"navigationBarTitleText": "首页", |
|||
"navigationStyle": "custom" |
|||
} |
|||
}, |
|||
{ |
|||
"path": "pages/userInfo/userInfo", |
|||
"style": { |
|||
"navigationBarTitleText": "个人信息", |
|||
"navigationStyle": "custom" |
|||
} |
|||
}, |
|||
{ |
|||
"path": "pages/payment/payment", |
|||
"style": { |
|||
"navigationBarTitleText": "缴费记录", |
|||
"navigationStyle": "custom" |
|||
} |
|||
}, |
|||
{ |
|||
"path": "pages/expense/expense", |
|||
"style": { |
|||
"navigationBarTitleText": "支出记录", |
|||
"navigationStyle": "custom" |
|||
} |
|||
} |
|||
], |
|||
"globalStyle": { |
|||
"navigationBarTextStyle": "black", |
|||
"navigationBarTitleText": "随便写点啥", |
|||
"navigationBarBackgroundColor": "#F8F8F8", |
|||
"backgroundColor": "#F5F5F5" |
|||
}, |
|||
"tabBar": { |
|||
"color": "#666", |
|||
"selectedColor": "#36bffa", |
|||
"backgroundColor": "#fff", |
|||
"borderStyle": "black", |
|||
"list": [ |
|||
{ |
|||
"pagePath": "pages/index/index", |
|||
"text": "首页", |
|||
"iconPath":"/static/bar/赵文康竖中指.jpg" |
|||
}, |
|||
{ |
|||
"pagePath": "pages/payment/payment", |
|||
"text": "缴费", |
|||
"iconPath": "/static/bar/原始黄其振.jpg" |
|||
}, |
|||
{ |
|||
"pagePath": "pages/expense/expense", |
|||
"text": "支出", |
|||
"iconPath": "/static/bar/无腿黄其振.jpg" |
|||
}, |
|||
{ |
|||
"pagePath": "pages/userInfo/userInfo", |
|||
"text": "我的", |
|||
"iconPath": "/static/bar/证件照黄其振.jpg" |
|||
} |
|||
] |
|||
} |
|||
} |
@ -0,0 +1,256 @@ |
|||
<template> |
|||
<view class="expense-container"> |
|||
<view class="top-bar"> |
|||
<view class="title">支出记录</view> |
|||
</view> |
|||
|
|||
<view class="filter-bar"> |
|||
<view class="filter-item" :class="{ active: filterType === 'all' }" @click="filterType = 'all'"> |
|||
全部 |
|||
</view> |
|||
<view class="filter-item" :class="{ active: filterType === 'water' }" @click="filterType = 'water'"> |
|||
水费 |
|||
</view> |
|||
<view class="filter-item" :class="{ active: filterType === 'electric' }" @click="filterType = 'electric'"> |
|||
电费 |
|||
</view> |
|||
<view class="filter-item" :class="{ active: filterType === 'public' }" @click="filterType = 'public'"> |
|||
公共支出 |
|||
</view> |
|||
</view> |
|||
|
|||
<view class="list"> |
|||
<view class="expense-item" v-for="(item, index) in expenses" :key="index"> |
|||
<view class="item-header"> |
|||
<view class="expense-type"> |
|||
<text>{{ item.room }}</text> |
|||
</view> |
|||
<view class="expense-amount">¥{{ item.exp_amount }}</view> |
|||
</view> |
|||
|
|||
<view class="item-body"> |
|||
<view class="detail-item"> |
|||
<view class="detail-label">支付方式</view> |
|||
<view>{{ item.exp_method }}</view> |
|||
</view> |
|||
|
|||
<view class="detail-item"> |
|||
<view class="detail-label">支出日期</view> |
|||
<view>{{ item.exp_date }}</view> |
|||
</view> |
|||
|
|||
<view class="detail-item"> |
|||
<view class="detail-label">支付人</view> |
|||
<view>{{ item.username }}</view> |
|||
</view> |
|||
|
|||
<view class="detail-item" v-if="item.remark"> |
|||
<view class="detail-label">备注</view> |
|||
<view>{{ item.remark }}</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { ref, computed } from 'vue' |
|||
import { onShow } from '@dcloudio/uni-app' |
|||
|
|||
const filterType = ref('all') |
|||
const expenses = ref([{ |
|||
id: 1, |
|||
room:'706', |
|||
exp_amount: 39.00, |
|||
exp_date: '2025-09-08 14:27:21', |
|||
username:'李慧琳', |
|||
exp_method: '微信支付', |
|||
exp_type: 1, |
|||
remark: '电卡充值' |
|||
}, |
|||
{ |
|||
id: 2, |
|||
room:'706', |
|||
exp_amount: 11.00, |
|||
exp_date: '2025-09-08 14:28:40', |
|||
username:'李慧琳', |
|||
exp_method: '微信支付', |
|||
exp_type: 1, |
|||
remark: '电卡充值' |
|||
}, |
|||
{ |
|||
id: 3, |
|||
room:'706', |
|||
exp_amount: 50.00, |
|||
exp_date: '2025-08-15 09:20:30', |
|||
username:'李慧琳', |
|||
exp_method: '支付宝', |
|||
exp_type: 0, |
|||
remark: '8月水费' |
|||
}, |
|||
{ |
|||
id: 4, |
|||
room:'706', |
|||
exp_amount: 120.00, |
|||
exp_date: '2025-09-01 16:45:12', |
|||
username:'李慧琳', |
|||
exp_method: '微信支付', |
|||
exp_type: 2, |
|||
remark: '购买扫帚、拖把等清洁用品' |
|||
}, |
|||
{ |
|||
id: 5, |
|||
room:'706', |
|||
exp_amount: 35.00, |
|||
exp_date: '2025-08-22 11:10:25', |
|||
username:'李慧琳', |
|||
exp_method: '现金', |
|||
exp_type: 2, |
|||
remark: '购买垃圾桶2个' |
|||
} |
|||
]) |
|||
|
|||
|
|||
onShow(() => { |
|||
const isLogin = uni.getStorageSync('isLogin') |
|||
console.log(isLogin) |
|||
if (!isLogin) { |
|||
uni.redirectTo({ |
|||
url: '/pages/login/login' |
|||
}) |
|||
} |
|||
}) |
|||
|
|||
const res = computed(() => { |
|||
switch (filterType.value) { |
|||
case 'water': |
|||
return expenses.value.filter(item => item.exp_type === '0') |
|||
case 'electric': |
|||
return expenses.value.filter(item => item.exp_type === '1') |
|||
case 'public': |
|||
return expenses.value.filter(item => item.exp_type === '1') |
|||
default: |
|||
return expenses.value |
|||
} |
|||
}) |
|||
|
|||
|
|||
const getTypeName = function(type) { |
|||
switch (type) { |
|||
case 0: |
|||
return '水费'; |
|||
case 1: |
|||
return '电费'; |
|||
case 2: |
|||
return '公共支出'; |
|||
default: |
|||
return '其他支出'; |
|||
} |
|||
} |
|||
|
|||
const getIconClass = function(type) { |
|||
switch (type) { |
|||
case 0: |
|||
return 'icon-water'; |
|||
case 1: |
|||
return 'icon-electric'; |
|||
case 2: |
|||
return 'icon-public'; |
|||
default: |
|||
return 'icon-expense'; |
|||
} |
|||
|
|||
} |
|||
|
|||
</script> |
|||
|
|||
<style scoped> |
|||
.expense-container { |
|||
background-color: #f5f5f5; |
|||
height: 100vh; |
|||
} |
|||
|
|||
.top-bar { |
|||
display: flex; |
|||
align-items: center; |
|||
padding: 30rpx 20rpx; |
|||
background-color: #fff; |
|||
border-bottom: 1px solid #eee; |
|||
} |
|||
|
|||
.title { |
|||
flex: 1; |
|||
text-align: center; |
|||
font-size: 34rpx; |
|||
font-weight: bold; |
|||
} |
|||
|
|||
.filter-bar { |
|||
display: flex; |
|||
background-color: #fff; |
|||
padding: 15rpx 10rpx; |
|||
border-bottom: 1px solid #eee; |
|||
} |
|||
|
|||
.filter-item { |
|||
display: inline-block; |
|||
padding: 15rpx 25rpx; |
|||
font-size: 26rpx; |
|||
border-radius: 30rpx; |
|||
margin: 0 5rpx; |
|||
} |
|||
|
|||
.filter-item.active { |
|||
background-color: #e6f7ff; |
|||
color: #36bffa; |
|||
} |
|||
|
|||
.list { |
|||
padding: 20rpx; |
|||
} |
|||
|
|||
.expense-item { |
|||
background-color: #fff; |
|||
border-radius: 16rpx; |
|||
padding: 25rpx; |
|||
margin-bottom: 20rpx; |
|||
box-shadow: 0 5rpx 15rpx rgba(0, 0, 0, 0.05); |
|||
} |
|||
|
|||
.item-header { |
|||
display: flex; |
|||
justify-content: space-between; |
|||
margin-bottom: 20rpx; |
|||
padding-bottom: 20rpx; |
|||
border-bottom: 1px solid #f5f5f5; |
|||
} |
|||
|
|||
.expense-type text { |
|||
font-size: 30rpx; |
|||
font-weight: bold; |
|||
color: #333; |
|||
} |
|||
|
|||
.expense-amount { |
|||
font-size: 32rpx; |
|||
font-weight: bold; |
|||
color: #f5222d; |
|||
} |
|||
|
|||
.item-body { |
|||
display: flex; |
|||
flex-direction: column; |
|||
} |
|||
|
|||
.detail-item { |
|||
display: flex; |
|||
justify-content: space-between; |
|||
padding: 15rpx 0; |
|||
font-size: 28rpx; |
|||
} |
|||
|
|||
.detail-label { |
|||
color: #666; |
|||
} |
|||
</style> |
@ -0,0 +1,214 @@ |
|||
<template> |
|||
<view class="index-container"> |
|||
<view class="user-info" @click="jumpTo('/pages/userInfo/userInfo')"> |
|||
<view class="avatar" /> |
|||
<view> |
|||
<view>李慧琳</view> |
|||
<view>706宿舍</view> |
|||
</view> |
|||
</view> |
|||
|
|||
<view class="swiper1"> |
|||
<swiper circular autoplay interval="1000" indicator-dots indicator-color="#8f939c" |
|||
indicator-active-color="#e43d33"> |
|||
<swiper-item> |
|||
<img src="/static/bar/爱莉1.jpg" /> |
|||
</swiper-item> |
|||
<swiper-item> |
|||
<img src="/static/bar/原始黄其振.jpg" /> |
|||
</swiper-item> |
|||
<swiper-item> |
|||
<img src="/static/bar/真我光锥.jpg" /> |
|||
</swiper-item> |
|||
</swiper> |
|||
</view> |
|||
|
|||
<view class="layout-grid"> |
|||
<view class="grid-item" @click="jumpTo('/pages/payment/payment')"> |
|||
<view class="grid-icon icon1" /> |
|||
<view>缴费记录</view> |
|||
</view> |
|||
|
|||
<view class="grid-item" @click="jumpTo('/pages/expense/expense')"> |
|||
<view class="grid-icon icon2" /> |
|||
<view>支出记录</view> |
|||
</view> |
|||
|
|||
<view class="grid-item" @click="showTip"> |
|||
<view class="grid-icon icon3" /> |
|||
<view>宿舍信息</view> |
|||
</view> |
|||
|
|||
<view class="grid-item" @click="showTip"> |
|||
<view class="grid-icon icon4" /> |
|||
<view>没想好写啥</view> |
|||
</view> |
|||
</view> |
|||
|
|||
<view class="stats"> |
|||
<view class="stats-title">费用统计</view> |
|||
|
|||
<view class="stats-cards"> |
|||
<view class="stat-card"> |
|||
<view class="stat-value">¥150.00</view> |
|||
<view class="stat-label">本月缴费</view> |
|||
</view> |
|||
<view class="stat-card"> |
|||
<view class="stat-value">¥50.00</view> |
|||
<view class="stat-label">本月支出</view> |
|||
</view> |
|||
</view> |
|||
|
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { |
|||
onShow |
|||
} from '@dcloudio/uni-app' |
|||
|
|||
const jumpTo = (url) => { |
|||
uni.switchTab({ |
|||
url |
|||
}) |
|||
} |
|||
|
|||
const showTip = () => { |
|||
uni.showToast({ |
|||
title: '前面的功能以后再来探索吧', |
|||
icon: 'none' |
|||
}) |
|||
} |
|||
|
|||
onShow(() => { |
|||
const isLogin = uni.getStorageSync('isLogin') |
|||
console.log(isLogin) |
|||
if (!isLogin) { |
|||
uni.redirectTo({ |
|||
url: '/pages/login/login' |
|||
}) |
|||
} |
|||
}) |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.index-container { |
|||
padding: 20rpx; |
|||
height: 100vh; |
|||
background-color: #f5f5f5; |
|||
} |
|||
|
|||
.user-info { |
|||
display: flex; |
|||
align-items: center; |
|||
background-color: #fff; |
|||
border-radius: 16rpx; |
|||
padding: 30rpx; |
|||
margin-bottom: 30rpx; |
|||
box-shadow: 0 5rpx 15rpx rgba(0, 0, 0, 0.1); |
|||
} |
|||
|
|||
.avatar { |
|||
width: 120rpx; |
|||
height: 120rpx; |
|||
border-radius: 50%; |
|||
background-color: red; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
margin-right: 30rpx; |
|||
} |
|||
|
|||
.swiper1 { |
|||
width: 100vw; |
|||
height: 20vh; |
|||
} |
|||
|
|||
.layout-grid { |
|||
display: grid; |
|||
grid-template-columns: repeat(2, 1fr); |
|||
gap: 20rpx; |
|||
margin-bottom: 30rpx; |
|||
} |
|||
|
|||
.grid-item { |
|||
background-color: #fff; |
|||
border-radius: 16rpx; |
|||
padding: 3vh; |
|||
display: flex; |
|||
flex-direction: column; |
|||
align-items: center; |
|||
justify-content: center; |
|||
box-shadow: 0 5rpx 15rpx rgba(0, 0, 0, 0.1); |
|||
} |
|||
|
|||
.grid-item:active { |
|||
transform: scale(0.95); |
|||
} |
|||
|
|||
.grid-icon { |
|||
width: 22vw; |
|||
height: 9vh; |
|||
border-radius: 50%; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
margin-bottom: 20rpx; |
|||
} |
|||
|
|||
.icon1 { |
|||
background-color: #fff0f0; |
|||
} |
|||
|
|||
.icon2 { |
|||
background-color: #f0f9ff; |
|||
} |
|||
|
|||
.icon3 { |
|||
background-color: #fff7e6; |
|||
} |
|||
|
|||
.icon4 { |
|||
background-color: #f6ffed; |
|||
} |
|||
|
|||
.stats { |
|||
background-color: #fff; |
|||
border-radius: 16rpx; |
|||
padding: 30rpx; |
|||
box-shadow: 0 5rpx 15rpx rgba(0, 0, 0, 0.05); |
|||
} |
|||
|
|||
.stats-title { |
|||
font-size: 30rpx; |
|||
font-weight: bold; |
|||
margin-bottom: 30rpx; |
|||
padding-bottom: 20rpx; |
|||
border-bottom: 1px solid #eee; |
|||
} |
|||
|
|||
.stats-cards { |
|||
display: flex; |
|||
justify-content: space-around; |
|||
} |
|||
|
|||
.stat-card { |
|||
display: flex; |
|||
flex-direction: column; |
|||
align-items: center; |
|||
padding: 20rpx; |
|||
} |
|||
|
|||
.stat-value { |
|||
font-size: 36rpx; |
|||
font-weight: bold; |
|||
color: #36bffa; |
|||
margin-bottom: 10rpx; |
|||
} |
|||
|
|||
.stat-label { |
|||
font-size: 26rpx; |
|||
color: #666; |
|||
} |
|||
</style> |
@ -0,0 +1,131 @@ |
|||
<template> |
|||
<view class="login-container"> |
|||
<view class="login-box"> |
|||
<view class="title">宿舍管理系统</view> |
|||
|
|||
<view class="input-group"> |
|||
<view class="input-item"> |
|||
<input type="text" v-model="username" placeholder="请输入账号" /> |
|||
</view> |
|||
|
|||
<view class="input-item"> |
|||
<input type="password" v-model="password" placeholder="请输入密码" /> |
|||
</view> |
|||
</view> |
|||
|
|||
<button class="login-btn" @click="handleLogin"> |
|||
<text>登录</text> |
|||
</button> |
|||
|
|||
<view class="tips"> |
|||
<text>账号: 20030229</text> |
|||
<text>密码: hahaha</text> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { ref } from 'vue' |
|||
|
|||
const username = ref('') |
|||
const password = ref('') |
|||
const handleLogin = function() { |
|||
if (!username.value & password.value) { |
|||
uni.showToast({ |
|||
title: '请输入账号', |
|||
icon:'none' |
|||
}) |
|||
return |
|||
} |
|||
if (username.value & !password.value) { |
|||
uni.showToast({ |
|||
title: '请输入密码', |
|||
icon:'none' |
|||
}) |
|||
return |
|||
} |
|||
if (!username.value & !password.value) { |
|||
uni.showToast({ |
|||
title: '请输入账号和密码', |
|||
icon:'none' |
|||
}) |
|||
return |
|||
} |
|||
|
|||
if (username.value === '20030229' && password.value === 'hahaha') { |
|||
setTimeout(() => { |
|||
uni.setStorageSync('isLogin', true) |
|||
uni.switchTab({ |
|||
url: '/pages/index/index' |
|||
}) |
|||
}, 1000) |
|||
} else { |
|||
uni.showToast({ |
|||
title: '账号或密码错误', |
|||
icon:'none' |
|||
}) |
|||
} |
|||
} |
|||
</script> |
|||
<style scoped> |
|||
.login-container { |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
height: 100vh; |
|||
background-color: #f5f5f5; |
|||
} |
|||
|
|||
.login-box { |
|||
width: 70vw; |
|||
background-color: #fff; |
|||
border-radius: 20rpx; |
|||
padding: 60rpx 40rpx; |
|||
box-shadow: 0 10rpx 30rpx rgba(0, 0, 0, 0.1); |
|||
} |
|||
|
|||
.title { |
|||
text-align: center; |
|||
font-size: 36rpx; |
|||
font-weight: bold; |
|||
color: #333; |
|||
margin-bottom: 10vh; |
|||
} |
|||
|
|||
.input-group { |
|||
margin-bottom: 60rpx; |
|||
} |
|||
|
|||
.input-item { |
|||
display: flex; |
|||
align-items: center; |
|||
border-bottom: 1px solid #eee; |
|||
padding: 20rpx 20rpx; |
|||
} |
|||
|
|||
.login-btn { |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
width: 40vw; |
|||
height: 4vh; |
|||
background-color: #36bffa; |
|||
color: #fff; |
|||
border-radius: 40rpx; |
|||
font-size: 30rpx; |
|||
} |
|||
|
|||
.tips { |
|||
display: flex; |
|||
flex-direction: column; |
|||
align-items: center; |
|||
margin-top: 5vh; |
|||
color: #999; |
|||
font-size: 24rpx; |
|||
} |
|||
|
|||
.tips text { |
|||
margin-top: 10rpx; |
|||
} |
|||
</style> |
@ -0,0 +1,193 @@ |
|||
<template> |
|||
<view class="payment-container"> |
|||
<view class="top-bar"> |
|||
<view class="title">缴费记录</view> |
|||
</view> |
|||
|
|||
<view class="filter-bar"> |
|||
<view class="filter-item" :class="{ active: filterType === 'all' }" @click="filterType = 'all'"> |
|||
全部 |
|||
</view> |
|||
<view class="filter-item" :class="{ active: filterType === 'pass' }" @click="filterType = 'pass'"> |
|||
已缴费 |
|||
</view> |
|||
<view class="filter-item" :class="{ active: filterType === 'pending' }" @click="filterType = 'pending'"> |
|||
待缴费 |
|||
</view> |
|||
</view> |
|||
|
|||
<view class="list-container"> |
|||
<view class="payment-item" v-for="(item, index) in res" :key="index"> |
|||
<view class="item-header"> |
|||
<view class="payment-type"> |
|||
<text>{{ item.room }}</text> |
|||
</view> |
|||
<view class="payment-status" :class="{ pass: item.pay_status === '0', pending: item.pay_status === '1' }"> |
|||
{{ item.pay_status === '0' ? '已缴费' : '待缴费' }} |
|||
</view> |
|||
</view> |
|||
|
|||
<view class="item-body"> |
|||
<view class="list"> |
|||
<view class="detail-label">金额</view> |
|||
<view>¥{{ item.pay_amount }}</view> |
|||
</view> |
|||
|
|||
<view class="list"> |
|||
<view class="detail-label">缴费日期</view> |
|||
<view>{{ item.pay_date }}</view> |
|||
</view> |
|||
|
|||
<view class="list"> |
|||
<view class="detail-label">缴费人</view> |
|||
<view>{{ item.username }}</view> |
|||
</view> |
|||
|
|||
<view class="list" v-if="item.remark"> |
|||
<view class="detail-label">备注</view> |
|||
<view>{{ item.remark }}</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
|
|||
<view v-if="res.length === 0"> |
|||
<text>暂无缴费记录</text> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
|
|||
<script setup> |
|||
import { ref, computed, onMounted } from 'vue' |
|||
import { onShow } from '@dcloudio/uni-app' |
|||
|
|||
const filterType = ref('all') |
|||
const payments = ref([ |
|||
{ id: 1, username:'李慧琳', room:'706', pay_amount: 75, pay_date: '2025-07-31', pay_status: '0', remark: '7月宿舍费' }, |
|||
{ id: 2, username:'李慧琳', room:'706', pay_amount: 75, pay_date: '2025-06-30', pay_status: '0', remark: '6月宿舍费' }, |
|||
{ id: 3, username:'李慧琳', room:'706', pay_amount: 75, pay_date: '2025-05-28', pay_status: '0', remark: '5月宿舍费' }, |
|||
{ id: 4, username:'李慧琳', room:'706', pay_amount: 80, pay_date: '2025-08-31', pay_status: '1', remark: '8月宿舍费' } |
|||
]) |
|||
|
|||
const res = computed(() => { |
|||
switch (filterType.value) { |
|||
case 'pass': |
|||
return payments.value.filter(item => item.pay_status === '0') |
|||
case 'pending': |
|||
return payments.value.filter(item => item.pay_status === '1') |
|||
default: |
|||
return payments.value |
|||
} |
|||
}) |
|||
|
|||
onShow(() => { |
|||
const isLogin = uni.getStorageSync('isLogin') |
|||
console.log(isLogin) |
|||
if (!isLogin) { |
|||
uni.redirectTo({ |
|||
url: '/pages/login/login' |
|||
}) |
|||
} |
|||
}) |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.payment-container { |
|||
background-color: #f5f5f5; |
|||
min-height: 100vh; |
|||
} |
|||
|
|||
.top-bar { |
|||
display: flex; |
|||
align-items: center; |
|||
padding: 30rpx 20rpx; |
|||
background-color: #fff; |
|||
border-bottom: 1px solid #eee; |
|||
} |
|||
|
|||
.title { |
|||
flex: 1; |
|||
text-align: center; |
|||
font-size: 34rpx; |
|||
font-weight: bold; |
|||
} |
|||
|
|||
.filter-bar { |
|||
display: flex; |
|||
background-color: #fff; |
|||
padding: 15rpx 20rpx; |
|||
border-bottom: 1px solid #eee; |
|||
} |
|||
|
|||
.filter-item { |
|||
flex: 1; |
|||
text-align: center; |
|||
padding: 15rpx 0; |
|||
font-size: 28rpx; |
|||
border-radius: 30rpx; |
|||
} |
|||
|
|||
.filter-item.active { |
|||
background-color: #e6f7ff; |
|||
color: #36bffa; |
|||
} |
|||
|
|||
.list-container { |
|||
padding: 20rpx; |
|||
} |
|||
|
|||
.payment-item { |
|||
background-color: #fff; |
|||
border-radius: 16rpx; |
|||
padding: 25rpx; |
|||
margin-bottom: 20rpx; |
|||
box-shadow: 0 5rpx 15rpx rgba(0, 0, 0, 0.05); |
|||
} |
|||
|
|||
.item-header { |
|||
display: flex; |
|||
justify-content: space-between; |
|||
align-items: center; |
|||
margin-bottom: 10rpx; |
|||
padding-bottom: 20rpx; |
|||
border-bottom: 1px solid #f5f5f5; |
|||
} |
|||
|
|||
.payment-type text { |
|||
font-size: 30rpx; |
|||
font-weight: bold; |
|||
} |
|||
|
|||
.payment-status { |
|||
padding: 5rpx 20rpx; |
|||
border-radius: 20rpx; |
|||
font-size: 30rpx; |
|||
} |
|||
|
|||
.payment-status.pass { |
|||
background-color: #e6fffb; |
|||
color: #00b42a; |
|||
} |
|||
|
|||
.payment-status.pending { |
|||
background-color: #fff2e8; |
|||
color: #ff7d00; |
|||
} |
|||
|
|||
.item-body { |
|||
display: flex; |
|||
flex-direction: column; |
|||
} |
|||
|
|||
.list { |
|||
display: flex; |
|||
justify-content: space-between; |
|||
padding: 15rpx 0; |
|||
font-size: 28rpx; |
|||
} |
|||
|
|||
.detail-label { |
|||
color: #666; |
|||
} |
|||
</style> |
@ -0,0 +1,187 @@ |
|||
<template> |
|||
<view class="userinfo-container"> |
|||
<view class="top-bar"> |
|||
<view class="title">个人信息</view> |
|||
</view> |
|||
|
|||
<view class="avatar-all"> |
|||
<view class="avatar" /> |
|||
<view class="name">李慧琳</view> |
|||
<view class="room">706宿舍</view> |
|||
</view> |
|||
|
|||
<view class="info-list"> |
|||
<view class="info-item"> |
|||
<view class="info-label">学号</view> |
|||
<view class="info-value">20030229</view> |
|||
</view> |
|||
|
|||
<view class="info-item"> |
|||
<view class="info-label">性别</view> |
|||
<view class="info-value">女</view> |
|||
</view> |
|||
|
|||
<view class="info-item"> |
|||
<view class="info-label">联系电话</view> |
|||
<view class="info-value">159****5202</view> |
|||
</view> |
|||
|
|||
<view class="info-item"> |
|||
<view class="info-label">入住日期</view> |
|||
<view class="info-value">2025-07-06</view> |
|||
</view> |
|||
|
|||
<view class="info-item"> |
|||
<view class="info-label">住宿状态</view> |
|||
<view class="info-value"> |
|||
<text class="status-in">在宿</text> |
|||
</view> |
|||
</view> |
|||
|
|||
<view class="info-item"> |
|||
<view class="info-label">宿舍地址</view> |
|||
<view class="info-value">706</view> |
|||
</view> |
|||
|
|||
<view class="info-item"> |
|||
<view class="info-label">宿舍人数</view> |
|||
<view class="info-value">5人 / 最多12人</view> |
|||
</view> |
|||
</view> |
|||
|
|||
<button class="logout-btn" @click="handleLogout"> |
|||
<text>退出登录</text> |
|||
</button> |
|||
</view> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { onShow } from '@dcloudio/uni-app' |
|||
|
|||
const handleLogout = () => { |
|||
uni.showModal({ |
|||
title: '提示', |
|||
content: '确定要退出登录吗?', |
|||
success: (res) => { |
|||
if (res.confirm) { |
|||
uni.removeStorageSync('isLogin') |
|||
uni.redirectTo({ |
|||
url: '/pages/login/login' |
|||
}) |
|||
} |
|||
} |
|||
}) |
|||
} |
|||
|
|||
onShow(() => { |
|||
const isLogin = uni.getStorageSync('isLogin') |
|||
console.log(isLogin) |
|||
if (!isLogin) { |
|||
uni.redirectTo({ |
|||
url: '/pages/login/login' |
|||
}) |
|||
} |
|||
}) |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.userinfo-container { |
|||
background-color: #f5f5f5; |
|||
height: 100vh; |
|||
} |
|||
|
|||
.top-bar { |
|||
display: flex; |
|||
align-items: center; |
|||
padding: 30rpx 20rpx; |
|||
background-color: #fff; |
|||
border-bottom: 1px solid #eee; |
|||
} |
|||
|
|||
.title { |
|||
width: 100vw; |
|||
text-align: center; |
|||
font-size: 34rpx; |
|||
font-weight: bold; |
|||
} |
|||
|
|||
.avatar-all { |
|||
display: flex; |
|||
flex-direction: column; |
|||
align-items: center; |
|||
padding: 60rpx 0; |
|||
background-color: #fff; |
|||
margin-bottom: 20rpx; |
|||
} |
|||
|
|||
.avatar { |
|||
width: 180rpx; |
|||
height: 180rpx; |
|||
border-radius: 50%; |
|||
background-color: #e6f7ff; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
margin-bottom: 30rpx; |
|||
} |
|||
|
|||
|
|||
.name { |
|||
font-size: 36rpx; |
|||
font-weight: bold; |
|||
color: #333; |
|||
margin-bottom: 15rpx; |
|||
} |
|||
|
|||
.room { |
|||
font-size: 28rpx; |
|||
color: #666; |
|||
background-color: #f0f9ff; |
|||
padding: 8rpx 20rpx; |
|||
border-radius: 20rpx; |
|||
} |
|||
|
|||
.info-list { |
|||
background-color: #fff; |
|||
padding: 0 20rpx; |
|||
} |
|||
|
|||
.info-item { |
|||
display: flex; |
|||
align-items: center; |
|||
padding: 30rpx; |
|||
border-bottom: 1px solid #eee; |
|||
} |
|||
|
|||
.info-label { |
|||
font-size: 30rpx; |
|||
color: #666; |
|||
} |
|||
|
|||
.info-value { |
|||
flex: 1; |
|||
font-size: 30rpx; |
|||
text-align: right; |
|||
} |
|||
|
|||
.status-in { |
|||
padding: 5rpx 20rpx; |
|||
border-radius: 20rpx; |
|||
font-size: 26rpx; |
|||
background-color: #e6fffb; |
|||
color: #00b42a; |
|||
} |
|||
|
|||
.logout-btn { |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
width: 40vw; |
|||
height: 4vh; |
|||
background-color: #36bffa; |
|||
color: #fff; |
|||
border-radius: 40rpx; |
|||
font-size: 30rpx; |
|||
margin-top:5vh; |
|||
} |
|||
</style> |
After Width: 360 | Height: 210 | Size: 7.5 KiB |
After Width: 611 | Height: 600 | Size: 35 KiB |
After Width: 360 | Height: 213 | Size: 9.7 KiB |
After Width: 360 | Height: 202 | Size: 28 KiB |
After Width: 360 | Height: 206 | Size: 8.3 KiB |
After Width: 344 | Height: 198 | Size: 28 KiB |
After Width: 1080 | Height: 1440 | Size: 91 KiB |
After Width: 72 | Height: 72 | Size: 3.9 KiB |
@ -0,0 +1,13 @@ |
|||
uni.addInterceptor({ |
|||
returnValue (res) { |
|||
if (!(!!res && (typeof res === "object" || typeof res === "function") && typeof res.then === "function")) { |
|||
return res; |
|||
} |
|||
return new Promise((resolve, reject) => { |
|||
res.then((res) => { |
|||
if (!res) return resolve(res) |
|||
return res[0] ? reject(res[0]) : resolve(res[1]) |
|||
}); |
|||
}); |
|||
}, |
|||
}); |
@ -0,0 +1,76 @@ |
|||
/** |
|||
* 这里是uni-app内置的常用样式变量 |
|||
* |
|||
* uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量 |
|||
* 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App |
|||
* |
|||
*/ |
|||
|
|||
/** |
|||
* 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能 |
|||
* |
|||
* 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件 |
|||
*/ |
|||
|
|||
/* 颜色变量 */ |
|||
|
|||
/* 行为相关颜色 */ |
|||
$uni-color-primary: #007aff; |
|||
$uni-color-success: #4cd964; |
|||
$uni-color-warning: #f0ad4e; |
|||
$uni-color-error: #dd524d; |
|||
|
|||
/* 文字基本颜色 */ |
|||
$uni-text-color:#333;//基本色 |
|||
$uni-text-color-inverse:#fff;//反色 |
|||
$uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息 |
|||
$uni-text-color-placeholder: #808080; |
|||
$uni-text-color-disable:#c0c0c0; |
|||
|
|||
/* 背景颜色 */ |
|||
$uni-bg-color:#ffffff; |
|||
$uni-bg-color-grey:#f8f8f8; |
|||
$uni-bg-color-hover:#f1f1f1;//点击状态颜色 |
|||
$uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色 |
|||
|
|||
/* 边框颜色 */ |
|||
$uni-border-color:#c8c7cc; |
|||
|
|||
/* 尺寸变量 */ |
|||
|
|||
/* 文字尺寸 */ |
|||
$uni-font-size-sm:12px; |
|||
$uni-font-size-base:14px; |
|||
$uni-font-size-lg:16px; |
|||
|
|||
/* 图片尺寸 */ |
|||
$uni-img-size-sm:20px; |
|||
$uni-img-size-base:26px; |
|||
$uni-img-size-lg:40px; |
|||
|
|||
/* Border Radius */ |
|||
$uni-border-radius-sm: 2px; |
|||
$uni-border-radius-base: 3px; |
|||
$uni-border-radius-lg: 6px; |
|||
$uni-border-radius-circle: 50%; |
|||
|
|||
/* 水平间距 */ |
|||
$uni-spacing-row-sm: 5px; |
|||
$uni-spacing-row-base: 10px; |
|||
$uni-spacing-row-lg: 15px; |
|||
|
|||
/* 垂直间距 */ |
|||
$uni-spacing-col-sm: 4px; |
|||
$uni-spacing-col-base: 8px; |
|||
$uni-spacing-col-lg: 12px; |
|||
|
|||
/* 透明度 */ |
|||
$uni-opacity-disabled: 0.3; // 组件禁用态的透明度 |
|||
|
|||
/* 文章场景相关 */ |
|||
$uni-color-title: #2C405A; // 文章标题颜色 |
|||
$uni-font-size-title:20px; |
|||
$uni-color-subtitle: #555555; // 二级标题颜色 |
|||
$uni-font-size-subtitle:26px; |
|||
$uni-color-paragraph: #3F536E; // 文章段落颜色 |
|||
$uni-font-size-paragraph:15px; |
@ -0,0 +1,8 @@ |
|||
{ |
|||
"hash": "de5c8cff", |
|||
"configHash": "727b7ea9", |
|||
"lockfileHash": "e3b0c442", |
|||
"browserHash": "f575ccf0", |
|||
"optimized": {}, |
|||
"chunks": {} |
|||
} |
@ -0,0 +1,3 @@ |
|||
{ |
|||
"type": "module" |
|||
} |