需要开发 IM
This commit is contained in:
@@ -17,4 +17,11 @@ unaipp多端im+会议+积分商城
|
|||||||
|
|
||||||
### TUILiveKit 文档地址
|
### TUILiveKit 文档地址
|
||||||
|
|
||||||
```https://trtc.io/zh/document/60034?platform=ios&product=live```
|
```https://trtc.io/zh/document/60034?platform=ios&product=live```
|
||||||
|
|
||||||
|
### 直播与语音 文档
|
||||||
|
|
||||||
|
```https://cloud.tencent.com/document/product/647/111859```
|
||||||
|
|
||||||
|
### 聊天列表
|
||||||
|
```https://cloud.tencent.com/document/product/269/105582```
|
||||||
33
api/index.js
33
api/index.js
@@ -95,3 +95,36 @@ export const getUserIntegralRank = data => {
|
|||||||
data
|
data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 签到列表 */
|
||||||
|
export const getSignList = data => {
|
||||||
|
return http({
|
||||||
|
url: '/api/system/signRecord/list',
|
||||||
|
method: 'get',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 签到 */
|
||||||
|
export const signIn = () => {
|
||||||
|
return http({
|
||||||
|
url: '/api/system/signRecord',
|
||||||
|
method: 'post'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 根据id获取文章详细信息 */
|
||||||
|
export const getArticleDetail = id => {
|
||||||
|
return http({
|
||||||
|
url: `/api/service/articleContent/type/${id}`,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获取腾讯usersig */
|
||||||
|
export const getTencentUserSig = () => {
|
||||||
|
return http({
|
||||||
|
url: '/api/user/usersig',
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
52
api/my-index.js
Normal file
52
api/my-index.js
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
import http from '@/utils/request'
|
||||||
|
|
||||||
|
/** 添加银行卡 */
|
||||||
|
export const addUserAddress = data => {
|
||||||
|
return http({
|
||||||
|
url: '/api/service/userCard',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 修改银行卡 */
|
||||||
|
export const updateUserAddress = data => {
|
||||||
|
return http({
|
||||||
|
url: '/api/service/userCard',
|
||||||
|
method: 'put',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获取用户银行卡列表 */
|
||||||
|
export const getUserAddress = data => {
|
||||||
|
return http({
|
||||||
|
url: '/api/service/userCard/list',
|
||||||
|
method: 'get',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除银行卡 */
|
||||||
|
export const deleteUserAddress = id => {
|
||||||
|
return http({
|
||||||
|
url: `/api/service/userCard/${id}`,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获取用户银行卡详情 */
|
||||||
|
export const getUserAddressDetail = id => {
|
||||||
|
return http({
|
||||||
|
url: `/api/service/userCard/details/${id}`,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获取用户支付密码详细信息 */
|
||||||
|
export const getUserPayPwd = () => {
|
||||||
|
return http({
|
||||||
|
url: '/api/service/userPassword/details',
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
|
import { navigateTo } from '@/utils/router'
|
||||||
|
|
||||||
const isShow = defineModel({
|
const isShow = defineModel({
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
@@ -20,9 +22,13 @@
|
|||||||
@click="isShow = false"
|
@click="isShow = false"
|
||||||
></image>
|
></image>
|
||||||
<text class="text">我已阅读并同意</text>
|
<text class="text">我已阅读并同意</text>
|
||||||
<text class="on">《用户权益》</text>
|
<text class="on" @click="navigateTo('/pages/login/protocol')">
|
||||||
|
《用户权益》
|
||||||
|
</text>
|
||||||
<text class="text">与</text>
|
<text class="text">与</text>
|
||||||
<text class="on">《隐私政策》</text>
|
<text class="on" @click="navigateTo('/pages/login/regime')">
|
||||||
|
《隐私政策》
|
||||||
|
</text>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
38
components/app-article-detail/app-article-detail.vue
Normal file
38
components/app-article-detail/app-article-detail.vue
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
<script setup>
|
||||||
|
import { getArticleDetail } from '@/api'
|
||||||
|
import { onMounted, ref } from 'vue'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
/** 文章类型
|
||||||
|
* user_rights: 用户权益
|
||||||
|
* privacy_policy: 隐私政策
|
||||||
|
* company_info: 公司介绍
|
||||||
|
*/
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
default: 'user_rights'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const articleDetails = ref('')
|
||||||
|
const getData = async () => {
|
||||||
|
const res = await getArticleDetail(props.type)
|
||||||
|
articleDetails.value = res.data.articleDetails
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getData()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="app-article-detail">
|
||||||
|
<mp-html :content="articleDetails"></mp-html>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.app-article-detail {
|
||||||
|
padding: 32rpx 24rpx;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,5 +1,10 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
const props = defineProps()
|
const props = defineProps({
|
||||||
|
placeholder: {
|
||||||
|
type: String,
|
||||||
|
default: '请输入内容'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
const placeholderStyle = `font-family: PingFang SC, PingFang SC; font-weight: 500; color: #666666; font-size: 24rpx; font-style: normal; text-transform: none;`
|
const placeholderStyle = `font-family: PingFang SC, PingFang SC; font-weight: 500; color: #666666; font-size: 24rpx; font-style: normal; text-transform: none;`
|
||||||
|
|
||||||
@@ -19,7 +24,7 @@
|
|||||||
<input
|
<input
|
||||||
v-model="name"
|
v-model="name"
|
||||||
:placeholder-style="placeholderStyle"
|
:placeholder-style="placeholderStyle"
|
||||||
placeholder="请输入内容"
|
:placeholder="props.placeholder"
|
||||||
class="search-box"
|
class="search-box"
|
||||||
/>
|
/>
|
||||||
<button class="search-btn">搜索</button>
|
<button class="search-btn">搜索</button>
|
||||||
|
|||||||
@@ -9,6 +9,11 @@
|
|||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: ''
|
||||||
},
|
},
|
||||||
|
/** 是否显示左侧返回按钮 */
|
||||||
|
showBack: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
/** 导航栏颜色 */
|
/** 导航栏颜色 */
|
||||||
targetColor: {
|
targetColor: {
|
||||||
type: String,
|
type: String,
|
||||||
@@ -39,7 +44,7 @@
|
|||||||
const emits = defineEmits(['onBack'])
|
const emits = defineEmits(['onBack'])
|
||||||
|
|
||||||
// 判断是否传入了名为 "back" 的插槽
|
// 判断是否传入了名为 "back" 的插槽
|
||||||
const hasBackSlot = !!slots.back
|
const hasBackSlot = computed(() => !!slots.back)
|
||||||
/** 全局存储当前滚动位置(供 computed 使用) */
|
/** 全局存储当前滚动位置(供 computed 使用) */
|
||||||
const currentScrollTop = ref(0)
|
const currentScrollTop = ref(0)
|
||||||
/** 缓存 rpx 转 px 的比例 */
|
/** 缓存 rpx 转 px 的比例 */
|
||||||
@@ -118,9 +123,10 @@
|
|||||||
</view>
|
</view>
|
||||||
<view class="nav-bar-box">
|
<view class="nav-bar-box">
|
||||||
<!-- 左侧插槽 -->
|
<!-- 左侧插槽 -->
|
||||||
<view @click="onBack">
|
<view @click="props.showBack && onBack()">
|
||||||
|
<!-- -->
|
||||||
<image
|
<image
|
||||||
v-if="!hasBackSlot"
|
v-if="props.showBack && !hasBackSlot"
|
||||||
src="/static/images/login/back.png"
|
src="/static/images/login/back.png"
|
||||||
mode="heightFix"
|
mode="heightFix"
|
||||||
class="top_left-icon"
|
class="top_left-icon"
|
||||||
|
|||||||
@@ -10,11 +10,12 @@ export const useAuthUser = () => {
|
|||||||
const tokenStore = useTokenStore()
|
const tokenStore = useTokenStore()
|
||||||
|
|
||||||
// 响应式状态(state & getters)
|
// 响应式状态(state & getters)
|
||||||
const { userInfo } = storeToRefs(userStore)
|
const { userInfo, tencentUserSig } = storeToRefs(userStore)
|
||||||
const { token } = storeToRefs(tokenStore)
|
const { token } = storeToRefs(tokenStore)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
userInfo,
|
userInfo,
|
||||||
|
tencentUserSig,
|
||||||
token
|
token
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
export const STORAGE_KEYS = {
|
export const STORAGE_KEYS = {
|
||||||
TOKEN: 'token',
|
TOKEN: 'token',
|
||||||
USER: 'userInfo'
|
USER: 'userInfo',
|
||||||
|
TENCENT_USER_SIG: 'tencentUserSig' // 腾讯 IM 签名
|
||||||
}
|
}
|
||||||
|
|||||||
20
pages.json
20
pages.json
@@ -14,6 +14,18 @@
|
|||||||
"navigationStyle": "custom"
|
"navigationStyle": "custom"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/login/protocol",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "用户权益"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/login/regime",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "隐私政策"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "pages/login/phone-register/phone-register",
|
"path": "pages/login/phone-register/phone-register",
|
||||||
"style": {
|
"style": {
|
||||||
@@ -38,7 +50,8 @@
|
|||||||
{
|
{
|
||||||
"path": "pages/news-list/news-list",
|
"path": "pages/news-list/news-list",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "消息"
|
"navigationBarTitleText": "消息",
|
||||||
|
"navigationStyle": "custom"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -230,7 +243,8 @@
|
|||||||
{
|
{
|
||||||
"path": "pages/discover/company",
|
"path": "pages/discover/company",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "公司介绍"
|
"navigationBarTitleText": "公司介绍",
|
||||||
|
"navigationBarBackgroundColor": "#ffffff"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -273,4 +287,4 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,18 +1,34 @@
|
|||||||
<script setup></script>
|
<script setup>
|
||||||
|
import { getArticleDetail } from '@/api'
|
||||||
|
import { onLoad } from '@dcloudio/uni-app'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
const formData = ref({})
|
||||||
|
const getData = async () => {
|
||||||
|
const res = await getArticleDetail('company_info')
|
||||||
|
formData.value = res.data
|
||||||
|
}
|
||||||
|
|
||||||
|
onLoad(() => {
|
||||||
|
getData()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<view class="company">
|
<view class="company">
|
||||||
<view class="top-log">
|
<view class="top-log">
|
||||||
<image
|
<image
|
||||||
src="https://qcloud.dpfile.com/pc/TrdZpLN1zkXDV4oN2FH98LdVnvHj694NKQu0_KA3ul4eYxZWRPQ7CJuw-PqyZBS4.jpg"
|
:src="formData.articleImg"
|
||||||
mode="aspectFill"
|
mode="aspectFill"
|
||||||
class="img"
|
class="img"
|
||||||
></image>
|
></image>
|
||||||
<text>名字</text>
|
<text>{{ formData.articleTitle }}</text>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="consten">
|
<view class="consten">
|
||||||
<view class="item">富文本</view>
|
<view class="item">
|
||||||
|
<mp-html :content="formData.articleDetails"></mp-html>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -23,7 +23,9 @@ text-transform: none;`
|
|||||||
<view class="release-box">
|
<view class="release-box">
|
||||||
<nav-bar isPlaceholder>
|
<nav-bar isPlaceholder>
|
||||||
<template #right>
|
<template #right>
|
||||||
<text class="right-btn" @click="onUpData">发布</text>
|
<text class="public-navbar__right-btn" @click="onUpData">
|
||||||
|
发布
|
||||||
|
</text>
|
||||||
</template>
|
</template>
|
||||||
</nav-bar>
|
</nav-bar>
|
||||||
|
|
||||||
@@ -46,18 +48,6 @@ text-transform: none;`
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.right-btn {
|
|
||||||
font-family: PingFang SC, PingFang SC;
|
|
||||||
font-weight: 500;
|
|
||||||
font-size: 28rpx;
|
|
||||||
color: #ffffff;
|
|
||||||
font-style: normal;
|
|
||||||
text-transform: none;
|
|
||||||
background: linear-gradient(0deg, #00d993 0%, #00d9c5 100%);
|
|
||||||
padding: 12rpx 36rpx;
|
|
||||||
border-radius: 8rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
padding: 32rpx 58rpx;
|
padding: 32rpx 58rpx;
|
||||||
.textarea {
|
.textarea {
|
||||||
|
|||||||
@@ -1,16 +1,164 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
|
import { formatMonthDay, formatDate } from '@/utils/dateUtils'
|
||||||
|
import { onLoad } from '@dcloudio/uni-app'
|
||||||
|
import { getSignList, signIn } from '@/api'
|
||||||
|
import { useUI } from '@/utils/use-ui'
|
||||||
|
import { useAuthUser } from '@/composables/useAuthUser'
|
||||||
|
import { useUserStore } from '@/stores/user'
|
||||||
|
|
||||||
const weekList = ['一', '二', '三', '四', '五', '六', '日']
|
const { showToast } = useUI()
|
||||||
|
const { userInfo } = useAuthUser()
|
||||||
|
const { refreshUserInfo } = useUserStore()
|
||||||
|
|
||||||
const indexData = ref([1, 2, 3, 4])
|
const weekList = [
|
||||||
|
{ name: '一', value: 1 },
|
||||||
|
{ name: '二', value: 2 },
|
||||||
|
{ name: '三', value: 3 },
|
||||||
|
{ name: '四', value: 4 },
|
||||||
|
{ name: '五', value: 5 },
|
||||||
|
{ name: '六', value: 6 },
|
||||||
|
{ name: '日', value: 7 }
|
||||||
|
]
|
||||||
|
const indexData = ref([])
|
||||||
|
|
||||||
const onItem = item => {
|
const currentYear = ref(2025)
|
||||||
if (indexData.value.includes(item)) {
|
const currentMonth = ref(12)
|
||||||
return
|
/** 日期列表 */
|
||||||
|
const dateList = ref([])
|
||||||
|
/** 连续天数 */
|
||||||
|
const continuousDays = ref(0)
|
||||||
|
|
||||||
|
const getData = async msg => {
|
||||||
|
const res = await getSignList({
|
||||||
|
signMonth: `${currentYear.value}-${currentMonth.value}`
|
||||||
|
})
|
||||||
|
|
||||||
|
dateList.value = generateCalendar(
|
||||||
|
currentYear.value,
|
||||||
|
currentMonth.value
|
||||||
|
)
|
||||||
|
|
||||||
|
if (msg) {
|
||||||
|
await refreshUserInfo()
|
||||||
|
showToast(msg)
|
||||||
}
|
}
|
||||||
indexData.value.push(item)
|
|
||||||
|
continuousDays.value = res.data.continuousDays
|
||||||
|
indexData.value = res.data.list.map(v => v.signDate)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成一个 5x7 的日历数组(从周一到周日)
|
||||||
|
* @param {number} year - 当前年份
|
||||||
|
* @param {number} month - 当前月份(1-12)
|
||||||
|
* @returns {Array<{ date: Date, type: 'prev' | 'current' | 'next' }>}
|
||||||
|
*/
|
||||||
|
const generateCalendar = (year, month) => {
|
||||||
|
const today = new Date()
|
||||||
|
const todayYear = today.getFullYear()
|
||||||
|
const todayMonth = today.getMonth()
|
||||||
|
const todayDate = today.getDate()
|
||||||
|
// 辅助函数:判断两个 Date 是否是同一天(忽略时分秒)
|
||||||
|
const isSameDay = (d1, d2) => {
|
||||||
|
return (
|
||||||
|
d1.getFullYear() === d2.getFullYear() &&
|
||||||
|
d1.getMonth() === d2.getMonth() &&
|
||||||
|
d1.getDate() === d2.getDate()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建当前月的第一天
|
||||||
|
const firstDay = new Date(year, month - 1, 1)
|
||||||
|
// 创建当前月的最后一天
|
||||||
|
const lastDay = new Date(year, month, 0)
|
||||||
|
|
||||||
|
// 获取当前月第一天是星期几
|
||||||
|
let startDayOfWeek = firstDay.getDay()
|
||||||
|
// 转换为以周一为 0:如果 getDay() 是 0(周日),则视为 6(即一周最后一天)
|
||||||
|
if (startDayOfWeek === 0) startDayOfWeek = 7
|
||||||
|
const offsetFromMonday = startDayOfWeek - 1 // 周一为0
|
||||||
|
|
||||||
|
// 上个月的最后一天
|
||||||
|
const prevMonthLastDay = new Date(year, month - 1, 0).getDate()
|
||||||
|
|
||||||
|
// 当前月总天数
|
||||||
|
const currentMonthDays = lastDay.getDate()
|
||||||
|
|
||||||
|
const calendar = []
|
||||||
|
// 仅用于比较
|
||||||
|
const todayRef = new Date(todayYear, todayMonth, todayDate)
|
||||||
|
|
||||||
|
// 填充上个月的尾几天
|
||||||
|
for (let i = 0; i < offsetFromMonday; i++) {
|
||||||
|
const day = prevMonthLastDay - offsetFromMonday + 1 + i
|
||||||
|
|
||||||
|
const date = new Date(year, month - 2, day) // month - 2 表示上个月
|
||||||
|
calendar.push({
|
||||||
|
date: formatMonthDay(date),
|
||||||
|
signDate: formatDate(date),
|
||||||
|
type: 'prev',
|
||||||
|
isToday: isSameDay(date, todayRef)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 填充当前月
|
||||||
|
for (let i = 0; i < currentMonthDays; i++) {
|
||||||
|
const date = new Date(year, month - 1, i + 1)
|
||||||
|
|
||||||
|
calendar.push({
|
||||||
|
date: formatMonthDay(date),
|
||||||
|
signDate: formatDate(date),
|
||||||
|
type: 'current',
|
||||||
|
isToday: isSameDay(date, todayRef)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 填充下个月的前几天,使总数达到 35(5*7)
|
||||||
|
const remaining = 35 - calendar.length
|
||||||
|
for (let i = 1; i <= remaining; i++) {
|
||||||
|
const date = new Date(year, month, i) // month 是下个月(因为 JS 月份从 0 开始)
|
||||||
|
calendar.push({
|
||||||
|
date: formatMonthDay(date),
|
||||||
|
signDate: formatDate(date),
|
||||||
|
type: 'next',
|
||||||
|
isToday: isSameDay(date, todayRef)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return calendar
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 点击签到 */
|
||||||
|
const onItem = async item => {
|
||||||
|
if (!item.isToday) return
|
||||||
|
const res = await signIn()
|
||||||
|
await getData(res.data.message)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 日期切换 */
|
||||||
|
const dateChange = e => {
|
||||||
|
if (e === 0) {
|
||||||
|
if (currentMonth.value === 1) {
|
||||||
|
currentYear.value--
|
||||||
|
currentMonth.value = 12
|
||||||
|
} else {
|
||||||
|
currentMonth.value--
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (currentMonth.value === 12) {
|
||||||
|
currentYear.value++
|
||||||
|
currentMonth.value = 1
|
||||||
|
} else {
|
||||||
|
currentMonth.value++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getData()
|
||||||
|
}
|
||||||
|
|
||||||
|
onLoad(() => {
|
||||||
|
getData()
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -27,7 +175,7 @@
|
|||||||
<view class="public-header—box">
|
<view class="public-header—box">
|
||||||
<view class="integral-box">
|
<view class="integral-box">
|
||||||
<text>我的积分</text>
|
<text>我的积分</text>
|
||||||
<text>410</text>
|
<text>{{ userInfo.totalPoints }}</text>
|
||||||
</view>
|
</view>
|
||||||
<image
|
<image
|
||||||
src="/static/images/discover/calendar.png"
|
src="/static/images/discover/calendar.png"
|
||||||
@@ -41,28 +189,40 @@
|
|||||||
<text class="title">每日签到领积分</text>
|
<text class="title">每日签到领积分</text>
|
||||||
<view class="right-box">
|
<view class="right-box">
|
||||||
<text>已连续签到</text>
|
<text>已连续签到</text>
|
||||||
<text>05</text>
|
<text>{{ continuousDays }}</text>
|
||||||
<text>天</text>
|
<text>天</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<!-- 切换 -->
|
<!-- 切换 -->
|
||||||
<view class="switch-box">
|
<view class="switch-box">
|
||||||
<text class="date">2025年12月</text>
|
<text class="date">{{ currentYear }}年{{ currentMonth }}月</text>
|
||||||
<view class="btn">
|
<view class="btn">
|
||||||
<uni-icons type="left" size="22" color="#666666"></uni-icons>
|
<uni-icons
|
||||||
<uni-icons type="right" size="22" color="#666666"></uni-icons>
|
type="left"
|
||||||
|
size="22"
|
||||||
|
color="#666666"
|
||||||
|
@click="dateChange(0)"
|
||||||
|
></uni-icons>
|
||||||
|
<uni-icons
|
||||||
|
type="right"
|
||||||
|
size="22"
|
||||||
|
color="#666666"
|
||||||
|
@click="dateChange(1)"
|
||||||
|
></uni-icons>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 签到列表 -->
|
<!-- 签到列表 -->
|
||||||
<view class="list-box">
|
<view class="list-box">
|
||||||
|
<!-- 星期列表 -->
|
||||||
<view v-for="(item, index) in weekList" :key="index" class="item">
|
<view v-for="(item, index) in weekList" :key="index" class="item">
|
||||||
<text class="bottom-name">{{ item }}</text>
|
<text class="bottom-name">{{ item.name }}</text>
|
||||||
</view>
|
</view>
|
||||||
|
<!-- 签到 -->
|
||||||
<view
|
<view
|
||||||
v-for="item in 30"
|
v-for="(item, index) in dateList"
|
||||||
:key="item"
|
:key="index"
|
||||||
:class="{ active: indexData.includes(item) }"
|
:class="{ active: indexData.includes(item.signDate) }"
|
||||||
class="item"
|
class="item"
|
||||||
@click="onItem(item)"
|
@click="onItem(item)"
|
||||||
>
|
>
|
||||||
@@ -72,9 +232,14 @@
|
|||||||
mode="heightFix"
|
mode="heightFix"
|
||||||
class="icon"
|
class="icon"
|
||||||
></image>
|
></image>
|
||||||
<text>+10</text>
|
<!-- <text>+10</text> -->
|
||||||
</view>
|
</view>
|
||||||
<text class="bottom-name">今天</text>
|
<text
|
||||||
|
:style="{ color: item.isToday ? '#00d993' : '#999999' }"
|
||||||
|
class="bottom-name"
|
||||||
|
>
|
||||||
|
{{ item.isToday ? '今日' : item.date }}
|
||||||
|
</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|||||||
9
pages/login/protocol.vue
Normal file
9
pages/login/protocol.vue
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<script setup></script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<view class="protocol-box">
|
||||||
|
<app-article-detail type="user_rights"></app-article-detail>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
9
pages/login/regime.vue
Normal file
9
pages/login/regime.vue
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<script setup></script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<view class="regime-box">
|
||||||
|
<app-article-detail type="privacy_policy"></app-article-detail>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
@@ -138,7 +138,10 @@
|
|||||||
<!-- 商品详情 -->
|
<!-- 商品详情 -->
|
||||||
<view class="detail-content">
|
<view class="detail-content">
|
||||||
<text class="title">商品详情</text>
|
<text class="title">商品详情</text>
|
||||||
<mp-html :content="viewData.description" class="rich-box" />
|
<mp-html
|
||||||
|
:content="viewData.description"
|
||||||
|
class="rich-box"
|
||||||
|
></mp-html>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,16 @@
|
|||||||
// 图片链接
|
// 图片链接
|
||||||
img: ''
|
img: ''
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const onAdd = () => {
|
||||||
|
console.log(formData)
|
||||||
|
const data = {
|
||||||
|
bankName: formData.name,
|
||||||
|
cardNumber: formData.cardNum,
|
||||||
|
bankName: formData.khName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onLoad(e => {
|
onLoad(e => {
|
||||||
const titltData = {
|
const titltData = {
|
||||||
0: '添加银行卡',
|
0: '添加银行卡',
|
||||||
@@ -33,7 +43,11 @@
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<view>
|
<view>
|
||||||
<nav-bar isTopBg isPlaceholder :title="stateData.title"></nav-bar>
|
<nav-bar isTopBg isPlaceholder :title="stateData.title">
|
||||||
|
<template #right>
|
||||||
|
<text class="public-navbar__right-btn" @click="onAdd">添加</text>
|
||||||
|
</template>
|
||||||
|
</nav-bar>
|
||||||
|
|
||||||
<view
|
<view
|
||||||
v-if="!['101', '102'].includes(stateData.state)"
|
v-if="!['101', '102'].includes(stateData.state)"
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { navigateTo } from '@/utils/router'
|
import { navigateTo } from '@/utils/router'
|
||||||
|
import { onShow } from '@dcloudio/uni-app'
|
||||||
|
import { getUserPayPwd } from '@/api/my-index'
|
||||||
|
|
||||||
const itemList = [
|
const itemList = [
|
||||||
{
|
{
|
||||||
@@ -15,6 +17,15 @@
|
|||||||
},
|
},
|
||||||
{ title: '实名认证', key: '4', url: '/pages/my-index/wallet/real-id' }
|
{ title: '实名认证', key: '4', url: '/pages/my-index/wallet/real-id' }
|
||||||
]
|
]
|
||||||
|
|
||||||
|
const getData = async () => {
|
||||||
|
const res = await getUserPayPwd()
|
||||||
|
console.log(res, '===')
|
||||||
|
}
|
||||||
|
|
||||||
|
onShow(() => {
|
||||||
|
getData()
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|||||||
@@ -1,13 +1,21 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
|
import { onLoad } from '@dcloudio/uni-app'
|
||||||
import { useAuthUser } from '@/composables/useAuthUser'
|
import { useAuthUser } from '@/composables/useAuthUser'
|
||||||
|
|
||||||
const { userInfo } = useAuthUser()
|
const { tencentUserSig } = useAuthUser()
|
||||||
|
onLoad(() => {
|
||||||
console.log(userInfo.value, '====use22rInfo===')
|
console.log(tencentUserSig.value, '===222===')
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<view class="news-list">消息列表</view>
|
<view class="news-list">
|
||||||
|
<nav-bar isTopBg isPlaceholder :showBack="false" title="消息(99+)">
|
||||||
|
<template #right>右侧按钮</template>
|
||||||
|
</nav-bar>
|
||||||
|
<cb-search placeholder="搜索"></cb-search>
|
||||||
|
消息列表
|
||||||
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped></style>
|
<style lang="scss" scoped></style>
|
||||||
|
|||||||
@@ -3,13 +3,17 @@ import {
|
|||||||
getToken,
|
getToken,
|
||||||
getUserInfoData,
|
getUserInfoData,
|
||||||
setUserInfoData,
|
setUserInfoData,
|
||||||
removeUserInfoData
|
removeUserInfoData,
|
||||||
|
getSig,
|
||||||
|
setSig,
|
||||||
|
removeSig
|
||||||
} from '@/utils/storage'
|
} from '@/utils/storage'
|
||||||
import { useTokenStore } from './token'
|
import { useTokenStore } from './token'
|
||||||
import { getUserData, userLogout } from '@/api'
|
import { getUserData, userLogout } from '@/api'
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { useUI } from '@/utils/use-ui'
|
import { useUI } from '@/utils/use-ui'
|
||||||
import { reLaunch } from '@/utils/router'
|
import { reLaunch } from '@/utils/router'
|
||||||
|
import { getTencentUserSig } from '@/api'
|
||||||
|
|
||||||
export const useUserStore = defineStore('user', () => {
|
export const useUserStore = defineStore('user', () => {
|
||||||
const { clearToken } = useTokenStore()
|
const { clearToken } = useTokenStore()
|
||||||
@@ -18,8 +22,8 @@ export const useUserStore = defineStore('user', () => {
|
|||||||
const userInfo = ref(
|
const userInfo = ref(
|
||||||
getUserInfoData() ? JSON?.parse(getUserInfoData()) : {}
|
getUserInfoData() ? JSON?.parse(getUserInfoData()) : {}
|
||||||
)
|
)
|
||||||
|
/** 腾讯 IM 存储数据 */
|
||||||
/** 用户信息对象 */
|
const tencentUserSig = ref(getSig() ? JSON?.parse(getSig()) : {})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取用户信息(可从缓存或接口)
|
* 获取用户信息(可从缓存或接口)
|
||||||
@@ -28,23 +32,27 @@ export const useUserStore = defineStore('user', () => {
|
|||||||
// 尝试从本地缓存读取
|
// 尝试从本地缓存读取
|
||||||
const cachedToken = getToken()
|
const cachedToken = getToken()
|
||||||
const cachedUserInfo = getUserInfoData()
|
const cachedUserInfo = getUserInfoData()
|
||||||
|
const cachedSig = getSig()
|
||||||
|
|
||||||
if (cachedToken && cachedUserInfo) {
|
if (cachedToken && cachedUserInfo) {
|
||||||
userInfo.value = JSON.parse(cachedUserInfo)
|
userInfo.value = JSON.parse(cachedUserInfo)
|
||||||
|
tencentUserSig.value = JSON.parse(cachedSig)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const res = await getUserData()
|
const res = await getUserData()
|
||||||
setUserInfo(res.data)
|
await setUserInfo(res.data)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置用户信息
|
* 设置用户信息
|
||||||
*/
|
*/
|
||||||
const setUserInfo = data => {
|
const setUserInfo = async data => {
|
||||||
|
const res = await getTencentUserSig()
|
||||||
|
tencentUserSig.value = res.data
|
||||||
userInfo.value = data
|
userInfo.value = data
|
||||||
// 同步到本地存储
|
|
||||||
setUserInfoData(data)
|
setUserInfoData(data)
|
||||||
|
setSig(res.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -57,6 +65,7 @@ export const useUserStore = defineStore('user', () => {
|
|||||||
userInfo.value = null
|
userInfo.value = null
|
||||||
clearToken()
|
clearToken()
|
||||||
removeUserInfoData()
|
removeUserInfoData()
|
||||||
|
removeSig()
|
||||||
reLaunch('/pages/login/login')
|
reLaunch('/pages/login/login')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -64,7 +73,7 @@ export const useUserStore = defineStore('user', () => {
|
|||||||
/** 刷新用户信息(如用户信息被修改) */
|
/** 刷新用户信息(如用户信息被修改) */
|
||||||
const refreshUserInfo = async () => {
|
const refreshUserInfo = async () => {
|
||||||
const res = await getUserData()
|
const res = await getUserData()
|
||||||
setUserInfo(res.data)
|
await setUserInfo(res.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -78,6 +87,7 @@ export const useUserStore = defineStore('user', () => {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
userInfo,
|
userInfo,
|
||||||
|
tencentUserSig,
|
||||||
refreshUserInfo,
|
refreshUserInfo,
|
||||||
fetchUserInfo,
|
fetchUserInfo,
|
||||||
setUserInfo,
|
setUserInfo,
|
||||||
|
|||||||
@@ -2,3 +2,16 @@
|
|||||||
page {
|
page {
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 顶部导航栏右侧按钮样式 */
|
||||||
|
.public-navbar__right-btn {
|
||||||
|
font-family: PingFang SC, PingFang SC;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #ffffff;
|
||||||
|
font-style: normal;
|
||||||
|
text-transform: none;
|
||||||
|
background: linear-gradient(0deg, #00d993 0%, #00d9c5 100%);
|
||||||
|
padding: 12rpx 36rpx;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
}
|
||||||
|
|||||||
25
utils/dateUtils.js
Normal file
25
utils/dateUtils.js
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
/** 日期格式化 YYYY-MM-DD */
|
||||||
|
export const formatDate = date => {
|
||||||
|
const d = new Date(date)
|
||||||
|
const year = d.getFullYear()
|
||||||
|
const month = String(d.getMonth() + 1).padStart(2, '0') // 月份从0开始
|
||||||
|
const day = String(d.getDate()).padStart(2, '0')
|
||||||
|
return `${year}-${month}-${day}`
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 日期格式化:月.日 */
|
||||||
|
export const formatMonthDay = date => {
|
||||||
|
// 统一处理为 Date 对象
|
||||||
|
const d = new Date(date)
|
||||||
|
|
||||||
|
// 检查是否是有效日期
|
||||||
|
if (isNaN(d.getTime())) {
|
||||||
|
console.error('Invalid date:', date)
|
||||||
|
return '--.--'
|
||||||
|
}
|
||||||
|
|
||||||
|
const month = String(d.getMonth() + 1).padStart(2, '0') // getMonth() 是 0-11
|
||||||
|
const day = String(d.getDate()).padStart(2, '0')
|
||||||
|
|
||||||
|
return `${month}.${day}`
|
||||||
|
}
|
||||||
@@ -17,7 +17,7 @@ export const removeToken = () => {
|
|||||||
|
|
||||||
/** 保存用户信息 */
|
/** 保存用户信息 */
|
||||||
export const setUserInfoData = v => {
|
export const setUserInfoData = v => {
|
||||||
return uni.setStorageSync(STORAGE_KEYS.USER, JSON.stringify(v))
|
return uni.setStorageSync(STORAGE_KEYS.USER, JSON.stringify(v))
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 获取用户信息 */
|
/** 获取用户信息 */
|
||||||
@@ -29,3 +29,21 @@ export const getUserInfoData = () => {
|
|||||||
export const removeUserInfoData = () => {
|
export const removeUserInfoData = () => {
|
||||||
return uni.removeStorageSync(STORAGE_KEYS.USER)
|
return uni.removeStorageSync(STORAGE_KEYS.USER)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 保存腾讯 IM */
|
||||||
|
export const setSig = v => {
|
||||||
|
return uni.setStorageSync(
|
||||||
|
STORAGE_KEYS.TENCENT_USER_SIG,
|
||||||
|
JSON.stringify(v)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获取腾讯 IM */
|
||||||
|
export const getSig = () => {
|
||||||
|
return uni.getStorageSync(STORAGE_KEYS.TENCENT_USER_SIG) || ''
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除腾讯 IM */
|
||||||
|
export const removeSig = () => {
|
||||||
|
return uni.removeStorageSync(STORAGE_KEYS.TENCENT_USER_SIG)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user