diff --git a/src/api/all/common.ts b/src/api/all/common.ts index 1e19878..9b210da 100644 --- a/src/api/all/common.ts +++ b/src/api/all/common.ts @@ -6,10 +6,10 @@ import Http from '@/api'; // 获取用户自定义列 export const getCustomColumns = (params = {}) => { - return Http.get('/v1/user-custom-columns', params); + return Http.get('/v1/custom-columns', params); }; // 保存用户自定义列 export const updateCustomColumns = (params = {}) => { - return Http.put('/v1/user-custom-columns', params); + return Http.put('/v1/custom-columns', params); }; diff --git a/src/api/all/propertyMarketing.ts b/src/api/all/propertyMarketing.ts index a1e6c6b..93f61a3 100644 --- a/src/api/all/propertyMarketing.ts +++ b/src/api/all/propertyMarketing.ts @@ -19,16 +19,21 @@ export const fetchAccountOperators = (params = {}) => { return Http.get('/v1/media-account-operators/list', params); }; -// 投放账户运营人员分组-列表 -export const fetchPlacementAccountOperators = (params = {}) => { - return Http.get('/v1/placement-account-operators/list', params); -}; - // 媒体账号-分页 export const getMediaAccounts = (params = {}) => { return Http.get('/v1/media-accounts', params); }; +// 媒体账号-健康情况 +export const getMediaAccountsHealth = (params = {}) => { + return Http.get('/v1/media-accounts/health', params); +}; + +// 投放账号-健康情况 +export const getPlacementAccountsHealth = (params = {}) => { + return Http.get('/v1/placement-accounts/health', params); +}; + // 媒体账号-添加 export const postMediaAccounts = (params = {}) => { return Http.post('/v1/media-accounts', params); @@ -298,3 +303,8 @@ export const getPlacementGuide = (params: {}) => { export const getAiResult = (params: {}) => { return Http.get(`/v1/placement-guide/getAiResult`); }; + +// 投放账号-列表 +export const getPlacementAccountsList = (params = {}) => { + return Http.get('/v1/placement-accounts/list', params); +}; diff --git a/src/api/index.ts b/src/api/index.ts index 30efc74..3eeb04b 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -2,7 +2,7 @@ * @Author: 田鑫 * @Date: 2023-02-17 11:58:44 * @LastEditors: Please set LastEditors - * @LastEditTime: 2025-06-23 05:51:32 + * @LastEditTime: 2025-07-05 17:59:59 * @Description: */ @@ -16,7 +16,7 @@ const contentType = 'application/json'; const requestTimeout = 30000; enum HttpStatusCode { - OK = 200, + Success = 200, BadRequest = 400, // 请求参数错误 Unauthorized = 401, // token 无效或过期 NotFound = 404, @@ -62,22 +62,30 @@ export class Request { (res: AxiosResponse) => { const { data } = res; switch (data.code) { - case HttpStatusCode.OK: + case HttpStatusCode.Success: return data; default: return Promise.reject(data); } }, (err: any) => { - const { message, code } = err.response?.data ?? {}; - AMessage.error(message ?? err.message); + const { response } = err; + const status = response?.status; + let errMessage = response?.data?.message ?? err.message; - switch (code) { + switch (status) { + case HttpStatusCode.InternalServerError: + errMessage = '系统繁忙,请稍后再试或联系管理员。'; + break; + case HttpStatusCode.NotFound: + errMessage = '接口不存在'; + break; case HttpStatusCode.Unauthorized: - goUserLogin(); + handleUserLogout(); break; } + AMessage.error(errMessage); return Promise.reject(err.response); }, ); diff --git a/src/components/_base/menu/index.vue b/src/components/_base/menu/index.vue index b4f9043..9714392 100644 --- a/src/components/_base/menu/index.vue +++ b/src/components/_base/menu/index.vue @@ -146,7 +146,7 @@ export default defineComponent({ } .arco-menu-title { color: var(--Text-2, #3c4043); - font-family: 'PuHuiTi-Regular'; + font-family: 'PuHuiTi-Medium'; font-size: 16px; font-style: normal; font-weight: 400; diff --git a/src/components/_base/navbar/index.vue b/src/components/_base/navbar/index.vue index 87e2fbb..79a11fc 100644 --- a/src/components/_base/navbar/index.vue +++ b/src/components/_base/navbar/index.vue @@ -9,6 +9,7 @@ import { MENU_GROUP_IDS } from '@/router/constants'; import router from '@/router'; import { useRoute } from 'vue-router'; import ExitAccountModal from '@/components/_base/exit-account-modal/index.vue'; +import { appRoutes } from '@/router/routes'; interface MenuItem { name: string; @@ -56,21 +57,31 @@ const handleSelect = (index: any) => { } }; +const flattenRoutes = (routes: any, parentPath = ''): any[] => { + let result: any[] = []; + for (const route of routes) { + const fullPath = route.path.startsWith('/') ? route.path : parentPath.replace(/\/$/, '') + '/' + route.path; + if (route.children && route.children.length) { + result = result.concat(flattenRoutes(route.children, fullPath)); + } else { + result.push({ ...route, fullPath }); + } + } + return result; +}; + const handleDopdownClick = (index: any, ind: any) => { const { children } = lists.value[index]; - const indPath = children[ind] as any; - if (indPath.name === '行业热门话题洞察') { - router.push('/dataEngine/hotTranslation'); - } else if (indPath.name === '行业词云') { - router.push('/dataEngine/hotCloud'); - } else if (indPath.name === '行业关键词动向') { - router.push('/dataEngine/keyWord'); - } else if (indPath.name === '用户痛点观察') { - router.push('/dataEngine/userPainPoints'); - } else if (indPath.name === '重点品牌动向') { - router.push('/dataEngine/keyBrandMovement'); - } else if (indPath.name === '用户画像') { - router.push('/dataEngine/userPersona'); + const indPath = children[ind]; + + const allChildren = flattenRoutes(appRoutes); + + const target = allChildren.find((item) => item.meta && item.meta.menuId === indPath.id); + + if (target) { + router.push(target.fullPath); + } else { + console.warn('未找到对应的菜单路由', indPath.id); } }; diff --git a/src/components/custom-table-column-modal/index.vue b/src/components/custom-table-column-modal/index.vue index 675ea98..9ffb83b 100644 --- a/src/components/custom-table-column-modal/index.vue +++ b/src/components/custom-table-column-modal/index.vue @@ -39,7 +39,7 @@ 已添加({{ checkColumns.length }})
-
+
icon {{ groupName }} @@ -117,48 +117,13 @@ const close = () => { }; const initData = async () => { - const data = { - selected_columns: [], - groups: [ - { - label: '基础信息', - is_require: 1, - columns: [ - { label: '账号名称', value: 'account_name', is_require: 1 }, - { label: '项目分组', value: 'project_group', is_require: 1 }, - { label: '状态', value: 'status', is_require: 1 }, - { label: '运营人员', value: 'operator', is_require: 1 }, - { label: 'AI评价', value: 'ai_score', is_require: 1 }, - ], - }, - { - label: '分析数据', - is_require: 0, - columns: [ - { label: '粉丝量', value: 'fans', is_require: 0 }, - { label: '总赞藏数', value: 'total_likes', is_require: 0 }, - { label: '观看量', value: 'views', is_require: 0 }, - { label: '观看量环比', value: 'views_ratio', is_require: 0 }, - { label: '点赞量', value: 'likes', is_require: 0 }, - { label: '点赞量环比', value: 'likes_ratio', is_require: 0 }, - { label: '最新内容标题/日期', value: 'latest_content', is_require: 0 }, - { label: '最新作品观看数', value: 'latest_views', is_require: 0 }, - { label: '最新作品日增长', value: 'latest_growth', is_require: 0 }, - { label: '次新内容标题/日期', value: 'second_latest_content', is_require: 0 }, - { label: '次新作品观看数', value: 'second_latest_views', is_require: 0 }, - { label: '次新作品日增长', value: 'second_latest_growth', is_require: 0 }, - ], - }, - ], - }; - - // const { code, data } = await getCustomColumns({ type: props.type }); - // if (code === 0) { - const { selected_columns, groups } = data; - dataSource.value = groups; - setDefaultCheckColumns(groups, selected_columns); - allColumns.value = groups.flatMap((group) => group.columns); - // } + const { code, data } = await getCustomColumns({ type: props.type }); + if (code === 200) { + const { selected_columns, groups } = data; + dataSource.value = groups; + setDefaultCheckColumns(groups, selected_columns); + allColumns.value = groups.flatMap((group) => group.columns); + } }; const isCheck = (option) => { @@ -195,7 +160,7 @@ const onSubmit = async () => { } }; -function setDefaultCheckColumns(groups, selected_columns) { +const setDefaultCheckColumns = (groups, selected_columns) => { const requiredGroups = groups.filter((group) => group.is_require === 1); const requiredValues = requiredGroups .flatMap((group) => (group.columns || []).filter((col) => col.is_require === 1)) @@ -205,7 +170,7 @@ function setDefaultCheckColumns(groups, selected_columns) { checkColumns.value = merged; requiredGroupNames.value = requiredGroups.map((group) => group.label); -} +}; // 暴露方法 defineExpose({ open }); diff --git a/src/router/routes/modules/dataEngine.ts b/src/router/routes/modules/dataEngine.ts index 3c77f74..9a06af3 100644 --- a/src/router/routes/modules/dataEngine.ts +++ b/src/router/routes/modules/dataEngine.ts @@ -27,7 +27,7 @@ const COMPONENTS: AppRouteRecordRaw[] = [ locale: '行业热门话题洞察', requiresAuth: true, roles: ['*'], - id: 2, + menuId: 2, }, component: () => import('@/views/components/dataEngine/hotTranslation.vue'), }, @@ -38,7 +38,7 @@ const COMPONENTS: AppRouteRecordRaw[] = [ locale: '行业词云', requiresAuth: true, roles: ['*'], - id: 3, + menuId: 3, }, component: () => import('@/views/components/dataEngine/hotCloud.vue'), }, @@ -49,7 +49,7 @@ const COMPONENTS: AppRouteRecordRaw[] = [ locale: '行业关键词动向', requiresAuth: true, roles: ['*'], - id: 4, + menuId: 4, }, component: () => import('@/views/components/dataEngine/keyWord.vue'), }, @@ -60,7 +60,7 @@ const COMPONENTS: AppRouteRecordRaw[] = [ locale: '用户痛点观察', requiresAuth: true, roles: ['*'], - id: 5, + menuId: 5, }, component: () => import('@/views/components/dataEngine/userPainPoints.vue'), }, @@ -71,7 +71,7 @@ const COMPONENTS: AppRouteRecordRaw[] = [ locale: '重点品牌动向', requiresAuth: true, roles: ['*'], - id: 6, + menuId: 6, }, component: () => import('@/views/components/dataEngine/keyBrandMovement.vue'), }, @@ -82,7 +82,7 @@ const COMPONENTS: AppRouteRecordRaw[] = [ locale: '用户画像', requiresAuth: true, roles: ['*'], - id: 7, + menuId: 7, }, component: () => import('@/views/components/dataEngine/userPersona.vue'), }, diff --git a/src/router/routes/modules/propertyMarketing.ts b/src/router/routes/modules/propertyMarketing.ts index 92702c2..4e3d6b4 100644 --- a/src/router/routes/modules/propertyMarketing.ts +++ b/src/router/routes/modules/propertyMarketing.ts @@ -27,6 +27,7 @@ const COMPONENTS: AppRouteRecordRaw[] = [ locale: '品牌信息', requiresAuth: true, roles: ['*'], + menuId: 11, }, component: () => import('@/views/property-marketing/brands/brand-materials/index.vue'), }, @@ -52,6 +53,7 @@ const COMPONENTS: AppRouteRecordRaw[] = [ locale: '账号管理', requiresAuth: true, roles: ['*'], + menuId: 12, }, component: () => import('@/views/property-marketing/media-account/account-manage'), }, @@ -99,6 +101,7 @@ const COMPONENTS: AppRouteRecordRaw[] = [ locale: '账户管理', requiresAuth: true, roles: ['*'], + menuId: 13, }, component: () => import('@/views/property-marketing/put-account/account-manage'), }, @@ -154,6 +157,7 @@ const COMPONENTS: AppRouteRecordRaw[] = [ locale: '业务洞察报告', requiresAuth: true, roles: ['*'], + menuId: 14, }, component: () => import('@/views/property-marketing/intelligent-solution/businessAnalysisReport'), }, diff --git a/src/utils/tools.ts b/src/utils/tools.ts index e182c34..e2093fc 100644 --- a/src/utils/tools.ts +++ b/src/utils/tools.ts @@ -93,3 +93,16 @@ export function exactFormatTime(val: number, curYearFmt = 'MM-DD HH:mm', otherYe const fmt = diff === 0 ? curYearFmt : otherYearFmt; return dayjs(val * 1000).format(fmt); } + +// 导出文件 +export function downloadByUrl(url: string, filename?: string) { + const a = document.createElement('a'); + a.href = url; + if (filename) { + a.download = filename; + } + a.style.display = 'none'; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); +} diff --git a/src/views/components/login/index.vue b/src/views/components/login/index.vue index ddd2363..a77e6b0 100644 --- a/src/views/components/login/index.vue +++ b/src/views/components/login/index.vue @@ -22,7 +22,7 @@
{ // 先重置验证状态 formRef.value.clearValidate('mobile'); - // 验证手机号字段 - try { - const result = await formRef.value.validateField('mobile'); - // 只有当验证通过时才会显示滑块验证 - if (result === true || result === undefined) { - isVerificationVisible.value = true; - } - } catch (error) { - // 验证失败,错误信息会自动显示 - console.log('手机号验证失败:', error); + const result = await formRef.value.validateField('mobile'); + // 只有当验证通过时才会显示滑块验证 + if (result === true || result === undefined) { + isVerificationVisible.value = true; } }; @@ -261,7 +255,6 @@ const handleVerificationSubmit = async () => { await fetchLoginCaptCha({ mobile: loginForm.mobile }); AMessage.success('验证码发送成功'); } catch (error) { - AMessage.error('验证码发送失败'); // 重置倒计时 countdown.value = 0; clearInterval(timer.value); diff --git a/src/views/components/login/style.scss b/src/views/components/login/style.scss index ca2849a..94f0789 100644 --- a/src/views/components/login/style.scss +++ b/src/views/components/login/style.scss @@ -1,4 +1,19 @@ .login-wrap { + .arco-input-wrapper, + .arco-select-view-single, + .arco-textarea-wrapper, + .arco-picker, + .arco-select-view-multiple { + border-radius: 4px; + border-color: #d7d7d9 !important; + background-color: #fff !important; + &:focus-within, + &.arco-input-focus { + background-color: var(--color-bg-2); + // border-color: rgb(var(--primary-6)); + box-shadow: 0 0 0 0 var(--color-primary-light-2); + } + } .login-bg { position: fixed; left: 0; @@ -38,8 +53,6 @@ } } - - .account-bind-container { width: 100%; max-width: 400px; diff --git a/src/views/property-marketing/brands/brand-materials/style.scss b/src/views/property-marketing/brands/brand-materials/style.scss index ba5bf26..eedda5f 100644 --- a/src/views/property-marketing/brands/brand-materials/style.scss +++ b/src/views/property-marketing/brands/brand-materials/style.scss @@ -44,7 +44,7 @@ .label { margin-right: 8px; color: #211f24; - font-family: 'PuHuiTi-Medium'; + font-family: 'PuHuiTi-Regular'; font-size: 14px; font-style: normal; font-weight: 400; diff --git a/src/views/property-marketing/media-account/account-dashboard/components/account-table/constants.ts b/src/views/property-marketing/media-account/account-dashboard/components/account-table/constants.ts deleted file mode 100644 index 4bfb578..0000000 --- a/src/views/property-marketing/media-account/account-dashboard/components/account-table/constants.ts +++ /dev/null @@ -1,153 +0,0 @@ -/* - * @Author: RenXiaoDong - * @Date: 2025-06-28 10:33:06 - */ -export const TABLE_COLUMNS = [ - { - title: '账号名称', - dataIndex: 'name', - width: 180, - fixed: 'left', - }, - { - title: '项目分组', - dataIndex: 'group.name', - width: 180, - fixed: 'left', - }, - { - title: '状态', - dataIndex: 'status', - width: 180, - fixed: 'left', - }, - { - title: '运营人员', - dataIndex: 'operator.name', - width: 180, - }, - { - title: 'AI评价', - dataIndex: 'ai_evaluation', - width: 260, - }, - { - title: '粉丝量', - dataIndex: 'fans_number', - width: 180, - tooltip: '账号当前粉丝总数', - align: 'right', - sortable: { - sortDirections: ['ascend', 'descend'], - }, - }, - { - title: '总赞藏数', - dataIndex: 'like_collect_number', - width: 180, - tooltip: '账号所有内容的点赞和收藏总数', - align: 'right', - sortable: { - sortDirections: ['ascend', 'descend'], - }, - }, - { - title: '观看量', - dataIndex: 'view_number', - width: 180, - tooltip: '账号所有内容的总观看次数', - align: 'right', - sortable: { - sortDirections: ['ascend', 'descend'], - }, - }, - { - title: '观看量环比', - dataIndex: 'view_chain', - width: 180, - tooltip: '相比上一周期的观看量变化百分比', - align: 'right', - suffix: '%', - sortable: { - sortDirections: ['ascend', 'descend'], - }, - }, - { - title: '点赞量', - dataIndex: 'like_number', - width: 180, - tooltip: '账号所有内容的总点赞数', - align: 'right', - sortable: { - sortDirections: ['ascend', 'descend'], - }, - }, - { - title: '点赞量环比', - dataIndex: 'like_chain', - width: 180, - tooltip: '相比上一周期的点赞量变化百分比', - align: 'right', - suffix: '%', - sortable: { - sortDirections: ['ascend', 'descend'], - }, - }, - { - title: '最新内容标题/日期', - dataIndex: 'like_chain1', - width: 240, - tooltip: '最新发布内容的标题和发布日期', - }, - { - title: '最新作品观看数', - dataIndex: 'latest_view_number', - width: 180, - tooltip: '最新发布内容的观看次数', - align: 'right', - sortable: { - sortDirections: ['ascend', 'descend'], - }, - }, - { - title: '最新作品日增长', - dataIndex: 'latest_daily_growth', - width: 180, - tooltip: '最新作品每日观看量的增长情况', - align: 'right', - sortable: { - sortDirections: ['ascend', 'descend'], - }, - }, - { - title: '次新内容标题/日期', - dataIndex: 'like_chain4', - width: 240, - }, - { - title: '次新作品观看数', - dataIndex: 'second_latest_view_number', - width: 180, - tooltip: '倒数第二个发布内容的观看次数', - align: 'right', - sortable: { - sortDirections: ['ascend', 'descend'], - }, - }, - { - title: '次新作品日增长', - dataIndex: 'second_latest_daily_growth', - width: 180, - tooltip: '倒数第二个作品每日观看量的增长情况', - align: 'right', - sortable: { - sortDirections: ['ascend', 'descend'], - }, - }, - { - title: '操作', - dataIndex: 'operation', - width: 100, - fixed: 'right', - }, -]; diff --git a/src/views/property-marketing/media-account/account-dashboard/components/account-table/index.vue b/src/views/property-marketing/media-account/account-dashboard/components/account-table/index.vue index c7b65ac..582dc23 100644 --- a/src/views/property-marketing/media-account/account-dashboard/components/account-table/index.vue +++ b/src/views/property-marketing/media-account/account-dashboard/components/account-table/index.vue @@ -32,7 +32,11 @@ ref="tableRef" :data="dataSource" row-key="id" - :row-selection="rowSelection" + :row-selection="{ + type: 'checkbox', + showCheckedAll: true, + width: 48, + }" :selected-keys="selectedItems" :pagination="false" :scroll="{ x: '100%' }" @@ -47,7 +51,7 @@