mirror of
https://gitee.com/niucloud-team/niucloud-admin.git
synced 2025-12-11 02:12:48 +00:00
更新web端
This commit is contained in:
parent
fa37c55a5d
commit
e2537e99b0
1
web/.gitignore
vendored
1
web/.gitignore
vendored
@ -1,5 +1,4 @@
|
||||
node_modules
|
||||
*.log*
|
||||
.nuxt
|
||||
.nitro
|
||||
.cache
|
||||
|
||||
@ -5,27 +5,27 @@ export function getMemberInfo() {
|
||||
/**
|
||||
* 会员信息修改
|
||||
*/
|
||||
export function updateMember(data : AnyObject) {
|
||||
export function modifyMember(data: AnyObject) {
|
||||
return request.put(`member/modify/${data.field}`, data, { showErrorMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取积分流水
|
||||
*/
|
||||
export function getPointList(data : AnyObject) {
|
||||
export function getPointList(data: AnyObject) {
|
||||
return request.get('member/account/point', data)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取余额流水
|
||||
*/
|
||||
export function getBalanceList(data : AnyObject) {
|
||||
export function getBalanceList(data: AnyObject) {
|
||||
return request.get('member/account/balance', data)
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录会员绑定手机号
|
||||
*/
|
||||
export function bindMobile(data : AnyObject) {
|
||||
export function bindMobile(data: AnyObject) {
|
||||
return request.put('member/mobile', data, { showErrorMessage: true })
|
||||
}
|
||||
@ -47,13 +47,6 @@ export function getWechatSkdConfig(data: AnyObject) {
|
||||
return request.get('wechat/jssdkconfig', data)
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传图片
|
||||
*/
|
||||
export function uploadImage(data: AnyObject) {
|
||||
return request.upload('file/image', data, { showErrorMessage: true })
|
||||
}
|
||||
|
||||
/**
|
||||
* 拉取图片
|
||||
*/
|
||||
|
||||
10
web/app.vue
10
web/app.vue
@ -18,6 +18,12 @@ import useMemberStore from '@/stores/member'
|
||||
// 引入全局样式
|
||||
import '@/assets/styles/index.scss'
|
||||
|
||||
if (process.client) {
|
||||
const match = location.href.match(/\/s(\d*)\//)
|
||||
const cookie = useCookie('siteId')
|
||||
match ? cookie.value = match[1] : cookie.value = null
|
||||
}
|
||||
|
||||
// 初始化设置语言
|
||||
const systemStore = useSystemStore()
|
||||
const locale = computed(() => (systemStore.lang === 'zh-cn' ? zhCn : en))
|
||||
@ -37,8 +43,10 @@ watch(route, (nval, oval) => {
|
||||
|
||||
// 设置页面title
|
||||
let path = route.path == '/' ? '/index' : route.path
|
||||
// 处理部署后不知道为什么url会自动拼接上 / 的问题
|
||||
if (path.slice(-1) == '/') path = path.slice(0, -1)
|
||||
path = !path.lastIndexOf('/') ? `${path}/index` : path
|
||||
const key = path.replace('/', '').replaceAll('/', '.')
|
||||
let key = path.replace('/', '').replaceAll('/', '.')
|
||||
|
||||
setTimeout(() => {
|
||||
useHead({
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 228 KiB After Width: | Height: | Size: 268 KiB |
@ -73,6 +73,7 @@ captcha.refresh()
|
||||
const sendSms = useSendSms()
|
||||
|
||||
const send = () => {
|
||||
formData.mobile = prop.mobile
|
||||
if (sendSms.canGetCode.value) {
|
||||
captchaDialog.value = true
|
||||
}
|
||||
@ -87,8 +88,10 @@ const confirm = async () => {
|
||||
if (sendRes) {
|
||||
value.value = sendRes
|
||||
captchaDialog.value = false
|
||||
loading.value = false
|
||||
} else if (sendRes === false) {
|
||||
captcha.refresh()
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@ -2,7 +2,9 @@ import useAppStore from '~/stores/app'
|
||||
|
||||
export function t(message: string) {
|
||||
const i18n = useNuxtApp().$getI18n()
|
||||
const path = useAppStore().route
|
||||
let path = useAppStore().route
|
||||
// 处理部署后不知道为什么url会自动拼接上 / 的问题
|
||||
if (path != '/' && path.slice(-1) == '/') path = path.slice(0, -1)
|
||||
const file = path == '/' ? 'index' : path.replace('/', '').replaceAll('/', '.')
|
||||
const key = `${file}.${message}`
|
||||
return i18n.global.t(key) != key ? i18n.global.t(key) : i18n.global.t(message)
|
||||
|
||||
3
web/lang/zh-cn/article.detail.json
Normal file
3
web/lang/zh-cn/article.detail.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"title": "文章"
|
||||
}
|
||||
3
web/lang/zh-cn/article.list.json
Normal file
3
web/lang/zh-cn/article.list.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"title": "文章"
|
||||
}
|
||||
13
web/lang/zh-cn/auth.login.json
Normal file
13
web/lang/zh-cn/auth.login.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"logining": "登录中",
|
||||
"usernamePlaceholder": "请输入账号",
|
||||
"passwordPlaceholder": "请输入密码",
|
||||
"resetpwd": "忘记密码",
|
||||
"noAccount": "还没有账号",
|
||||
"toRegister": "去注册",
|
||||
"and": "和",
|
||||
"agreeTips": "登录代表您同意",
|
||||
"usernameLogin": "密码登录",
|
||||
"mobileLogin": "验证码登录",
|
||||
"mobilePlaceholder": "请输入手机号"
|
||||
}
|
||||
@ -11,6 +11,10 @@
|
||||
"member": {
|
||||
"index": "欢迎页",
|
||||
"center": "个人中心"
|
||||
}
|
||||
},
|
||||
"article": {
|
||||
"list": "文章",
|
||||
"detail": "文章"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,13 +1,13 @@
|
||||
<template>
|
||||
<!-- main-container -->
|
||||
<!-- main-container -->
|
||||
<div class="flex h-full min-w-[1200px]">
|
||||
<div class="flex items-center ml-[20px]">
|
||||
<NuxtLink to="/">
|
||||
<div class="w-[132px] mr-[10px]"><img src="@/assets/images/index/logo.jpg" /></div>
|
||||
</NuxtLink>
|
||||
<div class="hidden text-[14px] text-[#A6B0C8] xl:block">|<span class="ml-[10px]">一款快速开发SAAS通用管理系统后台框架</span>
|
||||
</div>
|
||||
</div>
|
||||
<NuxtLink to="/">
|
||||
<div class="w-[132px] mr-[10px]"><img src="@/assets/images/index/logo.jpg" /></div>
|
||||
</NuxtLink>
|
||||
<div class="hidden text-[14px] text-[#A6B0C8] xl:block">|<span class="ml-[10px]">一款快速开发SAAS通用管理系统后台框架</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mx-auto flex-shrink">
|
||||
<el-menu :default-active="appStore.route" class="h-full" mode="horizontal" :ellipsis="false" :router="true">
|
||||
@ -15,11 +15,11 @@
|
||||
<span class="text-base mx-4">首页</span>
|
||||
<span></span>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="/community/answer" route="/">
|
||||
<el-menu-item index="/article/list" route="/article/list">
|
||||
<span class="text-base mx-4">文章</span>
|
||||
<span></span>
|
||||
</el-menu-item>
|
||||
<el-menu-item route="/">
|
||||
<el-menu-item route="/">
|
||||
<span class="text-base mx-4">社区</span>
|
||||
<span></span>
|
||||
</el-menu-item>
|
||||
@ -27,15 +27,13 @@
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-end mr-[20px] ml-auto whitespace-pre">
|
||||
<el-dropdown v-if="info">
|
||||
<div>
|
||||
<NuxtLink to="/member/center">
|
||||
<span class="cursor-pointer">{{info.nickname}}</span>
|
||||
</NuxtLink>
|
||||
<span class="mx-2">|</span>
|
||||
<span class="cursor-pointer" @click="logoutFn">退出</span>
|
||||
</div>
|
||||
</el-dropdown>
|
||||
<div v-if="info">
|
||||
<NuxtLink to="/member/center">
|
||||
<span class="cursor-pointer">{{ info.nickname }}</span>
|
||||
</NuxtLink>
|
||||
<span class="mx-2">|</span>
|
||||
<span class="cursor-pointer" @click="logoutFn">退出</span>
|
||||
</div>
|
||||
<NuxtLink to="/auth/login" v-else>
|
||||
<el-button type="primary" link>{{ t('login') }} / {{ t('register') }}</el-button>
|
||||
</NuxtLink>
|
||||
@ -50,7 +48,7 @@ import useAppStore from '@/stores/app'
|
||||
const memberStore = useMemberStore()
|
||||
const info = computed(() => memberStore.info)
|
||||
|
||||
const logoutFn = ()=>{
|
||||
const logoutFn = () => {
|
||||
memberStore.logout()
|
||||
navigateTo(`/auth/login`)
|
||||
}
|
||||
@ -62,23 +60,27 @@ const appStore = useAppStore()
|
||||
:deep(.el-menu--horizontal) {
|
||||
border-bottom: none;
|
||||
}
|
||||
.el-menu-item{
|
||||
|
||||
.el-menu-item {
|
||||
padding-left: 0;
|
||||
border: none !important;
|
||||
color: #000 !important;
|
||||
&.is-active{
|
||||
|
||||
&.is-active {
|
||||
border: none !important;
|
||||
color: #000 !important;
|
||||
span{
|
||||
&:first-of-type{
|
||||
|
||||
span {
|
||||
&:first-of-type {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
&:last-of-type{
|
||||
|
||||
&:last-of-type {
|
||||
position: absolute;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background-image: linear-gradient(to bottom right,#FFFFFF,var(--el-color-primary));
|
||||
background-image: linear-gradient(to bottom right, #FFFFFF, var(--el-color-primary));
|
||||
border-radius: 100px;
|
||||
bottom: 15px;
|
||||
right: 27px;
|
||||
@ -86,11 +88,13 @@ const appStore = useAppStore()
|
||||
}
|
||||
}
|
||||
}
|
||||
&:hover{
|
||||
|
||||
&:hover {
|
||||
background-color: transparent !important;
|
||||
color: var(--el-menu-hover-text-color) !important;
|
||||
}
|
||||
&:focus{
|
||||
|
||||
&:focus {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
}
|
||||
|
||||
43336
web/package-lock.json
generated
43336
web/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,27 +1,27 @@
|
||||
{
|
||||
|
||||
"name": "web",
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"build": "nuxt build --mode product",
|
||||
"dev": "nuxt dev --mode dev",
|
||||
"generate": "nuxt generate --mode product",
|
||||
"preview": "nuxt preview --mode product",
|
||||
"postinstall": "nuxt prepare --mode product"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@element-plus/nuxt": "^1.0.4",
|
||||
"nuxt": "^3.3.2",
|
||||
"nuxt-windicss": "^2.6.0",
|
||||
"sass": "^1.60.0",
|
||||
"vue-i18n": "^9.2.2",
|
||||
"@types/qrcode": "^1.5.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vueuse/core": "^9.13.0",
|
||||
"element-plus": "^2.3.2",
|
||||
"pinia": "^2.0.33",
|
||||
"qrcode": "^1.5.1"
|
||||
}
|
||||
}
|
||||
"name": "web",
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"build": "nuxt build --mode product",
|
||||
"dev": "nuxt dev --mode dev",
|
||||
"generate": "nuxt generate --mode product",
|
||||
"preview": "nuxt preview --mode product",
|
||||
"postinstall": "nuxt prepare --mode product"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@element-plus/nuxt": "^1.0.4",
|
||||
"@types/qrcode": "^1.5.0",
|
||||
"nuxt": "^3.4.1",
|
||||
"nuxt-windicss": "^2.6.0",
|
||||
"sass": "^1.60.0",
|
||||
"vue-i18n": "^9.2.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vueuse/core": "^9.13.0",
|
||||
"element-plus": "^2.3.2",
|
||||
"pinia": "^2.0.33",
|
||||
"qrcode": "^1.5.1",
|
||||
"sass": "^1.60.0"
|
||||
}
|
||||
}
|
||||
80
web/pages/article/detail.vue
Normal file
80
web/pages/article/detail.vue
Normal file
@ -0,0 +1,80 @@
|
||||
<template>
|
||||
<div class="w-full min-h-[100%] main-container pt-5">
|
||||
<div class="mt-[20px] mb-[50px]" v-if="articleDeatail">
|
||||
<el-breadcrumb :separator-icon="ArrowRight">
|
||||
<el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
|
||||
<el-breadcrumb-item :to="{ path: '/article/list' }">文章</el-breadcrumb-item>
|
||||
<el-breadcrumb-item >{{ articleDeatail.category_name }}</el-breadcrumb-item>
|
||||
</el-breadcrumb>
|
||||
<div >
|
||||
<p class="py-[20px] text-center text-[24px]">{{ articleDeatail.title }}</p>
|
||||
<div class="flex justify-center">
|
||||
<!-- <div class="mr-3 flex items-center text-gray-500 text-sm text-[#999]"><el-icon><View /></el-icon> <span class="ml-1">浏览量:158</span></div> -->
|
||||
<div class="mr-3 flex items-center text-gray-500 text-sm text-[#999]"><el-icon><Clock /></el-icon><span class="ml-1">时间:{{ articleDeatail.create_time }}</span></div>
|
||||
</div>
|
||||
<div class="mt-[50px]" v-html="articleDeatail.content"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, computed } from 'vue'
|
||||
import { getArticleDetail } from '@/api/article'
|
||||
import { ArrowRight } from '@element-plus/icons-vue'
|
||||
import { nMounted } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
|
||||
const Route = useRoute(); //获取到值
|
||||
const articleDeatail = ref();
|
||||
onMounted(() => {
|
||||
obtainArricleInfo(Route.query.id)
|
||||
});
|
||||
|
||||
const obtainArricleInfo = (id) => {
|
||||
getArticleDetail(id).then(res => {
|
||||
console.log(res)
|
||||
articleDeatail.value = res.data;
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.index-carousel {
|
||||
background-image: url('@/assets/images/index_carousel.png');
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.article-wrap{
|
||||
span{
|
||||
line-height: 1;
|
||||
box-shadow: 0 0 5px var(--el-color-primary-light-7);
|
||||
&.active{
|
||||
background-image: linear-gradient(to right,var(--el-color-primary-light-5), var(--el-color-primary));
|
||||
}
|
||||
&:hover{
|
||||
background-image: linear-gradient(to right,var(--el-color-primary-light-5), var(--el-color-primary));
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tow-line-overflow{
|
||||
overflow: hidden;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
.text-color{
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
|
||||
// .demo-tabs .el-ta
|
||||
.custom-tabs-label span{
|
||||
font-size: 20px;
|
||||
padding: 0px 10px;
|
||||
}
|
||||
</style>
|
||||
172
web/pages/article/list.vue
Normal file
172
web/pages/article/list.vue
Normal file
@ -0,0 +1,172 @@
|
||||
<template>
|
||||
<div class="w-full main-container pt-5">
|
||||
<el-carousel height="350px" indicator-position="none" arrow="never">
|
||||
<el-carousel-item>
|
||||
<div class="h-full index-carousel"></div>
|
||||
</el-carousel-item>
|
||||
</el-carousel>
|
||||
<div class="mt-[20px] mb-[50px]">
|
||||
<div>
|
||||
<div class="w-full">
|
||||
<el-breadcrumb :separator-icon="ArrowRight">
|
||||
<el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
|
||||
<el-breadcrumb-item :to="{ path: '/article/list' }">文章</el-breadcrumb-item>
|
||||
<el-breadcrumb-item v-if="selectedCategoryName">{{ selectedCategoryName }}</el-breadcrumb-item>
|
||||
</el-breadcrumb>
|
||||
<div class="flex mt-[20px] items-start">
|
||||
<div class="w-[50px]">类目:</div>
|
||||
<el-row>
|
||||
<el-button class="mb-[10px]" @click="selectedCategory(categoryItem)" v-for="(categoryItem, categoryIndex) in activeCategotyLsit" :key="categoryIndex">{{ categoryItem.name }}</el-button>
|
||||
</el-row>
|
||||
</div>
|
||||
<div class="article-list mb-[20px] cursor-pointer" v-for="(activeItem, activeIndex) in articleTableData.data" :key="activeIndex" @click="toLink(activeItem.id)">
|
||||
<div class="flex justify-between relative py-[20px] border-b-1 border-gray-300 border-solid">
|
||||
<div class="w-[150px] h-[150px] flex items-center">
|
||||
<img :src="img(activeItem.image)"/>
|
||||
</div>
|
||||
<div class="w-[1030px]">
|
||||
<p class="text-xl font-bold">{{ activeItem.title }}</p>
|
||||
<span class="overflow-ellipsis mt-2 mb-2 tow-line-overflow text-gray-500">{{ activeItem.intro }}</span>
|
||||
</div>
|
||||
<!-- <div class="activeBo flex items-right mt-2 justify-end absolute">
|
||||
<span class="mr-5 text-sm text-gray-500">{{ activeItem.create_time }}</span>
|
||||
<div class="mr-3 flex items-center text-gray-500 text-sm"><el-icon><View /></el-icon> <span class="ml-1">158</span></div>
|
||||
<div class="mr-3 flex items-center text-gray-500 text-sm"><el-icon><Pointer /></el-icon> <span class="ml-1">22</span></div>
|
||||
<div class="mr-3 flex items-center text-gray-500 text-sm"><el-icon><Star /></el-icon> <span class="ml-1">55</span></div>
|
||||
<div class="flex items-center text-gray-500 text-sm"><el-icon><ChatDotRound /></el-icon> <span class="ml-1">655</span></div>
|
||||
</div> -->
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<el-pagination
|
||||
class="justify-center"
|
||||
@current-change="handleCurrentChange"
|
||||
@size-change="handleSizeChange"
|
||||
:page-size="articleTableData.limit"
|
||||
background
|
||||
layout="prev, pager, next"
|
||||
:total="articleTableData.total"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, computed } from 'vue'
|
||||
import { bind } from '@/api/auth'
|
||||
import { bindMobile } from '@/api/member'
|
||||
import useMemberStore from '@/stores/member'
|
||||
import { getArticleCategory,getArticleList } from '@/api/article'
|
||||
import { FormInstance } from 'element-plus'
|
||||
import { ArrowRight } from '@element-plus/icons-vue'
|
||||
import type { TabsPaneContext } from 'element-plus'
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
const router = useRouter();
|
||||
const activeCategotyLsit = ref([])
|
||||
const selectedCategoryName = ref()
|
||||
const articleTableData = reactive({
|
||||
page: 1,
|
||||
limit: 10,
|
||||
total: 0,
|
||||
loading: true,
|
||||
data: [],
|
||||
searchParam: {
|
||||
title: '',
|
||||
category_id:''
|
||||
}
|
||||
})
|
||||
|
||||
const handleClick = (tab: TabsPaneContext, event: Event) => {
|
||||
console.log(tab, event)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文章列表
|
||||
*/
|
||||
const loadArticleList = (page: number = 1) => {
|
||||
articleTableData.loading = true
|
||||
articleTableData.page = page
|
||||
|
||||
getArticleList({
|
||||
page: articleTableData.page,
|
||||
limit: articleTableData.limit,
|
||||
...articleTableData.searchParam
|
||||
}).then(res => {
|
||||
articleTableData.loading = false
|
||||
articleTableData.data = res.data.data
|
||||
articleTableData.total = res.data.total
|
||||
}).catch(() => {
|
||||
articleTableData.loading = false
|
||||
})
|
||||
}
|
||||
loadArticleList()
|
||||
|
||||
const checkArticleCategory = () => {
|
||||
getArticleCategory().then(res => {
|
||||
activeCategotyLsit.value = res.data.data;
|
||||
})
|
||||
}
|
||||
checkArticleCategory()
|
||||
|
||||
const selectedCategory = (item) => {
|
||||
articleTableData.searchParam.category_id = item.category_id;
|
||||
selectedCategoryName.value = item.name
|
||||
}
|
||||
|
||||
const handleSizeChange = (val: number) => {
|
||||
loadArticleList(val)
|
||||
}
|
||||
const handleCurrentChange = (val: number) => {
|
||||
loadArticleList(val)
|
||||
}
|
||||
const toLink = (id) => {
|
||||
router.push(`/article/detail?id=${id}`)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.index-carousel {
|
||||
background-image: url('@/assets/images/index_carousel.png');
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.article-wrap{
|
||||
span{
|
||||
line-height: 1;
|
||||
box-shadow: 0 0 5px var(--el-color-primary-light-7);
|
||||
&.active{
|
||||
background-image: linear-gradient(to right,var(--el-color-primary-light-5), var(--el-color-primary));
|
||||
}
|
||||
&:hover{
|
||||
background-image: linear-gradient(to right,var(--el-color-primary-light-5), var(--el-color-primary));
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tow-line-overflow{
|
||||
overflow: hidden;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
.text-color{
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
|
||||
// .demo-tabs .el-ta
|
||||
.custom-tabs-label span{
|
||||
font-size: 20px;
|
||||
padding: 0px 10px;
|
||||
}
|
||||
.activeBo {
|
||||
bottom : 20px;
|
||||
right : 0px
|
||||
}
|
||||
</style>
|
||||
@ -194,9 +194,6 @@ const formRules = computed(() => {
|
||||
}
|
||||
}
|
||||
})
|
||||
console.log(
|
||||
"memberStore.setToken", memberStore
|
||||
)
|
||||
|
||||
const handleLogin = async () => {
|
||||
await formRef.value?.validate(async (valid, fields) => {
|
||||
|
||||
@ -5,28 +5,26 @@
|
||||
<el-card class="box-card flex-1 ml-4" v-loading="loading" shadow="never">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>{{t('personageInfo')}}</span>
|
||||
<span>{{ t('personageInfo') }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<div class="pr-15" v-if="info">
|
||||
<div class="pr-15" v-if="info">
|
||||
<el-form :model="info" class="form-wrap" label-width="120px">
|
||||
<el-form-item :label="t('memberHeadimg')">
|
||||
<div class="w-full flex justify-between content-center items-center">
|
||||
<img v-if="!info.headimg" class="w-[80px] h-[80px]" src="@/assets/images/default_headimg.png" alt="">
|
||||
<img v-if="!info.headimg" class="w-[80px] h-[80px]"
|
||||
src="@/assets/images/default_headimg.png" alt="">
|
||||
<img v-else :src="img(info.headimg)" class="w-[80px] h-[80px]" alt="">
|
||||
<el-upload
|
||||
class="avatar-uploader"
|
||||
:show-file-list="false"
|
||||
v-bind="upload"
|
||||
>
|
||||
<span class="cursor-pointer text-color">{{t('edit')}}</span>
|
||||
<el-upload class="avatar-uploader" :show-file-list="false" v-bind="upload">
|
||||
<span class="cursor-pointer text-color">{{ t('edit') }}</span>
|
||||
</el-upload>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('nickname')">
|
||||
<div class="w-full flex justify-between content-center">
|
||||
<span>{{updateNickname.value}}</span>
|
||||
<span class="cursor-pointer text-color" @click="updateNickname.modal = true">{{t('edit')}}</span>
|
||||
<span>{{ updateNickname.value }}</span>
|
||||
<span class="cursor-pointer text-color" @click="updateNickname.modal = true">{{ t('edit')
|
||||
}}</span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
@ -41,8 +39,8 @@
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="updateNickname.modal = false">{{t('cancel')}}</el-button>
|
||||
<el-button type="primary" @click="updateNicknameConfirm">{{t('confirm')}}</el-button>
|
||||
<el-button @click="updateNickname.modal = false">{{ t('cancel') }}</el-button>
|
||||
<el-button type="primary" @click="updateNicknameConfirm">{{ t('confirm') }}</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
@ -54,9 +52,7 @@
|
||||
import { reactive, ref, computed } from 'vue'
|
||||
import useMemberStore from '@/stores/member'
|
||||
import useAppStore from '@/stores/app'
|
||||
import { updateMember } from '@/api/member'
|
||||
import { uploadImage } from '@/api/system'
|
||||
import type { UploadProps } from 'element-plus'
|
||||
import { modifyMember } from '@/api/member'
|
||||
import { ElMessage, UploadFile, UploadFiles } from 'element-plus'
|
||||
import request from '@/utils/request'
|
||||
import storage from '@/utils/storage'
|
||||
@ -72,9 +68,9 @@ const updateNickname = reactive({
|
||||
value: ''
|
||||
})
|
||||
|
||||
const info = computed(() =>{
|
||||
const info = computed(() => {
|
||||
updateNickname.value = memberStore.info?.nickname;
|
||||
if(memberStore.info) loading.value = false;
|
||||
if (memberStore.info) loading.value = false;
|
||||
return memberStore.info;
|
||||
})
|
||||
const appStore = useAppStore()
|
||||
@ -89,13 +85,14 @@ const upload = computed(() => {
|
||||
limit: 1,
|
||||
headers,
|
||||
onSuccess: (response: any, uploadFile: UploadFile, uploadFiles: UploadFiles) => {
|
||||
console.log('uploadFile',);
|
||||
let img = uploadFile?.response?.data?.url;
|
||||
if (response.code == 200) {
|
||||
updateMember({
|
||||
modifyMember({
|
||||
field: 'headimg',
|
||||
value: img
|
||||
}).then(() => {
|
||||
info.headimg = img
|
||||
memberStore.info.headimg = img
|
||||
})
|
||||
} else {
|
||||
uploadFile.status = 'fail'
|
||||
@ -107,22 +104,23 @@ const upload = computed(() => {
|
||||
|
||||
// 修改会员名称
|
||||
const updateNicknameConfirm = () => {
|
||||
if (!updateNickname.value) { ElMessage.error('会员昵称不能为空'); return }
|
||||
if (!updateNickname.value) { ElMessage.error('会员昵称不能为空'); return }
|
||||
|
||||
updateMember({
|
||||
field: 'nickname',
|
||||
value: updateNickname.value
|
||||
}).then(res => {
|
||||
updateNickname.modal = false
|
||||
})
|
||||
modifyMember({
|
||||
field: 'nickname',
|
||||
value: updateNickname.value
|
||||
}).then(res => {
|
||||
updateNickname.modal = false
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.box-card{
|
||||
.box-card {
|
||||
border: none !important;
|
||||
}
|
||||
::v-deep .form-wrap .el-form-item{
|
||||
|
||||
::v-deep .form-wrap .el-form-item {
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
@ -14,14 +14,16 @@ interface FetchOptions {
|
||||
onRequest?: (data: any) => void,
|
||||
onResponse?: (data: any) => void,
|
||||
onResponseError?: (data: any) => void,
|
||||
showMessageConfig?: ShowMessageConfig
|
||||
showMessageConfig?: ShowMessageConfig,
|
||||
watch: boolean
|
||||
}
|
||||
|
||||
class Http {
|
||||
private options: FetchOptions = {
|
||||
baseURL: '',
|
||||
method: '',
|
||||
headers: {}
|
||||
headers: {},
|
||||
watch: false
|
||||
}
|
||||
|
||||
public constructor() {
|
||||
@ -32,7 +34,7 @@ class Http {
|
||||
const runtimeConfig = useRuntimeConfig()
|
||||
|
||||
this.options.baseURL = runtimeConfig.public.VITE_APP_BASE_URL || `${location.origin}/api/`
|
||||
this.options.headers[runtimeConfig.public.VITE_REQUEST_HEADER_SITEID_KEY] = runtimeConfig.public.VITE_SITE_ID
|
||||
this.options.headers[runtimeConfig.public.VITE_REQUEST_HEADER_SITEID_KEY] = useCookie('siteId').value || runtimeConfig.public.VITE_SITE_ID
|
||||
this.options.headers[runtimeConfig.public.VITE_REQUEST_HEADER_CHANNEL_KEY] = 'pc'
|
||||
if (getToken()) this.options.headers[runtimeConfig.public.VITE_REQUEST_HEADER_TOKEN_KEY] = getToken()
|
||||
|
||||
@ -46,7 +48,7 @@ class Http {
|
||||
this.options.onResponse = ({ response, options }) => {
|
||||
const { _data: data } = response
|
||||
|
||||
if (data.code == 200) {
|
||||
if (data.code == 1) {
|
||||
if (options.showMessageConfig.showSuccessMessage) ElMessage({ message: data.msg, type: 'success' })
|
||||
} else {
|
||||
if (options.showMessageConfig.showErrorMessage) ElMessage({ message: data.msg, type: 'error' })
|
||||
@ -89,7 +91,7 @@ class Http {
|
||||
const { data: { value }, error } = response
|
||||
|
||||
if (value) {
|
||||
if (value.code == 200) {
|
||||
if (value.code == 1) {
|
||||
resolve(value)
|
||||
} else {
|
||||
reject(value)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user