Compare commits
55 Commits
master
...
9ac4fa6e5d
| Author | SHA1 | Date | |
|---|---|---|---|
| 9ac4fa6e5d | |||
| 0bc2bdb9bb | |||
| 4db377161c | |||
| a60b28aa22 | |||
| fec929bf06 | |||
| b0b50ed960 | |||
| 78939951d9 | |||
| 02bc9c00b0 | |||
| 823e3d9f99 | |||
| a1735a5e94 | |||
| 7839fa565e | |||
| 9054376279 | |||
| 3ae61916ca | |||
| 1a86b4cb7e | |||
| 7a33f67aed | |||
| 9f5942546d | |||
| 7c82166781 | |||
| cd58054cfa | |||
| 615ac78156 | |||
| 18ebc08645 | |||
| d006b3e5af | |||
| b7d6b37e87 | |||
| 24d2b82221 | |||
| d24ece1724 | |||
| 0e8fb5c838 | |||
| c8d47fd959 | |||
| bdad6d4406 | |||
| 3d8ae8816d | |||
| c01f51a488 | |||
| 5073c33e61 | |||
| 4dcd59f1d4 | |||
| 1a27904f23 | |||
| 85c49890d1 | |||
| 272c380c6e | |||
| 5092efdaeb | |||
| df3873c6eb | |||
| addef04ff0 | |||
| b1d2378cec | |||
| 7f2edb91e4 | |||
| 694a032d0a | |||
| a96dbb67fe | |||
| d26970fb3d | |||
| 9222d47b37 | |||
| acb7ccaf46 | |||
| e1c1fefa20 | |||
| 21780580b8 | |||
| e0507f3bd1 | |||
| fa971cff5b | |||
| a900399dd0 | |||
| 8761a91f13 | |||
| f4312f5f0c | |||
| 2c2e6f600b | |||
| cb56f9b7ba | |||
| be82375202 | |||
| a0f1ec758e |
@ -7,6 +7,8 @@ import type {
|
||||
ProjectDrawStatisticAppRespVO,
|
||||
ProjectTrendingScoreUserInfoVO,
|
||||
PageResultIndexSettingRespVO,
|
||||
TdkSettingsRespVO,
|
||||
TdkSettingsDO,
|
||||
} from './type'
|
||||
|
||||
/**
|
||||
@ -88,3 +90,24 @@ export const tab2 = () => {
|
||||
export const getDictTree = (params: { type: number, id: number}) => {
|
||||
return useDollarFetchRequest.get<IResponse<ProjectDictNodeVO[]>>('/prod-api/app-api/business/app/dict/path-by-id', { query: params })
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得网站 TDK设置
|
||||
*/
|
||||
export const getTDK = () => {
|
||||
return useFetchRequest.get<IResponse<TdkSettingsRespVO>>('/prod-api/app-api/business/tdk-settings/get-index', {})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得网站 TDK栏目列表
|
||||
*/
|
||||
export const getTDKList = () => {
|
||||
return useFetchRequest.get<IResponse<TdkSettingsDO[]>>('/prod-api/app-api/business/tdk-settings/list-menu', {})
|
||||
}
|
||||
|
||||
/**
|
||||
* 通知列表
|
||||
*/
|
||||
export const getNoticeList = () => {
|
||||
return useDollarFetchRequest.get<IResponse<any>>('/prod-api/app-api/system/index-setting/notice-list', {})
|
||||
}
|
||||
@ -105,3 +105,25 @@ export interface PageResultIndexSettingRespVO {
|
||||
status: number
|
||||
createTime: string
|
||||
}
|
||||
|
||||
export interface TdkSettingsRespVO {
|
||||
title: string
|
||||
describeText: string
|
||||
keyword: string
|
||||
}
|
||||
|
||||
export interface TdkSettingsDO {
|
||||
createTime?: string
|
||||
updateTime?: string
|
||||
creator?: string
|
||||
updater?: string
|
||||
deleted?: boolean
|
||||
id?: number
|
||||
title?: string
|
||||
icon?: string
|
||||
type?: number
|
||||
path: string
|
||||
describeText?: string
|
||||
keyword?: string
|
||||
remark: string
|
||||
}
|
||||
|
||||
@ -43,7 +43,7 @@ export const updateUserExtend = (params: UserExtendSaveReqVO) => {
|
||||
* @returns
|
||||
*/
|
||||
export const getUserAuthInfo = () => {
|
||||
return useFetchRequest.get<IResponse<UserAuthInfoRespVO>>('/prod-api/app-api/member/user-auth-info/get', {})
|
||||
return useDollarFetchRequest.get<IResponse<UserAuthInfoRespVO>>('/prod-api/app-api/member/user-auth-info/get', {})
|
||||
}
|
||||
/**
|
||||
* 创建用户信息
|
||||
|
||||
@ -16,7 +16,7 @@ export const create = (params: TcreateReq) => {
|
||||
* @returns
|
||||
*/
|
||||
export const parent = (params: { type: string | number; parentId: number | string }) => {
|
||||
return useFetchRequest.get<IResponse<parentRes[]>>('/prod-api/app-api/business/app/dict/parent', { query: params })
|
||||
return useDollarFetchRequest.get<IResponse<parentRes[]>>('/prod-api/app-api/business/app/dict/parent', { query: params })
|
||||
}
|
||||
/**
|
||||
* 获取具有上下级的字典信息
|
||||
@ -32,7 +32,7 @@ export const parentV2 = (params: { type: string | number; parentId: number | str
|
||||
* @returns
|
||||
*/
|
||||
export const indexTabs = () => {
|
||||
return useFetchRequest.get<IResponse<parentRes[]>>('/prod-api/app-api/business/project/index/index-tab3')
|
||||
return useDollarFetchRequest.get<IResponse<parentRes[]>>('/prod-api/app-api/business/project/index/index-tab3')
|
||||
}
|
||||
/**
|
||||
* 模糊查询获取标签内容
|
||||
@ -73,3 +73,10 @@ export const recommendTop = (params: recommendTopReq) => {
|
||||
export const homeLabel = () => {
|
||||
return useFetchRequest.get<IResponse<ProjectDictNodeVO[]>>('/prod-api/app-api/business/app/dict/index-tab')
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取客服微信
|
||||
*/
|
||||
export const getWechat = () => {
|
||||
return useDollarFetchRequest.get<IResponse<string>>('/prod-api/app-api/system/index-setting/kefu-wechat')
|
||||
}
|
||||
|
||||
@ -10,9 +10,9 @@ export interface FileItem {
|
||||
|
||||
// 定义整个 JSON 对象的类型
|
||||
export interface TcreateReq {
|
||||
activeName: string
|
||||
activeName: string | number
|
||||
id: number | string
|
||||
type: any[]
|
||||
type: number
|
||||
isDomestic: number | string
|
||||
province: string // 省份编码
|
||||
city: string // 城市编码
|
||||
|
||||
BIN
assets/images/activity1.png
Normal file
|
After Width: | Height: | Size: 92 KiB |
BIN
assets/images/activity2.png
Normal file
|
After Width: | Height: | Size: 109 KiB |
BIN
assets/images/avater2 copy.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
assets/images/banner copy.png
Normal file
|
After Width: | Height: | Size: 434 KiB |
BIN
assets/images/bg-yy.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
assets/images/crown.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
assets/images/faxian.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
assets/images/home-l (1).png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
assets/images/home-l (2).png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
assets/images/home-l (3).png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
assets/images/info copy.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
assets/images/info.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
assets/images/my_attention.png
Normal file
|
After Width: | Height: | Size: 5.7 KiB |
BIN
assets/images/my_collect.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
BIN
assets/images/my_download.png
Normal file
|
After Width: | Height: | Size: 7.2 KiB |
BIN
assets/images/my_release.png
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
BIN
assets/images/pingdao.png
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
assets/images/shouye.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
assets/images/talent-detail-bg.png
Normal file
|
After Width: | Height: | Size: 324 KiB |
BIN
assets/images/technicalCertificates.png
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
assets/images/tuzhi (1).png
Normal file
|
After Width: | Height: | Size: 7.7 KiB |
BIN
assets/images/tuzhi (2).png
Normal file
|
After Width: | Height: | Size: 8.4 KiB |
BIN
assets/images/tuzhi (3).png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
assets/images/tuzhi (4).png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
assets/images/tuzhi (5).png
Normal file
|
After Width: | Height: | Size: 8.5 KiB |
BIN
assets/images/tuzhi (6).png
Normal file
|
After Width: | Height: | Size: 9.3 KiB |
BIN
assets/images/wode.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
assets/images/x.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="relative mt-[34px] w-[100%]">
|
||||
<KlTabBar v-model="query.source" :data="tabBar" />
|
||||
<div class="absolute right-[0px] top-[10px] text-[16px] text-[#999999] font-normal"
|
||||
<div class="absolute right-[0px] top-[0px] text-[16px] text-[#999999] font-normal"
|
||||
>共<span class="color-[#1A65FF]">{{ result?.total }}</span
|
||||
>个筛选结果</div
|
||||
>
|
||||
@ -17,7 +17,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import KlTabBar from '~/components/kl-tab-bar/index.vue'
|
||||
import KlTabBar from '~/components/kl-tab-bar/v3/index.vue'
|
||||
import CardPicture from '~/components/kl-card-picture/index.vue'
|
||||
import { ref } from 'vue'
|
||||
import type { pageRes, pageReq } from '~/api/upnew/types'
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<div class="relative mt-[34px] w-[100%]">
|
||||
<KlTabBar v-model="tabIndex" :data="tabBar" />
|
||||
<KlTabBar v-model="query.source" :data="tabBar" />
|
||||
<KlWallpaperCategory v-model="query" v-model:level="level" :type="1" />
|
||||
<div class="absolute right-[0px] top-[10px] text-[16px] text-[#999999] font-normal"
|
||||
<div class="absolute right-[0px] top-[0px] text-[16px] text-[#999999] font-normal"
|
||||
>共<span class="color-[#1A65FF]">{{ result?.total }}</span
|
||||
>个筛选结果</div
|
||||
>
|
||||
@ -18,7 +18,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import KlTabBar from '~/components/kl-tab-bar/index.vue'
|
||||
import KlTabBar from '~/components/kl-tab-bar/v3/index.vue'
|
||||
import CardPicture from '~/components/kl-card-picture/index.vue'
|
||||
import KlWallpaperCategory from '~/components/kl-wallpaper-category/index.vue'
|
||||
import { ref } from 'vue'
|
||||
|
||||
@ -1,16 +1,16 @@
|
||||
<template>
|
||||
<div class="mt-30px bg-[#14213d] px-[40px] pb-[20px] pt-[50px] text-white lg:px-[80px] sm:px-[60px]">
|
||||
<div class="mt-[30px] bg-[#14213d] px-[40px] pb-[20px] pt-[50px] text-white lg:px-[80px] sm:px-[60px]">
|
||||
<!-- 主内容区 -->
|
||||
<div class="mb-[40px] flex flex-col items-start justify-between gap-[30px] lg:flex-row">
|
||||
<!-- 左侧 Logo -->
|
||||
<div class="mx-auto w-[200px] shrink-0 lg:mx0">
|
||||
<div class="mx-auto w-[200px] shrink-0 lg:mx-0">
|
||||
<img src="~/assets/images/logo5.png" class="h-auto w-full" />
|
||||
</div>
|
||||
|
||||
<!-- 中间部分 -->
|
||||
<div class="grid grid-cols-2 mx-[80px] flex-1 gap-[10px] lg:grid-cols-3">
|
||||
<div v-for="(col, index) in bannerList?.slice(0, 3)" :key="index">
|
||||
<h3 v-if="handle(col)" class="ma-0px mb-[20px] pa-0px text-[16px]">{{ handle(col) }}</h3>
|
||||
<h3 v-if="handle(col)" class="ma-[0px] mb-[20px] pa-[0px] text-[16px]">{{ handle(col) }}</h3>
|
||||
<ul>
|
||||
<li
|
||||
v-for="(item, i) in handle2(col)"
|
||||
@ -44,6 +44,8 @@
|
||||
<div class="border-t border-white/20 pt-[20px] text-center text-[14px] text-white/70">
|
||||
Copyright 2007-2025 图夕夕网络科技(成都)有限公司
|
||||
<a href="http://beian.miit.gov.cn/" target="_blank" class="text-white/90 hover:text-blue-400!"> 蜀ICP备2025141494号-1</a>
|
||||
<img src="~/assets/images/x.png" class="w-[20px] h-[20px] relative top-[2px]" />
|
||||
<a href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=51010702043645" rel="noreferrer" target="_blank">川公网安备51010702043645号</a >
|
||||
</div>
|
||||
|
||||
<el-image-viewer v-if="showViewer" :url-list="previewImgList" :url-index="0" @close="showViewer = false"></el-image-viewer>
|
||||
|
||||
@ -8,13 +8,13 @@
|
||||
</div>
|
||||
<div class="item-center ml-[45px] w-[660px] flex justify-between">
|
||||
<nuxt-link
|
||||
v-for="(item, index) in menuItems"
|
||||
v-for="(item, index) in tdkList"
|
||||
:key="index"
|
||||
:to="item.path"
|
||||
class="parent-links relative rounded-lg px-3 py-2 text-[#1A65FF]"
|
||||
>
|
||||
{{ item.name }}
|
||||
<img v-if="item.path === '/communication/channel'" src="~/assets/images/hot.png" alt="火" class="absolute right-[-15px] top-[-2px]" />
|
||||
{{ item.remark }}
|
||||
<img v-if="item.path === '/channel'" src="~/assets/images/hot.png" alt="火" class="absolute right-[-12px] top-[0px]" />
|
||||
</nuxt-link>
|
||||
</div>
|
||||
</div>
|
||||
@ -31,19 +31,29 @@
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import useUserStore from '~/stores/user'
|
||||
import { getTDKList } from '~/api/home/index'
|
||||
const userStore = useUserStore()
|
||||
import { BellFilled } from '@element-plus/icons-vue'
|
||||
import { ref, computed } from 'vue'
|
||||
const menuItems = ref([
|
||||
{ name: '首页', path: '/' },
|
||||
{ name: '图纸', path: '/drawe' },
|
||||
{ name: '文本', path: '/text' },
|
||||
{ name: '模型', path: '/model' },
|
||||
{ name: '国外专区', path: '/foreign' },
|
||||
{ name: '工具箱', path: '/toolbox' },
|
||||
{ name: '交流频道', path: '/channel' },
|
||||
// { name: '牛人社区', path: '/community' },
|
||||
])
|
||||
// const menuItems = ref([
|
||||
// { name: '首页', path: '/' },
|
||||
// { name: '图纸', path: '/drawe' },
|
||||
// { name: '文本', path: '/text' },
|
||||
// { name: '模型', path: '/model' },
|
||||
// { name: '国外专区', path: '/foreign' },
|
||||
// { name: '工具箱', path: '/toolbox' },
|
||||
// { name: '交流频道', path: '/channel' },
|
||||
// // { name: '牛人社区', path: '/community' },
|
||||
// ])
|
||||
|
||||
const { data: tdkList } = await useAsyncData('get-tdk-list-home', async () => {
|
||||
const res = await getTDKList()
|
||||
// 添加首页
|
||||
if (!res.data.find((c) => c.remark === '首页')) {
|
||||
res.data.unshift({ remark: '首页', path: '/' })
|
||||
}
|
||||
return res.data
|
||||
})
|
||||
|
||||
// 是否登录
|
||||
const isLogin = computed(() => {
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<div class="relative ma-auto flex items-center py-[20px] w-[1500px]!">
|
||||
<img src="~/assets/images/logo5.png" alt="图夕夕" srcset="" class="h-[51px] w-[182px] cursor-pointer" @click="navigateTo('/')" />
|
||||
<div class="ml-[60px] flex items-center">
|
||||
<span v-for="item in navList" :key="item" class="nav" :class="props.active === item ? 'active' : ''" @click="handleClick(item)">{{ item }}</span>
|
||||
<span v-for="item in tdkList" :key="item.id" class="nav" :class="props.active === item.remark ? 'active' : ''" @click="handleClick(item.path)">{{ item.remark }}</span>
|
||||
</div>
|
||||
<div class="relative ml-[30px]">
|
||||
<el-input
|
||||
@ -38,11 +38,11 @@
|
||||
<div class="absolute right-[10px] flex items-center">
|
||||
<div class="h-[36px] w-[36px] border-rd-[50%] bg-[#F5F5F5] text-center line-height-[44px]">
|
||||
<img v-if="!isLogin" src="~/assets/images/user.png" alt="" srcset="" class="h-[19px] w-[17px] relative top-[0px] left-[0px]" />
|
||||
<img v-else :src="userStore.userInfoRes.avatar" alt="" srcset="" class="h-[19px] w-[17px] rd-[50%]" />
|
||||
<img v-else :src="userStore.userInfoRes.avatar" alt="" srcset="" class="h-full w-full rd-[50%]" />
|
||||
</div>
|
||||
<span v-if="!isLogin" class="ml-[14px] cursor-pointer text-[14px] text-[#1A65FF] font-normal" @click="handleLogin">立即登录</span>
|
||||
<el-dropdown v-else placement="top-start" @command="handleCommand">
|
||||
<span class="ml-[14px] cursor-pointer text-[14px] text-[#1A65FF] font-normal">{{ userStore.userInfoRes.nickname || '立即登录' }}</span>
|
||||
<span class="ml-[6px] cursor-pointer text-[14px] text-[#1A65FF] font-normal">{{ userStore.userInfoRes.nickname || '立即登录' }}</span>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item command="个人中心"
|
||||
@ -64,7 +64,7 @@
|
||||
import { ref, getCurrentInstance, computed, onMounted } from 'vue'
|
||||
import { Setting, SwitchButton } from '@element-plus/icons-vue'
|
||||
import { page } from '~/api/upnew/index'
|
||||
import { top } from '~/api/home/index'
|
||||
import { top, getTDKList } from '~/api/home/index'
|
||||
import type { ProjectDrawStatisticAppRespVO } from '~/api/home/type'
|
||||
import { Search } from '@element-plus/icons-vue'
|
||||
import refreshToken from '~/utils/RefreshToken'
|
||||
@ -92,7 +92,15 @@
|
||||
return !!userStore.token
|
||||
})
|
||||
|
||||
const navList = ref(['首页', '图纸', '文本', '模型', '国外专区', '工具箱', '交流频道'])
|
||||
const { data: tdkList } = await useAsyncData('get-tdk-list-nav', async () => {
|
||||
const res = await getTDKList()
|
||||
// 添加首页
|
||||
if (!res.data.find((c) => c.remark === '首页')) {
|
||||
res.data.unshift({ remark: '首页', path: '/' })
|
||||
}
|
||||
return res.data
|
||||
})
|
||||
// const navList = ref(['首页', '图纸', '文本', '模型', '国外专区', '工具箱', '交流频道'])
|
||||
|
||||
const loading = ref(false)
|
||||
const handleHot = async () => {
|
||||
@ -147,34 +155,7 @@
|
||||
}
|
||||
|
||||
const handleClick = (item: string) => {
|
||||
switch (item) {
|
||||
case '首页':
|
||||
navigateTo({ path: '/' }) // 修改为在新窗口打开
|
||||
break
|
||||
case '图纸':
|
||||
navigateTo('/drawe') // 修改为在新窗口打开
|
||||
break
|
||||
case '文本':
|
||||
navigateTo('/text') // 修改为在新窗口打开
|
||||
break
|
||||
case '模型':
|
||||
navigateTo('/model') // 修改为在新窗口打开
|
||||
break
|
||||
case '国外专区':
|
||||
navigateTo('/foreign') // 修改为在新窗口打开
|
||||
break
|
||||
case '牛人社区':
|
||||
navigateTo('/community') // 修改为在新窗口打开
|
||||
break
|
||||
case '交流频道':
|
||||
navigateTo('/channel') // 修改为在新窗口打开
|
||||
break
|
||||
case '工具箱':
|
||||
navigateTo('/toolbox') // 修改为在新窗口打开
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
navigateTo(item)
|
||||
}
|
||||
const handleLogin = () => {
|
||||
app?.$openLogin() // 调用全局方法
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
>
|
||||
<el-tab-pane v-for="(item, index) in data" :key="index" :label="item.label" :name="item.value">
|
||||
<template v-if="showNum" #label>
|
||||
<img v-if="item.value === tabActive && showIcon" src="~/assets/images/2.png" alt="" srcset="" class="mr-7px" />
|
||||
<img v-if="item.value === tabActive && showIcon" src="~/assets/images/2.png" alt="" srcset="" class="mr-[7px]" />
|
||||
<span>{{ item.label }}</span>
|
||||
<el-badge :value="item.num" class="item" :max="9999999999999" :hidden="!item.num" />
|
||||
</template>
|
||||
|
||||
47
components/kl-tab-bar/v3/index.vue
Normal file
@ -0,0 +1,47 @@
|
||||
<template>
|
||||
<div class="flex items-center gap-[50px] mb-[20px]">
|
||||
<el-link
|
||||
v-for="(item, index) in props.data"
|
||||
:key="index"
|
||||
class="text-[15px]!"
|
||||
:underline="modelValue === item.value ? 'always' : 'never'"
|
||||
:type="modelValue === item.value ? 'primary' : 'info'"
|
||||
@click="handleChange(item)"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-link>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { PropType } from 'vue'
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Array as PropType<{ num?: number; label: string; value: string | number; [key: string]: any }[]>,
|
||||
default: () => [],
|
||||
},
|
||||
})
|
||||
|
||||
const emits = defineEmits(['change'])
|
||||
|
||||
const modelValue = defineModel<any>('modelValue', {
|
||||
required: true,
|
||||
}) // 双向绑定的value
|
||||
|
||||
const handleChange = (value: { value: string | number; [key: string]: any }) => {
|
||||
modelValue.value = value.value
|
||||
emits('change', value)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:deep(.el-link.is-underline) {
|
||||
&::hover {
|
||||
color: #1a65ff !important; // 鼠标悬停时的颜色
|
||||
}
|
||||
&::after {
|
||||
bottom: -3px;
|
||||
border-bottom: 2px solid #1a65ff; // 去掉下划线
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -83,9 +83,16 @@
|
||||
return props.type === 1 ? '图纸' : props.type === 3 ? '模型' : '文本'
|
||||
})
|
||||
|
||||
/** 版本 */
|
||||
const { data: editionsList } = useAsyncData(`editionsList-${props.type}}`, async () => {
|
||||
const res = await parent({ type: 2, parentId: 0 })
|
||||
const all = [{ id: '-1', name: '全部' }]
|
||||
return [...all, ...res.data]
|
||||
})
|
||||
|
||||
// 获取面包屑
|
||||
const { data: breadList } = await useAsyncData(
|
||||
`breadList-${props.type}-${props.id}-${query.value.projectType}-${Date.now()}`,
|
||||
`breadList-${props.type}-${props.id}-${query.value.projectType}}`,
|
||||
async () => {
|
||||
const res = await getDictTree({ type: 1, id: query.value.projectType })
|
||||
const all = [
|
||||
@ -97,13 +104,8 @@
|
||||
]
|
||||
const arr = [...res.data, ...all]
|
||||
return arr.reverse()
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
}
|
||||
)
|
||||
|
||||
console.log('breadList', breadList);
|
||||
|
||||
// const projectTypeList = ref<any>([])
|
||||
/** 获取分类下拉框 */
|
||||
@ -133,35 +135,49 @@
|
||||
// }
|
||||
// getEditionsList()
|
||||
|
||||
/**获取分类下拉框 */
|
||||
const { data: projectTypeList } = await useAsyncData(
|
||||
`projectType-draw-${props.type}-${query.value.projectType}`,
|
||||
async () => {
|
||||
let parentId: any = '0'
|
||||
if (breadList?.value && breadList?.value.length > 1) {
|
||||
if (breadList.value.length > 2) {
|
||||
const length = breadList.value?.length
|
||||
parentId = breadList?.value[length - 2].id
|
||||
} else {
|
||||
const length = breadList.value?.length
|
||||
parentId = breadList?.value[length - 1].id
|
||||
}
|
||||
console.log('breadList.value.length----', breadList.value);
|
||||
|
||||
// 服务端渲染兼容方案:顺序执行异步操作
|
||||
// 1. 先获取面包屑数据(已在上面通过useAsyncData获取)
|
||||
|
||||
// 2. 顺序获取分类下拉框数据
|
||||
// 创建一个函数来获取分类数据,确保服务端渲染时能获取到数据
|
||||
const getProjectTypeList = async () => {
|
||||
let parentId: any = '0'
|
||||
|
||||
// 计算parentId的逻辑
|
||||
if (breadList?.value && breadList?.value.length > 1) {
|
||||
if (breadList.value.length > 2) {
|
||||
const length = breadList.value?.length
|
||||
parentId = breadList?.value[length - 2].id
|
||||
} else {
|
||||
const length = breadList.value?.length
|
||||
parentId = breadList?.value[length - 1].id
|
||||
}
|
||||
}
|
||||
|
||||
console.log('parentId', parentId);
|
||||
|
||||
|
||||
try {
|
||||
// 获取分类数据
|
||||
const res = await parent({ type: 1, parentId: parentId })
|
||||
const all = [{ id: parentId === '0' ? '-1' : parentId, name: '全部' }]
|
||||
return [...all, ...res.data]
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
} catch (error) {
|
||||
console.error('获取分类数据失败:', error)
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
// 使用useAsyncData获取分类列表,确保服务端渲染兼容性
|
||||
const { data: projectTypeList } = await useAsyncData(
|
||||
`projectType-draw-${props.type}-${query.value.projectType}}`,
|
||||
getProjectTypeList,
|
||||
{ server: true } // 确保在服务端执行
|
||||
)
|
||||
|
||||
/** 版本 */
|
||||
const { data: editionsList } = useAsyncData(`editionsList-${props.type}-${Date.now()}`, async () => {
|
||||
const res = await parent({ type: 2, parentId: 0 })
|
||||
const all = [{ id: '-1', name: '全部' }]
|
||||
return [...all, ...res.data]
|
||||
})
|
||||
|
||||
|
||||
const handleClick = (row: any) => {
|
||||
query.value.title = ''
|
||||
|
||||
181
components/m/RecommendItem/index.vue
Normal file
@ -0,0 +1,181 @@
|
||||
<template>
|
||||
<view class="design-list">
|
||||
<view class="design-item" v-for="(item, index) in items" :key="index">
|
||||
<view class="design-preview">
|
||||
<image :src="item.image" mode="aspectFit"></image>
|
||||
</view>
|
||||
<view class="design-info">
|
||||
<view class="design-title">{{ item.title }}</view>
|
||||
<view class="design-author">by:{{ item.author }}</view>
|
||||
|
||||
<view class="design-stats">
|
||||
<view class="stat-item">
|
||||
<text class="iconfont">👁</text>
|
||||
<text>{{ item.views }}</text>
|
||||
</view>
|
||||
<view class="stat-item">
|
||||
<text class="iconfont">👍</text>
|
||||
<text>{{ item.likes }}</text>
|
||||
</view>
|
||||
<view class="stat-item">
|
||||
<text class="iconfont">💬</text>
|
||||
<text>{{ item.comments }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="design-action">
|
||||
<button class="view-btn">查看</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "RecommendItem",
|
||||
props: {
|
||||
currentTab: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
items: [
|
||||
{
|
||||
id: 1,
|
||||
title: "高压细水雾灭火推车描述",
|
||||
author: "赵其",
|
||||
image: "/static/images/activity1.png",
|
||||
views: 128,
|
||||
likes: 16,
|
||||
comments: 35,
|
||||
url: "/pages/drawings/detail?id=1",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: "高压细水雾灭火推车描述",
|
||||
author: "赵其",
|
||||
image: "/static/images/activity2.png",
|
||||
views: 128,
|
||||
likes: 16,
|
||||
comments: 35,
|
||||
url: "/pages/drawings/detail?id=2",
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
title: "室内CAD模型设计室内CAD模型设计",
|
||||
author: "张泽",
|
||||
image: "/static/images/activity1.png",
|
||||
views: 95,
|
||||
likes: 12,
|
||||
comments: 28,
|
||||
url: "/pages/models/detail?id=1",
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
title: "CAD设计规范文档",
|
||||
author: "李华",
|
||||
image: "/static/images/activity2.png",
|
||||
views: 156,
|
||||
likes: 23,
|
||||
comments: 42,
|
||||
url: "/pages/documents/detail?id=1",
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
viewDetail(item) {
|
||||
console.log("View detail for:", item.title);
|
||||
uni.navigateTo({
|
||||
url: item.url,
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
// 变量定义
|
||||
$primary-color: #007aff;
|
||||
$text-color: #333;
|
||||
$secondary-text: #666;
|
||||
$light-text: #999;
|
||||
$bg-color: #f0f4f9;
|
||||
$white: #fff;
|
||||
$border-color: #eee;
|
||||
$border-radius: 15rpx;
|
||||
.design-list {
|
||||
// padding: 10rpx 20rpx;
|
||||
|
||||
.design-item {
|
||||
display: flex;
|
||||
margin-bottom: 20rpx;
|
||||
background-color: $white;
|
||||
border-radius: $border-radius;
|
||||
border: 1px solid $border-color;
|
||||
padding: 17rpx 10rpx;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
box-shadow: 0 0 10rpx rgba(0, 0, 0, 0.1);
|
||||
|
||||
.design-preview {
|
||||
width: 220rpx;
|
||||
height: 168rpx;
|
||||
overflow: hidden;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.design-info {
|
||||
flex: 1;
|
||||
padding: 0 20rpx;
|
||||
|
||||
.design-title {
|
||||
font-size: 27rpx;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.design-author {
|
||||
font-size: 25rpx;
|
||||
color: $light-text;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.design-stats {
|
||||
display: flex;
|
||||
|
||||
.stat-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: 20rpx;
|
||||
font-size: 24rpx;
|
||||
color: $light-text;
|
||||
|
||||
.iconfont {
|
||||
margin-right: 5rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.design-action {
|
||||
position: absolute;
|
||||
right: 20rpx;
|
||||
bottom: 20rpx;
|
||||
|
||||
.view-btn {
|
||||
background-color: $primary-color;
|
||||
color: $white;
|
||||
font-size: 25rpx;
|
||||
padding: 0rpx 25rpx !important;
|
||||
border-radius: 5rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
16
components/m/detail-components/Works.vue
Normal file
@ -0,0 +1,16 @@
|
||||
<template>
|
||||
<div class="works">
|
||||
<RecommendList />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
defineOptions({ name: 'Works' })
|
||||
import RecommendList from "~/components/m/RecommendItem/index.vue";
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.works {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
73
components/m/detail-components/certificates.vue
Normal file
@ -0,0 +1,73 @@
|
||||
<template>
|
||||
<div
|
||||
class="cert-item"
|
||||
v-for="(cert, index) in talentInfo.certificates"
|
||||
:key="index"
|
||||
>
|
||||
<div
|
||||
v-if="index !== talentInfo.certificates.length - 1"
|
||||
class="border-left"
|
||||
></div>
|
||||
<div class="cert-dot"></div>
|
||||
<div class="cert-info">
|
||||
<span class="cert-year">{{ cert.year }}</span>
|
||||
<span class="cert-desc">{{ cert.description }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
defineOptions({ name: 'Certificates' })
|
||||
interface Certificate { year: string; description: string }
|
||||
interface TalentInfo { certificates: Certificate[] }
|
||||
defineProps<{ talentInfo: TalentInfo }>()
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.border-left {
|
||||
width: 1px;
|
||||
height: calc(100%);
|
||||
border-left: 2px dotted #e6f0ff;
|
||||
position: absolute;
|
||||
left: 7rpx;
|
||||
top: 0;
|
||||
}
|
||||
// 证书列表
|
||||
.cert-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.cert-dot {
|
||||
width: 16rpx;
|
||||
height: 16rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #1a65ff;
|
||||
// margin-top: 12rpx;
|
||||
margin-right: 20rpx;
|
||||
flex-shrink: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.cert-info {
|
||||
flex: 1;
|
||||
margin-bottom: 11rpx;
|
||||
margin-top: -10rpx;
|
||||
padding-bottom: 32rpx;
|
||||
}
|
||||
|
||||
.cert-year {
|
||||
font-size: 25rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
display: block;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.cert-desc {
|
||||
font-size: 21rpx;
|
||||
color: #666;
|
||||
}
|
||||
</style>
|
||||
35
components/m/detail-components/technicalCertificates.vue
Normal file
@ -0,0 +1,35 @@
|
||||
<template>
|
||||
<div class="flex">
|
||||
<div
|
||||
class="cert-technicalCertificates"
|
||||
v-for="(cert, index) in 10"
|
||||
:key="index"
|
||||
>
|
||||
<img
|
||||
class="cert-image"
|
||||
:src="`https://picsum.photos/90/90?random=${index}`"
|
||||
alt="certificate"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
defineOptions({ name: 'TechnicalCertificates' })
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.flex {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 50rpx;
|
||||
}
|
||||
.cert-technicalCertificates {
|
||||
width: 135rpx;
|
||||
height: 191rpx;
|
||||
.cert-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
201
components/m/nav-bar/index.vue
Normal file
@ -0,0 +1,201 @@
|
||||
<template>
|
||||
<!-- 顶部导航栏 -->
|
||||
<view class="nav-bar">
|
||||
<view class="nav-item active">全部</view>
|
||||
<view class="nav-item">机械设备</view>
|
||||
<view class="nav-item">零部件模型</view>
|
||||
<view class="nav-item">交通运输</view>
|
||||
<view class="nav-item">电子产品</view>
|
||||
<view class="expand-btn" @tap="toggleCategoryMenu">
|
||||
<text class="expand-icon">≡</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 全部分类浮窗 -->
|
||||
<view
|
||||
class="category-popup"
|
||||
v-if="showCategoryMenu"
|
||||
@tap.stop="closeCategoryMenu"
|
||||
>
|
||||
<view class="popup-content" @tap.stop>
|
||||
<view class="category-list">
|
||||
<view
|
||||
:key="index"
|
||||
v-for="(section, index) in categoryList"
|
||||
class="category-item"
|
||||
@tap="selectCategory(section)"
|
||||
>
|
||||
{{ section.name }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 筛选选项 -->
|
||||
<view class="filter-bar">
|
||||
<view class="filter-item"> 软件分类 <text class="icon-down">∨</text> </view>
|
||||
<view class="filter-item"> 图纸类型 <text class="icon-down">∨</text> </view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
showCategoryMenu: false,
|
||||
categoryList: [
|
||||
{ name: "机械设备", active: false },
|
||||
{ name: "零部件模型", active: false },
|
||||
{ name: "交通运输", active: false },
|
||||
{ name: "电子产品", active: false },
|
||||
{ name: "机械设备", active: false },
|
||||
{ name: "零部件模型", active: false },
|
||||
{ name: "交通运输", active: false },
|
||||
{ name: "电子产品", active: false },
|
||||
{ name: "机械设备", active: false },
|
||||
{ name: "零部件模型", active: false },
|
||||
{ name: "交通运输", active: false },
|
||||
{ name: "电子产品", active: false },
|
||||
],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
toggleCategoryMenu() {
|
||||
this.showCategoryMenu = !this.showCategoryMenu;
|
||||
},
|
||||
closeCategoryMenu() {
|
||||
this.showCategoryMenu = false;
|
||||
},
|
||||
selectCategory(section) {
|
||||
// 演示用:显示toast提示
|
||||
},
|
||||
},
|
||||
onLoad(options) {
|
||||
console.log(options);
|
||||
// 监听点击事件,点击页面空白处关闭菜单
|
||||
uni.$on("page-click", () => {
|
||||
if (this.showCategoryMenu) {
|
||||
this.closeCategoryMenu();
|
||||
}
|
||||
});
|
||||
},
|
||||
onUnload() {
|
||||
// 移除事件监听
|
||||
uni.$off("page-click");
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
// 变量定义
|
||||
$primary-color: #007aff;
|
||||
$text-color: #333;
|
||||
$secondary-text: #666;
|
||||
$light-text: #999;
|
||||
$bg-color: #fff;
|
||||
$white: #fff;
|
||||
$border-color: #eee;
|
||||
$border-radius: 10rpx;
|
||||
$mask-bg: rgba(0, 0, 0, 0.5);
|
||||
.nav-bar {
|
||||
display: flex;
|
||||
background-color: $white;
|
||||
padding: 10rpx 0;
|
||||
position: relative;
|
||||
padding-right: 60rpx;
|
||||
|
||||
.nav-item {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
font-size: 25rpx;
|
||||
padding: 15rpx 0;
|
||||
|
||||
&.active {
|
||||
color: $primary-color;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
.expand-btn {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
width: 80rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.expand-icon {
|
||||
font-size: 40rpx;
|
||||
color: $text-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 分类浮窗样式
|
||||
.category-popup {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: $mask-bg;
|
||||
z-index: 999;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
.popup-content {
|
||||
width: 100%;
|
||||
max-height: 80vh;
|
||||
background-color: $white;
|
||||
animation: slideDown 0.3s ease;
|
||||
overflow-y: auto;
|
||||
|
||||
.category-list {
|
||||
padding: 20rpx;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.category-item {
|
||||
padding: 8rpx 12.94rpx;
|
||||
box-sizing: border-box;
|
||||
margin-right: 3%;
|
||||
margin-bottom: 20rpx;
|
||||
text-align: center;
|
||||
font-size: 25rpx;
|
||||
background-color: $bg-color;
|
||||
border-radius: 4rpx;
|
||||
border: 1px solid $border-color;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 滑入动画
|
||||
@keyframes slideDown {
|
||||
from {
|
||||
transform: translateY(-100%);
|
||||
opacity: 0.5;
|
||||
}
|
||||
to {
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.filter-bar {
|
||||
display: flex;
|
||||
padding: 20rpx 30rpx;
|
||||
|
||||
.filter-item {
|
||||
margin-right: 30rpx;
|
||||
font-size: 25rpx;
|
||||
color: $secondary-text;
|
||||
}
|
||||
|
||||
.icon-down {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="relative mt-[34px] w-[100%]">
|
||||
<KlTabBar v-model="query.source" :data="tabBar" />
|
||||
<div class="absolute right-[0px] top-[10px] text-[16px] text-[#999999] font-normal"
|
||||
<div class="absolute right-[0px] top-[0px] text-[16px] text-[#999999] font-normal"
|
||||
>共<span class="color-[#1A65FF]">{{ result?.total }}</span
|
||||
>个筛选结果</div
|
||||
>
|
||||
@ -17,7 +17,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import KlTabBar from '~/components/kl-tab-bar/index.vue'
|
||||
import KlTabBar from '~/components/kl-tab-bar/v3/index.vue'
|
||||
import CardPicture from '~/components/kl-card-picture/index.vue'
|
||||
import { ref } from 'vue'
|
||||
import type { pageRes, pageReq } from '~/api/upnew/types'
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
})
|
||||
|
||||
useHead({
|
||||
title: `${props.title} - 图夕夕`,
|
||||
title: `${props.title}`,
|
||||
meta: [
|
||||
{ name: 'description', content: `${props.description}`},
|
||||
{ name: 'keywords', content: props.keywords },
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="relative mt-[34px] w-[100%]">
|
||||
<KlTabBar v-model="query.source" :data="tabBar" />
|
||||
<div class="absolute right-[0px] top-[10px] text-[16px] text-[#999999] font-normal"
|
||||
<div class="absolute right-[0px] top-[0px] text-[16px] text-[#999999] font-normal"
|
||||
>共<span class="color-[#1A65FF]">{{ result?.total }}</span
|
||||
>个筛选结果</div
|
||||
>
|
||||
@ -17,7 +17,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import KlTabBar from '~/components/kl-tab-bar/index.vue'
|
||||
import KlTabBar from '~/components/kl-tab-bar/v3/index.vue'
|
||||
import CardPicture from '~/components/kl-card-picture/index.vue'
|
||||
import { ref } from 'vue'
|
||||
import type { pageRes, pageReq } from '~/api/upnew/types'
|
||||
|
||||
@ -1,77 +1,56 @@
|
||||
import { isArray } from "~/utils/utils";
|
||||
import { isArray } from '~/utils/utils'
|
||||
import useUserStore from '~/stores/user'
|
||||
// import refreshToken from "~/utils/RefreshToken";
|
||||
|
||||
type FetchType = typeof $fetch;
|
||||
export type FetchOptions = Parameters<FetchType>[1];
|
||||
type FetchType = typeof $fetch
|
||||
export type FetchOptions = Parameters<FetchType>[1]
|
||||
|
||||
const useClientRequest = async <T = unknown>(
|
||||
url: string,
|
||||
opts?: FetchOptions
|
||||
) => {
|
||||
const token = useCookie<string | undefined>("token");
|
||||
const runtimeConfig = useRuntimeConfig();
|
||||
const useClientRequest = async <T = unknown>(url: string, opts?: FetchOptions) => {
|
||||
const token = useCookie<string | undefined>('token')
|
||||
const runtimeConfig = useRuntimeConfig()
|
||||
const userStore = useUserStore()
|
||||
|
||||
const defaultOptions: FetchOptions = {
|
||||
baseURL: runtimeConfig.public.apiBase,
|
||||
onRequest({ options }) {
|
||||
options.headers = options.headers || 'application/json';
|
||||
if (token.value) {
|
||||
options.headers.set("Authorization", `Bearer ${token.value}`);
|
||||
options.headers = options.headers || 'application/json'
|
||||
if (token.value || userStore.token) {
|
||||
options.headers.set('Authorization', `Bearer ${token.value || userStore.token}`)
|
||||
}
|
||||
},
|
||||
onResponse({ response }) {
|
||||
if (+response.status === 200 && +response._data.code !== 0) {
|
||||
ElMessage.error(response._data.msg);
|
||||
ElMessage.error(response._data.msg)
|
||||
}
|
||||
},
|
||||
onResponseError({ response }) {
|
||||
ElMessage.error(
|
||||
isArray(response._data.data.msg)
|
||||
? response._data.data.msg[0]
|
||||
: response._data.data.msg
|
||||
);
|
||||
ElMessage.error(isArray(response._data.data.msg) ? response._data.data.msg[0] : response._data.data.msg)
|
||||
},
|
||||
};
|
||||
|
||||
// 明确转换返回类型
|
||||
const response = await $fetch(url, { ...defaultOptions, ...opts });
|
||||
return response as unknown as T;
|
||||
};
|
||||
|
||||
// GET请求
|
||||
export const get = <T = unknown>(
|
||||
endpoint: string,
|
||||
config?: Omit<FetchOptions, 'method'>
|
||||
): Promise<T> => {
|
||||
return useClientRequest<T>(endpoint, { ...config, method: 'GET' })
|
||||
|
||||
}
|
||||
|
||||
// POST请求
|
||||
export const post = <T = unknown>(
|
||||
endpoint: string,
|
||||
body?: any,
|
||||
config?: Omit<FetchOptions, 'method' | 'body'>
|
||||
): Promise<T> => {
|
||||
return useClientRequest<T>(endpoint, { ...config, method: 'POST', body })
|
||||
}
|
||||
// 明确转换返回类型
|
||||
const response = await $fetch(url, { ...defaultOptions, ...opts })
|
||||
return response as unknown as T
|
||||
}
|
||||
|
||||
|
||||
// DELETE请求
|
||||
export const del = <T = unknown>(
|
||||
endpoint: string,
|
||||
config?: Omit<FetchOptions, 'method'>
|
||||
): Promise<T> => {
|
||||
return useClientRequest<T>(endpoint, { ...config, method: 'DELETE' })
|
||||
}
|
||||
// GET请求
|
||||
export const get = <T = unknown>(endpoint: string, config?: Omit<FetchOptions, 'method'>): Promise<T> => {
|
||||
return useClientRequest<T>(endpoint, { ...config, method: 'GET' })
|
||||
}
|
||||
|
||||
// PUT请求
|
||||
export const put = <T = unknown>(
|
||||
endpoint: string,
|
||||
body?: any,
|
||||
config?: Omit<FetchOptions, 'method' | 'body'>
|
||||
): Promise<T> => {
|
||||
console.log({ ...config, method: 'PUT', body });
|
||||
|
||||
return useClientRequest<T>(endpoint, { ...config, method: 'PUT', body })
|
||||
}
|
||||
// POST请求
|
||||
export const post = <T = unknown>(endpoint: string, body?: any, config?: Omit<FetchOptions, 'method' | 'body'>): Promise<T> => {
|
||||
return useClientRequest<T>(endpoint, { ...config, method: 'POST', body })
|
||||
}
|
||||
|
||||
// DELETE请求
|
||||
export const del = <T = unknown>(endpoint: string, config?: Omit<FetchOptions, 'method'>): Promise<T> => {
|
||||
return useClientRequest<T>(endpoint, { ...config, method: 'DELETE' })
|
||||
}
|
||||
|
||||
// PUT请求
|
||||
export const put = <T = unknown>(endpoint: string, body?: any, config?: Omit<FetchOptions, 'method' | 'body'>): Promise<T> => {
|
||||
console.log({ ...config, method: 'PUT', body })
|
||||
|
||||
return useClientRequest<T>(endpoint, { ...config, method: 'PUT', body })
|
||||
}
|
||||
|
||||
@ -0,0 +1,70 @@
|
||||
<script setup lang="ts">
|
||||
const active = ref('home')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="m">
|
||||
<div class="scroll-container">
|
||||
<slot />
|
||||
</div>
|
||||
<!-- 底部信息 -->
|
||||
<div class="footer">
|
||||
<van-tabbar v-model="active">
|
||||
<van-tabbar-item name="home" icon="home-o">标签</van-tabbar-item>
|
||||
<van-tabbar-item name="search" icon="search">标签</van-tabbar-item>
|
||||
<van-tabbar-item name="friends" icon="friends-o">标签</van-tabbar-item>
|
||||
<van-tabbar-item name="setting" icon="setting-o">标签</van-tabbar-item>
|
||||
</van-tabbar>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* 移动端样式重置 - 只在移动端布局中生效 */
|
||||
.m {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #f8f8f8;
|
||||
.scroll-container {
|
||||
// flex: 1;
|
||||
overflow-y: auto;
|
||||
height: calc(100vh - 40px);
|
||||
}
|
||||
.footer {
|
||||
height: auto;
|
||||
}
|
||||
/* 重置 body 的最小宽度限制 */
|
||||
:global(body) {
|
||||
min-width: unset !important;
|
||||
width: 100% !important;
|
||||
max-width: 100% !important;
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
|
||||
/* 重置 #__nuxt 容器的样式 */
|
||||
:global(#__nuxt) {
|
||||
min-width: unset !important;
|
||||
width: 100% !important;
|
||||
max-width: 100% !important;
|
||||
|
||||
// .page-content {
|
||||
// padding: 0 !important;
|
||||
// overflow-x: hidden !important;
|
||||
|
||||
// .page-table-wrap {
|
||||
// padding: 8px !important;
|
||||
// }
|
||||
|
||||
// .page-card {
|
||||
// padding: 8px !important;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
/* 移动端优化滚动条 */
|
||||
:global(::-webkit-scrollbar) {
|
||||
width: 4px !important;
|
||||
height: 4px !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
12
middleware/login.global.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import useUserStore from '~/stores/user'
|
||||
export default defineNuxtRouteMiddleware((to, from) => {
|
||||
const { code, state, type } = to.query
|
||||
if (code && state && type && import.meta.client) {
|
||||
const userStore = useUserStore()
|
||||
userStore.getToken({
|
||||
code: code as string,
|
||||
state: state as string,
|
||||
type: type as string,
|
||||
})
|
||||
}
|
||||
})
|
||||
@ -6,13 +6,13 @@ export default defineNuxtRouteMiddleware((to, from) => {
|
||||
// 是否是移动端设备
|
||||
const isMobile = /(Android|webOS|iPhone|iPod|tablet|BlackBerry|Mobile)/i.test(navigator.userAgent)
|
||||
// 是否是手机端路由开头
|
||||
const isRouterMobile = to.path.startsWith('/m')
|
||||
const isRouterMobile = to.path.startsWith('/mobile')
|
||||
|
||||
console.log(isMobile, isRouterMobile);
|
||||
|
||||
// 移动端并且 不是/m开头路由
|
||||
if (isMobile && !isRouterMobile) {
|
||||
return navigateTo(`/m`)
|
||||
return navigateTo(`/mobile`)
|
||||
}
|
||||
// 不是移动端 是/m开头路由
|
||||
if (!isMobile && isRouterMobile) {
|
||||
19
middleware/tdk.global.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { getTDKList } from '~/api/home/index'
|
||||
// middleware/tdk.global.ts
|
||||
export default defineNuxtRouteMiddleware(async (to) => {
|
||||
const { data: tdkData } = await getTDKList()
|
||||
// 获取当前路由
|
||||
const currentPath = to.path;
|
||||
// 根据当前路由获取对应的TDK数据
|
||||
const currentTdk = tdkData.find((item) => item.path === currentPath)
|
||||
|
||||
if (currentTdk) {
|
||||
useHead({
|
||||
title: currentTdk.title,
|
||||
meta: [
|
||||
{ name: 'description', content: currentTdk.describeText },
|
||||
{ name: 'keywords', content: currentTdk.keyword }
|
||||
]
|
||||
})
|
||||
}
|
||||
})
|
||||
@ -12,7 +12,7 @@ export default defineNuxtConfig({
|
||||
debug: process.env.NODE_ENV === 'development', // 开启详细调试日志
|
||||
|
||||
ssr: true,
|
||||
modules: ['@unocss/nuxt', '@pinia/nuxt', '@element-plus/nuxt', 'pinia-plugin-persistedstate/nuxt'],
|
||||
modules: ['@unocss/nuxt', '@pinia/nuxt', '@element-plus/nuxt', 'pinia-plugin-persistedstate/nuxt','@vant/nuxt'],
|
||||
unocss: {
|
||||
nuxtLayers: true,
|
||||
},
|
||||
@ -31,26 +31,31 @@ export default defineNuxtConfig({
|
||||
postcss: {
|
||||
plugins: [
|
||||
postcsspxtoviewport({
|
||||
unitToConvert: 'px', // 要转化的单位
|
||||
viewportWidth: 750, // UI设计稿的宽度
|
||||
unitPrecision: 6, // 转换后的精度,即小数点位数
|
||||
propList: ['*'], // 指定转换的css属性的单位,*代表全部css属性的单位都进行转换
|
||||
viewportUnit: 'vw', // 指定需要转换成的视窗单位,默认vw
|
||||
fontViewportUnit: 'vw', // 指定字体需要转换成的视窗单位,默认vw
|
||||
selectorBlackList: ['el-'], // 指定不转换为视窗单位的类名,例如van-(vantUI组件),
|
||||
minPixelValue: 1, // 默认值1,小于或等于1px则不进行转换
|
||||
mediaQuery: true, // 是否在媒体查询的css代码中也进行转换,默认false
|
||||
replace: true, // 是否转换后直接更换属性值
|
||||
exclude: [/node_modules/, /^(?!.*\/pages\/m\/).*$/], // 排除node_modules和非pages/m目录下的文件
|
||||
landscape: false, // 是否处理横屏情况
|
||||
// 只转换pages下的m文件
|
||||
include: [/pages\/m/],
|
||||
unitToConvert: 'px',
|
||||
viewportWidth: 750,
|
||||
unitPrecision: 6,
|
||||
propList: ['*'],
|
||||
viewportUnit: 'vw',
|
||||
fontViewportUnit: 'vw',
|
||||
selectorBlackList: ['el-'],
|
||||
minPixelValue: 1,
|
||||
mediaQuery: true,
|
||||
replace: true,
|
||||
// 严格只允许 pages/mobile 下的文件被转换
|
||||
// 使用强排除:排除 node_modules 和 所有不在 pages/mobile 下的文件
|
||||
exclude: [
|
||||
/node_modules/,
|
||||
/^(?!.*\/(pages|src)\/mobile\/).*$/
|
||||
],
|
||||
landscape: false,
|
||||
// 可选:进一步放宽 include,以便某些移动端专用布局文件也参与
|
||||
include: [/\/pages\/mobile\//],
|
||||
}),
|
||||
],
|
||||
},
|
||||
},
|
||||
optimizeDeps: {
|
||||
include: ['naive-ui'],
|
||||
include: ['element-plus','unocss'], // 预构建依赖项
|
||||
},
|
||||
// 生产环境构建优化
|
||||
build: {
|
||||
@ -137,7 +142,7 @@ export default defineNuxtConfig({
|
||||
},
|
||||
|
||||
build: {
|
||||
transpile: ['vueuc', '@css-render/vue3-ssr', '@tinymce/tinymce-vue', 'tinymce'],
|
||||
transpile: process.env.NODE_ENV === 'production' ? ['lodash'] : [],
|
||||
},
|
||||
plugins: [
|
||||
// 在这里引入插件
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
{
|
||||
"name": "nuxt-app",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
@ -16,12 +17,14 @@
|
||||
"@wangeditor/editor-for-vue": "^5.1.12",
|
||||
"decimal.js": "^10.6.0",
|
||||
"echarts": "^6.0.0",
|
||||
"lodash": "^4.17.21",
|
||||
"mqtt": "^5.14.0",
|
||||
"nuxt": "^3.18.1",
|
||||
"pdfjs-dist": "^5.4.54",
|
||||
"pinia": "^3.0.3",
|
||||
"postcss-px-to-viewport": "^1.1.1",
|
||||
"qrcode.vue": "^3.6.0",
|
||||
"vant": "^4.9.21",
|
||||
"vue": "^3.5.18",
|
||||
"vue-pdf-embed": "^2.1.3",
|
||||
"vue-router": "^4.5.1",
|
||||
|
||||
@ -56,7 +56,7 @@
|
||||
{{ detail?.type === 1 ? '图纸' : detail?.type === 2 ? '文本' : '模型' }}中包含的文件
|
||||
</div>
|
||||
<div>
|
||||
<div v-for="item in detail?.files" :key="item.id" class="flex items-center justify-between border-b-[1px] border-b-[#eee] border-b-solid py-[10px]">
|
||||
<div v-for="item in detail?.otherFiles" :key="item.id" class="flex items-center justify-between border-b-[1px] border-b-[#eee] border-b-solid py-[10px]">
|
||||
<!-- <img src="~/assets/images/avater.png" alt="" srcset="" class="h-30px w-30px" /> -->
|
||||
<div>
|
||||
<!-- <span class="ml-[10px] cursor-pointer" @click="handleDownloadPreview(item)">{{ item.title }}</span> -->
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
<template>
|
||||
<!-- 导航 -->
|
||||
<SeoHead title="工程设计图纸下载_CAD设计图纸资源库" />
|
||||
<KlNavTab active="图纸" :type="1" />
|
||||
<div class="ma-auto w-[1440px]">
|
||||
<!-- 图纸分类 -->
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
<template>
|
||||
<!-- 导航 -->
|
||||
<SeoHead title="工程设计图纸下载_CAD设计图纸资源库" />
|
||||
<KlNavTab active="图纸" :type="1" />
|
||||
<div class="ma-auto w-[1440px]">
|
||||
<!-- 图纸分类 -->
|
||||
|
||||
@ -26,7 +26,6 @@
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import KlNavTab from '~/components/kl-nav-tab/index.vue'
|
||||
import KlWallpaperCategory from '~/components/kl-wallpaper-category/index.vue'
|
||||
import RecommendedColumnsV2 from '~/components/foreign-components/RecommendedColumnsV2.vue'
|
||||
import BannerTips from '~/components/foreign-components/BannerTips.vue'
|
||||
// import FeaturedSpecials from './components/FeaturedSpecials.vue'
|
||||
|
||||
@ -35,13 +35,19 @@
|
||||
import { page } from '~/api/upnew/index'
|
||||
import type { pageRes, pageReq } from '~/api/upnew/types'
|
||||
|
||||
const query = reactive<pageReq>({
|
||||
const query = reactive<
|
||||
pageReq & {
|
||||
isDomestic: number
|
||||
}
|
||||
>({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
projectType: '-1',
|
||||
editions: '-1',
|
||||
source: -1,
|
||||
type: 1,
|
||||
/**是否是国内: 1是 0否 */
|
||||
isDomestic: 1,
|
||||
})
|
||||
// const result = reactive<pageRes>({
|
||||
// list: [],
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div class="login-container flex flex-col justify-between">
|
||||
<div class="ma-auto mt-[25px] w-[100%] flex flex-col items-center">
|
||||
<el-image
|
||||
:src="userStore.userInfoRes.avatar || 'https://tuxixi.oss-cn-chengdu.aliyuncs.com/avater.png'"
|
||||
:src="userStore.userInfoRes.avatar || 'https://static.tuxixi.net/1757297277142/2025/09/08/10/07/57/tuxixi.png'"
|
||||
alt=""
|
||||
srcset=""
|
||||
class="h-[69px] w-[69px] rd-[50%]"
|
||||
@ -11,7 +11,7 @@
|
||||
@click="handleUserInfo"
|
||||
/>
|
||||
<div class="mt-[10px] text-[16px] text-[#333333] font-normal flex items-center">
|
||||
Hi,{{ userStore.userInfoRes.nickname || '欢迎访问~' }}
|
||||
Hi,{{ userStore.userInfoRes.nickname || '欢迎访问图夕夕' }}
|
||||
<img v-if="userStore.userInfoRes.vipLevel === 1" src="~/assets/svg/vip.svg" alt="" class="relative top-[1px]" />
|
||||
<img v-if="userStore.userInfoRes.vipLevel === 2" src="~/assets/svg/svip.svg" alt="" class="relative top-[1px]" />
|
||||
</div>
|
||||
@ -102,19 +102,19 @@
|
||||
}
|
||||
|
||||
const handleLogin = () => {
|
||||
app.$openLogin()
|
||||
app.$openLogin()
|
||||
}
|
||||
|
||||
const handleRegister = () => {
|
||||
app.$openRegister()
|
||||
app.$openRegister()
|
||||
}
|
||||
|
||||
const handleLoginPhone = () => {
|
||||
app.$openLogin('verify')
|
||||
app.$openLogin('verify')
|
||||
}
|
||||
|
||||
const handleLoginEmail = () => {
|
||||
app.$openLoginEmail()
|
||||
app.$openLoginEmail()
|
||||
}
|
||||
|
||||
const handleUserInfo = () => {
|
||||
@ -129,10 +129,9 @@
|
||||
|
||||
// 推出登录
|
||||
const handleLoginOut = () => {
|
||||
REFRESHTOKEN.removeToken()
|
||||
userStore.setToken('')
|
||||
userStore.setUserId('')
|
||||
userStore.setRefreshToken('')
|
||||
clearNuxtState(['token', 'userInfo'])
|
||||
userStore.logout()
|
||||
userStore.$reset()
|
||||
window.location.reload()
|
||||
}
|
||||
|
||||
|
||||
@ -2,27 +2,19 @@
|
||||
<template>
|
||||
<div class="main-content">
|
||||
<div class="flex">
|
||||
<div class="h-424px w-957px">
|
||||
<div class="h-[424px] w-[957px]">
|
||||
<el-carousel height="424px" indicator-position="none">
|
||||
<el-carousel-item v-for="(item, index) in bannerList" :key="index">
|
||||
<el-image
|
||||
:src="item.content"
|
||||
class="w-100%"
|
||||
:class="{ 'cursor-pointer': item.url }"
|
||||
fit="cover"
|
||||
@click="handleClick(item.url)"
|
||||
/>
|
||||
<el-image :src="item.content" class="w-[100%]" :class="{ 'cursor-pointer': item.url }" fit="cover" @click="handleClick(item.url)" />
|
||||
</el-carousel-item>
|
||||
</el-carousel>
|
||||
</div>
|
||||
<LoginForm />
|
||||
</div>
|
||||
<div
|
||||
class="box-border h-56px w-1219px flex items-center border border-[#EEEEEE] border-solid border-t-none bg-[#FFFFFF] pl-10px line-height-46px"
|
||||
>
|
||||
<img src="~/assets/images/voice.png" alt="" srcset="" class="mr-10px h-15px w-16px" />
|
||||
<div class="box-border h-[56px] w-[1219px] flex items-center border border-[#EEEEEE] border-solid border-t-none bg-[#FFFFFF] pl-[10px] line-height-[46px]">
|
||||
<img src="~/assets/images/voice.png" alt="" srcset="" class="mr-[10px] h-[15px] w-[16px]" />
|
||||
<Vue3Marquee :duration="10" direction="normal" pause-on-hover>
|
||||
· 经典来袭,SolidWorks装配经典案例之气动发动机
|
||||
<template v-for="(item, index) in noticeList" :key="index"> {{ item }} </template>
|
||||
</Vue3Marquee>
|
||||
</div>
|
||||
</div>
|
||||
@ -33,7 +25,7 @@
|
||||
import LoginForm from './LoginForm.vue'
|
||||
import { Vue3Marquee } from 'vue3-marquee'
|
||||
|
||||
import { getSettingPage } from '~/api/home/index'
|
||||
import { getSettingPage, getNoticeList } from '~/api/home/index'
|
||||
|
||||
const pageReq = reactive({
|
||||
type: 1,
|
||||
@ -50,6 +42,9 @@
|
||||
navigateTo(url)
|
||||
}
|
||||
}
|
||||
|
||||
const { data: noticeList } = await getNoticeList()
|
||||
console.log(noticeList)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<div class="ma-auto w-1440px">
|
||||
<SeoHead :title="tdkData?.title" :description="tdkData?.describeText" :keywords="tdkData?.keyword" />
|
||||
<!-- 搜索 -->
|
||||
<KlSearch></KlSearch>
|
||||
<!-- 菜单 -->
|
||||
@ -29,6 +30,12 @@
|
||||
import PopularDrawings from '~/pages/home/components/PopularDrawings.vue'
|
||||
import Leaderboard from '~/pages/home/components/Leaderboard.vue'
|
||||
import LearningRecommendations from '~/pages/home/components/LearningRecommendations.vue'
|
||||
import { getTDK } from '~/api/home/index'
|
||||
|
||||
const { data: tdkData } = useAsyncData('get-tdk-home', async () => {
|
||||
const res = await getTDK()
|
||||
return res.data
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Mobile Page</h1>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
// Mobile specific logic can be added here
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
14
pages/mobile/channel/index.vue
Normal file
@ -0,0 +1,14 @@
|
||||
<template>
|
||||
<div class="page-channel">
|
||||
<div class="text">交流频道</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
definePageMeta({ layout: 'm' })
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.page-channel { padding: 16px; }
|
||||
.text { font-size: 16px; }
|
||||
</style>
|
||||
14
pages/mobile/find/index.vue
Normal file
@ -0,0 +1,14 @@
|
||||
<template>
|
||||
<div class="page-find">
|
||||
<div class="text">发现</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
definePageMeta({ layout: 'm' })
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.page-find { padding: 16px; }
|
||||
.text { font-size: 16px; }
|
||||
</style>
|
||||
158
pages/mobile/gloabal-cad-drawings/index.vue
Normal file
@ -0,0 +1,158 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<!-- 设计图列表 -->
|
||||
<div class="design-list">
|
||||
<div
|
||||
class="design-item"
|
||||
v-for="(item, index) in designList"
|
||||
:key="index"
|
||||
>
|
||||
<div class="design-preview">
|
||||
<img :src="item.image" alt="preview" />
|
||||
</div>
|
||||
<div class="design-info">
|
||||
<div class="design-title">{{ item.title }}</div>
|
||||
<div class="design-author">by:{{ item.author }}</div>
|
||||
|
||||
<div class="design-stats">
|
||||
<div class="stat-item">
|
||||
<span class="iconfont">👁</span>
|
||||
<span>{{ item.views }}</span>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<span class="iconfont">👍</span>
|
||||
<span>{{ item.likes }}</span>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<span class="iconfont">💬</span>
|
||||
<span>{{ item.comments }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="design-action">
|
||||
<button class="view-btn" @click="viewDesign(index)">查看</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
definePageMeta({ layout: 'm' })
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
|
||||
const designList = ref([
|
||||
{ title: '高压细水雾灭火推车描述', author: '赵其', image: '/static/images/activity1.png', views: 128, likes: 16, comments: 35 },
|
||||
{ title: '高压细水雾灭火推车描述', author: '赵其', image: '/static/images/activity2.png', views: 128, likes: 16, comments: 35 },
|
||||
{ title: '高压细水雾灭火推车描述', author: '赵其', image: '/static/images/activity1.png', views: 128, likes: 16, comments: 35 },
|
||||
{ title: '高压细水雾灭火推车描述', author: '赵其', image: '/static/images/activity2.png', views: 128, likes: 16, comments: 35 },
|
||||
])
|
||||
|
||||
function viewDesign(index: number) {
|
||||
router.push({ path: '/mobile/design-detail', query: { id: String(index) } })
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
const titleFromQuery = (route.query.titleName as string) || '详情'
|
||||
if (titleFromQuery) {
|
||||
document.title = decodeURIComponent(titleFromQuery)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
// 变量定义
|
||||
$primary-color: #007aff;
|
||||
$text-color: #333;
|
||||
$secondary-text: #666;
|
||||
$light-text: #999;
|
||||
$bg-color: #fff;
|
||||
$white: #fff;
|
||||
$border-color: #eee;
|
||||
$border-radius: 10rpx;
|
||||
$mask-bg: rgba(0, 0, 0, 0.5);
|
||||
|
||||
.container {
|
||||
padding: 0;
|
||||
background-color: $bg-color;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.design-list {
|
||||
padding: 10rpx 20rpx;
|
||||
|
||||
.design-item {
|
||||
display: flex;
|
||||
margin-bottom: 20rpx;
|
||||
background-color: $white;
|
||||
border-radius: $border-radius;
|
||||
border: 1px solid $border-color;
|
||||
padding: 20rpx;
|
||||
position: relative;
|
||||
box-shadow: 0 0 10rpx rgba(0, 0, 0, 0.1);
|
||||
|
||||
.design-preview {
|
||||
width: 220rpx;
|
||||
height: 160rpx;
|
||||
overflow: hidden;
|
||||
border: 1px solid $border-color;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.design-info {
|
||||
flex: 1;
|
||||
padding: 0 20rpx;
|
||||
|
||||
.design-title {
|
||||
font-size: 27rpx;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.design-author {
|
||||
font-size: 25rpx;
|
||||
color: $light-text;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.design-stats {
|
||||
display: flex;
|
||||
|
||||
.stat-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: 20rpx;
|
||||
font-size: 24rpx;
|
||||
color: $light-text;
|
||||
|
||||
.iconfont {
|
||||
margin-right: 5rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.design-action {
|
||||
position: absolute;
|
||||
right: 20rpx;
|
||||
bottom: 20rpx;
|
||||
|
||||
.view-btn {
|
||||
background-color: $primary-color;
|
||||
color: $white;
|
||||
font-size: 26rpx;
|
||||
padding: 0rpx 25rpx;
|
||||
border-radius: 5rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
571
pages/mobile/index.vue
Normal file
@ -0,0 +1,571 @@
|
||||
<template>
|
||||
<div class="contains content">
|
||||
<div class="search-container">
|
||||
<van-search shape="round" class="vant-input" background="#fff" placeholder="请输入搜索关键词" />
|
||||
</div>
|
||||
|
||||
<!-- Banner Section -->
|
||||
<div class="banner-section">
|
||||
<div class="banner-swiper">
|
||||
<van-swipe class="my-swipe" :autoplay="3000" indicator-color="white">
|
||||
<van-swipe-item>
|
||||
<img src="~/assets/images/banner.png" alt="banner" />
|
||||
</van-swipe-item>
|
||||
<van-swipe-item>
|
||||
<img src="~/assets/images/banner.png" alt="banner" />
|
||||
</van-swipe-item>
|
||||
<van-swipe-item>
|
||||
<img src="~/assets/images/banner.png" alt="banner" />
|
||||
</van-swipe-item>
|
||||
<van-swipe-item>
|
||||
<img src="~/assets/images/banner.png" alt="banner" />
|
||||
</van-swipe-item>
|
||||
</van-swipe>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Category Grid -->
|
||||
<div class="category-grid">
|
||||
<!-- First Row -->
|
||||
<div class="category-row">
|
||||
<div class="category-item" @click="navigateTo('图纸')">
|
||||
<div class="category-icon">
|
||||
<img src="~/assets/images/tuzhi (3).png" alt="banner" />
|
||||
</div>
|
||||
<span class="category-text">图纸</span>
|
||||
</div>
|
||||
|
||||
<div class="category-item" @click="navigateTo('文本')">
|
||||
<div class="category-icon">
|
||||
<img src="~/assets/images/tuzhi (2).png" alt="banner" />
|
||||
</div>
|
||||
<span class="category-text">文本</span>
|
||||
</div>
|
||||
|
||||
<div class="category-item" @click="navigateTo('模型')">
|
||||
<div class="category-icon">
|
||||
<img src="~/assets/images/tuzhi (1).png" alt="banner" />
|
||||
</div>
|
||||
<span class="category-text">模型</span>
|
||||
</div>
|
||||
|
||||
<div class="category-item" @click="navigateTo('community')">
|
||||
<div class="category-icon">
|
||||
<img src="~/assets/images/tuzhi (4).png" alt="banner" />
|
||||
</div>
|
||||
<span class="category-text">牛人社区</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Second Row -->
|
||||
<div class="category-row mb-[10px]!">
|
||||
<div class="category-item" @click="navigateTo('international')">
|
||||
<div class="category-icon">
|
||||
<img src="~/assets/images/tuzhi (5).png" alt="banner" />
|
||||
</div>
|
||||
<span class="category-text">国外专区</span>
|
||||
</div>
|
||||
|
||||
<div class="category-item" @click="navigateTo('channel')">
|
||||
<div class="category-icon">
|
||||
<img src="~/assets/images/tuzhi (6).png" alt="banner" />
|
||||
</div>
|
||||
<span class="category-text">交流频道</span>
|
||||
</div>
|
||||
|
||||
<div class="category-item"></div>
|
||||
<div class="category-item"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- -->
|
||||
<div class="divider"></div>
|
||||
<div class="contains content">
|
||||
<!--最新活动 -->
|
||||
<div class="activity-section">
|
||||
<div class="section-header">
|
||||
<span class="section-title">最新活动</span>
|
||||
<a href="/mobile/activity/list" class="view-all">
|
||||
<span>查看全部</span>
|
||||
<span class="chevron">></span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="activity-scroll">
|
||||
<div class="activity-container">
|
||||
<div
|
||||
class="activity-card"
|
||||
v-for="(item, index) in activityList"
|
||||
:key="index"
|
||||
@click="goToActivity(item)"
|
||||
:style="{ marginRight: index === activityList.length - 1 ? '0px' : '9px' }"
|
||||
>
|
||||
<img :src="item.image" class="activity-image" alt="activity" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="divider"></div>
|
||||
<div class="contains content">
|
||||
<!-- 推荐功能 -->
|
||||
<div class="recommend-section">
|
||||
<div class="tab-navigation">
|
||||
<div v-for="(tab, index) in tabs" :key="index" class="tab-item" :class="{ active: currentTab === index }" @click="switchTab(index)">
|
||||
<span>{{ tab.title }}</span>
|
||||
</div>
|
||||
<button class="view-all" @click="viewAll">
|
||||
<span>查看全部</span>
|
||||
<span class="icon-right">></span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 内容区域 -->
|
||||
<div class="design-list">
|
||||
<div class="design-item" v-for="(item, index) in items" :key="index">
|
||||
<div class="design-preview">
|
||||
<img :src="activity2" mode="aspectFit"></img>
|
||||
</div>
|
||||
<div class="design-info">
|
||||
<div class="design-title">{{ item.title }}</div>
|
||||
<div class="design-author">by:{{ item.author }}</div>
|
||||
|
||||
<div class="design-stats">
|
||||
<div class="stat-item">
|
||||
<img class="img1" src="~/assets/images/home-l (2).png" alt="banner" />
|
||||
<span>{{ item.views }}</span>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<img class="img2" src="~/assets/images/home-l (3).png" alt="banner" />
|
||||
<span>{{ item.likes }}</span>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<img class="img3" src="~/assets/images/home-l (1).png" alt="banner" />
|
||||
<span>{{ item.comments }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="design-action">
|
||||
<button class="view-btn">查看</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useRouter } from 'vue-router'
|
||||
import activity1 from '~/assets/images/activity1.png'
|
||||
import activity2 from '~/assets/images/activity2.png'
|
||||
import activity3 from '~/assets/images/activity2.png'
|
||||
definePageMeta({
|
||||
layout: 'm'
|
||||
})
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
function navigateTo(category: string) {
|
||||
router.push({ path: '/mobile/gloabal-cad-drawings', query: { titleName: encodeURIComponent(category) } })
|
||||
}
|
||||
|
||||
const activityList = ref([
|
||||
{ id: 1, title: '积分兑换有好礼', image: activity1, url: '/mobile/activity/detail?id=1' },
|
||||
{ id: 2, title: 'CAD高效学习', image: activity2, url: '/mobile/activity/detail?id=2' },
|
||||
{ id: 3, title: '学习有奖', image: activity3, url: '/mobile/activity/detail?id=3' },
|
||||
])
|
||||
|
||||
function goToActivity(item: { url: string }) {
|
||||
router.push(item.url)
|
||||
}
|
||||
|
||||
const currentTab = ref(0)
|
||||
const tabs = ref([
|
||||
{ title: '推荐图纸', type: 'drawings' },
|
||||
{ title: '推荐模型', type: 'models' },
|
||||
{ title: '推荐文本', type: 'documents' },
|
||||
])
|
||||
|
||||
function switchTab(index: number) {
|
||||
currentTab.value = index
|
||||
}
|
||||
|
||||
function viewAll() {
|
||||
const type = tabs.value[currentTab.value].type
|
||||
router.push(`/mobile/${type}/list`)
|
||||
}
|
||||
|
||||
const items = [
|
||||
{
|
||||
id: 1,
|
||||
title: '高压细水雾灭火推车描述',
|
||||
author: '赵其',
|
||||
image: '/static/images/activity1.png',
|
||||
views: 128,
|
||||
likes: 16,
|
||||
comments: 35,
|
||||
url: '/pages/drawings/detail?id=1',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: '高压细水雾灭火推车描述',
|
||||
author: '赵其',
|
||||
image: '/static/images/activity2.png',
|
||||
views: 128,
|
||||
likes: 16,
|
||||
comments: 35,
|
||||
url: '/pages/drawings/detail?id=2',
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
title: '室内CAD模型设计室内CAD模型设计',
|
||||
author: '张泽',
|
||||
image: '/static/images/activity1.png',
|
||||
views: 95,
|
||||
likes: 12,
|
||||
comments: 28,
|
||||
url: '/pages/models/detail?id=1',
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
title: 'CAD设计规范文档',
|
||||
author: '李华',
|
||||
image: '/static/images/activity2.png',
|
||||
views: 156,
|
||||
likes: 23,
|
||||
comments: 42,
|
||||
url: '/pages/documents/detail?id=1',
|
||||
},
|
||||
]
|
||||
|
||||
const viewDetail = (item: any) => {
|
||||
console.log('View detail for:', item.title)
|
||||
// uni.navigateTo({
|
||||
// url: item.url,
|
||||
// });
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
// 变量定义
|
||||
$primary-color: #007aff;
|
||||
$text-color: #333;
|
||||
$secondary-text: #666;
|
||||
$light-text: #999;
|
||||
$bg-color: #f0f4f9;
|
||||
$white: #fff;
|
||||
$border-color: #eee;
|
||||
$border-radius: 15rpx;
|
||||
.design-list {
|
||||
.design-item {
|
||||
display: flex;
|
||||
margin-bottom: 20px;
|
||||
background-color: $white;
|
||||
border-radius: $border-radius;
|
||||
border: 1px solid $border-color;
|
||||
padding: 17px 10px;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
|
||||
.design-preview {
|
||||
width: 220px;
|
||||
height: 168px;
|
||||
overflow: hidden;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.design-info {
|
||||
flex: 1;
|
||||
padding: 0 20px;
|
||||
|
||||
.design-title {
|
||||
font-size: 27px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.design-author {
|
||||
font-size: 25px;
|
||||
color: $light-text;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
.design-stats {
|
||||
display: flex;
|
||||
|
||||
.stat-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: 20px;
|
||||
font-size: 24px;
|
||||
color: $light-text;
|
||||
|
||||
img {
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.img1 {
|
||||
width: 32px;
|
||||
height: 24px;
|
||||
}
|
||||
.img2 {
|
||||
width: 26px;
|
||||
height: 28px;
|
||||
}
|
||||
.img3 {
|
||||
width: 28px;
|
||||
height: 26px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.design-action {
|
||||
position: absolute;
|
||||
right: 20px;
|
||||
top: 70px;
|
||||
|
||||
.view-btn {
|
||||
background-color: $primary-color;
|
||||
color: $white;
|
||||
font-size: 25px;
|
||||
padding: 10px 26px !important;
|
||||
border-radius: 5px;
|
||||
border:none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.recommend-section {
|
||||
// padding: 0 20rpx;
|
||||
// margin: 30rpx 0 50rpx;
|
||||
}
|
||||
|
||||
.tab-navigation {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
padding: 8px 0;
|
||||
margin-right: 40px;
|
||||
font-size: 29px;
|
||||
color: #333;
|
||||
position: relative;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&.active {
|
||||
color: #2970ff;
|
||||
position: relative;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
background-image: url('~/assets/images/bg-yy.png');
|
||||
background-size: 100% 100%;
|
||||
background-repeat: no-repeat;
|
||||
position: absolute;
|
||||
bottom: 1px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.view-all {
|
||||
margin-left: auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 25px;
|
||||
color: #666;
|
||||
background: transparent;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
.view-all .icon-right {
|
||||
margin-left: 4rpx;
|
||||
font-size: 25px;
|
||||
}
|
||||
.activity-section {
|
||||
margin: 21.53rpx 0;
|
||||
// padding: 0 20rpx;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 31px;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.view-all {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 25px !important;
|
||||
color: #666;
|
||||
text-decoration: none;
|
||||
}
|
||||
.view-all .chevron {
|
||||
margin-left: 4px;
|
||||
font-size: 20rpx;
|
||||
}
|
||||
|
||||
.activity-scroll {
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
padding-left: 20rpx; // 左侧padding,与section对齐
|
||||
margin-left: -20rpx; // 抵消父容器的padding
|
||||
}
|
||||
|
||||
.activity-container {
|
||||
display: inline-flex;
|
||||
padding: 10px 0px 0px 0px !important; // 留出阴影空间
|
||||
}
|
||||
|
||||
.activity-card {
|
||||
width: 292px;
|
||||
height: 125px;
|
||||
border-radius: 12rpx;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
|
||||
transition: all 0.2s;
|
||||
|
||||
&:active {
|
||||
transform: scale(0.98);
|
||||
opacity: 0.9;
|
||||
}
|
||||
}
|
||||
|
||||
.activity-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.search-container {
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
.vant-input {
|
||||
flex: 1;
|
||||
padding: 0px !important;
|
||||
/* 设置 Vant Search 内部输入高度 */
|
||||
--van-search-input-height: 65px;
|
||||
:deep(.van-search__content) {
|
||||
min-height: 65px;
|
||||
}
|
||||
:deep(.van-field__control) {
|
||||
height: 65px;
|
||||
line-height: 65px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.divider {
|
||||
height: 17px;
|
||||
background-color: #f8f8f8;
|
||||
border-radius: 1px;
|
||||
}
|
||||
.content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #fff;
|
||||
padding: 21px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.banner-section {
|
||||
margin-top: 25px;
|
||||
border-radius: 20px;
|
||||
overflow: hidden;
|
||||
height: 285px;
|
||||
}
|
||||
|
||||
.banner-swiper {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
.my-swipe {
|
||||
height: 100%;
|
||||
.van-swipe-item {
|
||||
color: #fff;
|
||||
font-size: 20px;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
background-color: #39a9ed;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.slogan-main {
|
||||
font-size: 48rpx;
|
||||
font-weight: bold;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.slogan-sub {
|
||||
font-size: 38rpx;
|
||||
font-weight: bold;
|
||||
background-color: rgba(109, 200, 255, 0.8);
|
||||
align-self: flex-start;
|
||||
padding: 5rpx 20rpx;
|
||||
border-radius: 5rpx;
|
||||
}
|
||||
|
||||
.banner-graphics {
|
||||
flex: 1;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.category-grid {
|
||||
margin-top: 33px;
|
||||
}
|
||||
|
||||
.category-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.category-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 22%;
|
||||
}
|
||||
|
||||
.category-icon {
|
||||
width: 78px;
|
||||
height: 78px;
|
||||
border-radius: 20rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-bottom: 10rpx;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin-bottom: 17px;
|
||||
}
|
||||
}
|
||||
|
||||
.category-text {
|
||||
font-size: 25px;
|
||||
color: #191919;
|
||||
}
|
||||
</style>
|
||||
245
pages/mobile/message_notice/index.vue
Normal file
@ -0,0 +1,245 @@
|
||||
<template>
|
||||
<div class="message-notice-container">
|
||||
<div class="tab-navigation">
|
||||
<div
|
||||
v-for="(tab, index) in tabs"
|
||||
:key="index"
|
||||
:class="['tab-item', { active: activeTab === index }]"
|
||||
@click="activeTab = index"
|
||||
>
|
||||
<span v-if="index === 0" class="iconfont icon-system"></span>
|
||||
<span v-else-if="index === 1" class="iconfont icon-transaction"></span>
|
||||
<span v-else class="iconfont icon-forum"></span>
|
||||
{{ tab.name }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="message-content">
|
||||
<template v-if="activeTab === 0">
|
||||
<div
|
||||
class="message-item"
|
||||
v-for="(message, index) in systemMessages"
|
||||
:key="index"
|
||||
>
|
||||
<div class="message-left">
|
||||
<span class="iconfont icon-speaker"></span>
|
||||
<span class="dot"></span>
|
||||
</div>
|
||||
<div class="message-body">
|
||||
<div class="message-header">
|
||||
<div class="message-title text-ellipsis">{{ message.title }}</div>
|
||||
<div class="message-time">{{ message.time }}</div>
|
||||
</div>
|
||||
<div class="message-description">{{ message.content }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-if="activeTab === 1">
|
||||
<div class="empty-content">
|
||||
<div class="notice-text">交易消息和论坛社区互动的图标统一下,样式一样</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-if="activeTab === 2">
|
||||
<div class="empty-content">
|
||||
<div class="notice-text">交易消息和论坛社区互动的图标统一下,样式一样</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
definePageMeta({ layout: 'm' })
|
||||
import { ref } from 'vue'
|
||||
|
||||
const activeTab = ref(0)
|
||||
const tabs = ref([
|
||||
{ name: '系统消息', icon: 'icon-system' },
|
||||
{ name: '交易消息', icon: 'icon-transaction' },
|
||||
{ name: '论坛社区互动', icon: 'icon-forum' },
|
||||
])
|
||||
|
||||
const systemMessages = ref([
|
||||
{ title: '图夕夕金币充值有优惠!', content: '图夕夕限时优惠, 微信冲500送50金币, 充200送10金币', time: '2025-03-05 17:00:57' },
|
||||
{ title: '图夕夕金币充值有优惠!', content: '图夕夕限时优惠, 微信冲500送50金币, 充200送10金币图夕夕限时优惠, 微信冲500送50金币, 充200送10金币', time: '2025-03-05 17:00:57' },
|
||||
])
|
||||
|
||||
const transactionMessages = ref<any[]>([])
|
||||
const forumMessages = ref<any[]>([])
|
||||
</script>
|
||||
|
||||
<style>
|
||||
page {
|
||||
background-color: #f5f7fa;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.message-notice-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.tab-navigation {
|
||||
display: flex;
|
||||
background-color: #fff;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
flex: 1;
|
||||
padding: 30rpx 0;
|
||||
text-align: center;
|
||||
color: #666;
|
||||
position: relative;
|
||||
font-size: 28rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.tab-item .iconfont {
|
||||
font-size: 32rpx;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
.tab-item.active {
|
||||
color: #4082ff;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.tab-item.active::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 25%;
|
||||
width: 50%;
|
||||
height: 6rpx;
|
||||
background-color: #4082ff;
|
||||
}
|
||||
|
||||
.icon-system:before {
|
||||
content: "🔔";
|
||||
}
|
||||
|
||||
.icon-transaction:before {
|
||||
content: "💰";
|
||||
}
|
||||
|
||||
.icon-forum:before {
|
||||
content: "💬";
|
||||
}
|
||||
|
||||
.icon-speaker:before {
|
||||
content: "📢";
|
||||
}
|
||||
|
||||
.message-content {
|
||||
flex: 1;
|
||||
padding: 20rpx;
|
||||
background-color: #f5f7fa;
|
||||
}
|
||||
|
||||
.message-item {
|
||||
display: flex;
|
||||
background-color: #fff;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 16rpx;
|
||||
border-radius: 8rpx;
|
||||
align-items: flex-start;
|
||||
border-left: 6rpx solid transparent;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.message-left {
|
||||
position: relative;
|
||||
margin-right: 20rpx;
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.message-left .iconfont {
|
||||
font-size: 40rpx;
|
||||
color: #4082ff;
|
||||
}
|
||||
|
||||
.dot {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 16rpx;
|
||||
height: 16rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #ff4d4f;
|
||||
}
|
||||
|
||||
.message-body {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.message-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
|
||||
.message-title {
|
||||
font-weight: bold;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.message-time {
|
||||
color: #999;
|
||||
font-size: 24rpx;
|
||||
text-align: right;
|
||||
flex-shrink: 0;
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
|
||||
.message-description {
|
||||
color: #666;
|
||||
font-size: 26rpx;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.empty-content {
|
||||
height: 300rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: #e6f0ff;
|
||||
margin-top: 20rpx;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
|
||||
.notice-text {
|
||||
color: #666;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.page-title {
|
||||
padding: 20rpx;
|
||||
text-align: center;
|
||||
font-size: 28rpx;
|
||||
background-color: transparent;
|
||||
color: #666;
|
||||
border-top: 2rpx solid #eee;
|
||||
}
|
||||
|
||||
.text-ellipsis {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
</style>
|
||||
309
pages/mobile/talent-detail/index.vue
Normal file
@ -0,0 +1,309 @@
|
||||
<template>
|
||||
<view class="talent-detail">
|
||||
<!-- 个人信息卡片 -->
|
||||
<view class="profile-card">
|
||||
<view class="profile-header">
|
||||
<view class="left-section">
|
||||
<image
|
||||
class="avatar"
|
||||
:src="talentInfo.avatar"
|
||||
mode="aspectFill"
|
||||
></image>
|
||||
<view class="basic-info">
|
||||
<view class="name-row">
|
||||
<text class="name">{{ talentInfo.name }}</text>
|
||||
<view class="tags">
|
||||
<view
|
||||
class="tag"
|
||||
v-for="(tag, index) in talentInfo.tags"
|
||||
:key="index"
|
||||
>{{ tag }}</view
|
||||
>
|
||||
</view>
|
||||
</view>
|
||||
<text class="education">毕业院校:{{ talentInfo.education }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<div class="follow-btn" @click="followTalent">
|
||||
{{ isFollowed ? "已关注" : "+ 关注" }}
|
||||
</div>
|
||||
</view>
|
||||
|
||||
<!-- 数据统计 -->
|
||||
<view class="stats">
|
||||
<view class="stat-item works">
|
||||
<text class="stat-number">{{ talentInfo.worksCount }}</text>
|
||||
<text class="stat-label">作品量</text>
|
||||
</view>
|
||||
<!-- 加跟竖线 隔离下 -->
|
||||
<view class="stat-item-line"></view>
|
||||
<view class="stat-item fans">
|
||||
<text class="stat-number">{{ talentInfo.fansCount }}</text>
|
||||
<text class="stat-label">粉丝量</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 个人简介 -->
|
||||
<view class="section-header">
|
||||
<image class="crown-icon" src="/static/images/crown.png"></image>
|
||||
<text class="section-title">个人简介</text>
|
||||
</view>
|
||||
<text class="intro-text">{{ talentInfo.introduction }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 选项卡导航 -->
|
||||
<view class="tab-nav">
|
||||
<view
|
||||
v-for="(tab, index) in tabs"
|
||||
:key="index"
|
||||
class="tab-item"
|
||||
:class="{ active: currentTab === index }"
|
||||
@click="switchTab(index)"
|
||||
>
|
||||
<text>{{ tab }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 技术证书内容 -->
|
||||
<view class="tab-content" v-if="currentTab === 0">
|
||||
<!-- 技术证书列表 图片展示 -->
|
||||
<TechnicalCertificates />
|
||||
</view>
|
||||
|
||||
<!-- 个人履历内容 -->
|
||||
<view class="tab-content" v-if="currentTab === 1">
|
||||
<!-- 个人履历内容 -->
|
||||
<Certificates :talentInfo="talentInfo" />
|
||||
</view>
|
||||
|
||||
<!-- 作品展示内容 -->
|
||||
<view class="tab-content" v-if="currentTab === 2">
|
||||
<!-- 作品展示内容 -->
|
||||
<Works :talentInfo="talentInfo" />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
definePageMeta({ layout: 'm' })
|
||||
import TechnicalCertificates from "~/components/m/detail-components/technicalCertificates.vue";
|
||||
import Certificates from "~/components/m/detail-components/certificates.vue";
|
||||
import Works from "~/components/m/detail-components/Works.vue";
|
||||
import { reactive, ref } from 'vue'
|
||||
|
||||
const isFollowed = ref(false)
|
||||
const currentTab = ref(0)
|
||||
const tabs = ['技术证书', '个人履历', '作品展示']
|
||||
const talentInfo = reactive({
|
||||
id: 1,
|
||||
name: '王刚',
|
||||
avatar: '/static/images/avater2.png',
|
||||
tags: ['五金工具', '电子产品'],
|
||||
education: '重庆工商大学',
|
||||
worksCount: 876,
|
||||
fansCount: 98,
|
||||
introduction:
|
||||
'你好!我是专注于工业设计和机械设计领域的专业设计师,擅长进行外观设计、结构设计、板金设计等各类工程设计工作。我拥有丰富的经验,能够为客户提供高质量的设计解决方案,包括PCB外壳设计、框架设计、运动仿真、逆向工程等。此外,我熟练使用Creo、CAD等设计软件,能够进行精准的3D建模、渲染、2D工程图绘制、CAD代画以及三维转二维等工作。',
|
||||
certificates: [
|
||||
{ year: '2020年', description: '韩国内基211学府设计的一款月度采样机' },
|
||||
{ year: '2021年', description: '韩国内基211学府设计的一款月度采样机' },
|
||||
{ year: '2022年', description: '韩国内基211学府设计的一款月度采样机' },
|
||||
{ year: '2023年', description: '韩国内基211学府设计的一款月度采样机' },
|
||||
{ year: '2024年', description: '韩国内基211学府设计的一款月度采样机' },
|
||||
{ year: '2025年', description: '韩国内基211学府设计的一款月度采样机' },
|
||||
],
|
||||
})
|
||||
|
||||
function followTalent() {
|
||||
isFollowed.value = !isFollowed.value
|
||||
}
|
||||
function switchTab(index: number) {
|
||||
currentTab.value = index
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.talent-detail {
|
||||
min-height: 100vh;
|
||||
background-color: #fff;
|
||||
padding: 30rpx 30rpx 0;
|
||||
background-image: url("~/assets/images/talent-detail-bg.png");
|
||||
background-size: 100%;
|
||||
background-repeat: no-repeat;
|
||||
background-position: top;
|
||||
|
||||
// 个人信息卡片样式
|
||||
.profile-card {
|
||||
background-color: #fff;
|
||||
border-radius: 12rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 20rpx;
|
||||
border: 1px solid #eee;
|
||||
box-shadow: 0 0 10rpx rgba(0, 0, 0, 0.1);
|
||||
margin-top: 164rpx;
|
||||
|
||||
.profile-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
|
||||
.left-section {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
|
||||
.avatar {
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
border-radius: 50%;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.basic-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.name-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 10rpx;
|
||||
|
||||
.name {
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.tags {
|
||||
display: flex;
|
||||
|
||||
.tag {
|
||||
font-size: 24rpx;
|
||||
color: #1a65ff;
|
||||
background-color: #e6f0ff;
|
||||
padding: 4rpx 16rpx;
|
||||
border-radius: 20rpx;
|
||||
margin-right: 12rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.education {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.follow-btn {
|
||||
width: 89rpx;
|
||||
height: 44rpx;
|
||||
border-radius: 7rpx;
|
||||
border: 1px solid #d7d7d7;
|
||||
text-align: center;
|
||||
line-height: 44rpx;
|
||||
font-size: 21rpx;
|
||||
color: #0a6fff;
|
||||
}
|
||||
}
|
||||
|
||||
// 数据统计区域
|
||||
.stats {
|
||||
display: flex;
|
||||
margin-top: 30rpx;
|
||||
margin-left: 140rpx;
|
||||
|
||||
.stat-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
.stat-number {
|
||||
font-size: 40rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 28rpx;
|
||||
color: #999;
|
||||
margin-top: 4rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.stat-item-line {
|
||||
width: 1px;
|
||||
height: 90rpx;
|
||||
background-color: #eee;
|
||||
margin: 0 50rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.section-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 40rpx;
|
||||
margin-bottom: 20rpx;
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
height: 56rpx;
|
||||
background: rgba(26, 101, 255, 0.1);
|
||||
border-radius: 28rpx;
|
||||
|
||||
.crown-icon {
|
||||
width: 40.97rpx;
|
||||
height: 35.42rpx;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 29rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.intro-text {
|
||||
font-size: 24rpx;
|
||||
color: #666;
|
||||
line-height: 1.6;
|
||||
}
|
||||
}
|
||||
|
||||
// 选项卡导航
|
||||
.tab-nav {
|
||||
display: flex;
|
||||
background-color: #fff;
|
||||
border-radius: 12rpx 12rpx 0 0;
|
||||
|
||||
.tab-item {
|
||||
padding: 24rpx 0;
|
||||
margin-right: 60rpx;
|
||||
position: relative;
|
||||
font-size: 25rpx;
|
||||
color: #666;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&.active {
|
||||
color: #1a65ff;
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 14rpx;
|
||||
width: 100%;
|
||||
height: 4rpx;
|
||||
background-color: #1a65ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 选项卡内容
|
||||
.tab-content {
|
||||
background-color: #fff;
|
||||
border-radius: 0 0 12rpx 12rpx;
|
||||
padding: 20rpx 0rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
221
pages/mobile/transaction_record/index.vue
Normal file
@ -0,0 +1,221 @@
|
||||
<template>
|
||||
<div class="transaction-record">
|
||||
<!-- Balance Card -->
|
||||
<div class="balance-card">
|
||||
<div class="balance-title">
|
||||
<span>我的余额 (元)</span>
|
||||
<span class="verify-text">🏅 资产保障中</span>
|
||||
</div>
|
||||
<div class="balance-amount">{{ balance.toFixed(2) }}</div>
|
||||
<div class="action-buttons">
|
||||
<div class="btn-recharge">充值</div>
|
||||
<div class="btn-withdraw">提现</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Transaction Filter -->
|
||||
<div class="transaction-filter">
|
||||
<div class="filter-type">
|
||||
<span>全部</span>
|
||||
</div>
|
||||
<div class="filter-date">
|
||||
<label class="date-picker-trigger">
|
||||
<span>当前时间: <span style="color:#4080ff">{{ currentMonth }}</span></span>
|
||||
<input type="month" v-model="selectedMonth" @change="onMonthChange" />
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Transaction List -->
|
||||
<div class="transaction-list">
|
||||
<div
|
||||
v-for="(transaction, index) in transactions"
|
||||
:key="index"
|
||||
class="transaction-item"
|
||||
>
|
||||
<div class="transaction-info">
|
||||
<span class="transaction-type">{{ transaction.type }}</span>
|
||||
<span class="transaction-date">{{ transaction.date }}</span>
|
||||
</div>
|
||||
<div
|
||||
class="transaction-amount"
|
||||
:class="{ 'amount-positive': transaction.amount > 0 }"
|
||||
>
|
||||
<span>{{
|
||||
transaction.amount > 0
|
||||
? "+" + transaction.amount
|
||||
: transaction.amount
|
||||
}}</span>
|
||||
<span class="transaction-reference">{{ transaction.reference }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="transaction-footer">
|
||||
<span>当前仅展示本月明细,切换查看更多</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
definePageMeta({ layout: 'm' })
|
||||
import { ref, onMounted } from 'vue'
|
||||
|
||||
const balance = ref(6357.0)
|
||||
const selectedMonth = ref('')
|
||||
const currentMonth = ref('')
|
||||
const transactions = ref([
|
||||
{ type: '转出到银行卡', date: '2024-03-10 15:38', amount: -3578, reference: '56784' },
|
||||
{ type: '转出到银行卡', date: '2024-03-10 15:38', amount: 3578, reference: '56784' },
|
||||
{ type: '转出到银行卡', date: '2024-03-10 15:38', amount: -3578, reference: '56784' },
|
||||
{ type: '转出到银行卡', date: '2024-03-10 15:38', amount: -3578, reference: '56784' },
|
||||
{ type: '转出到银行卡', date: '2024-03-10 15:38', amount: -3578, reference: '56784' },
|
||||
{ type: '转出到银行卡', date: '2024-03-10 15:38', amount: -3578, reference: '56784' },
|
||||
])
|
||||
|
||||
function onMonthChange(e: Event) {
|
||||
const value = (e.target as HTMLInputElement).value // yyyy-mm
|
||||
if (!value) return
|
||||
const [y, m] = value.split('-')
|
||||
currentMonth.value = `${y}.${m}`
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
const now = new Date()
|
||||
const year = now.getFullYear()
|
||||
const month = String(now.getMonth() + 1).padStart(2, '0')
|
||||
currentMonth.value = `${year}.${month}`
|
||||
selectedMonth.value = `${year}-${month}`
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.transaction-record {
|
||||
background-color: #f5f5f5;
|
||||
padding-bottom: 20px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.balance-card {
|
||||
background-color: white;
|
||||
padding: 20px;
|
||||
margin-bottom: 10px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.balance-title {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.verify-text {
|
||||
color: #4080ff;
|
||||
font-size: 12px;
|
||||
border: 1px solid #4080ff;
|
||||
border-radius: 10px;
|
||||
padding: 0 5px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.balance-amount {
|
||||
font-size: 32px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.btn-recharge,
|
||||
.btn-withdraw {
|
||||
border: none;
|
||||
padding: 8px 60rpx;
|
||||
border-radius: 5px;
|
||||
margin-right: 30rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.btn-recharge {
|
||||
background-color: #4080ff;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-withdraw {
|
||||
background-color: white;
|
||||
border: 1px solid #ddd;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.transaction-filter {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 15px;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.transaction-list {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.transaction-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 15px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.transaction-type {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
margin-bottom: 5px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.transaction-date {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.transaction-amount {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.amount-positive {
|
||||
color: #4caf50;
|
||||
}
|
||||
|
||||
.transaction-reference {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
font-weight: normal;
|
||||
margin-top: 5px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.transaction-footer {
|
||||
text-align: center;
|
||||
color: #999;
|
||||
font-size: 12px;
|
||||
padding: 15px;
|
||||
background-color: white;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.date-picker-trigger {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
345
pages/mobile/user/index.vue
Normal file
@ -0,0 +1,345 @@
|
||||
<template>
|
||||
<div class="user-container">
|
||||
<!-- 顶部蓝色背景 -->
|
||||
<div class="top-bg"></div>
|
||||
|
||||
<!-- 用户信息卡片 -->
|
||||
<div class="user-card">
|
||||
<!-- 用户信息 -->
|
||||
<div class="user-info">
|
||||
<img class="avatar" src="~/assets/images/avater2.png" />
|
||||
<div class="login-info">
|
||||
<div class="login-text">登录/注册</div>
|
||||
<div class="login-desc">登录注册后享受更多精彩内容</div>
|
||||
</div>
|
||||
<!-- 设置图标 -->
|
||||
<div class="setting-icon">⚙️</div>
|
||||
</div>
|
||||
|
||||
<!-- 数据统计 -->
|
||||
<div class="data-stats">
|
||||
<div class="stat-item">
|
||||
<div class="stat-num">200</div>
|
||||
<div class="stat-text">金币余额(元)</div>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<div class="stat-num">135</div>
|
||||
<div class="stat-text">今日浏览量</div>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<div class="stat-num">370</div>
|
||||
<div class="stat-text">今日收益(元)</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 资源中心区域 -->
|
||||
<div class="resource-section">
|
||||
<div class="section-title">资源中心</div>
|
||||
|
||||
<div class="resource-grid">
|
||||
<div class="resource-item">
|
||||
<div class="resource-icon blue">
|
||||
<img
|
||||
src="~/assets/images/my_release.png"
|
||||
alt=""
|
||||
srcset=""
|
||||
class="w-77rpx h-71rpx"
|
||||
/>
|
||||
</div>
|
||||
<span class="resource-text">我的发布</span>
|
||||
</div>
|
||||
|
||||
<div class="resource-item">
|
||||
<div class="resource-icon blue">
|
||||
<img
|
||||
src="~/assets/images/my_download.png"
|
||||
alt=""
|
||||
srcset=""
|
||||
class="w-98rpx h-68rpx"
|
||||
/>
|
||||
</div>
|
||||
<span class="resource-text">我的下载</span>
|
||||
</div>
|
||||
|
||||
<div class="resource-item">
|
||||
<div class="resource-icon blue">
|
||||
<img
|
||||
src="~/assets/images/my_attention.png"
|
||||
alt=""
|
||||
srcset=""
|
||||
class="w-76rpx h-77rpx"
|
||||
/>
|
||||
</div>
|
||||
<span class="resource-text">我的关注</span>
|
||||
</div>
|
||||
|
||||
<div class="resource-item">
|
||||
<div class="resource-icon blue">
|
||||
<img
|
||||
src="~/assets/images/my_collect.png"
|
||||
alt=""
|
||||
srcset=""
|
||||
class="w-64rpx h-73rpx"
|
||||
/>
|
||||
</div>
|
||||
<span class="resource-text">我的收藏</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 功能列表 -->
|
||||
<div class="function-list">
|
||||
<!-- 安全中心 -->
|
||||
<div class="function-item" @click="navigateTo('/mobile/safety')">
|
||||
<div class="function-left">
|
||||
<div class="function-icon orange">✅</div>
|
||||
<span class="function-text">安全中心</span>
|
||||
</div>
|
||||
<span>›</span>
|
||||
</div>
|
||||
|
||||
<!-- 消息中心 -->
|
||||
<div class="function-item" @click="navigateTo('/mobile/message_notice')">
|
||||
<div class="function-left">
|
||||
<div class="function-icon blue">🔔</div>
|
||||
<span class="function-text">消息中心</span>
|
||||
</div>
|
||||
<span>›</span>
|
||||
</div>
|
||||
|
||||
<!-- 交易记录 -->
|
||||
<div
|
||||
class="function-item"
|
||||
@click="navigateTo('/mobile/transaction_record')"
|
||||
>
|
||||
<div class="function-left">
|
||||
<div class="function-icon green">🧾</div>
|
||||
<span class="function-text">交易记录</span>
|
||||
</div>
|
||||
<span>›</span>
|
||||
</div>
|
||||
|
||||
<!-- 关于我们 -->
|
||||
<div class="function-item" @click="navigateTo('/mobile/about')">
|
||||
<div class="function-left">
|
||||
<div class="function-icon purple">ℹ️</div>
|
||||
<span class="function-text">关于我们</span>
|
||||
</div>
|
||||
<span>›</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
definePageMeta({ layout: 'm' })
|
||||
import { useRouter } from 'vue-router'
|
||||
const router = useRouter()
|
||||
function navigateTo(url: string) {
|
||||
router.push(url)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
// 颜色变量
|
||||
$primary-color: #0080ff;
|
||||
$orange-color: #ff9500;
|
||||
$green-color: #34c759;
|
||||
$purple-color: #af52de;
|
||||
$text-primary: #333;
|
||||
$text-secondary: #999;
|
||||
$bg-color: #f7f7f7;
|
||||
$card-bg: #ffffff;
|
||||
$border-color: #f5f5f5;
|
||||
|
||||
.user-container {
|
||||
min-height: 100vh;
|
||||
background-color: $bg-color;
|
||||
position: relative;
|
||||
padding-top: 127rpx;
|
||||
|
||||
// 顶部蓝色背景
|
||||
.top-bg {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 200rpx;
|
||||
background-color: $primary-color;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
// 用户信息卡片
|
||||
.user-card {
|
||||
position: relative;
|
||||
margin: 0 20rpx;
|
||||
padding: 30rpx;
|
||||
background-color: $card-bg;
|
||||
border-radius: 16rpx;
|
||||
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
|
||||
z-index: 1;
|
||||
|
||||
.user-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.avatar {
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
border-radius: 60rpx;
|
||||
margin-right: 20rpx;
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.login-info {
|
||||
flex: 1;
|
||||
|
||||
.login-text {
|
||||
font-size: 34rpx;
|
||||
font-weight: 500;
|
||||
color: $text-primary;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.login-desc {
|
||||
font-size: 24rpx;
|
||||
color: $text-secondary;
|
||||
}
|
||||
}
|
||||
|
||||
.setting-icon {
|
||||
padding: 10rpx;
|
||||
}
|
||||
}
|
||||
|
||||
// 数据统计
|
||||
.data-stats {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-top: 30rpx;
|
||||
|
||||
.stat-item {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
.stat-num {
|
||||
font-size: 36rpx;
|
||||
font-weight: 500;
|
||||
color: $text-primary;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.stat-text {
|
||||
font-size: 24rpx;
|
||||
color: $text-secondary;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 资源中心
|
||||
.resource-section {
|
||||
margin: 20rpx;
|
||||
padding: 30rpx;
|
||||
background-color: $card-bg;
|
||||
border-radius: 16rpx;
|
||||
|
||||
.section-title {
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
color: $text-primary;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.resource-grid {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.resource-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 25%;
|
||||
|
||||
.resource-icon {
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-bottom: 16rpx;
|
||||
|
||||
&.blue {
|
||||
// background-color: $primary-color;
|
||||
}
|
||||
}
|
||||
|
||||
.resource-text {
|
||||
font-size: 28rpx;
|
||||
color: $text-primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 功能列表
|
||||
.function-list {
|
||||
margin: 20rpx;
|
||||
background-color: $card-bg;
|
||||
border-radius: 16rpx;
|
||||
overflow: hidden;
|
||||
|
||||
.function-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 30rpx;
|
||||
border-bottom: 1px solid $border-color;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.function-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.function-icon {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-right: 20rpx;
|
||||
|
||||
&.orange {
|
||||
background-color: $orange-color;
|
||||
}
|
||||
|
||||
&.blue {
|
||||
background-color: $primary-color;
|
||||
}
|
||||
|
||||
&.green {
|
||||
background-color: $green-color;
|
||||
}
|
||||
|
||||
&.purple {
|
||||
background-color: $purple-color;
|
||||
}
|
||||
}
|
||||
|
||||
.function-text {
|
||||
font-size: 30rpx;
|
||||
color: $text-primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
152
pages/mobile/user_info/index.vue
Normal file
@ -0,0 +1,152 @@
|
||||
<template>
|
||||
<div class="user-info-container">
|
||||
<div class="info-item">
|
||||
<div class="label">头像</div>
|
||||
<div class="value">
|
||||
<img :src="userInfo.avatar" alt="User Avatar" class="avatar" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="info-item">
|
||||
<div class="label">用户名</div>
|
||||
<div class="value">{{ userInfo.username }}</div>
|
||||
</div>
|
||||
|
||||
<div class="info-item">
|
||||
<div class="label">真实姓名</div>
|
||||
<div class="value">
|
||||
{{ userInfo.realName }}
|
||||
<span v-if="userInfo.verified" class="verified-badge">已认证</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="info-item">
|
||||
<div class="label">手机号</div>
|
||||
<div class="value">{{ userInfo.phone }}</div>
|
||||
</div>
|
||||
|
||||
<div class="info-item">
|
||||
<div class="label">邮箱</div>
|
||||
<div class="value">{{ userInfo.email }}</div>
|
||||
</div>
|
||||
|
||||
<div class="info-item">
|
||||
<div class="label">城市</div>
|
||||
<div class="value">{{ userInfo.city }}</div>
|
||||
</div>
|
||||
|
||||
<div class="info-item">
|
||||
<div class="label">技能标签</div>
|
||||
<div class="value">
|
||||
<span v-for="(tag, index) in userInfo.tags" :key="index" class="tag">
|
||||
#{{ tag }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="info-item">
|
||||
<div class="label">技能证书</div>
|
||||
<div class="value certificates">
|
||||
<img
|
||||
v-for="(cert, index) in userInfo.certificates"
|
||||
:key="index"
|
||||
:src="cert"
|
||||
alt="Certificate"
|
||||
class="certificate-image"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="info-item">
|
||||
<div class="label">个人简介</div>
|
||||
<div class="value bio">{{ userInfo.bio }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
definePageMeta({ layout: 'm' })
|
||||
import { reactive } from 'vue'
|
||||
|
||||
const userInfo = reactive({
|
||||
avatar: "/static/images/avater2.png",
|
||||
username: "王刚",
|
||||
realName: "王刚",
|
||||
verified: true,
|
||||
phone: "138******96",
|
||||
email: "651234754@qq.com",
|
||||
city: "重庆",
|
||||
tags: ["五金工具", "电子产品"],
|
||||
certificates: [
|
||||
"/static/images/cert1.jpg",
|
||||
"/static/images/cert2.jpg",
|
||||
"/static/images/cert3.jpg",
|
||||
],
|
||||
bio: "你好!我是专注于工业设计和机械设计领域...",
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.user-info-container {
|
||||
padding: 20px;
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
padding: 12px 0;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
.label {
|
||||
width: 80px;
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.value {
|
||||
flex: 1;
|
||||
text-align: right;
|
||||
color: #333;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.verified-badge {
|
||||
background-color: #4080ff;
|
||||
color: white;
|
||||
padding: 2px 8px;
|
||||
border-radius: 12px;
|
||||
font-size: 12px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.tag {
|
||||
margin-left: 8px;
|
||||
color: #4080ff;
|
||||
}
|
||||
|
||||
.certificates {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.certificate-image {
|
||||
width: 60px;
|
||||
height: 80px;
|
||||
margin-left: 10px;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.bio {
|
||||
text-align: left;
|
||||
line-height: 1.5;
|
||||
}
|
||||
</style>
|
||||
@ -1,6 +1,5 @@
|
||||
<template>
|
||||
<!-- 导航 -->
|
||||
<SeoHead title="工程设计模型下载_CAD设计图纸资源库" />
|
||||
<KlNavTab active="模型" :type="3" />
|
||||
<div class="ma-auto w-[1440px]">
|
||||
<!-- 图纸分类 -->
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
<template>
|
||||
<!-- 导航 -->
|
||||
<SeoHead title="工程设计模型下载_CAD设计图纸资源库" />
|
||||
<KlNavTab active="模型" :type="3" />
|
||||
<div class="ma-auto w-[1440px]">
|
||||
<!-- 图纸分类 -->
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<KlNavTab />
|
||||
<div class="ma-auto w-[1198px] flex justify-between">
|
||||
<div class="mx-auto w-[1198px] flex justify-between">
|
||||
<div
|
||||
class="left mt-[25px] box-border h-[370px] w-[260px] border border-[#EEEEEE] rounded-[4px] border-solid bg-[#FFFFFF] text-[15px] text-[#333333] font-medium"
|
||||
>
|
||||
@ -15,7 +15,7 @@
|
||||
</div>
|
||||
</nuxt-link>
|
||||
|
||||
<nuxt-link to="/personal-Center/personal-profile" class="flex items-center justify-between py-[14px]">
|
||||
<!-- <nuxt-link to="/personal-Center/personal-profile" class="flex items-center justify-between py-[14px]">
|
||||
<div class="flex items-center pl-[20px]">
|
||||
<img v-if="!route.path.startsWith('/personal-Center/personal-profile')" src="~/assets/images/user_zl.png" alt="" srcset="" class="h-[16px]" />
|
||||
<img v-else src="~/assets/images/个人资料 (1).png" alt="" srcset="" class="h-[16px]" />
|
||||
@ -34,6 +34,16 @@
|
||||
<div class="pr-[20px]">
|
||||
<el-icon><ArrowRight /></el-icon>
|
||||
</div>
|
||||
</nuxt-link> -->
|
||||
<nuxt-link to="/personal-Center/account-management" class="flex items-center justify-between py-[14px]">
|
||||
<div class="flex items-center pl-[20px]">
|
||||
<img v-if="!route.path.startsWith('/personal-Center/account-management')" src="~/assets/images/account.png" alt="" srcset="" class="h-[20px]" />
|
||||
<img v-else src="~/assets/images/账户安全.png" alt="" srcset="" class="h-[20px]" />
|
||||
<span class="ml-[14px]">账户管理</span>
|
||||
</div>
|
||||
<div class="pr-[20px]">
|
||||
<el-icon><ArrowRight /></el-icon>
|
||||
</div>
|
||||
</nuxt-link>
|
||||
<nuxt-link to="/personal-Center/resource-center" class="flex items-center justify-between py-[14px]">
|
||||
<div class="flex items-center pl-[20px]">
|
||||
|
||||
26
pages/personal-Center/index/account-bind.vue
Normal file
@ -0,0 +1,26 @@
|
||||
<template>
|
||||
<div class="box-border w-auto border border-[#EEEEEE] rounded-6px border-solid bg-[#FFFFFF] px-30px py-21px mt-10px">
|
||||
<div class="flex flex-col justify-center text-[14px] text-[#333333] font-normal">
|
||||
<div class="mt-[6px] flex items-center">
|
||||
<img src="~/assets/images/qq-v2.png" alt="" srcset="" class="h-[35px] w-[34px]" />
|
||||
<div class="ml-[19px] w-50px">手机号</div>
|
||||
<div class="ml-[100px] flex items-center"><div class="w-[90px]">手机号码:</div><div class="w-[180px]">xxx</div></div>
|
||||
<div class="btn">绑定</div>
|
||||
</div>
|
||||
<div class="mt-[30px] flex items-center">
|
||||
<img src="~/assets/images/qq-v2.png" alt="" srcset="" class="h-[35px] w-[34px]" />
|
||||
<div class="ml-[19px] w-50px">QQ</div>
|
||||
<div class="ml-[100px] flex items-center"><div class="w-[90px]">QQ昵称:</div><div class="w-[180px]">xxx</div></div>
|
||||
<div class="btn">绑定</div>
|
||||
</div>
|
||||
<div class="mt-[30px] flex items-center">
|
||||
<img src="~/assets/images/weixin-v2.png" alt="" srcset="" class="h-[35px] w-[34px]" />
|
||||
<div class="ml-[19px] w-50px">微信</div>
|
||||
<div class="ml-[95px] flex items-center"><div class="w-[90px]">微信昵称:</div><div class="w-[180px]">xxx</div></div>
|
||||
<div class="btn">绑定</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts"></script>
|
||||
18
pages/personal-Center/index/account-logout.vue
Normal file
@ -0,0 +1,18 @@
|
||||
<template>
|
||||
<div class="box-border w-auto border border-[#EEEEEE] rounded-6px border-solid bg-[#FFFFFF] px-30px py-21px mt-10px">
|
||||
<el-button type="danger" @click="handleClick">注销账号</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const handleClick = () => {
|
||||
console.log('注销账号')
|
||||
ElMessageBox.confirm('确定注销账号吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
}).then(() => {
|
||||
console.log('注销账号')
|
||||
})
|
||||
}
|
||||
</script>
|
||||
18
pages/personal-Center/index/account-management.vue
Normal file
@ -0,0 +1,18 @@
|
||||
<template>
|
||||
<div class="box-border w-913px border border-[#EEEEEE] rounded-6px border-solid bg-[#FFFFFF] px-30px py-21px">
|
||||
<el-tabs v-model="activeName" class="demo-tabs">
|
||||
<el-tab-pane label="个人资料" name="个人资料">
|
||||
<PersonalProfile />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="账户安全" name="账户安全">
|
||||
<AccountSecurityV2 />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import AccountSecurityV2 from './account-security-v2.vue'
|
||||
import PersonalProfile from './personal-profile.vue'
|
||||
const activeName = ref('个人资料')
|
||||
</script>
|
||||
37
pages/personal-Center/index/account-security-v2.vue
Normal file
@ -0,0 +1,37 @@
|
||||
<template>
|
||||
<KlTabBar v-model="type" :data="tabBar" />
|
||||
<div v-if="type === '修改密码'">
|
||||
<AccountSecurity />
|
||||
</div>
|
||||
<div v-else-if="type === '账号绑定'">
|
||||
<AccountBind />
|
||||
</div>
|
||||
<div v-else-if="type === '账号注销'">
|
||||
<AccountLogout />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import KlTabBar from '~/components/kl-tab-bar/v2/index.vue'
|
||||
import AccountSecurity from './account-security.vue'
|
||||
import AccountBind from './account-bind.vue'
|
||||
import AccountLogout from './account-logout.vue'
|
||||
|
||||
const tabBar = ref([
|
||||
{
|
||||
label: '修改密码',
|
||||
value: '修改密码',
|
||||
},
|
||||
{
|
||||
label: '账号绑定',
|
||||
value: '账号绑定',
|
||||
},
|
||||
{
|
||||
label: '账号注销',
|
||||
value: '账号注销',
|
||||
},
|
||||
])
|
||||
const type = ref('修改密码')
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="box-border w-913px border border-[#EEEEEE] rounded-6px border-solid bg-[#FFFFFF] px-30px py-21px">
|
||||
<el-tabs v-model="activeName" class="demo-tabs">
|
||||
<el-tab-pane label="修改密码" name="修改密码">
|
||||
<div class="box-border w-auto border border-[#EEEEEE] rounded-6px border-solid bg-[#FFFFFF] px-30px py-21px mt-10px">
|
||||
<!-- <el-tabs v-model="activeName" class="demo-tabs"> -->
|
||||
<!-- <el-tab-pane label="修改密码" name="修改密码"> -->
|
||||
<el-form ref="formRef" :model="form" label-width="120px" class="profile-form" autocomplete="off">
|
||||
<el-form-item
|
||||
label="手机号"
|
||||
@ -19,7 +19,7 @@
|
||||
<el-input v-model="form.phone" type="text" placeholder="请输入手机号" class="h-37px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="验证码" prop="code" class="mt-15px!" :rules="{ required: true, message: '请输入验证码', trigger: ['blur', 'change'] }">
|
||||
<div class="flex items-center gap10">
|
||||
<div class="flex items-center gap-10px">
|
||||
<el-input v-model="form.code" type="text" placeholder="请输入验证码" class="h-37px" />
|
||||
<el-button
|
||||
type="primary"
|
||||
@ -46,9 +46,9 @@
|
||||
<el-button type="primary" class="h-37px w-121px line-height-37px" @click="handleSave">保存</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-tab-pane>
|
||||
<!-- </el-tab-pane> -->
|
||||
<!-- <el-tab-pane label="登录设备管理" name="登录设备管理"> </el-tab-pane> -->
|
||||
</el-tabs>
|
||||
<!-- </el-tabs> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@ -7,7 +7,10 @@
|
||||
<el-image :src="scope.row.iconUrl" fit="cover" alt="" srcset="" class="h-91px w-181px rd-4px" />
|
||||
<div class="ml-17px">
|
||||
<div class="text-16px text-[#333333] font-normal">{{ scope.row.title }}</div>
|
||||
<div class="text-14px text-[#333333] font-normal my-10px!">{{ dayjs(scope.row.createTime).format('YYYY-MM-DD HH:mm:ss') }}</div>
|
||||
<div class="text-14px text-[#333333] font-normal my-10px!">
|
||||
{{ dayjs(scope.row.createTime).format('YYYY-MM-DD HH:mm:ss') }}
|
||||
<span class="ml-10px">{{ scope.row.sizecountry }}</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="flex items-center">
|
||||
<img src="~/assets/images/look.png" alt="" srcset="" class="h-17px" />
|
||||
@ -78,6 +81,10 @@
|
||||
label: '文本',
|
||||
value: 2,
|
||||
},
|
||||
{
|
||||
label: '工具箱',
|
||||
value: 4,
|
||||
},
|
||||
])
|
||||
|
||||
const handleStatus = (status: number) => {
|
||||
|
||||
@ -1,12 +1,14 @@
|
||||
<template>
|
||||
<div class="box-border w-[913px] border border-[#EEEEEE] rounded-[6px] border-solid bg-[#FFFFFF] px-[30px] py-[18px]">
|
||||
<div class="flex items-center">
|
||||
<img :src="userStore.userInfoRes.avatar" alt="" srcset="" class="h-[105px] w-[105px] rounded-full" />
|
||||
<div class="relative">
|
||||
<img :src="userStore.userInfoRes.avatar" alt="" srcset="" class="h-[105px] w-[105px] rounded-full" />
|
||||
<img v-if="userStore.userInfoRes.vipLevel === 1" src="~/assets/svg/vip.svg" alt="" class="absolute bottom-[0px] right-[4px]" />
|
||||
<img v-if="userStore.userInfoRes.vipLevel === 2" src="~/assets/svg/svip.svg" alt="" class="absolute bottom-[0px] right-[5px]" />
|
||||
</div>
|
||||
<div class="ml-[29px]">
|
||||
<div class="flex items-center">
|
||||
<span class="text-[20px] text-[#333333] font-normal">Hi,{{ userStore.userInfoRes.nickname }}</span>
|
||||
<img v-if="userStore.userInfoRes.vipLevel === 1" src="~/assets/svg/vip.svg" alt="" class="relative top-[2px] ml-[5px]" />
|
||||
<img v-if="userStore.userInfoRes.vipLevel === 2" src="~/assets/svg/svip.svg" alt="" class="relative top-[2px] ml-[5px]" />
|
||||
<div
|
||||
class="ml-[18px] h-[30px] w-[80px] cursor-pointer border border-[#1A65FF] rounded-[15px] border-solid text-center text-[14px] text-[#1A65FF] font-normal line-height-[30px]"
|
||||
@click="handleClick"
|
||||
@ -16,7 +18,7 @@
|
||||
<div class="mt-[20px] flex items-center text-[14px] text-[#333333] font-normal">
|
||||
<div class="flex items-center">
|
||||
<img src="~/assets/images/cad_0 (1).png" alt="" srcset="" />
|
||||
<span class="ml-[4px]">我的积分: {{ userStaticInfo?.pointCount || 0 }}</span>
|
||||
<span class="ml-[4px]">我的金币: {{ userStaticInfo?.pointCount || 0 }}</span>
|
||||
</div>
|
||||
<div class="ml-[37px] flex items-center">
|
||||
<img src="~/assets/images/cad_0 (2).png" alt="" srcset="" />
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
<template>
|
||||
<div class="box-border h-[782px] w-[913px] border border-[#EEEEEE] rounded-[6px] border-solid bg-[#FFFFFF] px-[30px] py-[21px]">
|
||||
<div class="flex items-center justify-between border-b-[1px] border-b-[#eeeeee] border-b-solid pb-[18px]">
|
||||
<div class="box-border h-[682px] w-[913px] border border-[#EEEEEE] rounded-[6px] border-solid bg-[#FFFFFF] px-[30px] py-[21px]">
|
||||
<!-- <div class="flex items-center justify-between border-b-[1px] border-b-[#eeeeee] border-b-solid pb-[18px]">
|
||||
<div class="text-[16px] text-[#333333] font-normal">个人资料</div>
|
||||
<div class="flex items-center">
|
||||
<!-- <img src="~/assets/images/fans.png" alt="" srcset="" /> -->
|
||||
<img src="~/assets/images/fans.png" alt="" srcset="" />
|
||||
<span class="ml-[8px] text-[14px] text-[#333333] font-normal"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
<div class="user-profile-container">
|
||||
<div class="avatar-section">
|
||||
<el-upload class="avatar-uploader" action="#" :show-file-list="false" :auto-upload="false" :on-change="handleAvatarChange">
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
<template>
|
||||
<!-- 导航 -->
|
||||
<SeoHead title="工程设计文本下载_CAD设计图纸资源库" />
|
||||
<KlNavTab active="文本" :type="2" />
|
||||
<div class="ma-auto w-[1440px]">
|
||||
<!-- 图纸分类 -->
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
<template>
|
||||
<!-- 导航 -->
|
||||
<SeoHead title="工程设计文本下载_CAD设计图纸资源库" />
|
||||
<KlNavTab active="文本" :type="2" />
|
||||
<div class="ma-auto w-[1440px]">
|
||||
<!-- 图纸分类 -->
|
||||
|
||||
@ -37,18 +37,16 @@
|
||||
<!-- <div class="text-16px text-[#999999] font-normal">暂无数据</div> -->
|
||||
<el-empty v-if="!pageRes.list.length" :image="emptyImg"></el-empty>
|
||||
</div>
|
||||
<div class="mt-[20px]">
|
||||
<el-pagination
|
||||
v-model:current-page="pageReq.pageNum"
|
||||
:page-size="pageReq.pageSize"
|
||||
layout="total, sizes, prev, pager, next"
|
||||
:total="pageRes?.total"
|
||||
:page-sizes="[10, 20, 30]"
|
||||
class="justify-center!"
|
||||
@current-change="handleCurrentChange"
|
||||
@size-change="handleSizeChange"
|
||||
/>
|
||||
</div>
|
||||
<el-pagination
|
||||
v-if="pageRes?.list.length"
|
||||
v-model:current-page="pageReq.pageNum"
|
||||
:page-size="pageReq.pageSize"
|
||||
layout="total, prev, pager, next"
|
||||
:total="pageRes?.total"
|
||||
:page-sizes="[10, 20, 30]"
|
||||
class="mt-[20px]"
|
||||
@current-change="handleCurrentChange"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right w-[398px]">
|
||||
@ -115,10 +113,16 @@
|
||||
// total: 0,
|
||||
// })
|
||||
|
||||
const {data: pageRes, refresh: getPage } = await useAsyncData(`draw-page-list-${Date.now()}`, async () => {
|
||||
const res = await page(pageReq)
|
||||
return res.data
|
||||
})
|
||||
const { data: pageRes, refresh: getPage } = await useAsyncData(
|
||||
`draw-page-toobox-list`,
|
||||
async () => {
|
||||
const res = await page(pageReq)
|
||||
return res.data
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
}
|
||||
)
|
||||
|
||||
const loading = ref(false)
|
||||
// const getPage = () => {
|
||||
@ -153,13 +157,13 @@
|
||||
getPage()
|
||||
}
|
||||
|
||||
const {data: recommendList} = await useAsyncData(`draw-recommend-list-${Date.now()}`, async () => {
|
||||
const { data: recommendList } = await useAsyncData(`draw-recommend-list-getRelationRecommend`, async () => {
|
||||
const res = await getRelationRecommend({
|
||||
type: 4,
|
||||
})
|
||||
return res.data
|
||||
})
|
||||
|
||||
|
||||
// 猜你喜欢
|
||||
// const recommendList = ref<ProjectDrawPageRespVO[]>([]) // 猜你喜欢数据
|
||||
// const getRelationRecommendList = () => {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-form-item label-width="110px" :prop="`${props.vaildRules}.files`" :rules="{ required: true, message: '请上传图纸', trigger: ['blur', 'change'] }">
|
||||
<!-- <el-form-item label-width="110px" :prop="`${props.vaildRules}.files`" :rules="{ required: true, message: '请上传图纸', trigger: ['blur', 'change'] }">
|
||||
<KlUploader
|
||||
v-model:file-list="form.files"
|
||||
:limit="1000"
|
||||
@ -11,33 +11,44 @@
|
||||
@preview="handlePreview"
|
||||
>
|
||||
</KlUploader>
|
||||
</el-form-item>
|
||||
</el-form-item> -->
|
||||
<el-form-item
|
||||
label-width="110px"
|
||||
label="标题:"
|
||||
:prop="`${props.vaildRules}.title`"
|
||||
:rules="{ required: true, message: '请输入标题', trigger: ['blur', 'change'] }"
|
||||
:rules="[
|
||||
{ required: true, message: '10-25 字符,结构可用分类关键词+作品名/资源价值版本/使用场景', trigger: ['blur', 'change'] },
|
||||
{
|
||||
validator: (rule: any, value: any, callback: any) => {
|
||||
if (value && value.length < 10) {
|
||||
callback(new Error('10-25 字符,结构可用分类关键词+作品名/资源价值版本/使用场景'))
|
||||
}
|
||||
callback()
|
||||
},
|
||||
trigger: ['blur', 'change'],
|
||||
},
|
||||
]"
|
||||
>
|
||||
<el-input v-model="form.title" placeholder="请输入标题" class="w-361px!" maxlength="128"></el-input>
|
||||
<el-input v-model="form.title" placeholder="10-25 字符,结构可用分类关键词+作品名/资源价值版本/使用场景" minlength="20" maxlength="50"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label-width="110px"
|
||||
label="分类:"
|
||||
label="专业分类:"
|
||||
:prop="`${props.vaildRules}.projectType`"
|
||||
:rules="{ required: true, message: '请选择分类', trigger: ['blur', 'change'] }"
|
||||
>
|
||||
<!-- <el-select v-model="form.projectType" placeholder="请选择分类" class="w-361px!" multiple>
|
||||
<el-option v-for="(item, index) in projectTypeList" :key="index" :label="item.name" :value="item.id" />
|
||||
</el-select> -->
|
||||
<el-cascader v-model="form.projectType" class="w-361px!" :options="projectTypeList" :props="cascaderProps" clearable collapse-tags />
|
||||
<el-cascader v-model="form.projectType" class="w-[100%]!" :options="projectTypeList" :props="cascaderProps" clearable collapse-tags />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label-width="110px"
|
||||
label="软件版本:"
|
||||
label="软件分类:"
|
||||
:prop="`${props.vaildRules}.editions`"
|
||||
:rules="{ required: true, message: '请选择软件版本', trigger: ['blur', 'change'] }"
|
||||
>
|
||||
<el-select v-model="form.editions" placeholder="请选择软件版本" class="w-361px!">
|
||||
<el-select v-model="form.editions" placeholder="请选择软件版本">
|
||||
<el-option v-for="(item, index) in editionsList" :key="index" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
@ -54,20 +65,11 @@
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label-width="110px"
|
||||
label="标签:"
|
||||
label="作品标签:"
|
||||
:prop="`${props.vaildRules}.labels`"
|
||||
:rules="{ required: true, message: '请选择标签', trigger: ['blur', 'change'] }"
|
||||
:rules="{ required: false, message: '请选择标签', trigger: ['blur', 'change'] }"
|
||||
>
|
||||
<el-select
|
||||
v-model="form.labels"
|
||||
:remote-method="remoteMethod"
|
||||
:loading="loading"
|
||||
multiple
|
||||
filterable
|
||||
remote
|
||||
placeholder="请输入搜索标签"
|
||||
class="w-361px!"
|
||||
>
|
||||
<el-select v-model="form.labels" :remote-method="remoteMethod" :loading="loading" multiple filterable remote placeholder="请输入搜索标签">
|
||||
<el-option v-for="(item, index) in labelsList" :key="index" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
@ -75,11 +77,11 @@
|
||||
label-width="110px"
|
||||
label="金币:"
|
||||
:prop="`${props.vaildRules}.points`"
|
||||
:rules="{ required: true, message: '请输入金币', trigger: ['blur', 'change'] }"
|
||||
:rules="{ required: true, message: '金币设置分销为0-15,设置0金币为专属资源可直接获利2-15金币', trigger: ['blur', 'change'] }"
|
||||
>
|
||||
<el-input-number v-model="form.points" :controls="false" :precision="0" :min="0" placeholder="请输入金币" class="w-361px! text-left!"></el-input-number>
|
||||
<el-input-number v-model="form.points" :controls="false" :precision="0" :min="0" placeholder="金币设置分销为0-15,设置0金币为专属资源可直接获利2-15金币" class="w-[100%]! text-left!"></el-input-number>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
<!-- <el-form-item
|
||||
label-width="110px"
|
||||
label="图形格式:"
|
||||
:prop="`${props.vaildRules}.formatType`"
|
||||
@ -88,7 +90,7 @@
|
||||
<el-checkbox-group v-model="form.formatType">
|
||||
<el-checkbox v-for="(item, index) in formatTypeList" :key="index" :label="item" :value="item"></el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
</el-form-item> -->
|
||||
<el-form-item
|
||||
label-width="110px"
|
||||
label="上传封面:"
|
||||
@ -103,9 +105,9 @@
|
||||
tips="上传图片支持jpg/gif/png格式、第一张为封面图片、每张图片大小不得超过1M"
|
||||
@validate="formRef?.validateField(`${props.vaildRules}.coverImages`)"
|
||||
>
|
||||
<div class="h-77px w-161px flex items-center justify-center border border-[#cdd0d6] rounded-1px border-dashed bg-[#fafafa]">
|
||||
<div class="h-[77px] w-[161px] flex items-center justify-center border border-[#cdd0d6] rounded-[1px] border-dashed bg-[#fafafa]">
|
||||
<el-icon class="text-[#999999]"><Plus /></el-icon>
|
||||
<div class="ml-4px mt-2px text-14px text-[#999999] font-normal">上传图纸</div>
|
||||
<div class="ml-[4px] mt-[2px] text-[14px] text-[#999999] font-normal">上传图纸</div>
|
||||
</div>
|
||||
</KlUploader>
|
||||
</el-form-item>
|
||||
@ -123,26 +125,26 @@
|
||||
:show-tip="false"
|
||||
@validate="formRef?.validateField(`${props.vaildRules}.renderings`)"
|
||||
>
|
||||
<div class="h-77px w-161px flex items-center justify-center border border-[#cdd0d6] rounded-1px border-dashed bg-[#fafafa]">
|
||||
<div class="h-[77px] w-[161px] flex items-center justify-center border border-[#cdd0d6] rounded-[1px] border-dashed bg-[#fafafa]">
|
||||
<el-icon class="text-[#999999]"><Plus /></el-icon>
|
||||
<div class="ml-4px mt-2px text-14px text-[#999999] font-normal">上传图纸</div>
|
||||
<div class="ml-[4px] mt-[2px] text-[14px] text-[#999999] font-normal">上传图纸</div>
|
||||
</div>
|
||||
</KlUploader>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="110px" label="上传附件:">
|
||||
<el-form-item label-width="110px" label="上传附件:" :prop="`${props.vaildRules}.otherFiles`" :rules="{ required: true, message: '请上传附件', trigger: ['blur', 'change'] }">
|
||||
<KlUploader v-model:file-list="form.otherFiles" tips="请将系列文件分别压缩后上传,支持批量上传"> </KlUploader>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label-width="110px"
|
||||
label="描述:"
|
||||
label="作品描述:"
|
||||
:prop="`${props.vaildRules}.description`"
|
||||
:rules="[
|
||||
{ required: true, message: '请输入描述', trigger: ['blur', 'change'] },
|
||||
{ required: true, message: '简介字数限制30-75 字符,需包含用途、文件介绍、适用场景等', trigger: ['blur', 'change'] },
|
||||
{
|
||||
validator: (rule, value, callback) => {
|
||||
console.log(rule)
|
||||
if (value.length < 70) {
|
||||
callback(new Error('输入内容不能少于 70 字'))
|
||||
if (value.length < 30) {
|
||||
callback(new Error('简介字数限制30-75 字符,需包含用途、文件介绍、适用场景等'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
@ -151,7 +153,7 @@
|
||||
},
|
||||
]"
|
||||
>
|
||||
<el-input v-model="form.description" type="textarea" :rows="6" placeholder="请输入描述" class="w-361px!" minlength="70" show-word-limit></el-input>
|
||||
<el-input v-model="form.description" type="textarea" :rows="6" placeholder="简介字数限制30-75 字符,需包含用途、文件介绍、适用场景等" minlength="60" maxlength="150" show-word-limit></el-input>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</template>
|
||||
@ -216,7 +218,7 @@
|
||||
formatTypeList.value = res.data
|
||||
})
|
||||
}
|
||||
getFormatTypeList()
|
||||
// getFormatTypeList()
|
||||
|
||||
const projectTypeList = ref<any>([])
|
||||
/** 获取分类下拉框 */
|
||||
@ -225,7 +227,6 @@
|
||||
projectTypeList.value = res.data
|
||||
})
|
||||
}
|
||||
getParent()
|
||||
|
||||
/** 版本 */
|
||||
const editionsList = ref<any>([])
|
||||
@ -237,11 +238,15 @@
|
||||
editionsList.value = res.data
|
||||
})
|
||||
}
|
||||
getEditionsList()
|
||||
|
||||
const handlePreview = (val: any) => {
|
||||
emit('preview', val)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getEditionsList()
|
||||
getParent()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="box-border border border-[#EEEEEE] rounded-12px border-solid bg-[#FFFFFF] px-33px py-22px pb-10px!">
|
||||
<div class="box-border border border-[#EEEEEE] rounded-[12px] border-solid bg-[#FFFFFF] px-[33px] py-[22px] pb-[10px]!">
|
||||
<el-form-item
|
||||
label="选择上传资料类型:"
|
||||
label-width="170px"
|
||||
@ -7,37 +7,40 @@
|
||||
prop="type"
|
||||
:rules="[{ required: true, message: '请选择上传资料类型', trigger: 'change' }]"
|
||||
>
|
||||
<el-checkbox-group v-model="form.type" @change="handleTypeChange">
|
||||
<el-checkbox :value="1">图纸</el-checkbox>
|
||||
<el-checkbox :value="3">模型</el-checkbox>
|
||||
<el-checkbox :value="2">文本</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
<el-radio-group v-model="form.type" @change="handleTypeChange(form.type)">
|
||||
<el-radio :value="1">图纸</el-radio>
|
||||
<el-radio :value="3">模型</el-radio>
|
||||
<el-radio :value="2">文本</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="选择国家:"
|
||||
label-width="110px"
|
||||
label-position="left"
|
||||
prop="isDomestic"
|
||||
:rules="[{ required: true, message: '请选择国家', trigger: 'change' }]"
|
||||
>
|
||||
<el-select v-model="form.isDomestic" placeholder="请选择" class="w-200px!" @change="handleCountryChange">
|
||||
<el-option label="国内" :value="1"></el-option>
|
||||
<el-option label="国外" :value="0"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<div class="flex">
|
||||
<div class="flex gap-[20px]">
|
||||
<el-form-item
|
||||
label="选择国家:"
|
||||
label-width="110px"
|
||||
label-position="left"
|
||||
prop="isDomestic"
|
||||
:rules="[{ required: true, message: '请选择国家', trigger: 'change' }]"
|
||||
>
|
||||
<el-select v-model="form.isDomestic" placeholder="请选择" class="w-[240px]!" @change="handleCountryChange">
|
||||
<el-option label="国内" :value="1"></el-option>
|
||||
<el-option label="国外" :value="0"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="form.isDomestic === 0"
|
||||
label="所在地区:"
|
||||
label-width="110px"
|
||||
label-position="left"
|
||||
prop="province"
|
||||
:rules="[{ required: true, message: '请选择所在地区', trigger: 'change' }]"
|
||||
>
|
||||
<el-select v-model="form.province" placeholder="请选择" class="w-200px!" @change="handleProvinceChange">
|
||||
<el-select v-model="form.province" filterable placeholder="请选择" class="w-[240px]!">
|
||||
<el-option v-for="(item, index) in provinceList" :key="index" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="10px" label-position="left" prop="city" :rules="[{ required: true, message: '请选择地址', trigger: 'change' }]">
|
||||
</div>
|
||||
<!-- <div class="flex"> -->
|
||||
<!-- <el-form-item label-width="10px" label-position="left" prop="city" :rules="[{ required: true, message: '请选择地址', trigger: 'change' }]">
|
||||
<el-select v-model="form.city" placeholder="请选择" class="w-200px!" @change="handleCityChange">
|
||||
<el-option v-for="(item, index) in cityList" :key="index" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
@ -46,8 +49,8 @@
|
||||
<el-select v-model="form.county" placeholder="请选择" class="w-200px!">
|
||||
<el-option v-for="(item, index) in countyList" :key="index" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form-item> -->
|
||||
<!-- </div> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -63,32 +66,16 @@
|
||||
|
||||
// 添加旧值引用
|
||||
const oldTypeValue = ref<(number | string)[]>([])
|
||||
const handleTypeChange = (val: any) => {
|
||||
console.log(val, 'val')
|
||||
|
||||
// 新增的项(当前值有但旧值没有的)
|
||||
const added = val.filter((item: number | string) => !oldTypeValue.value.includes(item))
|
||||
// 减少的项(旧值有但当前值没有的)
|
||||
const removed = oldTypeValue.value.filter((item) => !val.includes(item))
|
||||
|
||||
if (added.length) {
|
||||
form.value.draws.push({
|
||||
const handleTypeChange = (val: number) => {
|
||||
form.value.draws = [
|
||||
{
|
||||
...JSON.parse(JSON.stringify(DrawsEnmu)),
|
||||
type: added[0],
|
||||
})
|
||||
} else if (removed.length) {
|
||||
form.value.draws = form.value.draws.filter((item) => item.type !== removed[0])
|
||||
}
|
||||
|
||||
// 更新旧值
|
||||
oldTypeValue.value = [...val]
|
||||
// 更新当前activeName值
|
||||
if (!val?.length) {
|
||||
form.value.activeName = ''
|
||||
}
|
||||
type: val,
|
||||
},
|
||||
]
|
||||
|
||||
nextTick(() => {
|
||||
form.value.activeName = val[val.length - 1]
|
||||
form.value.activeName = val
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -1,34 +1,39 @@
|
||||
<template>
|
||||
<div class="ml-[23px] box-border min-h-[930px] w-[516px] border border-[#EEEEEE] rounded-[12px] border-solid bg-[#FFFFFF] px-[33px] py-[22px]">
|
||||
<div class="flex items-center">
|
||||
<img src="~/assets/images/preview.png" alt="" srcset="" width="16px" height="19px" /><span class="ml-[7px] text-[18px] text-[#333333] font-normal"
|
||||
>预览</span
|
||||
></div
|
||||
>
|
||||
<div class="mt-[20px]">
|
||||
<div class="ml-[23px] box-border h-[400px] w-[400px] border border-[#EEEEEE] rounded-[12px] border-solid bg-[#FFFFFF] px-[33px] py-[22px]">
|
||||
<!-- <div class="flex items-center">
|
||||
<img src="~/assets/images/preview.png" alt="" srcset="" width="16px" height="19px" /><span class="ml-[7px] text-[18px] text-[#333333] font-normal">
|
||||
预览
|
||||
</span>
|
||||
</div> -->
|
||||
<!-- <div class="mt-[20px]">
|
||||
<el-image :src="previewUrl" class="mb-[16px] max-h-[320px] max-w-[460px] min-h-[200px]" fit="contain"></el-image>
|
||||
<span class="text-[16px] text-[#333333] font-normal">{{ previewName || '图纸标题' }}</span></div
|
||||
>
|
||||
<div class="my-[30px] h-[1px] w-[460px] rounded-[1px] bg-[#EEEEEE]"></div>
|
||||
> -->
|
||||
<!-- <div class="my-[30px] h-[1px] w-[460px] rounded-[1px] bg-[#EEEEEE]"></div> -->
|
||||
<div class="flex items-center">
|
||||
<img src="~/assets/images/tip.png" width="20px" height="20px" />
|
||||
<span class="ml-[7px] text-[18px] text-[#333333] font-normal">
|
||||
上传遇到问题可以咨询
|
||||
</span>
|
||||
<!-- <img src="~/assets/images/tip.png" width="20px" height="20px" /> -->
|
||||
<span class="ml-[7px] text-[16px] text-[#666] font-normal">tips:遇到上传问题可以咨询 </span>
|
||||
</div>
|
||||
<div class="mt-[20px] text-center"><el-image src="https://picsum.photos/290/290?_t" alt="" srcset="" class="h-[290px] w-[290px]" /></div>
|
||||
<div class="mt-[30px] text-center text-[16px] text-[#333333] font-normal">
|
||||
<div class="mt-[20px] text-center">
|
||||
<!-- <qrcode-vue :value="wechatData" :size="200" level="H" class="mt-[10px]" /> -->
|
||||
<el-image :src="wechatData" alt="" srcset="" class="h-[290px] w-[290px]" />
|
||||
</div>
|
||||
<!-- <div class="mt-[30px] text-center text-[16px] text-[#333333] font-normal">
|
||||
<div>TEL:13315189735 </div>
|
||||
<div class="mt-[4px]">在线时间:8:30-18:00</div>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
// import QrcodeVue from 'qrcode.vue'
|
||||
import { getWechat } from '~/api/upnew/index'
|
||||
const previewUrl = defineModel<string>('previewUrl', {
|
||||
required: true,
|
||||
})
|
||||
const previewName = defineModel<string>('previewName', {
|
||||
required: true,
|
||||
})
|
||||
|
||||
const { data: wechatData } = await getWechat()
|
||||
</script>
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<KlNavTab />
|
||||
<!-- 发布图纸 -->
|
||||
<div class="ma-auto mt-[30px] w-[1440px] flex">
|
||||
<div class="w-[900px]">
|
||||
<div class="w-[1016px]">
|
||||
<el-form ref="formRef" :model="form" label-width="120px">
|
||||
<!-- 图纸分类 -->
|
||||
<DrawType ref="drawTypeRef" v-model="form" />
|
||||
@ -13,7 +13,7 @@
|
||||
<DrawForm v-if="form.draws[index]" v-model="form.draws[index]" :vaild-rules="'draws.' + index" :form-ref="formRef" @preview="handlePreview" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<el-form-item label-width="110px" class="mt-[20px]">
|
||||
<el-form-item label-width="110px">
|
||||
<!-- <el-button class="w-121px h-37px!" :loading="loading" @click="handleSubmit">预览</el-button> -->
|
||||
<el-button type="primary" class="w-[121px] h-[37px]!" :loading="loading" @click="handleSubmit">发布</el-button>
|
||||
</el-form-item>
|
||||
@ -36,9 +36,9 @@
|
||||
const router = useRouter() // 导入路由实例,用于跳转页面
|
||||
|
||||
const form = reactive<TcreateReq>({
|
||||
activeName: '', // 标签
|
||||
activeName: 1, // 标签
|
||||
id: '', // 图纸id id,示例值(24548)
|
||||
type: [], // 图纸类型 类型,示例值(1)
|
||||
type: 1, // 图纸类型 类型,示例值(1)
|
||||
isDomestic: '', // 是否是国内: 1是 0否
|
||||
province: '', // 省份编码
|
||||
city: '', // 城市编码
|
||||
@ -93,11 +93,14 @@
|
||||
if (code === 0) {
|
||||
// 弹窗提示
|
||||
ElMessage.success('操作成功')
|
||||
router.back()
|
||||
// 关闭弹窗
|
||||
// setTimeout(() => {
|
||||
// window.close()
|
||||
// }, 300)
|
||||
// 跳转页面
|
||||
if (form.type === 1) {
|
||||
navigateTo('/drawe')
|
||||
} else if (form.type === 2) {
|
||||
navigateTo('/text')
|
||||
} else if (form.type === 3) {
|
||||
navigateTo('/model')
|
||||
}
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
@ -121,12 +124,12 @@
|
||||
}
|
||||
|
||||
// 图纸类型
|
||||
const drawTypeRef = ref()
|
||||
const drawTypeRef = ref<InstanceType<typeof DrawType>>()
|
||||
onMounted(() => {
|
||||
// 初始化图纸类型
|
||||
drawTypeRef.value.handleTypeChange([1])
|
||||
drawTypeRef.value?.handleTypeChange(1)
|
||||
// 初始化图纸类型
|
||||
form.type = [1]
|
||||
form.type = 1
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
||||