This commit is contained in:
2025-03-25 16:35:39 +08:00
parent 2b456dc17e
commit 9463635e03
66 changed files with 864 additions and 64 deletions

View File

@@ -0,0 +1,7 @@
import system from "./system/index.js";
const Api = {
system: {...system},
}
export default Api;

13
src/api/system/index.js Normal file
View File

@@ -0,0 +1,13 @@
import request from "../../utils/request.js";
import MethodsENUM from "../../enum/MethodsENUM.js";
const system = {
getData: async () => {
return request({
method: MethodsENUM.POST,
url: "/m1/5995958-5684445-default/getList",
});
}
}
export default system;

28
src/components/XInput.vue Normal file
View File

@@ -0,0 +1,28 @@
<script setup>
const {placeholder} = defineProps({
placeholder: {
type: String,
default: "",
}
});
const modelValue = defineModel();
</script>
<template>
<view class="x-input h-[96rpx] rounded-[12rpx] !flex items-center px-[32rpx]">
<input v-model="modelValue" :placeholder="placeholder"></input>
<slot name="suffix"></slot>
</view>
</template>
<style lang="scss" scoped>
.x-input {
background-color: #F2F3F5;
:deep(input) {
background-color: rgba(0,0,0,0);
flex-grow: 1;
}
}
</style>

13
src/components/XLink.vue Normal file
View File

@@ -0,0 +1,13 @@
<script setup>
</script>
<template>
<view class="text-[var(--primary-color)]">
<slot></slot>
</view>
</template>
<style scoped>
</style>

33
src/components/XNav.vue Normal file
View File

@@ -0,0 +1,33 @@
<script setup>
import {isWXWeb} from "../utils/uils.js";
const {title} = defineProps({
title: {
type: String,
default: document.title || "页面",
}
});
</script>
<template>
<template v-if="!isWXWeb()">
<view class="!flex justify-center items-center h-[100rpx] bg-[#f9f9f9]">
<image class="!w-[9px] !h-[17px] cursor-pointer !absolute left-[50rpx]"
src="/static/icons/back.png"></image>
<view class="title">{{ title }}</view>
</view>
</template>
</template>
<style lang="scss" scoped>
.title {
color: rgb(0, 0, 0);
font-family: '思源黑体', sans-serif;
font-size: 17px;
font-weight: 500;
line-height: 25px;
letter-spacing: 0;
text-align: center;
}
</style>

8
src/enum/MethodsENUM.js Normal file
View File

@@ -0,0 +1,8 @@
const MethodsENUM = {
GET: "GET",
POST: "POST",
PUT: "PUT",
DELETE: "DELETE",
}
export default MethodsENUM;

View File

