-
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" |
||||
|
} |