first commit

This commit is contained in:
那些花儿
2025-04-24 15:53:31 +08:00
commit f55420fc1d
498 changed files with 205724 additions and 0 deletions
+21
View File
@@ -0,0 +1,21 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
.DS_Store
dist
*.local
# Editor directories and files
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
+20
View File
@@ -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="/src/main.js"></script>
</body>
</html>
+11639
View File
File diff suppressed because it is too large Load Diff
+71
View File
@@ -0,0 +1,71 @@
{
"name": "uni-preset-vue",
"version": "0.0.0",
"scripts": {
"dev:custom": "uni -p",
"dev:h5": "uni",
"dev:h5:ssr": "uni --ssr",
"dev:mp-alipay": "uni -p mp-alipay",
"dev:mp-baidu": "uni -p mp-baidu",
"dev:mp-jd": "uni -p mp-jd",
"dev:mp-kuaishou": "uni -p mp-kuaishou",
"dev:mp-lark": "uni -p mp-lark",
"dev:mp-qq": "uni -p mp-qq",
"dev:mp-toutiao": "uni -p mp-toutiao",
"dev:mp-harmony": "uni -p mp-harmony",
"dev:mp-weixin": "uni -p mp-weixin",
"dev:mp-xhs": "uni -p mp-xhs",
"dev:quickapp-webview": "uni -p quickapp-webview",
"dev:quickapp-webview-huawei": "uni -p quickapp-webview-huawei",
"dev:quickapp-webview-union": "uni -p quickapp-webview-union",
"build:custom": "uni build -p",
"build:h5": "uni build",
"build:h5:ssr": "uni build --ssr",
"build:mp-alipay": "uni build -p mp-alipay",
"build:mp-baidu": "uni build -p mp-baidu",
"build:mp-jd": "uni build -p mp-jd",
"build:mp-kuaishou": "uni build -p mp-kuaishou",
"build:mp-lark": "uni build -p mp-lark",
"build:mp-qq": "uni build -p mp-qq",
"build:mp-toutiao": "uni build -p mp-toutiao",
"build:mp-harmony": "uni build -p mp-harmony",
"build:mp-weixin": "uni build -p mp-weixin",
"build:mp-xhs": "uni build -p mp-xhs",
"build:quickapp-webview": "uni build -p quickapp-webview",
"build:quickapp-webview-huawei": "uni build -p quickapp-webview-huawei",
"build:quickapp-webview-union": "uni build -p quickapp-webview-union"
},
"dependencies": {
"@dcloudio/uni-app": "3.0.0-4050720250324001",
"@dcloudio/uni-app-harmony": "3.0.0-4050720250324001",
"@dcloudio/uni-app-plus": "3.0.0-4050720250324001",
"@dcloudio/uni-components": "3.0.0-4050720250324001",
"@dcloudio/uni-h5": "3.0.0-4050720250324001",
"@dcloudio/uni-mp-alipay": "3.0.0-4050720250324001",
"@dcloudio/uni-mp-baidu": "3.0.0-4050720250324001",
"@dcloudio/uni-mp-harmony": "3.0.0-4050720250324001",
"@dcloudio/uni-mp-jd": "3.0.0-4050720250324001",
"@dcloudio/uni-mp-kuaishou": "3.0.0-4050720250324001",
"@dcloudio/uni-mp-lark": "3.0.0-4050720250324001",
"@dcloudio/uni-mp-qq": "3.0.0-4050720250324001",
"@dcloudio/uni-mp-toutiao": "3.0.0-4050720250324001",
"@dcloudio/uni-mp-weixin": "3.0.0-4050720250324001",
"@dcloudio/uni-mp-xhs": "3.0.0-4050720250324001",
"@dcloudio/uni-quickapp-webview": "3.0.0-4050720250324001",
"tdesign-mobile-vue": "^1.8.3",
"vue": "^3.4.21",
"vue-i18n": "^9.1.9"
},
"devDependencies": {
"@dcloudio/types": "^3.4.8",
"@dcloudio/uni-automator": "3.0.0-4050720250324001",
"@dcloudio/uni-cli-shared": "3.0.0-4050720250324001",
"@dcloudio/uni-stacktracey": "3.0.0-4050720250324001",
"@dcloudio/vite-plugin-uni": "3.0.0-4050720250324001",
"@vue/runtime-core": "^3.4.21",
"less": "^4.3.0",
"unplugin-auto-import": "^19.1.2",
"unplugin-vue-components": "^28.5.0",
"vite": "5.2.8"
}
}
+10
View File
@@ -0,0 +1,10 @@
/// <reference types='@dcloudio/types' />
import 'vue'
declare module '@vue/runtime-core' {
type Hooks = App.AppInstance & Page.PageInstance;
interface ComponentCustomOptions extends Hooks {
}
}
+48
View File
@@ -0,0 +1,48 @@
<script>
export default {
onLaunch: function () {
console.log('App Launch')
},
onShow: function () {
console.log('App Show')
},
onHide: function () {
console.log('App Hide')
},
}
</script>
<style>
/*每个页面公共css */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif;
}
html, body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
font-size: 14px;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
color: #333;
background-color: #f5f5f5;
box-sizing: border-box;
}
.page-container {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
overflow-x: hidden;
}
uni-page-body{
height: 100%;
}
</style>
+17
View File
@@ -0,0 +1,17 @@
import {createSSRApp} from "vue";
import App from "./App.vue";
// 引入TDesign组件库
import TDesign from 'tdesign-mobile-vue';
// 引入组件库的少量全局样式变量
import 'tdesign-mobile-vue/es/style/index.css';
// 自定义组件库样式
import './theme.css'
export function createApp() {
const app = createSSRApp(App);
app.use(TDesign); // 使用TDesign组件库
return {
app,
};
}
+72
View File
@@ -0,0 +1,72 @@
{
"name" : "",
"appid" : "",
"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"
}
+60
View File
@@ -0,0 +1,60 @@
{
"pages": [
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "uni-app"
}
},
{
"path": "pages/activity/list/index",
"style": {
"navigationBarTitleText": "赛事活动"
}
},
{
"path": "pages/activity/detail/index",
"style": {
"navigationBarTitleText": "活动详情"
}
},
{
"path": "pages/activity/registration-form/index",
"style": {
"navigationBarTitleText": "活动报名"
}
},
{
"path": "pages/activity/team/index",
"style": {
"navigationBarTitleText": "我的团队"
}
}
],
"globalStyle": {
"navigationBarTextStyle": "#FFFFFF",
"navigationBarTitleText": "uni-app",
"navigationBarBackgroundColor": "#ff5050",
"backgroundColor": "#F8F8F8"
},
"tabBar": {
"color": "#000",
"selectedColor": "#ff5050",
"borderStyle": "black",
"backgroundColor": "#ffffff",
"height": "60px",
"fontSize": "12px",
"iconWidth": "24px",
"spacing": "3px",
"list": [
{
"pagePath": "pages/index/index",
"text": "组件"
},
{
"pagePath": "pages/my/index",
"text": "接口"
}
]
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,11 @@
<script setup>
</script>
<template>
</template>
<style scoped>
</style>
+372
View File
@@ -0,0 +1,372 @@
<template>
<view class="page-container">
<!-- 顶部搜索区域 -->
<view class="header">
<t-search
v-model="pageForm.searchKeyword"
placeholder="搜索活动"
shape="round"
class="search"
>
<template #action>
<t-button variant="text" @click="filterVisible = true">筛选</t-button>
</template>
</t-search>
</view>
<!-- 筛选弹出层 -->
<t-popup
v-model:visible="filterVisible"
placement="top"
>
<view class="filter">
<view class="filter-header">
<t-button variant="text" @click="handleClearFilter">重置</t-button>
<text class="filter-title">筛选条件</text>
<t-button theme="primary" variant="text" @click="handleSearch">确定</t-button>
</view>
<t-cell-group title="状态">
<t-radio-group v-model="pageForm.status">
<t-radio
v-for="option in statusOptions"
:key="option.value"
:value="option.value"
:label="option.label"
borderless
/>
</t-radio-group>
</t-cell-group>
</view>
</t-popup>
<!-- 活动列表 -->
<scroll-view
style="overflow-y: auto;flex: 1"
:scroll-y="true"
:show-scrollbar="false"
@scrolltolower="onLoadMore"
:refresher-enabled="true"
@refresherrefresh="getListData(true)"
:refresher-triggered="refreshIng"
refresher-background="#f5f5f5"
>
<view class="card"
v-for="item in dataList"
:key="item.id"
@click="navigateToDetail(item.id)"
>
<view class="card-head">
<image :src="item.image" mode="aspectFill" class="card-img"/>
<text class="card-tag" :class="getStatusClass(item.status)">
{{ getStatusText(item.status) }}
</text>
</view>
<view class="card-body">
<view class="card-title">{{ item.title }}</view>
<view class="card-info">
<view class="info-item">
<t-icon name="alarm" size="12px"/>
<text>{{ item.date }}</text>
</view>
<view class="info-item">
<t-icon name="location" size="12px"/>
<text>{{ item.location }}</text>
</view>
<view class="info-item">
<t-icon name="user" size="12px"/>
<text>{{ item.participants }}人已报名</text>
</view>
</view>
<view class="card-footer">
<view class="price">
<text class="price-symbol">¥</text>
<text class="price-value">{{ item.price }}</text>
</view>
<t-button
size="small"
shape="round"
:theme="item.status === 2 ? 'default' : 'primary'"
:disabled="item.status === 2"
>
{{ item.status === 1 ? '立即报名' : item.status === 3 ? '预约提醒' : '已结束' }}
</t-button>
</view>
</view>
</view>
<view class="loading-area">
<t-loading v-if="loading" text="加载中" layout="vertical"/>
<t-divider v-else-if="!hasMore && dataList.length > 0" content="没有更多了"/>
</view>
<t-empty v-if="!loading && !refreshIng && dataList.length === 0"
image="https://tdesign.gtimg.com/mobile/demos/empty1.png" description="暂无活动">
<template #action>
<t-button theme="primary" size="small" shape="round">刷新试试</t-button>
</template>
</t-empty>
</scroll-view>
</view>
</template>
<script setup>
import {ref, reactive, onMounted} from 'vue';
import {Toast} from 'tdesign-mobile-vue';
import {useRequest} from "@/util/request";
// 筛选选项
const statusOptions = [
{value: '', label: '全部'},
{value: '1', label: '进行中'},
{value: '2', label: '已结束'},
{value: '3', label: '未开始'}
];
const pageForm = reactive({
pageNumber: 1,
pageSize: 10,
totalCount: 0,
searchKeyword: null,
status: null
})
// 数据与状态
const dataList = ref([]);
const loading = ref(false);
const hasMore = ref(true);
const refreshIng = ref(false);
const filterVisible = ref(false);
// 搜索表单
const searchForm = reactive({
keyword: '',
status: ''
});
// 获取状态样式类
const getStatusClass = (status) => {
return {
1: 'status-active',
2: 'status-ended',
3: 'status-upcoming'
}[status] || '';
};
// 获取状态文本
const getStatusText = (status) => {
return {
1: '报名中',
2: '已结束',
3: '即将开始'
}[status] || '未知状态';
};
// 获取列表数据
const getListData = async (isRefresh = false) => {
if (isRefresh) {
refreshIng.value = true;
pageForm.pageNumber = 1;
} else {
loading.value = true
}
await new Promise(resolve => setTimeout(resolve, 1000));
try {
const {code, data, msg} = await useRequest().post('/client/activity/pageData', {
...pageForm
})
if (code === 0) {
if (isRefresh) {
dataList.value = data.list;
} else {
dataList.value = [...dataList.value, ...data.list];
}
hasMore.value = dataList.value.length < data.totalCount;
pageForm.pageNumber++;
console.log(hasMore.value)
} else {
console.error('获取列表失败', msg)
Toast({message: '获取列表失败', theme: 'error'});
}
} catch (error) {
console.error('获取列表失败', error);
Toast({message: '获取列表失败', theme: 'error'});
} finally {
loading.value = false;
refreshIng.value = false;
}
};
// 搜索处理
const handleSearch = () => {
hasMore.value = true;
dataList.value = [];
getListData();
};
// 清空筛选
const handleClearFilter = () => {
pageForm.keyword = null
pageForm.status = null
filterVisible.value = false;
};
// 加载更多
const onLoadMore = () => {
if (loading.value || !hasMore.value) return;
getListData();
};
// 跳转详情
const navigateToDetail = (id) => {
uni.navigateTo({
url: `/pages/activity/detail/index?id=${id}`
});
};
// 初始化
onMounted(() => {
getListData();
});
</script>
<style scoped>
.header {
background-color: #fff;
padding: 10px 16px;
box-shadow: 0 1px 6px rgba(0, 0, 0, 0.05);
position: sticky;
top: 0;
z-index: 10;
}
.search {
--td-search-bg-color: #f0f0f0;
}
.filter {
background-color: #fff;
border-radius: 0 0 16px 16px;
padding: 0 16px 20px;
}
.filter-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16px 0;
border-bottom: 1px solid #eee;
}
.filter-title {
font-weight: bold;
font-size: 16px;
}
.card {
background-color: #fff;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
margin: 10px;
}
.card-head {
position: relative;
height: 160px;
}
.card-img {
width: 100%;
height: 100%;
object-fit: cover;
}
.card-tag {
position: absolute;
top: 12px;
right: 0;
padding: 4px 12px;
color: #fff;
font-size: 12px;
font-weight: bold;
border-radius: 4px 0 0 4px;
}
.status-active {
background-color: #28c445;
}
.status-ended {
background-color: #999;
}
.status-upcoming {
background-color: #ff9800;
}
.card-body {
padding: 16px;
}
.card-title {
font-size: 16px;
font-weight: bold;
line-height: 1.4;
margin-bottom: 12px;
color: #333;
}
.card-info {
margin-bottom: 12px;
}
.info-item {
display: flex;
align-items: center;
font-size: 13px;
color: #666;
margin-bottom: 6px;
}
.info-item :deep(i) {
margin-right: 6px;
color: #999;
}
.card-footer {
display: flex;
justify-content: space-between;
align-items: center;
border-top: 1px solid #f0f0f0;
padding-top: 10px;
}
.price {
display: flex;
align-items: baseline;
}
.price-symbol {
font-size: 14px;
color: #ff5050;
font-weight: bold;
}
.price-value {
font-size: 22px;
color: #ff5050;
font-weight: bold;
}
.loading-area {
padding: 16px 0;
text-align: center;
}
</style>
@@ -0,0 +1,276 @@
<template>
<view class="page-container">
<view class="act-info">
<view class="act-title">奋进新征程 运动促健康 2024晴江第六届"牧城之夜"荧光跑</view>
<view class="act-meta">
<view class="act-meta-item">22222</view>
<view class="act-meta-item">22222222222222222222</view>
</view>
</view>
<view class="form-area">
<t-form
ref="formRef"
:data="formData"
reset-type="initial"
show-error-message
label-align="left"
scroll-to-first-error="auto"
>
<view class="form-block">
<view class="form-block-title">
<t-icon name="institution"></t-icon>
单位信息
</view>
<t-form-item label="参加单位" name="unitName" :rules="[{required:true,message: '请输入单位名称'}]">
<t-input v-model="formData.unitName" borderless placeholder="请输入参加单位名称"></t-input>
</t-form-item>
<t-form-item label="联系人" name="contactName" :rules="[{required:true,message: '请输入联系人姓名'}]">
<t-input v-model="formData.contactName" borderless placeholder="请输入联系人姓名"></t-input>
</t-form-item>
<t-form-item label="联系方式" name="contactPhone" :rules="[{required:true,message: '请输入联系电话'}]">
<t-input v-model="formData.contactPhone" borderless placeholder="请输入联系电话"></t-input>
</t-form-item>
</view>
<view class="form-block">
<view class="form-block-title">
<t-icon name="usergroup"></t-icon>
报名人员信息
</view>
<view v-for="(user,index) in formData.userList" :key="index" class="user-card">
<view class="user-card-header">
<view class="user-card-header-title">
<span>{{ index + 1 }}</span>
</view>
<view class="remove" @click="formData.userList.splice(index, 1)">
<t-icon name="delete" size="18px"></t-icon>
</view>
</view>
<t-form-item label="姓名" :name="`userList[${index}].name`"
:rules="[{required:true,message: '请输入姓名'}]">
<t-input v-model="user.name" borderless placeholder="请输入内容"></t-input>
</t-form-item>
<t-form-item label="性别" :name="`userList[${index}].sex`" :rules="[{required:true,message: '请选择性别'}]">
<t-radio-group v-model="user.sex" borderless class="radio-box">
<t-radio :block="false" label="男" value="男"/>
<t-radio :block="false" label="女" value="女"/>
</t-radio-group>
</t-form-item>
<t-form-item label="职务" :name="`userList[${index}].job`" :rules="[{required:true,message: '请输入职务'}]">
<t-input v-model="user.job" borderless placeholder="请输入职务"></t-input>
</t-form-item>
<t-form-item label="身份证号" :name="`userList[${index}].idCard`"
:rules="[{required:true,message: '请输入身份证号码'},{idcard:true, message: '请输入正确的身份证号码'}]">
<t-input v-model="user.idCard" borderless placeholder="请输入身份证号码"></t-input>
</t-form-item>
<t-form-item label="联系电话" :name="`userList[${index}].phone`"
:rules="[{required:true,message: '请输入联系电话'},{telnumber:true, message: '请输入正确的联系电话'}]">
<t-input v-model="user.phone" borderless placeholder="请输入联系电话"></t-input>
</t-form-item>
<t-form-item label="是否住宿" :name="`userList[${index}].sleep`"
:rules="[{required:true,message: '请选择是否住宿'}]">
<t-radio-group v-model="user.sleep" class="radio-box">
<t-radio :block="false" name="radio" value="1" label="是"/>
<t-radio :block="false" name="radio" value="2" label="否"/>
</t-radio-group>
</t-form-item>
</view>
</view>
</t-form>
<view class="add-user" @click="formData.userList.push({})">
<t-icon name="plus" size="24px"></t-icon>
<text>添加人员</text>
</view>
</view>
<view class="footer">
<view class="agreement-checkbox">
<t-checkbox label="多选" icon="rectangle" v-model:checked="agreementChecked" default-checked>
<label>我已阅读并同意
<text class="agreement-link">《参赛承诺书》</text>
</label>
</t-checkbox>
</view>
<t-button
block
theme="primary"
size="large"
shape="round"
@click="onSubmit"
>
提交报名
</t-button>
</view>
</view>
</template>
<script setup>
import {ref} from 'vue'
const agreementChecked = ref(false)
const formRef = ref(null)
const formData = ref({
unitName: null,
userList: []
})
function onSubmit() {
console.log(formRef)
console.log(formRef.value)
formRef.value.validate()
}
</script>
<style scoped lang="less">
.act-info {
position: fixed;
top: 44px;
left: 0;
right: 0;
background: white;
padding: 12px 16px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05);
z-index: 9;
max-width: 750px;
margin: 0 auto;
width: 100%;
height: auto;
min-height: 70px;
display: flex;
flex-direction: column;
justify-content: center;
.act-title {
font-size: 16px;
font-weight: 500;
margin-bottom: 8px;
line-height: 1.4;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.event-meta {
display: flex;
font-size: 13px;
color: #666;
margin-top: 2px;
.event-meta-item {
display: flex;
align-items: center;
margin-right: 16px;
white-space: nowrap;
}
}
}
.form-area{
flex: 1;
overflow-y: auto;
margin-top: 100px;
margin-bottom: 130px;
}
.form-block {
padding: 20px 16px;
background: white;
margin-bottom: 10px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
.form-block-title {
font-size: 16px;
font-weight: 500;
margin-bottom: 16px;
color: #333;
display: flex;
align-items: center;
.t-icon {
margin-right: 5px;
color: var(--td-brand-color);
}
}
}
.user-card {
background: white;
margin-bottom: 20px;
position: relative;
border-left: 3px solid #e74c3c;
padding-left: 12px;
.user-card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
.user-card-header-title {
font-weight: 500;
color: #333;
font-size: 15px;
display: flex;
align-items: center;
span {
display: flex;
justify-content: center;
align-items: center;
width: 24px;
height: 24px;
background-color: #e74c3c;
color: white;
border-radius: 50%;
font-size: 14px;
margin-right: 8px;
}
}
.remove {
color: #e74c3c;
//font-size: 14px;
display: flex;
align-items: center;
background: none;
border: none;
cursor: pointer;
}
}
}
.add-user {
padding: 15px;
text-align: center;
color: #e74c3c;
font-weight: 500;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
background: #ffffff;
}
.radio-box {
width: 100%;
display: flex;
column-gap: 20px;
}
.footer {
position: fixed;
bottom: 0;
left: 0;
right: 0;
padding: 0 16px 16px;
background-color: white;
box-shadow: 0 -1px 5px rgba(0, 0, 0, 0.1);
z-index: 10;
max-width: 750px;
margin: 0 auto;
width: 100%;
}
</style>
+313
View File
@@ -0,0 +1,313 @@
<template>
<view class="page-container">
<t-dropdown-menu @menu-opened="handleMenuOpened" @menu-closed="handleMenuClosed">
<t-dropdown-item :options="actOptions" :value="pageForm.actId" @change="actChange" />
</t-dropdown-menu>
<div class="content-area">
<!-- 团队信息卡片 -->
<div class="team-card">
<div class="team-banner">
<div class="team-logo">
<i class="bi bi-people-fill" v-if="!team.logoUrl"></i>
<img :src="team.logoUrl" alt="团队logo" v-if="team.logoUrl">
</div>
<div class="team-info">
<div class="team-name">{{ team.name }}</div>
<div class="team-meta">创建于 {{ team.createdDate }}</div>
<div class="team-id">团队ID: {{ team.id }}</div>
</div>
<div class="event-name">{{ team.eventName }}</div>
</div>
<div class="team-detail">
<div class="team-stat-row">
<div class="team-stat-item">
<div class="team-stat-value">{{ team.memberCount }}</div>
<div class="team-stat-label">团队成员</div>
</div>
<div class="team-stat-item">
<div class="team-stat-value">{{ team.rank }}</div>
<div class="team-stat-label">当前排名</div>
</div>
<div class="team-stat-item">
<div class="team-stat-value">{{ team.score }}</div>
<div class="team-stat-label">团队积分</div>
</div>
</div>
<div style="font-size: 14px; color: #666; line-height: 1.6;">
{{ team.description }}
</div>
</div>
</div>
<!-- 团队成员 -->
<div class="team-section">
<div class="section-header">
<div class="section-title">
<i class="bi bi-people"></i>团队成员
</div>
</div>
<div class="member-list">
<div class="member-item" v-for="member in team.members" :key="member.id">
<div class="member-avatar">
<img :src="member.avatar" :alt="member.name" onerror="this.src='data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj48cmVjdCB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgZmlsbD0iI2YwZjBmMCIvPjx0ZXh0IHg9IjUwJSIgeT0iNTAlIiBmb250LXNpemU9IjIwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBhbGlnbm1lbnQtYmFzZWxpbmU9Im1pZGRsZSIgZm9udC1mYW1pbHk9IkFyaWFsLCBzYW5zLXNlcmlmIiBmaWxsPSIjNTU1Ij57eyBtZW1iZXIubmFtZS5jaGFyQXQoMCkgfX08L3RleHQ+PC9zdmc+'">
</div>
<div class="member-info">
<div class="member-name">
{{ member.name }}
<span class="member-role" v-if="member.role === 'leader'">队长</span>
<span class="member-role" v-else-if="member.role === 'admin'" style="background-color: #ff9a5a;">管理员</span>
</div>
<div class="member-detail">
<div class="member-detail-item">
<i class="bi bi-gender-ambiguous"></i>
<span>{{ member.gender }}</span>
</div>
<div class="member-detail-item">
<i class="bi bi-building"></i>
<span>{{ member.organization }}</span>
</div>
</div>
</div>
<div class="member-actions">
<i class="bi bi-three-dots-vertical"></i>
</div>
</div>
</div>
<!-- 当前角色与申请队长 -->
<div v-if="currentUserRole !== 'leader'">
<div class="role-notice" v-if="currentUserRole === 'admin'">
<i class="bi bi-info-circle"></i>
您当前是管理员身份,拥有团队管理权限
</div>
<div class="role-notice" v-else>
<i class="bi bi-info-circle"></i>
您当前是普通成员身份
</div>
<button class="apply-leader-btn" @click="showLeaderConfirm">
<i class="bi bi-award"></i>申请成为队长
</button>
</div>
<div class="role-notice" v-else>
<i class="bi bi-check-circle"></i>
您当前是队长身份,拥有团队所有权限
</div>
</div>
<!-- 项目报名按钮 -->
<div class="team-section">
<button class="register-btn" @click="goToEventRegistration">
<i class="bi bi-calendar-check"></i>
项目报名
</button>
</div>
</div>
</view>
</template>
<script setup>
import {ref,reactive} from "vue";
const actOptions = ref([])
const pageForm = reactive({
actId: null,
})
const teamId = ''
const team = reactive({
id: teamId,
name: '江苏健康跑团',
logoUrl: null,
createdDate: '2023-10-15',
eventId: '',
eventName: '',
memberCount: 12,
rank: 5,
score: 256,
description: '我们是一支来自江苏省的健康跑团队,致力于推广健康跑步文化,鼓励大家积极参与体育活动,共同展现江苏的活力风采。',
// 团队成员
members: [
{
id: '101',
name: '张伟',
role: 'leader',
gender: '男',
organization: '江苏体育学院',
avatar: null
},
{
id: '102',
name: '李娜',
role: 'admin',
gender: '女',
organization: '南京体育局',
avatar: null
},
{
id: '103',
name: '王强',
role: 'member',
gender: '男',
organization: '南京体育学院',
avatar: null
},
{
id: '104',
name: '刘芳',
role: 'member',
gender: '女',
organization: '江苏大学',
avatar: null
},
{
id: '105',
name: '陈明',
role: 'member',
gender: '男',
organization: '苏州体育中心',
avatar: null
}
]
});
function handleMenuOpened(){
}
function handleMenuClosed(){}
function actChange(val){
console.log(val)
}
</script>
<style scoped lang="less">
/* 主体内容区 */
.content-area {
}
/* 团队信息卡片 */
.team-card {
background-color: white;
margin: 15px;
border-radius: 12px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
overflow: hidden;
}
.team-banner {
position: relative;
height: 120px;
background: linear-gradient(135deg, #e74c3c, #ff7675);
display: flex;
align-items: center;
padding: 20px;
}
.team-logo {
width: 80px;
height: 80px;
border-radius: 50%;
background-color: white;
display: flex;
justify-content: center;
align-items: center;
margin-right: 15px;
border: 2px solid rgba(255, 255, 255, 0.8);
box-shadow: 0 2px 15px rgba(0, 0, 0, 0.1);
overflow: hidden;
}
.team-logo img {
width: 100%;
height: 100%;
object-fit: cover;
}
.team-logo i {
font-size: 40px;
color: #e74c3c;
}
.team-info {
flex: 1;
color: white;
}
.team-name {
font-size: 20px;
font-weight: 600;
margin-bottom: 6px;
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
}
.team-meta {
font-size: 13px;
opacity: 0.95;
}
.team-id {
display: inline-block;
background-color: rgba(255, 255, 255, 0.2);
padding: 2px 8px;
border-radius: 10px;
margin-top: 6px;
font-size: 12px;
}
.event-name {
position: absolute;
bottom: 10px;
right: 15px;
background-color: rgba(0, 0, 0, 0.2);
padding: 3px 10px;
border-radius: 15px;
font-size: 12px;
color: white;
}
/* 团队详情内容 */
.team-detail {
padding: 15px;
}
.team-stat-row {
display: flex;
margin-bottom: 15px;
border-bottom: 1px solid #f0f0f0;
padding-bottom: 15px;
}
.team-stat-item {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
padding: 5px 0;
}
.team-stat-value {
font-size: 22px;
font-weight: 600;
color: #e74c3c;
margin-bottom: 5px;
}
.team-stat-label {
font-size: 13px;
color: #666;
}
</style>
+267
View File
@@ -0,0 +1,267 @@
<template>
<view class="page-container">
<!-- 顶部背景和内容区 -->
<view class="header">
<image class="header-bg" src="https://erp-bucket.pek3b.qingstor.com/assistant/89c4b573-c54f-467a-b703-0bc44679ab08.png" mode="aspectFill"></image>
</view>
<!-- 功能菜单区 -->
<view class="menu-container">
<view class="menu-item" @click="navigateTo('/pages/activity/list/index')">
<view class="menu-icon-wrapper red-bg">
<view class="menu-icon trophy-icon"></view>
</view>
<view class="menu-text">赛事报名</view>
</view>
<view class="menu-item" @click="navigateTo('/pages/scan/index')">
<view class="menu-icon-wrapper orange-bg">
<view class="menu-icon qrcode-icon"></view>
</view>
<view class="menu-text">扫码签到</view>
</view>
<view class="menu-item" @click="navigateTo('/pages/activity/team/index')">
<view class="menu-icon-wrapper yellow-bg">
<view class="menu-icon team-icon"></view>
<view class="badge">3</view>
</view>
<view class="menu-text">我的团队</view>
</view>
<view class="menu-item" @click="navigateTo('/pages/activity/team/index')">
<view class="menu-icon-wrapper blue-bg">
<view class="menu-icon star-icon"></view>
</view>
<view class="menu-text">项目报名</view>
</view>
</view>
<!-- 精选内容区 -->
<view class="content-section">
<view class="section-header">
<view class="section-title">精选活动</view>
<view class="section-more" @click="navigateTo('/pages/activity/index')">更多</view>
</view>
<view class="activity-list">
<view class="activity-item" @click="navigateTo('/pages/process/index')">
<image class="activity-image" src="https://erp-bucket.pek3b.qingstor.com/assistant/746c37d6-018d-4c64-8a98-ea9ec8b0b3b5.png" mode="widthFix"></image>
<view class="activity-info">
<view class="activity-title">一分钟了解运动会流程</view>
<view class="activity-meta">
<text class="activity-time">6月15日-20日</text>
<text class="activity-location">江苏省体育中心</text>
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script setup>
import { onMounted } from "vue";
function navigateTo(url) {
uni.navigateTo({
url
})
}
onMounted(()=>{
console.log('...........')
uni.showToast({
title: '欢迎使用',
icon: 'none',
duration: 2000
})
})
</script>
<style lang="less" scoped>
// 头部区域样式
.header {
position: relative;
height: 245px;
overflow: hidden;
}
.header-bg {
width: 100%;
height: 100%;
object-fit: cover;
}
// 菜单区域样式
.menu-container {
display: flex;
justify-content: space-around;
padding: 20px;
background-color: #fff;
border-radius: 15px;
margin: -30px 15px 15px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
z-index: 10;
}
.menu-item {
display: flex;
flex-direction: column;
align-items: center;
width: 22%;
}
.menu-icon-wrapper {
width: 50px;
height: 50px;
border-radius: 12px;
display: flex;
justify-content: center;
align-items: center;
position: relative;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
.red-bg {
background: linear-gradient(135deg, #ff7676, #f45a5a);
}
.orange-bg {
background: linear-gradient(135deg, #ffa76a, #f89f58);
}
.yellow-bg {
background: linear-gradient(135deg, #ffd166, #f8c158);
}
.blue-bg {
background: linear-gradient(135deg, #72a1ff, #5c7cfa);
}
.menu-icon {
width: 28px;
height: 28px;
background-size: contain;
background-repeat: no-repeat;
background-position: center;
}
.trophy-icon {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='%23ffffff'%3E%3Cpath d='M19 5h-2V3H7v2H5c-1.1 0-2 .9-2 2v1c0 2.55 1.92 4.63 4.39 4.94.63 1.5 1.98 2.63 3.61 2.96V19H7v2h10v-2h-4v-3.1c1.63-.33 2.98-1.46 3.61-2.96C19.08 12.63 21 10.55 21 8V7c0-1.1-.9-2-2-2zM5 8V7h2v3.82C5.84 10.4 5 9.3 5 8zm14 0c0 1.3-.84 2.4-2 2.82V7h2v1z'/%3E%3C/svg%3E");
}
.qrcode-icon {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='%23ffffff'%3E%3Cpath d='M3 11h8V3H3v8zm2-6h4v4H5V5zM3 21h8v-8H3v8zm2-6h4v4H5v-4zM13 3v8h8V3h-8zm6 6h-4V5h4v4zM13 13h2v2h-2zM15 15h2v2h-2zM13 17h2v2h-2zM17 17h2v2h-2zM19 19h2v2h-2zM15 19h2v2h-2zM17 13h2v2h-2zM19 15h2v2h-2z'/%3E%3C/svg%3E");
}
.team-icon {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='%23ffffff'%3E%3Cpath d='M16 11c1.66 0 2.99-1.34 2.99-3S17.66 5 16 5s-3 1.34-3 3 1.34 3 3 3zm-8 0c1.66 0 2.99-1.34 2.99-3S9.66 5 8 5 5 6.34 5 8s1.34 3 3 3zm0 2c-2.33 0-7 1.17-7 3.5V19h14v-2.5c0-2.33-4.67-3.5-7-3.5zm8 0c-.29 0-.62.02-.97.05 1.16.84 1.97 1.97 1.97 3.45V19h6v-2.5c0-2.33-4.67-3.5-7-3.5z'/%3E%3C/svg%3E");
}
.star-icon {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='%23ffffff'%3E%3Cpath d='M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z'/%3E%3C/svg%3E");
}
.badge {
position: absolute;
top: -5px;
right: -5px;
background-color: #ff4d4f;
color: white;
border-radius: 10px;
min-width: 18px;
height: 18px;
font-size: 12px;
line-height: 18px;
text-align: center;
padding: 0 5px;
font-weight: bold;
box-shadow: 0 2px 4px rgba(255, 77, 79, 0.3);
}
.menu-text {
margin-top: 10px;
font-size: 14px;
color: #333;
font-weight: 500;
}
// 内容区域样式
.content-section {
margin: 0 0 15px;
padding: 15px;
background-color: #fff;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
}
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
}
.section-title {
font-size: 16px;
font-weight: bold;
color: #333;
position: relative;
padding-left: 10px;
}
.section-title::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 3px;
height: 16px;
background: linear-gradient(to bottom, #ff6b6b, #e83a3a);
border-radius: 3px;
}
.section-more {
font-size: 14px;
color: #666;
}
// 活动列表样式
.activity-list {
width: 100%;
}
.activity-item {
width: 100%;
margin-bottom: 15px;
}
.activity-item:last-child {
margin-bottom: 0;
}
.activity-image {
width: 100%;
}
.activity-info {
padding: 10px 0;
}
.activity-title {
font-size: 16px;
font-weight: 500;
color: #333;
margin-bottom: 5px;
}
.activity-meta {
display: flex;
font-size: 12px;
color: #999;
}
.activity-time {
margin-right: 15px;
}
</style>
+11
View File
@@ -0,0 +1,11 @@
<script setup>
</script>
<template>
我的页面
</template>
<style scoped>
</style>
+6
View File
@@ -0,0 +1,6 @@
export {};
declare module "vue" {
type Hooks = App.AppInstance & Page.PageInstance;
interface ComponentCustomOptions extends Hooks {}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

+337
View File
@@ -0,0 +1,337 @@
:root, :root[theme-mode="light"] {
--td-brand-color-1: #fff0ed;
--td-brand-color-2: #ffd8d3;
--td-brand-color-3: #ffb8b1;
--td-brand-color-4: #ff928c;
--td-brand-color-5: #ff5f5c;
--td-brand-color-6: #df3d3f;
--td-brand-color-7: #b6292d;
--td-brand-color-8: #8f121b;
--td-brand-color-9: #6b000a;
--td-brand-color-10: #490005;
--td-brand-color-light: var(--td-brand-color-1);
--td-brand-color-focus: var(--td-brand-color-2);
--td-brand-color-disabled: var(--td-brand-color-3);
--td-brand-color: var(--td-brand-color-5);
--td-brand-color-active: var(--td-brand-color-6);
--td-warning-color-1: #fef3e6;
--td-warning-color-2: #f9e0c7;
--td-warning-color-3: #f7c797;
--td-warning-color-4: #f2995f;
--td-warning-color-5: #ed7b2f;
--td-warning-color-6: #d35a21;
--td-warning-color-7: #ba431b;
--td-warning-color-8: #9e3610;
--td-warning-color-9: #842b0b;
--td-warning-color-10: #5a1907;
--td-warning-color: var(--td-warning-color-5);
--td-warning-color-focus: var(--td-warning-color-2);
--td-warning-color-active: var(--td-warning-color-6);
--td-warning-color-disabled: var(--td-warning-color-3);
--td-warning-color-light: var(--td-warning-color-1);
--td-error-color-1: #fdecee;
--td-error-color-2: #f9d7d9;
--td-error-color-3: #f8b9be;
--td-error-color-4: #f78d94;
--td-error-color-5: #f36d78;
--td-error-color-6: #e34d59;
--td-error-color-7: #c9353f;
--td-error-color-8: #b11f26;
--td-error-color-9: #951114;
--td-error-color-10: #680506;
--td-error-color: var(--td-error-color-6);
--td-error-color-focus: var(--td-error-color-2);
--td-error-color-active: var(--td-error-color-7);
--td-error-color-disabled: var(--td-error-color-3);
--td-error-color-light: var(--td-error-color-1);
--td-success-color-1: #e8f8f2;
--td-success-color-2: #bcebdc;
--td-success-color-3: #85dbbe;
--td-success-color-4: #48c79c;
--td-success-color-5: #00a870;
--td-success-color-6: #078d5c;
--td-success-color-7: #067945;
--td-success-color-8: #056334;
--td-success-color-9: #044f2a;
--td-success-color-10: #033017;
--td-success-color: var(--td-success-color-5);
--td-success-color-focus: var(--td-success-color-2);
--td-success-color-active: var(--td-success-color-6);
--td-success-color-disabled: var(--td-success-color-3);
--td-success-color-light: var(--td-success-color-1);
--td-gray-color-1: #f3f3f3;
--td-gray-color-2: #eee;
--td-gray-color-3: #e8e8e8;
--td-gray-color-4: #ddd;
--td-gray-color-5: #c5c5c5;
--td-gray-color-6: #a6a6a6;
--td-gray-color-7: #8b8b8b;
--td-gray-color-8: #777;
--td-gray-color-9: #5e5e5e;
--td-gray-color-10: #4b4b4b;
--td-gray-color-11: #383838;
--td-gray-color-12: #2c2c2c;
--td-gray-color-13: #242424;
--td-gray-color-14: #181818;
--td-bg-color-container: #fff;
--td-bg-color-page: var(--td-gray-color-2);
--td-bg-color-container-active: var(--td-gray-color-3);
--td-bg-color-secondarycontainer: var(--td-gray-color-1);
--td-bg-color-secondarycontainer-active: var(--td-gray-color-4);
--td-bg-color-component: var(--td-gray-color-3);
--td-bg-color-component-active: var(--td-gray-color-6);
--td-bg-color-component-disabled: var(--td-gray-color-2);
--td-component-stroke: var(--td-gray-color-3);
--td-component-border: var(--td-gray-color-4);
--td-font-white-1: #ffffff;
--td-font-white-2: rgba(255, 255, 255, 0.55);
--td-font-white-3: rgba(255, 255, 255, 0.35);
--td-font-white-4: rgba(255, 255, 255, 0.22);
--td-font-gray-1: rgba(0, 0, 0, 0.9);
--td-font-gray-2: rgba(0, 0, 0, 0.6);
--td-font-gray-3: rgba(0, 0, 0, 0.4);
--td-font-gray-4: rgba(0, 0, 0, 0.26);
--td-text-color-primary: var(--td-font-gray-1);
--td-text-color-secondary: var(--td-font-gray-2);
--td-text-color-placeholder: var(--td-font-gray-3);
--td-text-color-disabled: var(--td-font-gray-4);
--td-text-color-anti: #fff;
--td-text-color-brand: var(--td-brand-color);
--td-text-color-link: var(--td-brand-color);
--td-bg-color-secondarycomponent: var(--td-gray-color-4);
--td-bg-color-secondarycomponent-active: var(--td-gray-color-6);
--td-table-shadow-color: rgba(0, 0, 0, 8%);
--td-scrollbar-color: rgba(0, 0, 0, 10%);
--td-scrollbar-hover-color: rgba(0, 0, 0, 30%);
--td-scroll-track-color: #fff;
--td-bg-color-specialcomponent: #fff;
--td-border-level-1-color: var(--td-gray-color-3);
--td-border-level-2-color: var(--td-gray-color-4);
--td-shadow-1: 0 1px 10px rgba(0, 0, 0, 5%), 0 4px 5px rgba(0, 0, 0, 8%), 0 2px 4px -1px rgba(0, 0, 0, 12%);
--td-shadow-2: 0 3px 14px 2px rgba(0, 0, 0, 5%), 0 8px 10px 1px rgba(0, 0, 0, 6%), 0 5px 5px -3px rgba(0, 0, 0, 10%);
--td-shadow-3: 0 6px 30px 5px rgba(0, 0, 0, 5%), 0 16px 24px 2px rgba(0, 0, 0, 4%), 0 8px 10px -5px rgba(0, 0, 0, 8%);
--td-shadow-inset-top: inset 0 0.5px 0 #dcdcdc;
--td-shadow-inset-right: inset 0.5px 0 0 #dcdcdc;
--td-shadow-inset-bottom: inset 0 -0.5px 0 #dcdcdc;
--td-shadow-inset-left: inset -0.5px 0 0 #dcdcdc;
--td-mask-active: rgba(0, 0, 0, 0.6);
--td-mask-disabled: rgba(255, 255, 255, 0.6);
}
:root[theme-mode="dark"] {
--td-brand-color-1: #ff505020;
--td-brand-color-2: #6b000a;
--td-brand-color-3: #8f121b;
--td-brand-color-4: #b6292d;
--td-brand-color-5: #df3d3f;
--td-brand-color-6: #ff5050;
--td-brand-color-7: #ff928c;
--td-brand-color-8: #ffb8b1;
--td-brand-color-9: #ffd8d3;
--td-brand-color-10: #fff0ed;
--td-brand-color-light: var(--td-brand-color-1);
--td-brand-color-focus: var(--td-brand-color-2);
--td-brand-color-disabled: var(--td-brand-color-3);
--td-brand-color: var(--td-brand-color-6);
--td-brand-color-active: var(--td-brand-color-7);
--td-warning-color-1: #4f2a1d;
--td-warning-color-2: #582f21;
--td-warning-color-3: #733c23;
--td-warning-color-4: #a75d2b;
--td-warning-color-5: #cf6e2d;
--td-warning-color-6: #dc7633;
--td-warning-color-7: #e8935c;
--td-warning-color-8: #ecbf91;
--td-warning-color-9: #eed7bf;
--td-warning-color-10: #f3e9dc;
--td-error-color-1: #472324;
--td-error-color-2: #5e2a2d;
--td-error-color-3: #703439;
--td-error-color-4: #83383e;
--td-error-color-5: #a03f46;
--td-error-color-6: #c64751;
--td-error-color-7: #de6670;
--td-error-color-8: #ec888e;
--td-error-color-9: #edb1b6;
--td-error-color-10: #eeced0;
--td-success-color-1: #193a2a;
--td-success-color-2: #1a4230;
--td-success-color-3: #17533d;
--td-success-color-4: #0d7a55;
--td-success-color-5: #059465;
--td-success-color-6: #43af8a;
--td-success-color-7: #46bf96;
--td-success-color-8: #80d2b6;
--td-success-color-9: #b4e1d3;
--td-success-color-10: #deede8;
--td-gray-color-1: #f3f3f3;
--td-gray-color-2: #eee;
--td-gray-color-3: #e8e8e8;
--td-gray-color-4: #ddd;
--td-gray-color-5: #c5c5c5;
--td-gray-color-6: #a6a6a6;
--td-gray-color-7: #8b8b8b;
--td-gray-color-8: #777;
--td-gray-color-9: #5e5e5e;
--td-gray-color-10: #4b4b4b;
--td-gray-color-11: #383838;
--td-gray-color-12: #2c2c2c;
--td-gray-color-13: #242424;
--td-gray-color-14: #181818;
--td-bg-color-page: var(--td-gray-color-14);
--td-bg-color-container: var(--td-gray-color-13);
--td-bg-color-container-active: var(--td-gray-color-10);
--td-bg-color-secondarycontainer: var(--td-gray-color-12);
--td-bg-color-secondarycontainer-active: var(--td-gray-color-9);
--td-bg-color-component: var(--td-gray-color-11);
--td-bg-color-component-active: var(--td-gray-color-9);
--td-bg-color-component-disabled: var(--td-gray-color-12);
--td-component-stroke: var(--td-gray-color-11);
--td-component-border: var(--td-gray-color-9);
--td-font-white-1: rgba(255, 255, 255, 0.9);
--td-font-white-2: rgba(255, 255, 255, 0.55);
--td-font-white-3: rgba(255, 255, 255, 0.35);
--td-font-white-4: rgba(255, 255, 255, 0.22);
--td-font-gray-1: rgba(0, 0, 0, 0.9);
--td-font-gray-2: rgba(0, 0, 0, 0.6);
--td-font-gray-3: rgba(0, 0, 0, 0.4);
--td-font-gray-4: rgba(0, 0, 0, 0.26);
--td-text-color-primary: var(--td-font-white-1);
--td-text-color-secondary: var(--td-font-white-2);
--td-text-color-placeholder: var(--td-font-white-3);
--td-text-color-disabled: var(--td-font-white-4);
--td-text-color-anti: #fff;
--td-text-color-brand: var(--td-brand-color);
--td-text-color-link: var(--td-brand-color);
--td-shadow-1: 0 4px 6px rgba(0, 0, 0, 0.06), 0 1px 10px rgba(0, 0, 0, 0.08), 0 2px 4px rgba(0, 0, 0, 0.12);
--td-shadow-2: 0 8px 10px rgba(0, 0, 0, 0.12), 0 3px 14px rgba(0, 0, 0, 0.10), 0 5px 5px rgba(0, 0, 0, 0.16);
--td-shadow-3: 0 16px 24px rgba(0, 0, 0, 0.14), 0 6px 30px rgba(0, 0, 0, 0.12), 0 8px 10px rgba(0, 0, 0, 0.20);
--td-shadow-inset-top: inset 0 0.5px 0 #5e5e5e;
--td-shadow-inset-right: inset 0.5px 0 0 #5e5e5e;
--td-shadow-inset-bottom: inset 0 -0.5px 0 #5e5e5e;
--td-shadow-inset-left: inset -0.5px 0 0 #5e5e5e;
--td-table-shadow-color: rgba(0, 0, 0, 55%);
--td-scrollbar-color: rgba(255, 255, 255, 10%);
--td-scrollbar-hover-color: rgba(255, 255, 255, 30%);
--td-scroll-track-color: #333;
--td-bg-color-specialcomponent: transparent;
--td-border-level-1-color: var(--td-gray-color-11);
--td-border-level-2-color: var(--td-gray-color-9);
--td-mask-active: rgba(0, 0, 0, 0.4);
--td-mask-disabled: rgba(0, 0, 0, 0.6);
}
:root {
--td-font-family: pingfang sc, microsoft yahei, arial regular;
--td-font-family-medium: pingfang sc, microsoft yahei, arial medium;
--td-font-size-link-small: 12px;
--td-font-size-link-medium: 14px;
--td-font-size-link-large: 16px;
--td-font-size-mark-small: 12px;
--td-font-size-mark-medium: 14px;
--td-font-size-body-small: 12px;
--td-font-size-body-medium: 14px;
--td-font-size-body-large: 16px;
--td-font-size-title-small: 14px;
--td-font-size-title-medium: 16px;
--td-font-size-title-large: 20px;
--td-font-size-headline-small: 24px;
--td-font-size-headline-medium: 28px;
--td-font-size-headline-large: 36px;
--td-font-size-display-medium: 48px;
--td-font-size-display-large: 64px;
--td-line-height-link-small: 20px;
--td-line-height-link-medium: 22px;
--td-line-height-link-large: 24px;
--td-line-height-mark-small: 20px;
--td-line-height-mark-medium: 22px;
--td-line-height-body-small: 20px;
--td-line-height-body-medium: 22px;
--td-line-height-body-large: 24px;
--td-line-height-title-small: 22px;
--td-line-height-title-medium: 24px;
--td-line-height-title-large: 28px;
--td-line-height-headline-small: 32px;
--td-line-height-headline-medium: 36px;
--td-line-height-headline-large: 44px;
--td-line-height-display-medium: 56px;
--td-line-height-display-large: 72px;
--td-font-link-small: var(--td-font-size-link-small) / var(--td-line-height-link-small) var(--td-font-family);
--td-font-link-medium: var(--td-font-size-link-medium) / var(--td-line-height-link-medium) var(--td-font-family);
--td-font-link-large: var(--td-font-size-link-large) / var(--td-line-height-link-large) var(--td-font-family);
--td-font-mark-small: 600 var(--td-font-size-mark-small) / var(--td-line-height-mark-small) var(--td-font-family);
--td-font-mark-medium: 600 var(--td-font-size-mark-medium) / var(--td-line-height-mark-medium) var(--td-font-family);
--td-font-body-small: var(--td-font-size-body-small) / var(--td-line-height-body-small) var(--td-font-family);
--td-font-body-medium: var(--td-font-size-body-medium) / var(--td-line-height-body-medium) var(--td-font-family);
--td-font-body-large: var(--td-font-size-body-large) / var(--td-line-height-body-large) var(--td-font-family);
--td-font-title-small: 600 var(--td-font-size-title-small) / var(--td-line-height-title-small) var(--td-font-family);
--td-font-title-medium: 600 var(--td-font-size-title-medium) / var(--td-line-height-title-medium) var(--td-font-family);
--td-font-title-large: 600 var(--td-font-size-title-large) / var(--td-line-height-title-large) var(--td-font-family);
--td-font-headline-small: 600 var(--td-font-size-headline-small) / var(--td-line-height-headline-small) var(--td-font-family);
--td-font-headline-medium: 600 var(--td-font-size-headline-medium) / var(--td-line-height-headline-medium) var(--td-font-family);
--td-font-headline-large: 600 var(--td-font-size-headline-large) / var(--td-line-height-headline-large) var(--td-font-family);
--td-font-display-medium: 600 var(--td-font-size-display-medium) / var(--td-line-height-display-medium) var(--td-font-family);
--td-font-display-large: 600 var(--td-font-size-display-large) / var(--td-line-height-display-large) var(--td-font-family);
--td-radius-small: 2px;
--td-radius-default: 3px;
--td-radius-medium: 6px;
--td-radius-large: 9px;
--td-radius-extraLarge: 12px;
--td-radius-round: 999px;
--td-radius-circle: 50%;
--td-size-1: 2px;
--td-size-2: 4px;
--td-size-3: 6px;
--td-size-4: 8px;
--td-size-5: 12px;
--td-size-6: 16px;
--td-size-7: 20px;
--td-size-8: 24px;
--td-size-9: 28px;
--td-size-10: 32px;
--td-size-11: 36px;
--td-size-12: 40px;
--td-size-13: 48px;
--td-size-14: 56px;
--td-size-15: 64px;
--td-size-16: 72px;
--td-comp-size-xxxs: var(--td-size-6);
--td-comp-size-xxs: var(--td-size-7);
--td-comp-size-xs: var(--td-size-8);
--td-comp-size-s: var(--td-size-9);
--td-comp-size-m: var(--td-size-10);
--td-comp-size-l: var(--td-size-11);
--td-comp-size-xl: var(--td-size-12);
--td-comp-size-xxl: var(--td-size-13);
--td-comp-size-xxxl: var(--td-size-14);
--td-comp-size-xxxxl: var(--td-size-15);
--td-comp-size-xxxxxl: var(--td-size-16);
--td-pop-padding-s: var(--td-size-2);
--td-pop-padding-m: var(--td-size-3);
--td-pop-padding-l: var(--td-size-4);
--td-pop-padding-xl: var(--td-size-5);
--td-pop-padding-xxl: var(--td-size-6);
--td-comp-paddingLR-xxs: var(--td-size-1);
--td-comp-paddingLR-xs: var(--td-size-2);
--td-comp-paddingLR-s: var(--td-size-4);
--td-comp-paddingLR-m: var(--td-size-5);
--td-comp-paddingLR-l: var(--td-size-6);
--td-comp-paddingLR-xl: var(--td-size-8);
--td-comp-paddingLR-xxl: var(--td-size-10);
--td-comp-paddingTB-xxs: var(--td-size-1);
--td-comp-paddingTB-xs: var(--td-size-2);
--td-comp-paddingTB-s: var(--td-size-4);
--td-comp-paddingTB-m: var(--td-size-5);
--td-comp-paddingTB-l: var(--td-size-6);
--td-comp-paddingTB-xl: var(--td-size-8);
--td-comp-paddingTB-xxl: var(--td-size-10);
--td-comp-margin-xxs: var(--td-size-1);
--td-comp-margin-xs: var(--td-size-2);
--td-comp-margin-s: var(--td-size-4);
--td-comp-margin-m: var(--td-size-5);
--td-comp-margin-l: var(--td-size-6);
--td-comp-margin-xl: var(--td-size-7);
--td-comp-margin-xxl: var(--td-size-8);
--td-comp-margin-xxxl: var(--td-size-10);
--td-comp-margin-xxxxl: var(--td-size-12);
}
View File
+81
View File
@@ -0,0 +1,81 @@
import { ref } from 'vue'
// 基础配置
// const BASE_URL = "http://192.168.41.118:9090/api"
const BASE_URL = "/api"
export function useRequest() {
const loading = ref(false)
const error = ref<any>(null)
// 核心请求方法
const sendRequest = <T = any>(options: UniApp.RequestOptions): Promise<T> => {
loading.value = true
error.value = null
return new Promise((resolve, reject) => {
// 处理URL
const url = options.url.startsWith('http')
? options.url
: `${BASE_URL}/${options.url.replace(/^\//, '')}`
// 添加token
const token = uni.getStorageSync('token')
const headers = {
'Content-Type': 'application/json',
...(token ? { 'Authorization': `Bearer ${token}` } : {}),
...options.header
}
uni.request({
url,
method: options.method || 'GET',
data: options.data,
header: headers,
timeout: options.timeout || 10000,
success: (res) => {
if (res.statusCode >= 200 && res.statusCode < 300) {
resolve(res.data as T)
} else {
const err = new Error(res.data?.message || '请求失败')
error.value = err
reject(err)
}
},
fail: (err) => {
error.value = err
reject(err)
},
complete: () => {
loading.value = false
}
})
})
}
// GET请求
const get = <T = any>(url: string, params?: any) => {
return sendRequest<T>({
url,
method: 'GET',
data: params
})
}
// POST请求
const post = <T = any>(url: string, data?: any) => {
return sendRequest<T>({
url,
method: 'POST',
data
})
}
return {
loading,
error,
request: sendRequest,
get,
post
}
}
+32
View File
@@ -0,0 +1,32 @@
import { defineConfig } from 'vite'
import uni from '@dcloudio/vite-plugin-uni'
import AutoImport from 'unplugin-auto-import/vite';
import Components from 'unplugin-vue-components/vite';
import { TDesignResolver } from 'unplugin-vue-components/resolvers';
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
uni(),
AutoImport({
resolvers: [TDesignResolver({
library: 'mobile-vue'
})],
}),
Components({
resolvers: [TDesignResolver({
library: 'mobile-vue'
})],
})
],
server: {
proxy: {
'/api': {
target: 'http://192.168.41.118:9090',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
}
}
}
})