@@ -3,6 +3,12 @@ import {
} from "vue";
import App from "./App.vue";
import './scss/index.css';
import './scss/index.scss';
import './scss/global.scss';
import './scss/uni.scss';
import propsConfig from "./scss/thorui.config.js";
uni.$tui = propsConfig;
export function createApp() {
const app = createSSRApp(App);

View File

@@ -1,28 +1,28 @@
{
"name" : "",
"appid" : "",
"description" : "",
"versionName" : "1.0.0",
"versionCode" : "100",
"transformPx" : false,
"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
"app-plus": {
"usingComponents": true,
"nvueStyleCompiler": "uni-app",
"compilerVersion": 3,
"splashscreen": {
"alwaysShowBeforeRender": true,
"waiting": true,
"autoclose": true,
"delay": 0
},
/* */
"modules" : {},
"modules": {},
/* */
"distribute" : {
"distribute": {
/* android */
"android" : {
"permissions" : [
"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\"/>",
@@ -41,32 +41,34 @@
]
},
/* ios */
"ios" : {},
"ios": {},
/* SDK */
"sdkConfigs" : {}
"sdkConfigs": {}
}
},
/* */
"quickapp" : {},
"quickapp": {},
/* */
"mp-weixin" : {
"appid" : "",
"setting" : {
"urlCheck" : false
"mp-weixin": {
"appid": "",
"setting": {
"urlCheck": false
},
"usingComponents" : true
"usingComponents": true
},
"mp-alipay" : {
"usingComponents" : true
"h5": {
},
"mp-baidu" : {
"usingComponents" : true
"mp-alipay": {
"usingComponents": true
},
"mp-toutiao" : {
"usingComponents" : true
"mp-baidu": {
"usingComponents": true
},
"uniStatistics": {
"mp-toutiao": {
"usingComponents": true
},
"uniStatistics": {
"enable": false
},
"vueVersion" : "3"
"vueVersion": "3"
}

View File

@@ -1,16 +1,86 @@
{
"pages": [ //pages数组中第一项表示应用启动页参考https://uniapp.dcloud.io/collocation/pages
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "uni-app"
}
}
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "uni-app",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8"
}
}
"pages": [
// 其他页面
{
"path": "pages/login/index",
"style": {
"navigationBarTitleText": "登陆",
"navigationStyle": "custom"
}
},
//pages数组中第一项表示应用启动页参考https://uniapp.dcloud.io/collocation/pages
{
"path": "pages/home/index",
"style": {
"navigationBarTitleText": "首页",
"navigationStyle": "custom"
}
},
{
"path": "pages/myTask/index",
"style": {
"navigationBarTitleText": "我的任务",
"navigationStyle": "custom"
}
},
{
"path": "pages/messageCenter/index",
"style": {
"navigationBarTitleText": "消息",
"navigationStyle": "custom"
}
},
{
"path": "pages/user/index",
"style": {
"navigationBarTitleText": "我的",
"navigationStyle": "custom"
}
}
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "uni-app",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8",
"dynamicRpx": true
},
"easycom": {
"autoscan": true,
"custom": {
"tui-(.*)": "thorui-uni/lib/thorui/tui-$1/tui-$1.vue"
}
},
"tabBar": {
"color": "#C9CDD4",
"selectedColor": "#2D5CF6",
"backgroundColor": "#FFFFFF",
"borderStyle": "black",
"list": [
{
"pagePath": "pages/home/index",
"text": "首页",
"iconPath": "./static/icons/home.png",
"selectedIconPath": "./static/icons/homes.png"
},
{
"pagePath": "pages/myTask/index",
"text": "我的任务",
"iconPath": "./static/icons/task.png",
"selectedIconPath": "./static/icons/tasks.png"
},
{
"pagePath": "pages/messageCenter/index",
"text": "消息",
"iconPath": "./static/icons/message.png",
"selectedIconPath": "./static/icons/messages.png"
},
{
"pagePath": "pages/user/index",
"text": "我的",
"iconPath": "./static/icons/user.png",
"selectedIconPath": "./static/icons/users.png"
}
]
}
}

View File

@@ -0,0 +1,11 @@
<script setup>
</script>
<template>
<!--邀请好友-->
</template>
<style scoped>
</style>

View File

@@ -0,0 +1,11 @@
<script setup>
</script>
<template>
<!--账号管理-->
</template>
<style scoped>
</style>

View File

@@ -0,0 +1,11 @@
<script setup>
</script>
<template>
<!--添加账号-->
</template>
<style scoped>
</style>

View File

@@ -0,0 +1,11 @@
<script setup>
</script>
<template>
<!--添加钱包-->
</template>
<style scoped>
</style>

View File

@@ -0,0 +1,11 @@
<script setup>
</script>
<template>
<!--新手教程-->
</template>
<style scoped>
</style>

View File

@@ -0,0 +1,11 @@
<script setup>
</script>
<template>
<!--变动记录-->
</template>
<style scoped>
</style>

View File

@@ -0,0 +1,11 @@
<script setup>
</script>
<template>
<!--忘记密码-->
</template>
<style scoped>
</style>

11
src/pages/home/index.vue Normal file
View File

@@ -0,0 +1,11 @@
<script setup>
</script>
<template>
<!--首页-->
</template>
<style scoped>
</style>

View File

@@ -0,0 +1,11 @@
<script setup>
</script>
<template>
<!--收益记录-->
</template>
<style scoped>
</style>

View File

@@ -1,13 +0,0 @@
<template>
<view class="text-[red]">
123
</view>
</template>
<script>
</script>
<style>
</style>

View File

@@ -0,0 +1,29 @@
<script setup>
import {reactive} from "vue";
import XInput from "../../components/XInput.vue";
import XLink from "../../components/XLink.vue";
const form = reactive({
phone: null,
verificationCode: null,
});
</script>
<template>
<view class="!px-[34rpx] !flex flex-col gap-[40rpx]">
<x-input v-model:model-value="form.phone" placeholder="请输入手机号"></x-input>
<x-input v-model:model-value="form.verificationCode" placeholder="密码">
<template #suffix>
<x-link>忘记密码?</x-link>
</template>
</x-input>
<tui-button class="!mt-[80rpx]">登录</tui-button>
<tui-button class="!mt-[40rpx]" plain link>
<image class="!h-[26rpx]" mode="heightFix" src="../../static/icons/去注册.png"></image>
</tui-button>
</view>
</template>
<style scoped>
</style>

View File

@@ -0,0 +1,62 @@
<script setup>
import dm1 from '../../static/icons/弹幕1.png';
import dm2 from '../../static/icons/弹幕2.png';
import dm3 from '../../static/icons/弹幕3.png';
import dm4 from '../../static/icons/弹幕4.png';
import dm5 from '../../static/icons/弹幕5.png';
import dm6 from '../../static/icons/弹幕6.png';
import dm7 from '../../static/icons/弹幕7.png';
import dm8 from '../../static/icons/弹幕8.png';
import dm9 from '../../static/icons/弹幕9.png';
import {reactive} from "vue";
const MAP = [dm1,dm2,dm3,dm4,dm5,dm6,dm7,dm8,dm9];
const list1 = reactive([]);
const list2 = reactive([]);
for (let i = 0; i <= 100; i++) {
list1.push(MAP[Math.floor(Math.random() * 9)]);
list2.push(MAP[Math.floor(Math.random() * 9)]);
}
</script>
<template>
<view class="!mt-[68rpx] !flex flex-col gap-[20rpx]">
<view class="!flex gap-[30rpx] scrollX">
<image
v-for="item in list1"
class="!h-[72rpx]"
mode="heightFix"
:src="item">
</image>
</view>
<view class="!flex gap-[30rpx] scrollX">
<image
v-for="item in list2"
class="!h-[72rpx]"
mode="heightFix"
:src="item">
</image>
</view>
</view>
</template>
<style lang="scss" scoped>
.scrollX {
width: max-content !important;
animation: scroll 150s linear infinite;
image {
flex-shrink: 0;
}
}
@keyframes scroll {
0% {
transform: translateX(100vw); /* 从右侧开始 */
}
100% {
transform: translateX(-100%); /* 滚动到左侧结束 */
}
}
</style>

View File

@@ -0,0 +1,29 @@
<script setup>
import {reactive} from "vue";
import XInput from "../../components/XInput.vue";
import XLink from "../../components/XLink.vue";
const form = reactive({
phone: null,
verificationCode: null,
});
</script>
<template>
<view class="!px-[34rpx] !flex flex-col gap-[40rpx]">
<x-input v-model:model-value="form.phone" placeholder="请输入手机号"></x-input>
<x-input v-model:model-value="form.verificationCode" placeholder="验证码">
<template #suffix>
<x-link>发送验证码</x-link>
</template>
</x-input>
<tui-button class="!mt-[80rpx]">登录</tui-button>
<tui-button class="!mt-[40rpx]" plain link>
<image class="!h-[26rpx]" mode="heightFix" src="../../static/icons/去注册.png"></image>
</tui-button>
</view>
</template>
<style scoped>
</style>

52
src/pages/login/index.vue Normal file
View File

@@ -0,0 +1,52 @@
<script setup>
import XNav from "../../components/XNav.vue";
import BulletChat from "./BulletChat.vue";
import {ref} from "vue";
import AccountLogin from "./AccountLogin.vue";
import PhoneLogin from "./PhoneLogin.vue";
const currentTab = ref(0);
const tabs = [
{
name: '手机号登录',
},
{
name: '账号密码登录',
},
];
</script>
<template>
<!--登陆-->
<XNav></XNav>
<view class="h-[390rpx] relative overflow-hidden">
<image class="!absolute left-1/2 top-1/2 -translate-1/2 !w-[1198rpx] !h-[806rpx] -z-10 !pb-[40rpx]"
src="/static/icons/bg.png"></image>
<view class="!flex gap-[16rpx] items-center !mt-[56rpx] !ml-[16rpx]">
<image class="!w-[68rpx] !h-[68rpx]" src="/static/icons/hi.png"></image>
<view class="title">欢迎登录系统</view>
</view>
<BulletChat></BulletChat>
</view>
<view class="h-full bg-white !-mt-[20rpx] rounded-t-[20rpx]">
<tui-tabs class="!mx-auto !mb-[40rpx]" :tabs="tabs" :currentTab="currentTab" itemWidth="50%" @change="({index}) => currentTab=index" :width="300" :sliderWidth="130"></tui-tabs>
<PhoneLogin v-if="currentTab === 0"></PhoneLogin>
<AccountLogin v-else></AccountLogin>
</view>
</template>
<style lang="scss" scoped>
.title {
color: rgb(29, 33, 41);
font-size: 26px;
font-weight: 700;
line-height: 28px;
letter-spacing: 0;
text-align: left;
}
</style>

View File

@@ -0,0 +1,11 @@
<script setup>
</script>
<template>
<!--消息中心-->
</template>
<style scoped>
</style>

View File

@@ -0,0 +1,11 @@
<script setup>
</script>
<template>
<!--消息推送-->
</template>
<style scoped>
</style>

View File

@@ -0,0 +1,11 @@
<script setup>
</script>
<template>
<!--我的任务-->
</template>
<style scoped>
</style>

View File

@@ -0,0 +1,11 @@
<script setup>
</script>
<template>
<!--注册-->
</template>
<style scoped>
</style>

View File

@@ -0,0 +1,11 @@
<script setup>
</script>
<template>
<!--单页-->
</template>
<style scoped>
</style>

View File

@@ -0,0 +1,11 @@
<script setup>
</script>
<template>
<!--邀请好友-->
</template>
<style scoped>
</style>

11
src/pages/user/index.vue Normal file
View File

@@ -0,0 +1,11 @@
<script setup>
</script>
<template>
<!--我的-->
</template>
<style scoped>
</style>

View File

@@ -0,0 +1,11 @@
<script setup>
</script>
<template>
<!--编辑信息-->
</template>
<style scoped>
</style>

View File

@@ -0,0 +1,11 @@
<script setup>
</script>
<template>
<!--钱包-->
</template>
<style scoped>
</style>

View File

@@ -0,0 +1,11 @@
<script setup>
</script>
<template>
<!--变动记录-->
</template>
<style scoped>
</style>

View File

@@ -0,0 +1,11 @@
<script setup>
</script>
<template>
<!--提现记录-->
</template>
<style scoped>
</style>

4
src/scss/global.scss Normal file
View File

@@ -0,0 +1,4 @@
.test {
border: 1px solid red;
@apply box-border;
}

3
src/scss/index.scss Normal file
View File

@@ -0,0 +1,3 @@
Page {
--primary-color: #2D5CF6;
}

131
src/scss/thorui.config.js Normal file
View File

@@ -0,0 +1,131 @@
/*
基础组件props属性全局配置文件。优先级全局配置文件props < 单独设置组件props
温馨提示未设置则使用组件内默认值避免出错请勿删减以下配置切勿修改key仅可修改key对应值。
组件属性介绍请查看文档
*/
//组件内主色配置
const color = {
primary: '#2D5CF6',
success: '#07c160',
warning: '#ff7900',
danger: '#EB0909',
pink: '#f74d54',
blue: '#2D5CF6',
link: '#586c94'
}
const propsConfig = {
//组件内主色配置
color,
//组件名称,字体图标组件 tui-icon
tuiIcon: {
//组件属性值
size: 32,
unit: 'px',
color: '#999'
},
//按钮组件 tui-button
tuiButton: {
height: '96rpx',
size: 32,
},
//列表项组件 tui-list-cell
tuiListCell: {
arrowColor: '#c0c0c0',
lineColor: '#eaeef1',
lineLeft: 30,
padding: '26rpx 30rpx',
color: '#333',
size: 28,
},
//按钮组件 tui-form-button
tuiFormButton: {
background: color.primary,
color: '#fff',
height: '96rpx',
size: 32,
radius: '6rpx',
},
//文本组件 tui-text
tuiText: {
size: 32,
unit: 'rpx',
color: ''
},
//输入框组件 tui-input
tuiInput: {
requiredColor: color.danger,
labelSize: 32,
labelColor: '#333',
size: 32,
color: '#333',
padding: '26rpx 30rpx',
backgroundColor: '#FFFFFF',
radius: 0
},
//表单项组件 tui-form-item
tuiFormItem: {
padding: '28rpx 30rpx',
labelSize: 32,
labelColor: '#333',
labelFontWeight: 400,
asteriskColor: color.danger,
background: '#fff',
arrowColor: '#c0c0c0',
borderColor: '#eaeef1',
radius: '0rpx',
position: 2
},
//表单校验组件 tui-form
tuiForm: {
tipBackgroundColor: color.pink,
duration: 2000
},
//全局方法,调用 uni.$tui.toast
toast(text, duration, success) {
uni.showToast({
// #ifndef MP-ALIPAY
duration: duration || 2000,
// #endif
title: text || "出错啦~",
icon: success ? 'success' : 'none'
})
},
//全局方法,调用 uni.$tui.modal
modal(title, content, showCancel, callback, confirmColor, confirmText) {
uni.showModal({
title: title || '提示',
content: content,
showCancel: showCancel,
cancelColor: "#555",
confirmColor: confirmColor || color.primary,
confirmText: confirmText || "确定",
success(res) {
if (res.confirm) {
callback && callback(true)
} else {
callback && callback(false)
}
}
})
},
//跳转页面调用uni.$tui.href
href(url, isMain) {
if (isMain) {
uni.switchTab({
url: url
})
} else {
uni.navigateTo({
url: url
});
}
},
//全局方法rpx转px调用 uni.$tui.rpx2px
rpx2px(value) {
return uni.upx2px(value)
}
}
export default propsConfig

1
src/scss/uni.scss Normal file
View File

@@ -0,0 +1 @@

BIN
src/static/icons/back.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 511 B

BIN
src/static/icons/bg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 605 KiB

BIN
src/static/icons/hi.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
src/static/icons/home.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 608 B

BIN
src/static/icons/homes.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 599 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 769 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 762 B

BIN
src/static/icons/task.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 693 B

BIN
src/static/icons/tasks.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 673 B

BIN
src/static/icons/user.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 827 B

BIN
src/static/icons/users.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 811 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
src/static/icons/弹幕1.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

BIN
src/static/icons/弹幕2.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

BIN
src/static/icons/弹幕3.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

BIN
src/static/icons/弹幕4.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

BIN
src/static/icons/弹幕5.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

BIN
src/static/icons/弹幕6.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

BIN
src/static/icons/弹幕7.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

BIN
src/static/icons/弹幕8.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

BIN
src/static/icons/弹幕9.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

30
src/utils/AESCrypto.js Normal file
View File

@@ -0,0 +1,30 @@
import AES from 'crypto-js/aes.js';
import utf8 from 'crypto-js/enc-utf8.js';
class AESCrypto {
/**
* 密钥
* @type {string}
*/
static #AES_KEY = import.meta.env.VITE_AES_KEY;
/**
* AES加密
* @param context {string} 加密内容
*/
static encrypt = (context) => {
return AES.encrypt(context, this.#AES_KEY).toString();
}
/**
* AES解密
* @param context {string}
* @return {string}
*/
static decrypt = (context) => {
const bytes = AES.decrypt(context, this.#AES_KEY);
return bytes.toString(utf8);
}
}
export default AESCrypto;

24
src/utils/request.js Normal file
View File

@@ -0,0 +1,24 @@
import {showToast} from "./uils.js";
const request = (options) => {
return new Promise((resolve, reject) => {
const {url, method} = options;
uni.request({
method: method,
url: `${import.meta.env.VITE_API_URL}${url}`,
success: ({data}) => {
if (data.code !== 0) {
showToast(data.msg);
reject(data.msg);
}
resolve(data);
},
fail: (err) => {
reject(err);
}
});
});
}
export default request;

15
src/utils/uils.js Normal file
View File

@@ -0,0 +1,15 @@
export const showToast = (options) => {
if (typeof options === 'string') {
uni.showToast({
title: options,
icon: 'none',
}).then();
} else {
uni.showToast(options).then();
}
}
export const isWXWeb = () => {
const userAgent = navigator.userAgent;
return userAgent.includes('MicroMessenger');
}