账户状态\待办事项\客服\客户管理页面迁移
This commit is contained in:
parent
0d17baa9c9
commit
65c88c24eb
@ -62,6 +62,11 @@ https:://apis.haibao.shop
|
|||||||
[腾讯的] (https://www.tapd.cn/tapd_fe/55592674/storywall)
|
[腾讯的] (https://www.tapd.cn/tapd_fe/55592674/storywall)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```shell
|
||||||
|
12. 分包命名
|
||||||
|
注意:分包命名不能与主包相同,主包为`pages`,分包为`pagesXxx`,xxx为分包名称,例如商城相关分包命名为`pagesShop`
|
||||||
|
```
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
12. PC端首页 https://www.haibao.shop
|
12. PC端首页 https://www.haibao.shop
|
||||||
13. 后台地址 https://apis.haibao.shop/index.html#/admin
|
13. 后台地址 https://apis.haibao.shop/index.html#/admin
|
||||||
|
960
package-lock.json
generated
960
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -59,9 +59,11 @@
|
|||||||
"@dcloudio/uni-mp-xhs": "3.0.0-alpha-3081220230802001",
|
"@dcloudio/uni-mp-xhs": "3.0.0-alpha-3081220230802001",
|
||||||
"@dcloudio/uni-quickapp-webview": "3.0.0-alpha-3081220230802001",
|
"@dcloudio/uni-quickapp-webview": "3.0.0-alpha-3081220230802001",
|
||||||
"@dcloudio/uni-ui": "^1.4.28",
|
"@dcloudio/uni-ui": "^1.4.28",
|
||||||
|
"@tailwindcss/cli": "^4.1.12",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"pinia": "2.0.27",
|
"pinia": "2.0.27",
|
||||||
"pinia-plugin-persistedstate": "^3.2.0",
|
"pinia-plugin-persistedstate": "^3.2.0",
|
||||||
|
"tailwindcss": "^4.1.12",
|
||||||
"vue": "^3.2.47",
|
"vue": "^3.2.47",
|
||||||
"vue-i18n": "^9.2.2",
|
"vue-i18n": "^9.2.2",
|
||||||
"wot-design-uni": "^1.12.3"
|
"wot-design-uni": "^1.12.3"
|
||||||
|
@ -55,3 +55,11 @@ export const configIndex = (data : { page : number, page_size : number }) => {
|
|||||||
data,
|
data,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
// 移动端-首页接口-搜索接口
|
||||||
|
export const configSearch = (data:Record<string, any>) => {
|
||||||
|
return request({
|
||||||
|
url: '/api/index/search',
|
||||||
|
method: 'POST',
|
||||||
|
data,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
293
src/composables/useTodoPage.ts
Normal file
293
src/composables/useTodoPage.ts
Normal file
@ -0,0 +1,293 @@
|
|||||||
|
import { ref, unref, computed, nextTick } from 'vue'
|
||||||
|
import { useBackground } from './common/useBackground'
|
||||||
|
import { useRefreshLoad } from './common/useRefreshLoad'
|
||||||
|
import { useDataFetch } from './common/useDataFetch'
|
||||||
|
import { getBannerApi, getHotRecommendApi, getNoticeBartApi, configIndex, configSearch } from '@/api/home'
|
||||||
|
import { getTopCategoryApi } from '@/api/catogory'
|
||||||
|
import type { bannerItem, noticeBarItem } from '@/types/home'
|
||||||
|
|
||||||
|
|
||||||
|
export function useTodoPage() {
|
||||||
|
// ==================== 使用其他 composables ====================
|
||||||
|
const { backgroundStyle } = useBackground()
|
||||||
|
const topGradientStyle = useBackground().setTopGradientStyle('#FCDC9D', '#F2EFE7');
|
||||||
|
const {
|
||||||
|
isRefreshing,
|
||||||
|
isLoading,
|
||||||
|
hasMore,
|
||||||
|
currentPage,
|
||||||
|
handleRefresh,
|
||||||
|
handleLoadMore,
|
||||||
|
resetState,
|
||||||
|
} = useRefreshLoad({
|
||||||
|
showRefreshSuccess: true,
|
||||||
|
showLoadError: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
// ==================== 页面数据 ====================
|
||||||
|
const bannerList = ref<bannerItem[]>([])
|
||||||
|
const noticeBarList = ref<string[]>([])
|
||||||
|
const categoryList = ref<any[]>([])
|
||||||
|
const hotRecommendList = ref<any[]>([])
|
||||||
|
|
||||||
|
// 新增接口返回的数据
|
||||||
|
const menuList = ref<any[]>([])
|
||||||
|
const switchList = ref<any[]>([])
|
||||||
|
const systemInfo = ref<any>({})
|
||||||
|
const noticeInfo = ref<any>({})
|
||||||
|
const hbsmNotice = ref<any>({})
|
||||||
|
const blackInfo = ref<any>({})
|
||||||
|
|
||||||
|
|
||||||
|
// ==================== Tab切换相关 ====================
|
||||||
|
const activeTab = ref(0) // 当前激活的tab索引
|
||||||
|
const activeTabKey = ref('goods') // 当前激活的tab key
|
||||||
|
const tabContentList = ref<any[]>([]) // tab对应的内容列表
|
||||||
|
const tabLoading = ref(false) // tab内容加载状态
|
||||||
|
const tabCurrentPage = ref(1) // tab内容当前页
|
||||||
|
const tabHasMore = ref(true) // tab内容是否还有更多
|
||||||
|
|
||||||
|
// ==================== 数据获取 ====================
|
||||||
|
const { execute: fetchBanners } = useDataFetch(getBannerApi, {
|
||||||
|
immediate: false,
|
||||||
|
showLoading: false,
|
||||||
|
showError: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
const { execute: fetchNotices } = useDataFetch(getNoticeBartApi, {
|
||||||
|
immediate: false,
|
||||||
|
showLoading: false,
|
||||||
|
showError: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
const { execute: fetchCategories } = useDataFetch(getTopCategoryApi, {
|
||||||
|
immediate: false,
|
||||||
|
showLoading: false,
|
||||||
|
showError: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
const { execute: fetchHotRecommend } = useDataFetch(getHotRecommendApi, {
|
||||||
|
immediate: false,
|
||||||
|
showLoading: false,
|
||||||
|
showError: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
// ==================== 页面初始化 ====================
|
||||||
|
const initPage = async () => {
|
||||||
|
try {
|
||||||
|
await Promise.all([
|
||||||
|
fetchBanners(),
|
||||||
|
fetchNotices(),
|
||||||
|
fetchCategories(),
|
||||||
|
fetchHotRecommend(),
|
||||||
|
configIndexApi()
|
||||||
|
])
|
||||||
|
|
||||||
|
// 初始化完成后,加载默认tab的内容
|
||||||
|
if (switchList.value.length > 0) {
|
||||||
|
activeTabKey.value = switchList.value[0].keys
|
||||||
|
await loadTabContent(activeTabKey.value, 1, true)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('页面初始化失败:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== 刷新处理 ====================
|
||||||
|
const onRefresh = async () => {
|
||||||
|
await handleRefresh(async () => {
|
||||||
|
await initPage()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== 加载更多处理 ====================
|
||||||
|
const onLoadMore = async () => {
|
||||||
|
if (tabHasMore.value && !tabLoading.value) {
|
||||||
|
await loadTabContent(activeTabKey.value, tabCurrentPage.value + 1, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const configIndexApi = async () => {
|
||||||
|
try {
|
||||||
|
const res = await configIndex({ page: 1, page_size: 10 })
|
||||||
|
console.log(res, '-----------------configIndex')
|
||||||
|
|
||||||
|
if (res.code === 1 && res.data) {
|
||||||
|
const { data } = res
|
||||||
|
|
||||||
|
// 处理菜单数据
|
||||||
|
if (data.menu && Array.isArray(data.menu)) {
|
||||||
|
menuList.value = data.menu
|
||||||
|
}
|
||||||
|
bannerList.value = data.adv
|
||||||
|
|
||||||
|
// [
|
||||||
|
// { title: '推荐', route: '/pages/home/index' },
|
||||||
|
// { title: '合作伙伴', route: '/pagesMember/pages/profile/profile' },
|
||||||
|
// { title: '商机', route: '/pagesForeignTrade/pages/trade/trade' },
|
||||||
|
// { title: '关于我们', route: '/pagesOther/pages/blank/rich-text' },
|
||||||
|
// { title: '找买家', route: '/pagesMember/pages/profile/profile' },
|
||||||
|
// { title: '找卖家', route: '/pagesMember/pages/profile/profile' },
|
||||||
|
// ]
|
||||||
|
// 处理切换列表数据
|
||||||
|
if (data?.switchList && Array.isArray(data?.switchList)) {
|
||||||
|
switchList.value = data?.switchList
|
||||||
|
// 设置默认激活的tab
|
||||||
|
if (data.switchList.length > 0) {
|
||||||
|
activeTabKey.value = data.switchList[0].keys
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理系统信息
|
||||||
|
if (data.system) {
|
||||||
|
systemInfo.value = data.system
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理通知栏数据
|
||||||
|
if (data.notice) {
|
||||||
|
noticeInfo.value = data.notice
|
||||||
|
// 将通知列表转换为字符串数组格式
|
||||||
|
if (data.notice.list && Array.isArray(data.notice.list)) {
|
||||||
|
noticeBarList.value = data.notice.list.map((item : any) => item.content || item.title)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 处理海保世贸通知
|
||||||
|
if (data.hbsmNotice) {
|
||||||
|
hbsmNotice.value = data.hbsmNotice;
|
||||||
|
//弹出系统维护窗口
|
||||||
|
//status 系统提示状态,1=弹出系统提示, 弹出hbsm_notice.title,和hbsm_notice.content ; 0不用管
|
||||||
|
if (data.hbsmNotice.status == 1)
|
||||||
|
uni.showModal({
|
||||||
|
showCancel: false,
|
||||||
|
title: data.hbsmNotice.title,
|
||||||
|
content: data.hbsmNotice.content
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理黑名单信息
|
||||||
|
if (data.black) {
|
||||||
|
blackInfo.value = data.black
|
||||||
|
//status 黑名单状态,1=已被拉黑,弹窗弹窗,不能关闭,或者跳到新页面无法返回
|
||||||
|
if (data.black.status == 1) {
|
||||||
|
uni.setStorage({
|
||||||
|
key: 'blackInfo',
|
||||||
|
data: data.black,
|
||||||
|
success: () => {
|
||||||
|
uni.reLaunch({
|
||||||
|
url: '/pages/black/index'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取首页配置失败:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== Tab切换和内容加载 ====================
|
||||||
|
/**
|
||||||
|
* 切换Tab
|
||||||
|
* @param index tab索引
|
||||||
|
* @param tabKey tab的key值
|
||||||
|
*/
|
||||||
|
const switchTab = async (index : number, tabKey : string) => {
|
||||||
|
if (activeTab.value === index) return
|
||||||
|
|
||||||
|
activeTab.value = index
|
||||||
|
activeTabKey.value = tabKey
|
||||||
|
|
||||||
|
// 切换tab时重新加载内容
|
||||||
|
await loadTabContent(tabKey, 1, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载Tab内容
|
||||||
|
* @param type tab类型
|
||||||
|
* @param page 页码
|
||||||
|
* @param isRefresh 是否刷新(清空原有数据)
|
||||||
|
* @param keywords 搜索关键词
|
||||||
|
*/
|
||||||
|
const loadTabContent = async (type : string, page : number = 1, isRefresh : boolean = false, keywords : string = '') => {
|
||||||
|
try {
|
||||||
|
tabLoading.value = true
|
||||||
|
|
||||||
|
const res = await configSearch({
|
||||||
|
page,
|
||||||
|
page_size: 10,
|
||||||
|
keywords,
|
||||||
|
type
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log(res, '-----------------configSearch')
|
||||||
|
|
||||||
|
if (res.code === 1 && res.data) {
|
||||||
|
const { data } = res
|
||||||
|
|
||||||
|
if (isRefresh) {
|
||||||
|
// 刷新时清空原有数据
|
||||||
|
tabContentList.value = data.list || []
|
||||||
|
tabCurrentPage.value = 1
|
||||||
|
} else {
|
||||||
|
// 加载更多时追加数据
|
||||||
|
tabContentList.value = [...tabContentList.value, ...(data.list || [])]
|
||||||
|
tabCurrentPage.value = page
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断是否还有更多数据
|
||||||
|
tabHasMore.value = (data.list && data.list.length === 10) || false
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载tab内容失败:', error)
|
||||||
|
} finally {
|
||||||
|
tabLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== 返回数据和方法 ====================
|
||||||
|
return {
|
||||||
|
// 背景样式
|
||||||
|
backgroundStyle,
|
||||||
|
topGradientStyle,
|
||||||
|
|
||||||
|
// 页面状态
|
||||||
|
isRefreshing,
|
||||||
|
isLoading,
|
||||||
|
hasMore,
|
||||||
|
currentPage,
|
||||||
|
|
||||||
|
// 页面数据
|
||||||
|
bannerList,
|
||||||
|
noticeBarList,
|
||||||
|
categoryList,
|
||||||
|
hotRecommendList,
|
||||||
|
|
||||||
|
// 新增的接口数据
|
||||||
|
menuList,
|
||||||
|
switchList,
|
||||||
|
systemInfo,
|
||||||
|
noticeInfo,
|
||||||
|
hbsmNotice,
|
||||||
|
blackInfo,
|
||||||
|
|
||||||
|
// Tab相关数据和状态
|
||||||
|
activeTab,
|
||||||
|
activeTabKey,
|
||||||
|
tabContentList,
|
||||||
|
tabLoading,
|
||||||
|
tabCurrentPage,
|
||||||
|
tabHasMore,
|
||||||
|
|
||||||
|
// 页面方法
|
||||||
|
initPage,
|
||||||
|
onRefresh,
|
||||||
|
onLoadMore,
|
||||||
|
resetState,
|
||||||
|
|
||||||
|
// Tab相关方法
|
||||||
|
switchTab,
|
||||||
|
loadTabContent,
|
||||||
|
}
|
||||||
|
}
|
@ -49,6 +49,30 @@
|
|||||||
"navigationStyle": "custom",
|
"navigationStyle": "custom",
|
||||||
"navigationBarTitleText": "个人中心"
|
"navigationBarTitleText": "个人中心"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/black/index",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTextStyle": "white",
|
||||||
|
"navigationStyle": "custom",
|
||||||
|
"navigationBarTitleText": "账户状态"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/todo/index",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTextStyle": "white",
|
||||||
|
"navigationStyle": "custom",
|
||||||
|
"navigationBarTitleText": "待办事项"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/service/index",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTextStyle": "white",
|
||||||
|
"navigationStyle": "custom",
|
||||||
|
"navigationBarTitleText": "客服"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"globalStyle": {
|
"globalStyle": {
|
||||||
@ -80,12 +104,6 @@
|
|||||||
"iconPath": "/static/tabs/cart_default.png",
|
"iconPath": "/static/tabs/cart_default.png",
|
||||||
"selectedIconPath": "/static/tabs/cart_selected.png"
|
"selectedIconPath": "/static/tabs/cart_selected.png"
|
||||||
},
|
},
|
||||||
// {
|
|
||||||
// "text": "我的",
|
|
||||||
// "pagePath": "pages/my/my",
|
|
||||||
// "iconPath": "/static/tabs/user_default.png",
|
|
||||||
// "selectedIconPath": "/static/tabs/user_selected.png"
|
|
||||||
// }
|
|
||||||
{
|
{
|
||||||
"text": "个人中心",
|
"text": "个人中心",
|
||||||
"pagePath": "pages/my/userCenter",
|
"pagePath": "pages/my/userCenter",
|
||||||
@ -361,7 +379,7 @@
|
|||||||
}]
|
}]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"root": "pagesEnterprise",
|
"root": "pageCompany",
|
||||||
"pages": [{
|
"pages": [{
|
||||||
"path": "pages/portrait/index",
|
"path": "pages/portrait/index",
|
||||||
"style": {
|
"style": {
|
||||||
@ -371,6 +389,16 @@
|
|||||||
// #endif
|
// #endif
|
||||||
}
|
}
|
||||||
}]
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"root": "pagesCustomer",
|
||||||
|
"pages": [{
|
||||||
|
"path": "pages/customer/customer",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "客户管理",
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
|
}]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"preloadRule": {
|
"preloadRule": {
|
||||||
@ -388,7 +416,7 @@
|
|||||||
},
|
},
|
||||||
"pages/my/userCenter": {
|
"pages/my/userCenter": {
|
||||||
"network": "all",
|
"network": "all",
|
||||||
"packages": ["pagesMember", "pagesOrder","pagesEnterprise"]
|
"packages": ["pagesMember", "pagesOrder", "pagesEnterprise"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
297
src/pages/black/index.vue
Normal file
297
src/pages/black/index.vue
Normal file
@ -0,0 +1,297 @@
|
|||||||
|
<template>
|
||||||
|
<!-- 黑名单页面 -->
|
||||||
|
<view class="page-container">
|
||||||
|
|
||||||
|
<!-- 导航栏 -->
|
||||||
|
<wd-navbar title="账户状态" safeAreaInsetTop :bordered="false"></wd-navbar>
|
||||||
|
<!-- 主要内容区域 -->
|
||||||
|
<view class="content-wrapper">
|
||||||
|
<!-- 状态图标 -->
|
||||||
|
<view class="status-icon-wrapper">
|
||||||
|
<view class="icon-bg">
|
||||||
|
<wd-icon name="warning" size="100rpx" color="#fff"></wd-icon>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- 标题 -->
|
||||||
|
<view class="title-text">账户已被限制</view>
|
||||||
|
<!-- 描述信息 -->
|
||||||
|
<view class="description-text">
|
||||||
|
<text>{{blackInfo.content}}</text>
|
||||||
|
</view>
|
||||||
|
<!-- 联系客服卡片 -->
|
||||||
|
<view class="contact-card-new">
|
||||||
|
<!-- <view class="contact-header">
|
||||||
|
<uv-icon name="server-man" size="36rpx" color="#389054"></uv-icon>
|
||||||
|
<text class="header-title">联系我们</text>
|
||||||
|
</view> -->
|
||||||
|
<view class="contact-body">
|
||||||
|
<view class="contact-item-new">
|
||||||
|
<image class="item-img" :src="blackInfo.qrCode" mode="widthFix"></image>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="contact-footer">
|
||||||
|
<wd-icon name="time" size="28rpx" color="#999"></wd-icon>
|
||||||
|
<text class="footer-text">服务时间:{{blackInfo.date}}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
|
||||||
|
</view>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- 底部提示 -->
|
||||||
|
<view class="footer-tips">
|
||||||
|
<view class="tip-card">
|
||||||
|
<uv-icon name="info-circle" size="32rpx" color="#f9ae3d"></uv-icon>
|
||||||
|
<view class="tip-content">
|
||||||
|
<view class="tip-title">温馨提示</view>
|
||||||
|
<view class="tip-text">账户异常可能由违规操作、安全风险等原因导致,请您理解与配合。</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import {
|
||||||
|
ref,
|
||||||
|
onMounted
|
||||||
|
} from "vue";
|
||||||
|
|
||||||
|
interface blackObj {
|
||||||
|
//商品ID
|
||||||
|
status : number
|
||||||
|
content : string
|
||||||
|
//客服二维码路径
|
||||||
|
qrCode : string
|
||||||
|
//服务时间
|
||||||
|
date : string
|
||||||
|
}
|
||||||
|
const blackInfo = ref<blackObj>({});
|
||||||
|
onMounted(() => {
|
||||||
|
uni.getStorage({
|
||||||
|
key: 'blackInfo',
|
||||||
|
success: (res) => {
|
||||||
|
console.log(res.data);
|
||||||
|
blackInfo.value = res.data;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
// // 客服电话
|
||||||
|
// const phoneValue = ref("");
|
||||||
|
|
||||||
|
// // 拨打客服电话
|
||||||
|
// const makePhoneCall = () => {
|
||||||
|
// // 检查电话号码是否存在
|
||||||
|
// if (!phoneValue.value) {
|
||||||
|
// uni.showToast({
|
||||||
|
// title: "暂未获取到客服电话",
|
||||||
|
// icon: "none",
|
||||||
|
// });
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// uni.makePhoneCall({
|
||||||
|
// phoneNumber: phoneValue.value,
|
||||||
|
// success: () => {
|
||||||
|
// console.log("成功发起拨打电话");
|
||||||
|
// },
|
||||||
|
// fail: (err) => {
|
||||||
|
// console.error("拨打电话失败:", err);
|
||||||
|
// uni.showToast({
|
||||||
|
// title: "拨打电话功能暂不可用",
|
||||||
|
// icon: "none",
|
||||||
|
// });
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
// };
|
||||||
|
|
||||||
|
// // 处理联系客服操作
|
||||||
|
// const handleContactService = () => {
|
||||||
|
// // 添加触觉反馈,提升用户体验
|
||||||
|
// uni.vibrateShort && uni.vibrateShort();
|
||||||
|
// makePhoneCall();
|
||||||
|
// };
|
||||||
|
|
||||||
|
// // 获取远程设置,例如客服电话
|
||||||
|
// const getSetting = async () => {
|
||||||
|
// try {
|
||||||
|
// const { kefu } = await useHttp("/api/setting");
|
||||||
|
// if (kefu && kefu.kefu_mobile) {
|
||||||
|
// phoneValue.value = kefu.kefu_mobile;
|
||||||
|
// } else {
|
||||||
|
// console.warn("未获取到客服电话");
|
||||||
|
// }
|
||||||
|
// } catch (e) {
|
||||||
|
// console.error("获取配置失败", e);
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
// // 页面加载时获取设置
|
||||||
|
// getSetting();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.page-container {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: linear-gradient(180deg, #f0f8f2 0%, #ffffff 40%);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-wrapper {
|
||||||
|
// flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
padding: 40rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
.status-icon-wrapper {
|
||||||
|
margin-top: 60rpx;
|
||||||
|
margin-bottom: 40rpx;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.icon-bg {
|
||||||
|
width: 160rpx;
|
||||||
|
height: 160rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: linear-gradient(145deg, #ff7575, #dd524d);
|
||||||
|
box-shadow: 0 10rpx 30rpx rgba(221, 82, 77, 0.4);
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
animation: pulse 2s infinite;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-text {
|
||||||
|
font-size: 48rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #303133;
|
||||||
|
margin-bottom: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description-text {
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #606266;
|
||||||
|
line-height: 1.6;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 60rpx;
|
||||||
|
padding: 0 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-card-new {
|
||||||
|
width: 100%;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 24rpx;
|
||||||
|
padding: 32rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
box-shadow: 0 8rpx 40rpx rgba(0, 0, 0, 0.08);
|
||||||
|
// margin-bottom: 60rpx;
|
||||||
|
|
||||||
|
.contact-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 32rpx;
|
||||||
|
|
||||||
|
.header-title {
|
||||||
|
font-size: 36rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #303133;
|
||||||
|
margin-left: 16rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-body {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 16rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-item-new {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 24rpx;
|
||||||
|
background-color: #f7f8fa;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
background-color: #f2f3f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-image {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-footer {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding-top: 24rpx;
|
||||||
|
margin-top: 24rpx;
|
||||||
|
border-top: 1rpx solid #f2f3f5;
|
||||||
|
|
||||||
|
.footer-text {
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #909399;
|
||||||
|
margin-left: 12rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-tips {
|
||||||
|
padding: 0 40rpx 40rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
.tip-card {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
background-color: #fff7e8;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
padding: 24rpx;
|
||||||
|
|
||||||
|
.tip-content {
|
||||||
|
margin-left: 16rpx;
|
||||||
|
|
||||||
|
.tip-title {
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #f29100;
|
||||||
|
margin-bottom: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tip-text {
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #b87a28;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pulse {
|
||||||
|
0% {
|
||||||
|
transform: scale(1);
|
||||||
|
box-shadow: 0 10rpx 30rpx rgba(221, 82, 77, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
transform: scale(1.05);
|
||||||
|
box-shadow: 0 15rpx 40rpx rgba(221, 82, 77, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
transform: scale(1);
|
||||||
|
box-shadow: 0 10rpx 30rpx rgba(221, 82, 77, 0.4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
97
src/pages/home/components/service-grid.vue
Normal file
97
src/pages/home/components/service-grid.vue
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
<template>
|
||||||
|
<view class="service-grid">
|
||||||
|
<view class="grid-container">
|
||||||
|
<view
|
||||||
|
v-for="(service, index) in props.list"
|
||||||
|
:key="index"
|
||||||
|
class="service-item"
|
||||||
|
@click="handleServiceClick(service)"
|
||||||
|
>
|
||||||
|
<view class="service-icon flex-row align-center justify-center">
|
||||||
|
<image
|
||||||
|
:src="service.img"
|
||||||
|
mode="aspectFit"
|
||||||
|
:class="getIconClass(1)"
|
||||||
|
></image>
|
||||||
|
</view>
|
||||||
|
<text class="service-title">{{ service.name }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { pageUrl } from '@/utils/constants'
|
||||||
|
import type { menuItem } from '@/types/home'
|
||||||
|
interface ServiceItem {
|
||||||
|
title: string
|
||||||
|
iconPath: string
|
||||||
|
route?: string
|
||||||
|
floor?: number
|
||||||
|
}
|
||||||
|
//接收组件值
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
list: menuItem[]
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
const handleServiceClick = (service: ServiceItem) => {
|
||||||
|
if (service.url && service.url != "#") {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: service.url,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getIconClass = (floor: number | undefined) => {
|
||||||
|
return floor === 1 ? 'icon-size-1' : floor === 2 ? 'icon-size-2' : 'icon-size-3'
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.service-grid {
|
||||||
|
.grid-container {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(5, 1fr);
|
||||||
|
gap: 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10rpx;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: transform 0.2s ease;
|
||||||
|
|
||||||
|
.service-icon {
|
||||||
|
.icon-size-1 {
|
||||||
|
width: 80rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
}
|
||||||
|
.icon-size-2 {
|
||||||
|
width: 50rpx;
|
||||||
|
height: 50rpx;
|
||||||
|
}
|
||||||
|
.icon-size-3 {
|
||||||
|
width: 50rpx;
|
||||||
|
height: 50rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-title {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #333;
|
||||||
|
text-align: center;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
881
src/pages/home/components/tab-content.vue
Normal file
881
src/pages/home/components/tab-content.vue
Normal file
@ -0,0 +1,881 @@
|
|||||||
|
<template>
|
||||||
|
<view class="tab-content">
|
||||||
|
<!-- 推荐 tab - 商品展示 -->
|
||||||
|
<view v-if="activeTab === 'goods'" class="recommend-content">
|
||||||
|
<view class="goods-list flex-col">
|
||||||
|
<view
|
||||||
|
v-for="(item,index) in dataList"
|
||||||
|
:key="index"
|
||||||
|
class="goods-item"
|
||||||
|
@click="jumpUrl(item.url)"
|
||||||
|
>
|
||||||
|
<view class="goods-image">
|
||||||
|
<image :src="item.cover" mode="aspectFill"></image>
|
||||||
|
</view>
|
||||||
|
<view class="goods-info flex-col">
|
||||||
|
<text class="goods-title">{{ item.name }}</text>
|
||||||
|
<view class="goods-tags">
|
||||||
|
<text v-for="tag in item.tags" :key="tag" class="goods-tag">{{ tag }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="goods-price align-end">
|
||||||
|
<text class="price-symbol">¥</text>
|
||||||
|
<text class="price-value">{{ item.min_price}}</text>
|
||||||
|
<text class="price-unit">/起</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 合作伙伴 tab -->
|
||||||
|
<view v-else-if="activeTab === 1" class="partners-content">
|
||||||
|
<view class="partners-list">
|
||||||
|
<view class="partner-item" v-for="partner in partners" :key="partner.id">
|
||||||
|
<image class="partner-logo" :src="partner.logo" mode="aspectFit"></image>
|
||||||
|
<text class="partner-name">{{ partner.name }}</text>
|
||||||
|
<text class="partner-desc">{{ partner.description }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 商机 tab -->
|
||||||
|
<view v-else-if="activeTab === 'opportunity'" class="opportunities-content"
|
||||||
|
>
|
||||||
|
<view class="opportunities-list">
|
||||||
|
<view class="opportunity-item" v-for="(opp,index) in dataList" :key="index" @click="jumpUrl(opp.url)">
|
||||||
|
<view class="opp-header">
|
||||||
|
<text class="opp-title">{{ opp.name }}</text>
|
||||||
|
<view class="opp-status active" >{{ opp.service_fee }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="opp-desc">{{ opp.desc }}</view>
|
||||||
|
<view class="opp-meta">
|
||||||
|
<text class="opp-location">{{ opp.cate_name }}</text>
|
||||||
|
<text class="opp-date">{{ opp.create_time }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 关于我们 tab -->
|
||||||
|
<view v-else-if="activeTab === 3" class="about-content">
|
||||||
|
<view class="about-info">
|
||||||
|
<text class="about-text">
|
||||||
|
我们是一家专注于国际贸易和物流服务的综合性企业,致力于为客户提供优质、高效、便捷的服务。
|
||||||
|
</text>
|
||||||
|
<view class="company-stats">
|
||||||
|
<view class="stat-item">
|
||||||
|
<text class="stat-number">10+</text>
|
||||||
|
<text class="stat-label">年行业经验</text>
|
||||||
|
</view>
|
||||||
|
<view class="stat-item">
|
||||||
|
<text class="stat-number">1000+</text>
|
||||||
|
<text class="stat-label">服务客户</text>
|
||||||
|
</view>
|
||||||
|
<view class="stat-item">
|
||||||
|
<text class="stat-number">50+</text>
|
||||||
|
<text class="stat-label">合作国家</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 找买家 tab -->
|
||||||
|
<view v-else-if="activeTab === 'buy'" class="buyers-content">
|
||||||
|
<!-- <view class="buyers-search">
|
||||||
|
<search-bar
|
||||||
|
ref="buyersSearchBarRef"
|
||||||
|
:placeholder="'请输入搜索关键字'"
|
||||||
|
:showSearchButton="false"
|
||||||
|
@search="handleSearch"
|
||||||
|
@input="handleSearchInput"
|
||||||
|
@clear="handleClearSearch"
|
||||||
|
/>
|
||||||
|
</view> -->
|
||||||
|
<view class="buyers-list">
|
||||||
|
<view class="buyer-card flex-col" @click="jumpUrl(buyer.url)" v-for="(buyer,index) in dataList" :key="buyer.id">
|
||||||
|
<!-- 标题行 -->
|
||||||
|
<view class="card-header flex-row justify-between align-center">
|
||||||
|
<text class="product-title">{{ buyer.name }}</text>
|
||||||
|
<view class="view-more">
|
||||||
|
<text class="view-more-text">查看更多</text>
|
||||||
|
<wd-icon name="arrow-right" size="14" color="#666666"></wd-icon>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 海关编码 -->
|
||||||
|
<!-- <view class="customs-code">
|
||||||
|
<text class="code-label">海关编码</text>
|
||||||
|
<text class="code-value">{{ buyer.customsCode }}</text>
|
||||||
|
</view> -->
|
||||||
|
|
||||||
|
<view class="divider"></view>
|
||||||
|
|
||||||
|
<!-- 主要数据 -->
|
||||||
|
<view class="data-section">
|
||||||
|
<view class="data-items-combined">
|
||||||
|
<view class="data-item">
|
||||||
|
<text class="data-label1">类型</text>
|
||||||
|
<text class="data-value">{{ buyer.cate_name }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="data-item">
|
||||||
|
<text class="data-label1">贸易伙伴</text>
|
||||||
|
<text class="data-value">{{ buyer.partner }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="data-item">
|
||||||
|
<text class="data-label1">邮箱</text>
|
||||||
|
<text class="data-value">{{ buyer.email }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="data-item">
|
||||||
|
<text class="data-label2">日期</text>
|
||||||
|
<text class="data-value">{{ buyer.date }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="product-info">
|
||||||
|
<view class="data-item">
|
||||||
|
<text class="data-label1">描述</text>
|
||||||
|
<view class="data-value">{{ buyer.remarks }}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 进出口商信息 -->
|
||||||
|
<view class="trade-info flex-row justify-between">
|
||||||
|
<view class="exporter-info flex-row">
|
||||||
|
<view class="exporter-item">
|
||||||
|
<view class="info-label">主营业务</view>
|
||||||
|
<view class="info-value">{{ buyer.business }}</view>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
<!-- <view class="exporter-item flex-col">
|
||||||
|
<image :src="buyer.logo" mode="aspectFit" class="logo"></image>
|
||||||
|
</view> -->
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 竖向分隔线 -->
|
||||||
|
<view class="vertical-divider"></view>
|
||||||
|
|
||||||
|
<view class="importer-info flex-row">
|
||||||
|
<view class="importer-item">
|
||||||
|
<view class="info-label">是否有联系方式</view>
|
||||||
|
<text class="info-value">{{ buyer.is_contact == 1 ? '有' :'无' }}</text>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
<!-- <view class="importer-item flex-col">
|
||||||
|
<text class="info-value">{{ buyer.importerCountry }}</text>
|
||||||
|
<view class="info-label">所在国</view>
|
||||||
|
</view> -->
|
||||||
|
<view class="importer-item flex-col">
|
||||||
|
<image :src="buyer.logo" class="logo"></image>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 找卖家 tab -->
|
||||||
|
<view v-else-if="activeTab === 'sell'" class="sellers-content">
|
||||||
|
<view class="sellers-list">
|
||||||
|
<view class="seller-item" @click="jumpUrl(seller.url)" v-for="(seller,index) in dataList" :key="index">
|
||||||
|
<view class="seller-avatar">
|
||||||
|
<image :src="seller.logo" mode="aspectFill"></image>
|
||||||
|
</view>
|
||||||
|
<view class="seller-info">
|
||||||
|
<view class="seller-name">{{ seller.name }}</view>
|
||||||
|
<text class="seller-company">{{ seller.cate_name }}</text>
|
||||||
|
<view class="seller-products">{{ seller.remarks }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="seller-action">
|
||||||
|
<text class="contact-btn">联系</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- 保税生活 -->
|
||||||
|
<view v-else-if="activeTab === 'life'" class="sellers-content">
|
||||||
|
<view class="sellers-list">
|
||||||
|
<view class="seller-item" @click="jumpUrl(seller.url)" v-for="(seller,index) in dataList" :key="index">
|
||||||
|
<view class="seller-avatar">
|
||||||
|
<image :src="seller.logo" mode="aspectFill"></image>
|
||||||
|
</view>
|
||||||
|
<view class="seller-info">
|
||||||
|
<view class="seller-name">{{ seller.name }}</view>
|
||||||
|
<view class="tags_box">
|
||||||
|
<view class="tag_item" v-for="(t,ti) in seller.tag" :key="index">
|
||||||
|
{{t}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- <view class="seller-company">{{ setTag(seller.tag)}}</view> -->
|
||||||
|
<view class="seller-products">{{ seller.remarks }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="seller-action">
|
||||||
|
<text class="contact-btn">联系</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 默认内容 -->
|
||||||
|
<view v-if="!dataList.length" class="default-content">
|
||||||
|
<text class="default-text">暂无内容</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { computed, ref, reactive, watch } from 'vue'
|
||||||
|
import { configSearch } from '@/api/home'
|
||||||
|
// 定义 props
|
||||||
|
const props = defineProps({
|
||||||
|
activeTab: {
|
||||||
|
type: [String,Number],
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
const dataList = ref([])
|
||||||
|
const hasNextPage = ref(false)
|
||||||
|
watch(() => props.activeTab, (newValue, oldValue) => {
|
||||||
|
queryParams.page = 1
|
||||||
|
dataList.value = []
|
||||||
|
getList()
|
||||||
|
});
|
||||||
|
// 推荐商品数据
|
||||||
|
const recommendGoods = ref([
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
title: '劳斯莱斯',
|
||||||
|
image: '/static/images/home/goods1.png',
|
||||||
|
tags: ['拍卖', '进口', '展会清仓', '海关处置', '零售'],
|
||||||
|
priceType: '¥',
|
||||||
|
price: '500',
|
||||||
|
unit: 'CBM',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
title: '优质商品B',
|
||||||
|
image: '/static/images/home/goods2.png',
|
||||||
|
tags: ['拍卖', '进口', '展会清仓', '海关处置', '零售'],
|
||||||
|
priceType: '¥',
|
||||||
|
price: '500',
|
||||||
|
unit: 'CBM',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
// 合作伙伴数据
|
||||||
|
const partners = ref([
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: '合作伙伴A',
|
||||||
|
logo: '/static/images/home/partner1.png',
|
||||||
|
description: '长期合作伙伴,提供优质服务',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: '合作伙伴B',
|
||||||
|
logo: '/static/images/home/partner2.png',
|
||||||
|
description: '战略合作伙伴,共同发展',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
// 商机数据
|
||||||
|
const opportunities = ref([
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
title: '国际贸易合作机会',
|
||||||
|
description: '寻找长期稳定的贸易合作伙伴,共同开拓国际市场',
|
||||||
|
status: 'active',
|
||||||
|
statusText: '进行中',
|
||||||
|
location: '上海',
|
||||||
|
date: '2024-01-15',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
title: '物流服务招标',
|
||||||
|
description: '大型物流项目招标,诚邀有实力的物流企业参与',
|
||||||
|
status: 'pending',
|
||||||
|
statusText: '待审核',
|
||||||
|
location: '深圳',
|
||||||
|
date: '2024-01-20',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
// 买家数据
|
||||||
|
const buyers = ref([
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
productName: '优质商品A',
|
||||||
|
customsCode: '12345678901234567890',
|
||||||
|
quantity: '1000',
|
||||||
|
amount: '100000',
|
||||||
|
description: '这是一款高质量的商品,适合长期合作。',
|
||||||
|
metricTons: '10',
|
||||||
|
date: '2023-12-30',
|
||||||
|
exporter: 'ABC贸易公司',
|
||||||
|
exporterCountry: '中国',
|
||||||
|
importer: 'XYZ进出口公司',
|
||||||
|
importerCountry: '美国',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
productName: '商品B',
|
||||||
|
customsCode: '98765432109876543210',
|
||||||
|
quantity: '500',
|
||||||
|
amount: '50000',
|
||||||
|
description: '这是一款价格合理的商品,需求量大。',
|
||||||
|
metricTons: '5',
|
||||||
|
date: '2024-01-10',
|
||||||
|
exporter: 'DEF进出口公司',
|
||||||
|
exporterCountry: '英国',
|
||||||
|
importer: 'GHI贸易公司',
|
||||||
|
importerCountry: '德国',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
// 搜索栏组件引用
|
||||||
|
const buyersSearchBarRef = ref()
|
||||||
|
const queryParams = reactive({
|
||||||
|
page:1,
|
||||||
|
page_size:10,
|
||||||
|
keywords:''
|
||||||
|
})
|
||||||
|
|
||||||
|
// 处理搜索
|
||||||
|
const handleSearch = (keyword) => {
|
||||||
|
console.log('找买家调用api搜索:', keyword)
|
||||||
|
// 这里可以添加搜索逻辑,比如跳转到搜索页面
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理搜索输入
|
||||||
|
const handleSearchInput = (keyword) => {
|
||||||
|
console.log('搜索输入:', keyword)
|
||||||
|
}
|
||||||
|
const setTag = (list)=>{
|
||||||
|
if(list && list.length){
|
||||||
|
return list.join(",")
|
||||||
|
|
||||||
|
}else{
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 处理清空搜索
|
||||||
|
const handleClearSearch = () => {
|
||||||
|
console.log('清空搜索')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 卖家数据
|
||||||
|
const sellers = ref([
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: '王先生',
|
||||||
|
company: '优质供应商A',
|
||||||
|
avatar: '/static/images/home/avatar3.png',
|
||||||
|
products: '提供各类商品,质量保证',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: '赵女士',
|
||||||
|
company: '优质供应商B',
|
||||||
|
avatar: '/static/images/home/avatar4.png',
|
||||||
|
products: '专业生产,价格优惠',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
// 处理查看更多
|
||||||
|
const handleViewMore = () => {
|
||||||
|
console.log('查看更多推荐商品')
|
||||||
|
// 这里可以跳转到商品列表页面
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理商品点击
|
||||||
|
const handleGoodsClick = (goods) => {
|
||||||
|
// console.log('点击商品:', goods)
|
||||||
|
uni.navigateTo({
|
||||||
|
url:goods.url
|
||||||
|
})
|
||||||
|
// 这里可以跳转到商品详情页面
|
||||||
|
}
|
||||||
|
const jumpOppo = (data)=>{
|
||||||
|
console.log('点击商品:', data)
|
||||||
|
}
|
||||||
|
const jumpBuy = (data)=>{
|
||||||
|
console.log('点击商品:', data)
|
||||||
|
}
|
||||||
|
const jumpUrl=(url)=>{
|
||||||
|
uni.navigateTo({
|
||||||
|
url:'/'+url,
|
||||||
|
fail: () => {
|
||||||
|
uni.reLaunch({
|
||||||
|
url:'/'+url,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const getList = (page = 1 )=>{
|
||||||
|
queryParams.page = page
|
||||||
|
configSearch({
|
||||||
|
...queryParams,
|
||||||
|
key:props.activeTab
|
||||||
|
}).then(res=>{
|
||||||
|
if(res.code == 1){
|
||||||
|
if(queryParams.page == 1){
|
||||||
|
dataList.value = res.data.list
|
||||||
|
}else{
|
||||||
|
dataList.value = [...dataList.value,...res.data.list]
|
||||||
|
}
|
||||||
|
hasNextPage.vaue = dataList.value.length >= res.data.count ? false : true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const getMoreData = ()=>{
|
||||||
|
if(!hasNextPage.value)return
|
||||||
|
queryParams.page++
|
||||||
|
getList()
|
||||||
|
|
||||||
|
}
|
||||||
|
getList()
|
||||||
|
defineExpose({
|
||||||
|
getList,
|
||||||
|
queryParams,
|
||||||
|
getMoreData
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import '@/styles/common.scss';
|
||||||
|
.tab-content {
|
||||||
|
// 推荐内容样式
|
||||||
|
.recommend-content {
|
||||||
|
.goods-list {
|
||||||
|
gap: 20rpx;
|
||||||
|
|
||||||
|
.goods-item {
|
||||||
|
display: flex;
|
||||||
|
gap: 20rpx;
|
||||||
|
padding: 30rpx;
|
||||||
|
background: #f8f8f8;
|
||||||
|
border-radius: $border-radius;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.goods-image {
|
||||||
|
width: 150rpx;
|
||||||
|
height: 150rpx;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
background: #697efe;
|
||||||
|
image{
|
||||||
|
width: 150rpx;
|
||||||
|
height: 150rpx;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-info {
|
||||||
|
padding: 9rpx 0;
|
||||||
|
gap: 20rpx;
|
||||||
|
|
||||||
|
.goods-title {
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-tags {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 10rpx;
|
||||||
|
|
||||||
|
.goods-tag {
|
||||||
|
height: 30rpx;
|
||||||
|
line-height: 30rpx;
|
||||||
|
padding: 0 10rpx;
|
||||||
|
background: #e7e7e7;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 20rpx;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.goods-price {
|
||||||
|
display: flex;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 32rpx;
|
||||||
|
color: #ff8500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 合作伙伴样式
|
||||||
|
.partners-content {
|
||||||
|
.partners-list {
|
||||||
|
.partner-item {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
padding: 30rpx;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 20rpx;
|
||||||
|
|
||||||
|
.partner-logo {
|
||||||
|
width: 80rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.partner-name {
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 8rpx;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.partner-desc {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 商机样式
|
||||||
|
.opportunities-content {
|
||||||
|
.opportunities-list {
|
||||||
|
.opportunity-item {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
padding: 30rpx;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
|
||||||
|
.opp-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 16rpx;
|
||||||
|
|
||||||
|
.opp-title {
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.opp-status {
|
||||||
|
padding: 8rpx 16rpx;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
font-size: 22rpx;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background: #e8f5e8;
|
||||||
|
color: #52c41a;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.pending {
|
||||||
|
background: #fff7e6;
|
||||||
|
color: #fa8c16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.opp-desc {
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #666;
|
||||||
|
display: -webkit-box; /* 设置为WebKit内核的弹性盒子模型 */
|
||||||
|
margin-bottom: 16rpx;
|
||||||
|
-webkit-box-orient: vertical; /* 垂直排列 */
|
||||||
|
-webkit-line-clamp: 2; /* 限制显示两行 */
|
||||||
|
overflow: hidden; /* 隐藏超出范围的内容 */
|
||||||
|
text-overflow: ellipsis; /* 使用省略号 */
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.opp-meta {
|
||||||
|
display: flex;
|
||||||
|
gap: 20rpx;
|
||||||
|
// margin-top: 10px;
|
||||||
|
.opp-location,
|
||||||
|
.opp-date {
|
||||||
|
font-size: 22rpx;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关于我们样式
|
||||||
|
.about-content {
|
||||||
|
.about-info {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
padding: 30rpx;
|
||||||
|
|
||||||
|
.about-text {
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #666;
|
||||||
|
line-height: 1.6;
|
||||||
|
margin-bottom: 30rpx;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.company-stats {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
|
||||||
|
.stat-item {
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
.stat-number {
|
||||||
|
font-size: 36rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #0478f4;
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-label {
|
||||||
|
font-size: 22rpx;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 找买家样式
|
||||||
|
.buyers-content {
|
||||||
|
.buyers-search {
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
}
|
||||||
|
.buyers-list {
|
||||||
|
.buyer-card {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: $border-radius;
|
||||||
|
padding: 24rpx 29rpx;
|
||||||
|
padding-bottom: 30rpx;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
|
||||||
|
.card-header {
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
.product-title {
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
flex: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.view-more {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #666666;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.customs-code {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10rpx;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #666666;
|
||||||
|
margin-bottom: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.divider {
|
||||||
|
height: 1rpx;
|
||||||
|
background: #eee;
|
||||||
|
margin-bottom: 28rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.data-section {
|
||||||
|
.data-items-combined {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
row-gap: 30rpx;
|
||||||
|
margin-bottom: 30rpx;
|
||||||
|
}
|
||||||
|
.product-info {
|
||||||
|
margin-bottom: 38rpx;
|
||||||
|
}
|
||||||
|
.data-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10rpx;
|
||||||
|
|
||||||
|
.data-label1 {
|
||||||
|
width: 100rpx;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
.data-label2 {
|
||||||
|
width: 60rpx;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.data-value {
|
||||||
|
// width: 200px;
|
||||||
|
display: -webkit-box; /* 设置为WebKit内核的弹性盒子模型 */
|
||||||
|
-webkit-box-orient: vertical; /* 垂直排列 */
|
||||||
|
-webkit-line-clamp: 3; /* 限制显示三行 */
|
||||||
|
overflow: hidden; /* 隐藏超出范围的内容 */
|
||||||
|
text-overflow: ellipsis; /* 使用省略号 */
|
||||||
|
font-size: 24rpx;
|
||||||
|
font-weight: 540;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.trade-info {
|
||||||
|
.exporter-info,
|
||||||
|
.importer-info {
|
||||||
|
flex: 1;
|
||||||
|
justify-content: space-between;
|
||||||
|
overflow: hidden;
|
||||||
|
.exporter-item,
|
||||||
|
.importer-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 8rpx;
|
||||||
|
.logo{
|
||||||
|
width: 30px;
|
||||||
|
|
||||||
|
height: 30px;
|
||||||
|
}
|
||||||
|
.info-value {
|
||||||
|
width: 120px;
|
||||||
|
font-size: 24rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333333;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-label {
|
||||||
|
font-size: 22rpx;
|
||||||
|
color: #666666;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.exporter-info {
|
||||||
|
padding-right: 20rpx;
|
||||||
|
}
|
||||||
|
.importer-info {
|
||||||
|
padding-left: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vertical-divider {
|
||||||
|
width: 1rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
background: #e5e5e5;
|
||||||
|
margin: 0 20rpx;
|
||||||
|
align-self: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 找卖家样式
|
||||||
|
.sellers-content {
|
||||||
|
.sellers-list {
|
||||||
|
.seller-item {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
padding: 30rpx;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 20rpx;
|
||||||
|
|
||||||
|
.seller-avatar {
|
||||||
|
width: 80rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.seller-info {
|
||||||
|
flex: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
.tags_box{
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
.tag_item{
|
||||||
|
height: 30rpx;
|
||||||
|
line-height: 30rpx;
|
||||||
|
padding: 0 10rpx;
|
||||||
|
background: #e7e7e7;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 20rpx;
|
||||||
|
color: #999999;
|
||||||
|
// margin-top: 10px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.seller-name {
|
||||||
|
width: 100%;
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 8rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.seller-company {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #666;
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.seller-products {
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
font-size: 22rpx;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.seller-action {
|
||||||
|
.contact-btn {
|
||||||
|
background: #0478f4;
|
||||||
|
color: #fff;
|
||||||
|
padding: 12rpx 24rpx;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
font-size: 24rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 默认内容样式
|
||||||
|
.default-content {
|
||||||
|
text-align: center;
|
||||||
|
padding: 100rpx 0;
|
||||||
|
|
||||||
|
.default-text {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
115
src/pages/home/components/tab-navigation.vue
Normal file
115
src/pages/home/components/tab-navigation.vue
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
<template>
|
||||||
|
<view class="tab-navigation">
|
||||||
|
<scroll-view class="tab-scroll" scroll-x="true" show-scrollbar="false">
|
||||||
|
<view class="tab-list">
|
||||||
|
<view
|
||||||
|
v-for="(tab, index) in switchList"
|
||||||
|
:key="index"
|
||||||
|
class="tab-item"
|
||||||
|
:class="{ active: activeTab === index }"
|
||||||
|
@click="handleTabClick(index, tab)"
|
||||||
|
>
|
||||||
|
<text class="tab-text">{{ tab.name }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
// 定义TabItem接口,匹配接口返回的switchList数据结构
|
||||||
|
interface TabItem {
|
||||||
|
name: string
|
||||||
|
keys: string
|
||||||
|
route: string
|
||||||
|
}
|
||||||
|
|
||||||
|
// 定义props,接收来自父组件的switchList和activeTab
|
||||||
|
const props = defineProps({
|
||||||
|
switchList: {
|
||||||
|
type: Array as () => TabItem[],
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
activeTab: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const handleTabClick = (index: number, tab: TabItem) => {
|
||||||
|
// 发射事件给父组件,让父组件控制其他组件的内容
|
||||||
|
emit('tabChange', { index, tab })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 定义事件发射器
|
||||||
|
const emit = defineEmits<{
|
||||||
|
tabChange: [{ index: number; tab: TabItem }]
|
||||||
|
}>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.tab-navigation {
|
||||||
|
.tab-scroll {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden; // 完全隐藏滚动条
|
||||||
|
|
||||||
|
// 隐藏滚动条 - Uni-app 兼容方式
|
||||||
|
::v-deep .uni-scroll-view::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .uni-scroll-view {
|
||||||
|
-ms-overflow-style: none; /* IE and Edge */
|
||||||
|
scrollbar-width: none; /* Firefox */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-list {
|
||||||
|
display: flex;
|
||||||
|
gap: 50rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-item {
|
||||||
|
flex-shrink: 0;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 8rpx;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
.tab-text {
|
||||||
|
color: #333333;
|
||||||
|
font-weight: bold;
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加圆形渐变背景
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
width: 40rpx;
|
||||||
|
height: 40rpx;
|
||||||
|
background: linear-gradient(0deg, #0478f4 0%, rgba(4, 120, 244, 0) 100%);
|
||||||
|
border-radius: 50%;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-text {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #666;
|
||||||
|
font-weight: 500;
|
||||||
|
transition: color 0.3s ease;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
188
src/pages/home/index.vue
Normal file
188
src/pages/home/index.vue
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
<template>
|
||||||
|
<view class="home-page" :style="backgroundStyle">
|
||||||
|
<!-- 顶部渐变背景 -->
|
||||||
|
<view :style="topGradientStyle"></view>
|
||||||
|
|
||||||
|
<!-- 状态栏占位 -->
|
||||||
|
<view class="status-bar"></view>
|
||||||
|
|
||||||
|
<!-- 小程序端右上角胶囊菜单栏占位 -->
|
||||||
|
<!-- #ifdef MP-WEIXIN -->
|
||||||
|
<view class="capsule-menu-section"></view>
|
||||||
|
<!-- #endif -->
|
||||||
|
|
||||||
|
<!-- 搜索栏 -->
|
||||||
|
<view class="search-section">
|
||||||
|
<search-bar ref="searchBarRef" :placeholder="'请输入搜索关键字'" :showSearchButton="true" @search="handleSearch"
|
||||||
|
@input="handleSearchInput" @clear="handleClearSearch" />
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 轮播横幅 -->
|
||||||
|
<view class="banner-section">
|
||||||
|
<shop-swiper v-if="homeData.adv" :isFullUrl="true" :height="250" :list="homeData.adv" />
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 服务网格 -->
|
||||||
|
<view class="service-grid-section">
|
||||||
|
<service-grid v-if="homeData.menu" :list="homeData.menu" />
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 公告栏 -->
|
||||||
|
<view class="notice-section">
|
||||||
|
<notice-bar v-if="homeData.notice" :noticeData="homeData.notice" :prefix="true" :suffix="true"
|
||||||
|
@noticeClick="handleNoticeClick" />
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 导航标签 -->
|
||||||
|
<view class="tab-section">
|
||||||
|
<tab-navigation v-if="homeData.switchList" :activeTab="activeTab" :switchList="homeData.switchList"
|
||||||
|
@tabChange="handleTabChange" />
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 热门推荐 -->
|
||||||
|
<view class="hot-recommend-section">
|
||||||
|
<tab-content :activeTab="activeKey" ref="tabContentRef" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { onPullDownRefresh, onReachBottom } from "@dcloudio/uni-app"
|
||||||
|
import { onMounted, onUnmounted, ref } from 'vue'
|
||||||
|
import { useHomePage } from '@/composables/useHomePage'
|
||||||
|
// import SearchBar from '@/components/search-bar/search-bar.vue'
|
||||||
|
import ServiceGrid from './components/service-grid.vue'
|
||||||
|
import TabNavigation from './components/tab-navigation.vue'
|
||||||
|
import TabContent from './components/tab-content.vue'
|
||||||
|
|
||||||
|
|
||||||
|
// 使用首页逻辑
|
||||||
|
const {
|
||||||
|
backgroundStyle,
|
||||||
|
topGradientStyle,
|
||||||
|
isRefreshing,
|
||||||
|
isLoading,
|
||||||
|
hasMore,
|
||||||
|
currentPage,
|
||||||
|
bannerList,
|
||||||
|
noticeBarList,
|
||||||
|
categoryList,
|
||||||
|
hotRecommendList,
|
||||||
|
initPage,
|
||||||
|
onRefresh,
|
||||||
|
onLoadMore,
|
||||||
|
resetState,
|
||||||
|
homeData
|
||||||
|
} = useHomePage()
|
||||||
|
|
||||||
|
// 搜索栏组件引用
|
||||||
|
const searchBarRef = ref()
|
||||||
|
const tabContentRef = ref(null)
|
||||||
|
|
||||||
|
// 当前激活的 tab
|
||||||
|
const activeTab = ref(0)
|
||||||
|
const activeKey = ref('goods')
|
||||||
|
|
||||||
|
const handleNoticeClick = (index : number) => {
|
||||||
|
console.log('handleNoticeClick', index)
|
||||||
|
|
||||||
|
// uni.navigateTo({
|
||||||
|
// url: '/pagesOther/pages/blank/rich-text',
|
||||||
|
// })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理 tab 变化
|
||||||
|
const handleTabChange = ({ index, tab } : { index : number; tab : any }) => {
|
||||||
|
activeTab.value = index
|
||||||
|
activeKey.value = tab.keys
|
||||||
|
// 这里可以根据不同的 tab 来加载不同的数据或切换组件
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理搜索
|
||||||
|
const handleSearch = (keyword : string) => {
|
||||||
|
// tabContentRef.value.queryParams.keywords = keyword
|
||||||
|
// tabContentRef.value.getList()
|
||||||
|
// 这里可以添加搜索逻辑,比如跳转到搜索页
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理搜索输入
|
||||||
|
const handleSearchInput = (keyword : string) => {
|
||||||
|
tabContentRef.value.queryParams.keywords = keyword
|
||||||
|
tabContentRef.value.getList()
|
||||||
|
// console.log('搜索输入:', keyword)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理清空搜索
|
||||||
|
const handleClearSearch = () => {
|
||||||
|
tabContentRef.value.queryParams.keywords = ''
|
||||||
|
tabContentRef.value.getList()
|
||||||
|
console.log('清空搜索')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 页面生命周期
|
||||||
|
onMounted(() => {
|
||||||
|
initPage()
|
||||||
|
})
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
resetState()
|
||||||
|
})
|
||||||
|
|
||||||
|
onPullDownRefresh(() => {
|
||||||
|
console.log("下拉刷新")
|
||||||
|
})
|
||||||
|
onReachBottom(() => {
|
||||||
|
tabContentRef.value.getMoreData()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import '@/styles/common.scss';
|
||||||
|
|
||||||
|
.home-page {
|
||||||
|
position: relative;
|
||||||
|
min-height: 100vh;
|
||||||
|
padding: 0 32rpx;
|
||||||
|
// 底部状态栏一般建议预留60rpx-100rpx,具体根据实际底部栏高度调整
|
||||||
|
padding-bottom: 60rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-bar {
|
||||||
|
height: 88rpx;
|
||||||
|
background: transparent;
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.capsule-menu-section {
|
||||||
|
height: 100rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-section {
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner-section {
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
|
margin-bottom: 22rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-grid-section {
|
||||||
|
margin-bottom: 32rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notice-section {
|
||||||
|
margin-bottom: 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-section {
|
||||||
|
margin-bottom: 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hot-recommend-section {
|
||||||
|
margin-bottom: 44rpx;
|
||||||
|
}
|
||||||
|
</style>
|
46
src/pages/service/index.vue
Normal file
46
src/pages/service/index.vue
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
<template>
|
||||||
|
<view class="px-24 py-20 box-border">
|
||||||
|
<rk-bg :status-bar="false"></rk-bg>
|
||||||
|
<view class="w-full flex justify-center">
|
||||||
|
<uv-image src="/static/logo.png" width="200rpx" height="200rpx"></uv-image>
|
||||||
|
</view>
|
||||||
|
<view class="w-full mt-20 py-20 bg-#fff shadow rd-16 flex flex-col items-center">
|
||||||
|
<view class="font-500 fs-48 color-#001A0B">为出海加速</view>
|
||||||
|
<view class="mt-20 fs-36 color-#050E19">添加海保客服</view>
|
||||||
|
<view class="mt-20">
|
||||||
|
<uv-qrcode ref="qrcode" size="300rpx" value="https://haibao.shop" :options="{'foregroundColor': '#45908F'}"></uv-qrcode>
|
||||||
|
</view>
|
||||||
|
<view class="mt-20 color-#71757A">海保世贸-一站式服务贸易平台</view>
|
||||||
|
<view class="w-324 mt-30">
|
||||||
|
<uv-button type="primary">长按二维码添加</uv-button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="mt-40 font-600 text-center">添加后您还可以获得以下福利</view>
|
||||||
|
<view class="w-full mt-40 px-20 py-24 box-border bg-#fff rd-16 shadow flex flex-wrap justify-between items-center">
|
||||||
|
<view v-for="(item, index) in funcList" :key="`func` + index" class="w-180 mb-28 flex flex-col items-center">
|
||||||
|
<!-- <uv-image :src="platformImg(item.img)" width="84rpx" height="84rpx"></uv-image> -->
|
||||||
|
<image src="/static/images/service/service01.png"></image>
|
||||||
|
<view class="mt-12 font-500 fs-24 color-#333">{{item.name}}</view>
|
||||||
|
<view class="mt-10 fs-18 color-#999">{{item.desc}}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
|
||||||
|
// 功能列表
|
||||||
|
let funcList = ref([
|
||||||
|
{name: '8元现金到账', desc: '注册即送入账户', img: '/stat/service01.png'},
|
||||||
|
{name: '222元优惠券', desc: '注册即送入账户', img: '/img/service02.png'},
|
||||||
|
{name: '铂金会员7天', desc: '高峰买票', img: '/img/service03.png'},
|
||||||
|
{name: '8元现金到账', desc: '一手福利消息', img: '/img/service04.png'},
|
||||||
|
{name: 'VIP抢票券', desc: '高峰买票', img: '/img/service05.png'},
|
||||||
|
{name: '一对一服务', desc: '有问题人工咨询', img: '/img/service06.png'},
|
||||||
|
])
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
|
||||||
|
</style>
|
498
src/pages/todo/index.vue
Normal file
498
src/pages/todo/index.vue
Normal file
@ -0,0 +1,498 @@
|
|||||||
|
<template>
|
||||||
|
<view class="todo-page" :style="backgroundStyle">
|
||||||
|
<!-- 顶部渐变背景 -->
|
||||||
|
<view :style="topGradientStyle"></view>
|
||||||
|
<view class="todo-page-content">
|
||||||
|
<wd-navbar title="待办事项" :bordered="false" safeAreaInsetTop
|
||||||
|
custom-style="background-color: transparent !important;"></wd-navbar>
|
||||||
|
<view class="top-content mt-20 cardbox flex-row align-center justify-evenly">
|
||||||
|
<view class="top-content-item">
|
||||||
|
<view class="num">99+</view>
|
||||||
|
<view class="txt1">今日待处理</view>
|
||||||
|
</view>
|
||||||
|
<view class="top-content-item">
|
||||||
|
<view class="num">3</view>
|
||||||
|
<view class="txt2">未处理</view>
|
||||||
|
</view>
|
||||||
|
<view class="top-content-item">
|
||||||
|
<view class="num">5</view>
|
||||||
|
<view class="txt3">异常</view>
|
||||||
|
</view>
|
||||||
|
<view class="top-content-item">
|
||||||
|
<view class="num">1</view>
|
||||||
|
<view class="txt4">丢件</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- 切换 -->
|
||||||
|
<view class="tab-section">
|
||||||
|
<tab-navigation @tabChange="handleTabChange" :switchList="switchList" :activeTab="activeTab"
|
||||||
|
start-color="#FFA800" end-color="rgba(4,120,244,0)" />
|
||||||
|
</view>
|
||||||
|
<!-- 搜索区域 -->
|
||||||
|
<view class="search-input flex-row">
|
||||||
|
<view class="flex-row input-content align-center">
|
||||||
|
<wd-picker class="picker" :columns="columns" v-model="state" @confirm="handleConfirm">
|
||||||
|
<view class="picker-cotent flex-row align-center">{{state}}
|
||||||
|
<wd-icon name="caret-down-small" size="22px"></wd-icon>
|
||||||
|
</view>
|
||||||
|
</wd-picker>
|
||||||
|
<input v-model="searchValue" placeholder="请输入" />
|
||||||
|
</view>
|
||||||
|
<wd-button class="search-btn">查询</wd-button>
|
||||||
|
</view>
|
||||||
|
<!-- 列表 -->
|
||||||
|
<view class="carditem cardbox">
|
||||||
|
<view class="carditem-top flex-row align-center">
|
||||||
|
<view class="time">2025-08-17 17:06:12</view>
|
||||||
|
<view class="status1">今日待处理</view>
|
||||||
|
</view>
|
||||||
|
<view class="carditem-info flex-row align-center">
|
||||||
|
<view class="title">
|
||||||
|
二手劳斯莱斯
|
||||||
|
</view>
|
||||||
|
<view class="label">海保服务</view>
|
||||||
|
</view>
|
||||||
|
<view class="carditem-bottom flex-row justify-between align-center">
|
||||||
|
<view class="carditem-bottom-item">
|
||||||
|
<view class="label">Joicom Corp</view>
|
||||||
|
<view class="val">出口商</view>
|
||||||
|
</view>
|
||||||
|
<view class="carditem-bottom-item">
|
||||||
|
<view class="label">USA</view>
|
||||||
|
<view class="val">所在国</view>
|
||||||
|
</view>
|
||||||
|
<view class="carditem-bottom-item">
|
||||||
|
<view class="label">Joicom Corp</view>
|
||||||
|
<view class="val">进口商</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="carditem cardbox">
|
||||||
|
<view class="carditem-top flex-row align-center">
|
||||||
|
<view class="time">2025-08-17 17:06:12</view>
|
||||||
|
<view class="status2">待提货</view>
|
||||||
|
</view>
|
||||||
|
<view class="carditem-info flex-row align-center">
|
||||||
|
<view class="title">
|
||||||
|
二手劳斯莱斯
|
||||||
|
</view>
|
||||||
|
<view class="label">海保服务</view>
|
||||||
|
</view>
|
||||||
|
<view class="carditem-bottom flex-row justify-between align-center">
|
||||||
|
<view class="carditem-bottom-item">
|
||||||
|
<view class="label">Joicom Corp</view>
|
||||||
|
<view class="val">出口商</view>
|
||||||
|
</view>
|
||||||
|
<view class="carditem-bottom-item">
|
||||||
|
<view class="label">USA</view>
|
||||||
|
<view class="val">所在国</view>
|
||||||
|
</view>
|
||||||
|
<view class="carditem-bottom-item">
|
||||||
|
<view class="label">Joicom Corp</view>
|
||||||
|
<view class="val">进口商</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="carditem cardbox">
|
||||||
|
<view class="carditem-top flex-row align-center">
|
||||||
|
<view class="time">2025-08-17 17:06:12</view>
|
||||||
|
<view class="status3">待清关</view>
|
||||||
|
</view>
|
||||||
|
<view class="carditem-info flex-row align-center">
|
||||||
|
<view class="title">
|
||||||
|
二手劳斯莱斯
|
||||||
|
</view>
|
||||||
|
<view class="label">海保服务</view>
|
||||||
|
</view>
|
||||||
|
<view class="carditem-bottom flex-row justify-between align-center">
|
||||||
|
<view class="carditem-bottom-item">
|
||||||
|
<view class="label">Joicom Corp</view>
|
||||||
|
<view class="val">出口商</view>
|
||||||
|
</view>
|
||||||
|
<view class="carditem-bottom-item">
|
||||||
|
<view class="label">USA</view>
|
||||||
|
<view class="val">所在国</view>
|
||||||
|
</view>
|
||||||
|
<view class="carditem-bottom-item">
|
||||||
|
<view class="label">Joicom Corp</view>
|
||||||
|
<view class="val">进口商</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="carditem cardbox">
|
||||||
|
<view class="carditem-top flex-row align-center">
|
||||||
|
<view class="time">2025-08-17 17:06:12</view>
|
||||||
|
<view class="status5">历史待处理</view>
|
||||||
|
</view>
|
||||||
|
<view class="carditem-info flex-row align-center">
|
||||||
|
<view class="title">
|
||||||
|
二手劳斯莱斯
|
||||||
|
</view>
|
||||||
|
<view class="label">海保服务</view>
|
||||||
|
</view>
|
||||||
|
<view class="carditem-bottom flex-row justify-between align-center">
|
||||||
|
<view class="carditem-bottom-item">
|
||||||
|
<view class="label">Joicom Corp</view>
|
||||||
|
<view class="val">出口商</view>
|
||||||
|
</view>
|
||||||
|
<view class="carditem-bottom-item">
|
||||||
|
<view class="label">USA</view>
|
||||||
|
<view class="val">所在国</view>
|
||||||
|
</view>
|
||||||
|
<view class="carditem-bottom-item">
|
||||||
|
<view class="label">Joicom Corp</view>
|
||||||
|
<view class="val">进口商</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="carditem cardbox">
|
||||||
|
<view class="carditem-top flex-row align-center">
|
||||||
|
<view class="time">2025-08-17 17:06:12</view>
|
||||||
|
<view class="status6">丢件</view>
|
||||||
|
<view class="status7">异常</view>
|
||||||
|
<view class="status4">待处理</view>
|
||||||
|
</view>
|
||||||
|
<view class="carditem-info flex-row align-center">
|
||||||
|
<view class="title">
|
||||||
|
二手劳斯莱斯
|
||||||
|
</view>
|
||||||
|
<view class="label">海保服务</view>
|
||||||
|
</view>
|
||||||
|
<view class="carditem-bottom flex-row justify-between align-center">
|
||||||
|
<view class="carditem-bottom-item">
|
||||||
|
<view class="label">Joicom Corp</view>
|
||||||
|
<view class="val">出口商</view>
|
||||||
|
</view>
|
||||||
|
<view class="carditem-bottom-item">
|
||||||
|
<view class="label">USA</view>
|
||||||
|
<view class="val">所在国</view>
|
||||||
|
</view>
|
||||||
|
<view class="carditem-bottom-item">
|
||||||
|
<view class="label">Joicom Corp</view>
|
||||||
|
<view class="val">进口商</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { useTodoPage } from '@/composables/useTodoPage'
|
||||||
|
import TabNavigation from '../home/components/tab-navigation.vue'
|
||||||
|
const switchList = ref([{
|
||||||
|
name: '全部',
|
||||||
|
keys: '1',
|
||||||
|
route: '1'
|
||||||
|
}, {
|
||||||
|
name: '海报服务',
|
||||||
|
keys: '1',
|
||||||
|
route: '1'
|
||||||
|
}, {
|
||||||
|
name: '商机',
|
||||||
|
keys: '1',
|
||||||
|
route: '1'
|
||||||
|
}, {
|
||||||
|
name: '关务',
|
||||||
|
keys: '1',
|
||||||
|
route: '1'
|
||||||
|
}, {
|
||||||
|
name: '商城',
|
||||||
|
keys: '1',
|
||||||
|
route: '1'
|
||||||
|
}, {
|
||||||
|
name: '竞拍',
|
||||||
|
keys: '1',
|
||||||
|
route: '1'
|
||||||
|
}, {
|
||||||
|
name: '海运',
|
||||||
|
keys: '1',
|
||||||
|
route: '1'
|
||||||
|
}]);
|
||||||
|
const columns = ref(['状态', '选项2', '选项3', '选项4', '选项5', '选项6', '选项7'])
|
||||||
|
const state = ref('状态')
|
||||||
|
const searchValue = ref('');
|
||||||
|
const handleConfirm = ({ value: string }) => {
|
||||||
|
console.log(value)
|
||||||
|
state.value = value
|
||||||
|
}
|
||||||
|
const {
|
||||||
|
backgroundStyle,
|
||||||
|
topGradientStyle,
|
||||||
|
isRefreshing,
|
||||||
|
isLoading,
|
||||||
|
hasMore,
|
||||||
|
currentPage,
|
||||||
|
bannerList,
|
||||||
|
noticeBarList,
|
||||||
|
categoryList,
|
||||||
|
hotRecommendList,
|
||||||
|
menuList,
|
||||||
|
// switchList,
|
||||||
|
systemInfo,
|
||||||
|
noticeInfo,
|
||||||
|
hbsmNotice,
|
||||||
|
blackInfo,
|
||||||
|
activeTab,
|
||||||
|
activeTabKey,
|
||||||
|
tabContentList,
|
||||||
|
tabLoading,
|
||||||
|
tabCurrentPage,
|
||||||
|
tabHasMore,
|
||||||
|
initPage,
|
||||||
|
onRefresh,
|
||||||
|
onLoadMore,
|
||||||
|
resetState,
|
||||||
|
switchTab,
|
||||||
|
loadTabContent
|
||||||
|
} = useTodoPage()
|
||||||
|
// 处理 tab 变化
|
||||||
|
const handleTabChange = ({ index, tab } : { index : number; tab : any }) => {
|
||||||
|
console.log('Tab changed:', index, tab.name)
|
||||||
|
|
||||||
|
// 根据静态的tab标题映射到对应的key
|
||||||
|
const tabKeyMap : { [key : string] : string } = {
|
||||||
|
'推荐': 'goods',
|
||||||
|
'商机': 'opportunity',
|
||||||
|
'找买家': 'buy',
|
||||||
|
'找卖家': 'sell',
|
||||||
|
'保税生活': 'life'
|
||||||
|
}
|
||||||
|
|
||||||
|
const tabKey = tabKeyMap[tab.name] || 'goods'
|
||||||
|
switchTab(index, tabKey)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.todo-page {
|
||||||
|
position: relative;
|
||||||
|
min-height: 100vh;
|
||||||
|
|
||||||
|
// 底部状态栏一般建议预留60rpx-100rpx,具体根据实际底部栏高度调整
|
||||||
|
padding-bottom: 60rpx;
|
||||||
|
|
||||||
|
.todo-page-content {
|
||||||
|
padding: 0 32rpx;
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 100;
|
||||||
|
width: 100vw;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cardbox {
|
||||||
|
background: #FFFFFF;
|
||||||
|
box-shadow: 0rpx 6rpx 34rpx 1rpx rgba(194, 148, 56, 0.1);
|
||||||
|
border-radius: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-content {
|
||||||
|
padding: 50rpx 0;
|
||||||
|
|
||||||
|
.top-content-item {
|
||||||
|
text-align: center;
|
||||||
|
position: relative;
|
||||||
|
padding: 0 39rpx;
|
||||||
|
|
||||||
|
// flex:1;
|
||||||
|
&:not(:last-child) {
|
||||||
|
&::after {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 10%;
|
||||||
|
content: '';
|
||||||
|
width: 1px;
|
||||||
|
height: 80%;
|
||||||
|
background: #EFF0F2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.num {
|
||||||
|
font-family: Alibaba PuHuiTi;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 40rpx;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
[class^='txt'] {
|
||||||
|
font-family: Alibaba PuHuiTi;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 28rpx;
|
||||||
|
margin-top: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.txt1 {
|
||||||
|
color: #F45E04;
|
||||||
|
}
|
||||||
|
|
||||||
|
.txt2 {
|
||||||
|
color: #666666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.txt3 {
|
||||||
|
color: #FF0B0B;
|
||||||
|
}
|
||||||
|
|
||||||
|
.txt4 {
|
||||||
|
color: #057D51;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-section {
|
||||||
|
margin: 40rpx 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-input {
|
||||||
|
.input-content {
|
||||||
|
background-color: white;
|
||||||
|
border-radius: 30rpx;
|
||||||
|
height: 60rpx;
|
||||||
|
margin-right: 16rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
::v-deep(.picker) {
|
||||||
|
height: 60rpx;
|
||||||
|
|
||||||
|
.picker-cotent {
|
||||||
|
font-family: Alibaba PuHuiTi;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333333;
|
||||||
|
padding-left: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wd-cell__wrapper {
|
||||||
|
// padding: 0 !important;
|
||||||
|
// padding-right: 20rpx !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
flex: 1;
|
||||||
|
height: 50rpx;
|
||||||
|
border-left: 1px solid #f1f1f1;
|
||||||
|
padding: 0 20rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep(.search-btn) {
|
||||||
|
button {
|
||||||
|
width: 130rpx !important;
|
||||||
|
min-width: 130rpx !important;
|
||||||
|
height: 60rpx !important;
|
||||||
|
background: #0478F4;
|
||||||
|
border-radius: 30rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.carditem {
|
||||||
|
padding: 30rpx;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
|
||||||
|
.carditem-top {
|
||||||
|
gap: 10rpx;
|
||||||
|
|
||||||
|
.time {
|
||||||
|
font-family: Alibaba PuHuiTi;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999999;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
[class^='status'] {
|
||||||
|
font-family: Alibaba PuHuiTi;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 24rpx;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
padding: 5rpx 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
$status-map: (
|
||||||
|
1: #F45E04,
|
||||||
|
2: #FF0000,
|
||||||
|
3:#3F8E0B,
|
||||||
|
4:#3A43EF,
|
||||||
|
5:#666666
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
@each $status,
|
||||||
|
$color in $status-map {
|
||||||
|
.status#{$status} {
|
||||||
|
color: $color;
|
||||||
|
border: 1px solid $color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$goodstatus-map: (
|
||||||
|
6: #0478F4,
|
||||||
|
7: #FF0B0B
|
||||||
|
);
|
||||||
|
|
||||||
|
@each $status,
|
||||||
|
$color in $goodstatus-map {
|
||||||
|
.status#{$status} {
|
||||||
|
color: white;
|
||||||
|
background: $color ;
|
||||||
|
border: 1px solid $color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.carditem-info {
|
||||||
|
gap: 5rpx;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-family: Alibaba PuHuiTi;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333333
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-family: Alibaba PuHuiTi;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 20rpx;
|
||||||
|
color: #999999;
|
||||||
|
line-height: 30rpx;
|
||||||
|
height: 30rpx;
|
||||||
|
padding: 0rpx 10rpx;
|
||||||
|
background: #E7E7E7;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.carditem-bottom {
|
||||||
|
background: #F8F8F8;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
padding: 25rpx;
|
||||||
|
margin-top: 25rpx;
|
||||||
|
|
||||||
|
.carditem-bottom-item {
|
||||||
|
font-family: Alibaba PuHuiTi;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 24rpx;
|
||||||
|
line-height: 34rpx;
|
||||||
|
|
||||||
|
.label {
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.val {
|
||||||
|
color: #666666;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
796
src/pagesCustomer/pages/customer/customer.vue
Normal file
796
src/pagesCustomer/pages/customer/customer.vue
Normal file
@ -0,0 +1,796 @@
|
|||||||
|
<template>
|
||||||
|
<view class="container">
|
||||||
|
<view class="top-bg"></view>
|
||||||
|
<view class="top">
|
||||||
|
<view class="top-left">
|
||||||
|
<wd-icon name="arrow-left" size="22px"></wd-icon>
|
||||||
|
</view>
|
||||||
|
<view class="top-title">
|
||||||
|
客户管理
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="tab-bar">
|
||||||
|
<view
|
||||||
|
v-for="(tab, index) in tabList"
|
||||||
|
:key="tab.id"
|
||||||
|
class="tab-item"
|
||||||
|
:class="{ active: activeTab === index }"
|
||||||
|
@click="handleTabClick(index)"
|
||||||
|
>
|
||||||
|
{{ tab.name }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="content">
|
||||||
|
<!-- 客户列表 -->
|
||||||
|
<view v-if="activeTab === 0" class="list">
|
||||||
|
<view class="search">
|
||||||
|
<wd-search :placeholder-left="true" hide-cancel light class="search-box" />
|
||||||
|
<view class="right">
|
||||||
|
<view class="item">
|
||||||
|
排序
|
||||||
|
<image
|
||||||
|
src="https://apis.haibao.shop/storage/config/20250826/Polygon22x096dd60f7ca5e4e1ec14a75787200d19556225e7.jpg"
|
||||||
|
mode="widthFix"></image>
|
||||||
|
</view>
|
||||||
|
<view class="item" style="margin-left: 44rpx;">
|
||||||
|
筛选
|
||||||
|
<image
|
||||||
|
src="https://apis.haibao.shop/storage/config/20250826/Polygon22x096dd60f7ca5e4e1ec14a75787200d19556225e7.jpg"
|
||||||
|
mode="widthFix"></image>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="list-item">
|
||||||
|
<view class="item-top">
|
||||||
|
<view class="item-top-left">
|
||||||
|
<view class="avatar">
|
||||||
|
|
||||||
|
</view>
|
||||||
|
<view class="name">
|
||||||
|
空气猫有限公司
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="item-top-right">
|
||||||
|
<image
|
||||||
|
src="https://apis.haibao.shop/storage/config/20250826/Vector2xedb375099c44a935a7add35fdb9901e086191475.png"
|
||||||
|
class="phone" mode="widthFix"></image>
|
||||||
|
<image
|
||||||
|
src="https://apis.haibao.shop/storage/config/20250826/更多12x8a0b1bca93e23a53d85843c64f375d82efa4199b.png"
|
||||||
|
class="more" mode="widthFix"></image>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="item-content">
|
||||||
|
<view class="item-content-left">
|
||||||
|
<view class="line">
|
||||||
|
<view class="label">
|
||||||
|
最后跟进:
|
||||||
|
</view>
|
||||||
|
<view class="date">
|
||||||
|
2025-08023 12:22
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="line">
|
||||||
|
<view class="label">
|
||||||
|
客户星级:
|
||||||
|
</view>
|
||||||
|
<view>
|
||||||
|
<image class="icon"
|
||||||
|
src="https://apis.haibao.shop/storage/config/20250826/Component302xad7d6290c98da23282c2a64713987e2456827bad.png"
|
||||||
|
mode="widthFix"></image>
|
||||||
|
<image class="icon"
|
||||||
|
src="https://apis.haibao.shop/storage/config/20250826/Component302xad7d6290c98da23282c2a64713987e2456827bad.png"
|
||||||
|
mode="widthFix"></image>
|
||||||
|
<image class="icon"
|
||||||
|
src="https://apis.haibao.shop/storage/config/20250826/Component302xad7d6290c98da23282c2a64713987e2456827bad.png"
|
||||||
|
mode="widthFix"></image>
|
||||||
|
<image class="icon"
|
||||||
|
src="https://apis.haibao.shop/storage/config/20250826/Component302xad7d6290c98da23282c2a64713987e2456827bad.png"
|
||||||
|
mode="widthFix"></image>
|
||||||
|
<image class="icon"
|
||||||
|
src="https://apis.haibao.shop/storage/config/20250826/Component302xad7d6290c98da23282c2a64713987e2456827bad.png"
|
||||||
|
mode="widthFix"></image>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="item-content-right">
|
||||||
|
正在进行
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="item-bottom">
|
||||||
|
<view class="btn-left">
|
||||||
|
跟进
|
||||||
|
</view>
|
||||||
|
<view class="btn-right">
|
||||||
|
任务
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- 新建客户 -->
|
||||||
|
<view v-else-if="activeTab === 1" class="create-customer">
|
||||||
|
<view class="form-container">
|
||||||
|
<!-- 基本信息标题 -->
|
||||||
|
<view class="section-title">基本信息</view>
|
||||||
|
|
||||||
|
<!-- 企业名称 -->
|
||||||
|
<view class="form-item">
|
||||||
|
<view class="form-label required">企业名称</view>
|
||||||
|
<wd-input
|
||||||
|
v-model="customerForm.companyName"
|
||||||
|
placeholder="请输入企业名称"
|
||||||
|
class="form-input"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 选择行业 -->
|
||||||
|
<view class="form-item">
|
||||||
|
<view class="form-label">选择行业</view>
|
||||||
|
<wd-picker
|
||||||
|
:columns="industryOptions"
|
||||||
|
v-model="customerForm.industry"
|
||||||
|
placeholder="请选择行业"
|
||||||
|
class="form-picker"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 国家地区 -->
|
||||||
|
<view class="form-item">
|
||||||
|
<view class="form-label">国家地区</view>
|
||||||
|
<wd-picker
|
||||||
|
:columns="countryOptions"
|
||||||
|
v-model="customerForm.country"
|
||||||
|
placeholder="请选择国家"
|
||||||
|
class="form-picker"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 企业地址 -->
|
||||||
|
<view class="form-item">
|
||||||
|
<view class="form-label">企业地址</view>
|
||||||
|
<wd-picker
|
||||||
|
:columns="addressOptions"
|
||||||
|
v-model="customerForm.address"
|
||||||
|
placeholder="请选择企业地址"
|
||||||
|
class="form-picker"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 营销阶段 -->
|
||||||
|
<view class="form-item">
|
||||||
|
<view class="form-label">营销阶段</view>
|
||||||
|
<wd-picker
|
||||||
|
:columns="marketingStageOptions"
|
||||||
|
v-model="customerForm.marketingStage"
|
||||||
|
placeholder="请选择营销阶段"
|
||||||
|
class="form-picker"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 标签 -->
|
||||||
|
<view class="form-item">
|
||||||
|
<view class="form-label">标签</view>
|
||||||
|
<wd-picker
|
||||||
|
:columns="tagOptions"
|
||||||
|
v-model="customerForm.tags"
|
||||||
|
placeholder="请选择标签"
|
||||||
|
class="form-picker"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 联系人基本信息 -->
|
||||||
|
<view v-if="activeTab === 1" class="create-customer" style="margin-top: 20rpx;">
|
||||||
|
<view class="form-container">
|
||||||
|
<!-- 基本信息标题 -->
|
||||||
|
<view class="section-title">基本信息</view>
|
||||||
|
|
||||||
|
<!-- 联系人姓名和性别 -->
|
||||||
|
<view class="form-item">
|
||||||
|
<view class="name-gender-row">
|
||||||
|
<view class="name-section">
|
||||||
|
<view class="form-label">联系人姓名</view>
|
||||||
|
<wd-input
|
||||||
|
v-model="customerForm.contactName"
|
||||||
|
placeholder="请输入联系人姓名"
|
||||||
|
class="form-input"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
<view class="gender-section">
|
||||||
|
<view class="gender-label">性别</view>
|
||||||
|
<wd-picker
|
||||||
|
:columns="genderOptions"
|
||||||
|
v-model="customerForm.gender"
|
||||||
|
placeholder="请选择性别"
|
||||||
|
class="form-picker"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 联系电话 -->
|
||||||
|
<view class="form-item">
|
||||||
|
<view class="form-label">联系电话</view>
|
||||||
|
<wd-input
|
||||||
|
v-model="customerForm.phone"
|
||||||
|
type="number"
|
||||||
|
placeholder="请输入联系电话"
|
||||||
|
class="form-input"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 邮箱 -->
|
||||||
|
<view class="form-item">
|
||||||
|
<view class="form-label">邮箱</view>
|
||||||
|
<wd-input
|
||||||
|
v-model="customerForm.email"
|
||||||
|
placeholder="请输入邮箱"
|
||||||
|
class="form-input"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 职位 -->
|
||||||
|
<view class="form-item">
|
||||||
|
<view class="form-label">职位</view>
|
||||||
|
<wd-input
|
||||||
|
v-model="customerForm.position"
|
||||||
|
placeholder="请输入职位"
|
||||||
|
class="form-input"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 备注 -->
|
||||||
|
<view class="form-item">
|
||||||
|
<view class="form-label">备注</view>
|
||||||
|
<wd-input
|
||||||
|
v-model="customerForm.remarks"
|
||||||
|
placeholder="请输入备注"
|
||||||
|
class="form-input"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 提交按钮 -->
|
||||||
|
<view class="submit-btn-container">
|
||||||
|
<wd-button
|
||||||
|
type="primary"
|
||||||
|
block
|
||||||
|
@click="submitCustomer"
|
||||||
|
class="submit-btn"
|
||||||
|
>
|
||||||
|
保存客户
|
||||||
|
</wd-button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 数据看板 -->
|
||||||
|
<view v-else-if="activeTab === 2" class="dashboard">
|
||||||
|
<view class="placeholder-content">
|
||||||
|
<text>数据看板页面内容</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
// 当前激活的tab索引
|
||||||
|
const activeTab = ref(0)
|
||||||
|
|
||||||
|
// tab列表数据
|
||||||
|
const tabList = ref([
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
name: '客户列表'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: '新建客户'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: '数据看板'
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
// 客户表单数据
|
||||||
|
const customerForm = ref({
|
||||||
|
companyName: '',
|
||||||
|
industry: '',
|
||||||
|
country: '',
|
||||||
|
address: '',
|
||||||
|
marketingStage: '',
|
||||||
|
tags: '',
|
||||||
|
contactName: '',
|
||||||
|
gender: '',
|
||||||
|
phone: '',
|
||||||
|
email: '',
|
||||||
|
position: '',
|
||||||
|
remarks: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
// 下拉选项数据
|
||||||
|
const industryOptions = ref(['制造业', '服务业', '科技行业', '金融业', '教育行业', '医疗行业', '其他'])
|
||||||
|
const countryOptions = ref(['中国', '美国', '英国', '德国', '日本', '韩国', '其他'])
|
||||||
|
const addressOptions = ref(['北京市', '上海市', '广州市', '深圳市', '杭州市', '成都市', '其他'])
|
||||||
|
const marketingStageOptions = ref(['潜在客户', '意向客户', '商机客户', '成交客户', '流失客户'])
|
||||||
|
const tagOptions = ref(['重要客户', '优质客户', '普通客户', '新客户', '老客户'])
|
||||||
|
const genderOptions = ref(['男', '女'])
|
||||||
|
|
||||||
|
// 处理tab点击事件
|
||||||
|
const handleTabClick = (index: number) => {
|
||||||
|
activeTab.value = index
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交客户信息
|
||||||
|
const submitCustomer = () => {
|
||||||
|
// 表单验证
|
||||||
|
if (!customerForm.value.companyName.trim()) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '请输入企业名称',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!customerForm.value.contactName.trim()) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '请输入联系人姓名',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!customerForm.value.phone.trim()) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '请输入联系电话',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 手机号格式验证
|
||||||
|
const phoneRegex = /^1[3-9]\d{9}$/
|
||||||
|
if (!phoneRegex.test(customerForm.value.phone)) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '请输入正确的手机号',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 邮箱格式验证(如果填写了邮箱)
|
||||||
|
if (customerForm.value.email && customerForm.value.email.trim()) {
|
||||||
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
|
||||||
|
if (!emailRegex.test(customerForm.value.email)) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '请输入正确的邮箱格式',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示保存中
|
||||||
|
uni.showLoading({
|
||||||
|
title: '保存中...'
|
||||||
|
})
|
||||||
|
|
||||||
|
// 模拟保存延迟
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.hideLoading()
|
||||||
|
uni.showToast({
|
||||||
|
title: '保存成功',
|
||||||
|
icon: 'success'
|
||||||
|
})
|
||||||
|
|
||||||
|
// 重置表单
|
||||||
|
customerForm.value = {
|
||||||
|
companyName: '',
|
||||||
|
industry: '',
|
||||||
|
country: '',
|
||||||
|
address: '',
|
||||||
|
marketingStage: '',
|
||||||
|
tags: '',
|
||||||
|
contactName: '',
|
||||||
|
gender: '',
|
||||||
|
phone: '',
|
||||||
|
email: '',
|
||||||
|
position: '',
|
||||||
|
remarks: ''
|
||||||
|
}
|
||||||
|
|
||||||
|
// 切换到客户列表tab
|
||||||
|
setTimeout(() => {
|
||||||
|
activeTab.value = 0
|
||||||
|
}, 1500)
|
||||||
|
}, 1500)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.active {
|
||||||
|
color: #333333 !important;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: "";
|
||||||
|
display: block;
|
||||||
|
width: 35rpx;
|
||||||
|
height: 6rpx;
|
||||||
|
background: #333333;
|
||||||
|
border-radius: 20rpx 20rpx 20rpx 20rpx;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
overflow: hidden;
|
||||||
|
background: #FAFAFA;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-bg {
|
||||||
|
width: 750rpx;
|
||||||
|
height: 513rpx;
|
||||||
|
background: linear-gradient(134deg, #E8FFDE 0%, #BCF3FF 100%);
|
||||||
|
border-radius: 50rpx 50rpx 50rpx 50rpx;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top {
|
||||||
|
height: 176rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-end;
|
||||||
|
padding-bottom: 20rpx;
|
||||||
|
box-sizing: content-box;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.top-left {
|
||||||
|
height: 88rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding-left: 33rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.top-title {
|
||||||
|
font-size: 32rpx;
|
||||||
|
height: 88rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-bar {
|
||||||
|
padding: 0 33rpx;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
.tab-item {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 10rpx 0;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #9CA9AA;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
padding: 0 33rpx;
|
||||||
|
margin-top: 27rpx;
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.create-customer {
|
||||||
|
padding: 30rpx;
|
||||||
|
box-shadow: 0rpx 1rpx 20rpx 0rpx rgba(177, 211, 255, 0.15);
|
||||||
|
border-radius: 12rpx 12rpx 12rpx 12rpx;
|
||||||
|
background: #FFFFFF;
|
||||||
|
|
||||||
|
.form-container {
|
||||||
|
.section-title {
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333333;
|
||||||
|
margin-bottom: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item {
|
||||||
|
margin-bottom: 30rpx;
|
||||||
|
|
||||||
|
.form-label {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333333;
|
||||||
|
margin-bottom: 16rpx;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&.required::before {
|
||||||
|
content: "*";
|
||||||
|
color: #ff4757;
|
||||||
|
margin-right: 8rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-input {
|
||||||
|
background: #F8F8F8 !important;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
padding: 10rpx 31rpx;
|
||||||
|
font-size: 24rpx;
|
||||||
|
border: none !important;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
border-color: #4398FF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-picker {
|
||||||
|
background: #F8F8F8;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
border: none;
|
||||||
|
color: #333333;
|
||||||
|
min-height: 88rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.name-gender-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 20rpx;
|
||||||
|
|
||||||
|
.name-section {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.form-label {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333333;
|
||||||
|
margin-bottom: 16rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.gender-section {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.gender-label {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333333;
|
||||||
|
margin-bottom: 16rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-btn-container {
|
||||||
|
margin-top: 60rpx;
|
||||||
|
|
||||||
|
.submit-btn {
|
||||||
|
background: #4398FF;
|
||||||
|
border-radius: 50rpx;
|
||||||
|
height: 88rpx;
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 深度选择器覆盖组件样式
|
||||||
|
::v-deep .wd-input {
|
||||||
|
background: #F8F9FA !important;
|
||||||
|
border-radius: 12rpx !important;
|
||||||
|
border: 1rpx solid #E9ECEF !important;
|
||||||
|
font-size: 28rpx !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移除特定的背景色样式
|
||||||
|
::v-deep .wd-input.is-not-empty:not(.is-disabled)::after {
|
||||||
|
background-color: transparent !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .wd-input::after {
|
||||||
|
background-color: transparent !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .wd-picker {
|
||||||
|
background: #F8F9FA !important;
|
||||||
|
border-radius: 12rpx !important;
|
||||||
|
border: none !important;
|
||||||
|
font-size: 28rpx !important;
|
||||||
|
min-height: 88rpx !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移除picker内部元素的边框
|
||||||
|
::v-deep .wd-picker__inner {
|
||||||
|
border: none !important;
|
||||||
|
background: #F8F9FA !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .wd-picker__cell {
|
||||||
|
border: none !important;
|
||||||
|
background: #F8F9FA !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .wd-picker__placeholder {
|
||||||
|
color: #999999 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .wd-button--primary {
|
||||||
|
background: #4398FF !important;
|
||||||
|
border-color: #4398FF !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboard {
|
||||||
|
padding: 30rpx;
|
||||||
|
box-shadow: 0rpx 1rpx 20rpx 0rpx rgba(177, 211, 255, 0.15);
|
||||||
|
border-radius: 12rpx 12rpx 12rpx 12rpx;
|
||||||
|
background: #FFFFFF;
|
||||||
|
min-height: 400rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.placeholder-content {
|
||||||
|
text-align: center;
|
||||||
|
color: #999999;
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.search {
|
||||||
|
display: flex;
|
||||||
|
// align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.search-box {
|
||||||
|
width: 60%;
|
||||||
|
background-color: #fff !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
border-radius: 40rpx;
|
||||||
|
border: 1rpx solid #62DF91;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.item {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333333;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 23rpx;
|
||||||
|
margin-left: 4rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.list {
|
||||||
|
padding: 30rpx;
|
||||||
|
box-shadow: 0rpx 1rpx 20rpx 0rpx rgba(177, 211, 255, 0.15);
|
||||||
|
border-radius: 12rpx 12rpx 12rpx 12rpx;
|
||||||
|
background: #FFFFFF;
|
||||||
|
|
||||||
|
.list-item {
|
||||||
|
padding: 30rpx 0;
|
||||||
|
border-bottom: 1rpx solid #E9E9E9;
|
||||||
|
|
||||||
|
.item-top {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.item-top-left {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
width: 38rpx;
|
||||||
|
height: 38rpx;
|
||||||
|
background: #D9D9D9;
|
||||||
|
border-radius: 50%;
|
||||||
|
margin-right: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.name {
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-top-right {
|
||||||
|
.phone {
|
||||||
|
width: 23rpx;
|
||||||
|
margin-right: 11rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.more {
|
||||||
|
width: 26rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-content {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: flex-end;
|
||||||
|
margin: 10rpx 0 30rpx;
|
||||||
|
|
||||||
|
.item-content-left {
|
||||||
|
.line {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
line-height: 44rpx;
|
||||||
|
font-size: 24rpx;
|
||||||
|
|
||||||
|
.label {
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date {
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
width: 24rpx;
|
||||||
|
margin-right: 20rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-content-right {
|
||||||
|
padding: 10rpx 30rpx;
|
||||||
|
border-radius: 30rpx;
|
||||||
|
background: #D9FFDC;
|
||||||
|
border-radius: 30rpx 30rpx 30rpx 30rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #00BE33;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-bottom {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
flex: 1;
|
||||||
|
border-radius: 50rpx;
|
||||||
|
padding: 18rpx 0;
|
||||||
|
font-size: 32rpx;
|
||||||
|
text-align: center
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-left {
|
||||||
|
@extend .btn;
|
||||||
|
margin-right: 13rpx;
|
||||||
|
color: #FFFFFF;
|
||||||
|
background: #4398FF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-right {
|
||||||
|
@extend .btn;
|
||||||
|
margin-left: 13rpx;
|
||||||
|
color: #4398FF;
|
||||||
|
border: 2rpx solid #4398FF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
Loading…
Reference in New Issue
Block a user