1
0
Fork 0
mirror of https://github.com/silenty4ng/k5web synced 2025-04-01 21:25:02 +00:00

Clean up unused code

This commit is contained in:
Silent YANG 2025-02-13 14:29:31 +08:00
parent 676b2918bb
commit bf7bf23454
50 changed files with 1 additions and 4987 deletions

View file

@ -1,22 +0,0 @@
import axios from 'axios';
import type { TableData } from '@arco-design/web-vue/es/table/interface';
export interface ContentDataRecord {
x: string;
y: number;
}
export function queryContentData() {
return axios.get<ContentDataRecord[]>('/api/content-data');
}
export interface PopularRecord {
key: number;
clickNumber: string;
title: string;
increases: number;
}
export function queryPopularList(params: { type: string }) {
return axios.get<TableData[]>('/api/popular/list', { params });
}

View file

@ -1,21 +0,0 @@
import axios from 'axios';
export interface BaseInfoModel {
activityName: string;
channelType: string;
promotionTime: string[];
promoteLink: string;
}
export interface ChannelInfoModel {
advertisingSource: string;
advertisingMedia: string;
keyword: string[];
pushNotify: boolean;
advertisingContent: string;
}
export type UnitChannelModel = BaseInfoModel & ChannelInfoModel;
export function submitChannelForm(data: UnitChannelModel) {
return axios.post('/api/channel-form/submit', { data });
}

View file

@ -1,56 +0,0 @@
import axios from 'axios';
import qs from 'query-string';
import type { DescData } from '@arco-design/web-vue/es/descriptions/interface';
export interface PolicyRecord {
id: string;
number: number;
name: string;
contentType: 'img' | 'horizontalVideo' | 'verticalVideo';
filterType: 'artificial' | 'rules';
count: number;
status: 'online' | 'offline';
createdTime: string;
}
export interface PolicyParams extends Partial<PolicyRecord> {
current: number;
pageSize: number;
}
export interface PolicyListRes {
list: PolicyRecord[];
total: number;
}
export function queryPolicyList(params: PolicyParams) {
return axios.get<PolicyListRes>('/api/list/policy', {
params,
paramsSerializer: (obj) => {
return qs.stringify(obj);
},
});
}
export interface ServiceRecord {
id: number;
title: string;
description: string;
name?: string;
actionType?: string;
icon?: string;
data?: DescData[];
enable?: boolean;
expires?: boolean;
}
export function queryInspectionList() {
return axios.get('/api/list/quality-inspection');
}
export function queryTheServiceList() {
return axios.get('/api/list/the-service');
}
export function queryRulesPresetList() {
return axios.get('/api/list/rules-preset');
}

View file

@ -1,38 +0,0 @@
import axios from 'axios';
export interface MessageRecord {
id: number;
type: string;
title: string;
subTitle: string;
avatar?: string;
content: string;
time: string;
status: 0 | 1;
messageType?: number;
}
export type MessageListType = MessageRecord[];
export function queryMessageList() {
return axios.post<MessageListType>('/api/message/list');
}
interface MessageStatus {
ids: number[];
}
export function setMessageStatus(data: MessageStatus) {
return axios.post<MessageListType>('/api/message/read', data);
}
export interface ChatRecord {
id: number;
username: string;
content: string;
time: string;
isCollect: boolean;
}
export function queryChatList() {
return axios.post<ChatRecord[]>('/api/chat/list');
}

View file

@ -1,49 +0,0 @@
import axios from 'axios';
export interface ProfileBasicRes {
status: number;
video: {
mode: string;
acquisition: {
resolution: string;
frameRate: number;
};
encoding: {
resolution: string;
rate: {
min: number;
max: number;
default: number;
};
frameRate: number;
profile: string;
};
};
audio: {
mode: string;
acquisition: {
channels: number;
};
encoding: {
channels: number;
rate: number;
profile: string;
};
};
}
export function queryProfileBasic() {
return axios.get<ProfileBasicRes>('/api/profile/basic');
}
export type operationLogRes = Array<{
key: string;
contentNumber: string;
updateContent: string;
status: number;
updateTime: string;
}>;
export function queryOperationLog() {
return axios.get<operationLogRes>('/api/operation/log');
}

View file

@ -1,88 +0,0 @@
import axios from 'axios';
export interface MyProjectRecord {
id: number;
name: string;
description: string;
peopleNumber: number;
contributors: {
name: string;
email: string;
avatar: string;
}[];
}
export function queryMyProjectList() {
return axios.post('/api/user/my-project/list');
}
export interface MyTeamRecord {
id: number;
avatar: string;
name: string;
peopleNumber: number;
}
export function queryMyTeamList() {
return axios.post('/api/user/my-team/list');
}
export interface LatestActivity {
id: number;
title: string;
description: string;
avatar: string;
}
export function queryLatestActivity() {
return axios.post<LatestActivity[]>('/api/user/latest-activity');
}
export function saveUserInfo() {
return axios.post('/api/user/save-info');
}
export interface BasicInfoModel {
email: string;
nickname: string;
countryRegion: string;
area: string;
address: string;
profile: string;
}
export interface EnterpriseCertificationModel {
accountType: number;
status: number;
time: string;
legalPerson: string;
certificateType: string;
authenticationNumber: string;
enterpriseName: string;
enterpriseCertificateType: string;
organizationCode: string;
}
export type CertificationRecord = Array<{
certificationType: number;
certificationContent: string;
status: number;
time: string;
}>;
export interface UnitCertification {
enterpriseInfo: EnterpriseCertificationModel;
record: CertificationRecord;
}
export function queryCertification() {
return axios.post<UnitCertification>('/api/user/certification');
}
export function userUploadApi(
data: FormData,
config: {
controller: AbortController;
onUploadProgress?: (progressEvent: any) => void;
}
) {
// const controller = new AbortController();
return axios.post('/api/user/upload', data, config);
}

View file

@ -1,73 +0,0 @@
import axios from 'axios';
import { GeneralChart } from '@/types/global';
export interface ChartDataRecord {
x: string;
y: number;
name: string;
}
export interface DataChainGrowth {
quota: string;
}
export interface DataChainGrowthRes {
count: number;
growth: number;
chartData: {
xAxis: string[];
data: { name: string; value: number[] };
};
}
export function queryDataChainGrowth(data: DataChainGrowth) {
return axios.post<DataChainGrowthRes>('/api/data-chain-growth', data);
}
export interface PopularAuthorRes {
list: {
ranking: number;
author: string;
contentCount: number;
clickCount: number;
}[];
}
export function queryPopularAuthor() {
return axios.get<PopularAuthorRes>('/api/popular-author/list');
}
export interface ContentPublishRecord {
x: string[];
y: number[];
name: string;
}
export function queryContentPublish() {
return axios.get<ContentPublishRecord[]>('/api/content-publish');
}
export function queryContentPeriodAnalysis() {
return axios.post<GeneralChart>('/api/content-period-analysis');
}
export interface PublicOpinionAnalysis {
quota: string;
}
export interface PublicOpinionAnalysisRes {
count: number;
growth: number;
chartData: ChartDataRecord[];
}
export function queryPublicOpinionAnalysis(data: DataChainGrowth) {
return axios.post<PublicOpinionAnalysisRes>(
'/api/public-opinion-analysis',
data
);
}
export interface DataOverviewRes {
xAxis: string[];
data: Array<{ name: string; value: number[]; count: number }>;
}
export function queryDataOverview() {
return axios.post<DataOverviewRes>('/api/data-overview');
}

View file

@ -1,129 +0,0 @@
<template>
<a-spin style="display: block" :loading="loading">
<a-tabs v-model:activeKey="messageType" type="rounded" destroy-on-hide>
<a-tab-pane v-for="item in tabList" :key="item.key">
<template #title>
<span> {{ item.title }}{{ formatUnreadLength(item.key) }} </span>
</template>
<a-result v-if="!renderList.length" status="404">
<template #subtitle> {{ $t('messageBox.noContent') }} </template>
</a-result>
<List
:render-list="renderList"
:unread-count="unreadCount"
@item-click="handleItemClick"
/>
</a-tab-pane>
<template #extra>
<a-button type="text" @click="emptyList">
{{ $t('messageBox.tab.button') }}
</a-button>
</template>
</a-tabs>
</a-spin>
</template>
<script lang="ts" setup>
import { ref, reactive, toRefs, computed } from 'vue';
import { useI18n } from 'vue-i18n';
import {
queryMessageList,
setMessageStatus,
MessageRecord,
MessageListType,
} from '@/api/message';
import useLoading from '@/hooks/loading';
import List from './list.vue';
interface TabItem {
key: string;
title: string;
avatar?: string;
}
const { loading, setLoading } = useLoading(true);
const messageType = ref('message');
const { t } = useI18n();
const messageData = reactive<{
renderList: MessageRecord[];
messageList: MessageRecord[];
}>({
renderList: [],
messageList: [],
});
toRefs(messageData);
const tabList: TabItem[] = [
{
key: 'message',
title: t('messageBox.tab.title.message'),
},
{
key: 'notice',
title: t('messageBox.tab.title.notice'),
},
{
key: 'todo',
title: t('messageBox.tab.title.todo'),
},
];
async function fetchSourceData() {
setLoading(true);
try {
const { data } = await queryMessageList();
messageData.messageList = data;
} catch (err) {
// you can report use errorHandler or other
} finally {
setLoading(false);
}
}
async function readMessage(data: MessageListType) {
const ids = data.map((item) => item.id);
await setMessageStatus({ ids });
fetchSourceData();
}
const renderList = computed(() => {
return messageData.messageList.filter(
(item) => messageType.value === item.type
);
});
const unreadCount = computed(() => {
return renderList.value.filter((item) => !item.status).length;
});
const getUnreadList = (type: string) => {
const list = messageData.messageList.filter(
(item) => item.type === type && !item.status
);
return list;
};
const formatUnreadLength = (type: string) => {
const list = getUnreadList(type);
return list.length ? `(${list.length})` : ``;
};
const handleItemClick = (items: MessageListType) => {
if (renderList.value.length) readMessage([...items]);
};
const emptyList = () => {
messageData.messageList = [];
};
fetchSourceData();
</script>
<style scoped lang="less">
:deep(.arco-popover-popup-content) {
padding: 0;
}
:deep(.arco-list-item-meta) {
align-items: flex-start;
}
:deep(.arco-tabs-nav) {
padding: 14px 0 12px 16px;
border-bottom: 1px solid var(--color-neutral-3);
}
:deep(.arco-tabs-content) {
padding-top: 0;
.arco-result-subtitle {
color: rgb(var(--gray-6));
}
}
</style>

View file

@ -1,149 +0,0 @@
<template>
<a-list :bordered="false">
<a-list-item
v-for="item in renderList"
:key="item.id"
action-layout="vertical"
:style="{
opacity: item.status ? 0.5 : 1,
}"
>
<template #extra>
<a-tag v-if="item.messageType === 0" color="gray">未开始</a-tag>
<a-tag v-else-if="item.messageType === 1" color="green">已开通</a-tag>
<a-tag v-else-if="item.messageType === 2" color="blue">进行中</a-tag>
<a-tag v-else-if="item.messageType === 3" color="red">即将到期</a-tag>
</template>
<div class="item-wrap" @click="onItemClick(item)">
<a-list-item-meta>
<template v-if="item.avatar" #avatar>
<a-avatar shape="circle">
<img v-if="item.avatar" :src="item.avatar" />
<icon-desktop v-else />
</a-avatar>
</template>
<template #title>
<a-space :size="4">
<span>{{ item.title }}</span>
<a-typography-text type="secondary">
{{ item.subTitle }}
</a-typography-text>
</a-space>
</template>
<template #description>
<div>
<a-typography-paragraph
:ellipsis="{
rows: 1,
}"
>{{ item.content }}</a-typography-paragraph
>
<a-typography-text
v-if="item.type === 'message'"
class="time-text"
>
{{ item.time }}
</a-typography-text>
</div>
</template>
</a-list-item-meta>
</div>
</a-list-item>
<template #footer>
<a-space
fill
:size="0"
:class="{ 'add-border-top': renderList.length < showMax }"
>
<div class="footer-wrap">
<a-link @click="allRead">{{ $t('messageBox.allRead') }}</a-link>
</div>
<div class="footer-wrap">
<a-link>{{ $t('messageBox.viewMore') }}</a-link>
</div>
</a-space>
</template>
<div
v-if="renderList.length && renderList.length < 3"
:style="{ height: (showMax - renderList.length) * 86 + 'px' }"
></div>
</a-list>
</template>
<script lang="ts" setup>
import { PropType } from 'vue';
import { MessageRecord, MessageListType } from '@/api/message';
const props = defineProps({
renderList: {
type: Array as PropType<MessageListType>,
required: true,
},
unreadCount: {
type: Number,
default: 0,
},
});
const emit = defineEmits(['itemClick']);
const allRead = () => {
emit('itemClick', [...props.renderList]);
};
const onItemClick = (item: MessageRecord) => {
if (!item.status) {
emit('itemClick', [item]);
}
};
const showMax = 3;
</script>
<style scoped lang="less">
:deep(.arco-list) {
.arco-list-item {
min-height: 86px;
border-bottom: 1px solid rgb(var(--gray-3));
}
.arco-list-item-extra {
position: absolute;
right: 20px;
}
.arco-list-item-meta-content {
flex: 1;
}
.item-wrap {
cursor: pointer;
}
.time-text {
font-size: 12px;
color: rgb(var(--gray-6));
}
.arco-empty {
display: none;
}
.arco-list-footer {
padding: 0;
height: 50px;
line-height: 50px;
border-top: none;
.arco-space-item {
width: 100%;
border-right: 1px solid rgb(var(--gray-3));
&:last-child {
border-right: none;
}
}
.add-border-top {
border-top: 1px solid rgb(var(--gray-3));
}
}
.footer-wrap {
text-align: center;
}
.arco-typography {
margin-bottom: 0;
}
.add-border {
border-top: 1px solid rgb(var(--gray-3));
}
}
</style>

View file

@ -1,13 +0,0 @@
export default {
'messageBox.tab.title.message': 'Message',
'messageBox.tab.title.notice': 'Notice',
'messageBox.tab.title.todo': 'Todo',
'messageBox.tab.button': 'empty',
'messageBox.allRead': 'All Read',
'messageBox.viewMore': 'View More',
'messageBox.noContent': 'No Content',
'messageBox.switchRoles': 'Switch Roles',
'messageBox.userCenter': 'User Center',
'messageBox.userSettings': 'User Settings',
'messageBox.logout': 'Logout',
};

View file

@ -1,13 +0,0 @@
export default {
'messageBox.tab.title.message': '消息',
'messageBox.tab.title.notice': '通知',
'messageBox.tab.title.todo': '待办',
'messageBox.tab.button': '清空',
'messageBox.allRead': '全部已读',
'messageBox.viewMore': '查看更多',
'messageBox.noContent': '暂无内容',
'messageBox.switchRoles': '切换角色',
'messageBox.userCenter': '用户中心',
'messageBox.userSettings': '用户设置',
'messageBox.logout': '登出登录',
};

View file

@ -167,7 +167,7 @@
import { Message } from '@arco-design/web-vue';
import { useRoute } from 'vue-router';
import { useDark, useToggle, useFullscreen } from '@vueuse/core';
import { useAppStore, useUserStore } from '@/store';
import { useAppStore } from '@/store';
import { LOCALE_OPTIONS } from '@/locale';
import useLocale from '@/hooks/locale';
import useUser from '@/hooks/user';
@ -178,7 +178,6 @@
const drivers = import.meta.glob('@/drivers/*.json', { eager: true });
const appStore = useAppStore();
const userStore = useUserStore();
const route = useRoute();
const { logout } = useUser();

View file

@ -1,5 +1,3 @@
import localeMessageBox from '@/components/message-box/locale/en-US';
import localeWorkplace from '@/views/dashboard/workplace/locale/en-US';
import localeSearchTable from '@/views/list/search-table/locale/en-US';
@ -166,7 +164,6 @@ export default {
'menu.cps.writeNoticeContent': "Confirmation to write the channel shown on the web page to the device? (will override the device's current channel configuration)",
'menu.satellite2': 'Satcom 2.0',
...localeSettings,
...localeMessageBox,
...localeWorkplace,
...localeSearchTable,

View file

@ -1,5 +1,3 @@
import localeMessageBox from '@/components/message-box/locale/zh-CN';
import localeWorkplace from '@/views/dashboard/workplace/locale/zh-CN';
import localeSearchTable from '@/views/list/search-table/locale/zh-CN';
@ -166,7 +164,6 @@ export default {
'menu.cps.writeNoticeContent': '确认将网页显示的信道写入设备吗?(将覆盖设备当前信道配置)',
'menu.satellite2': '星历写入 2.0',
...localeSettings,
...localeMessageBox,
...localeWorkplace,
...localeSearchTable,

View file

@ -1,204 +0,0 @@
<template>
<div class="card-wrap">
<a-card v-if="loading" :bordered="false" hoverable>
<slot name="skeleton"></slot>
</a-card>
<a-card v-else :bordered="false" hoverable>
<a-space align="start">
<a-avatar
v-if="icon"
:size="24"
style="margin-right: 8px; background-color: #626aea"
>
<icon-filter />
</a-avatar>
<a-card-meta>
<template #title>
<a-typography-text style="margin-right: 10px">
{{ title }}
</a-typography-text>
<template v-if="showTag">
<a-tag
v-if="open && isExpires === false"
size="small"
color="green"
>
<template #icon>
<icon-check-circle-fill />
</template>
<span>{{ tagText }}</span>
</a-tag>
<a-tag v-else-if="isExpires" size="small" color="red">
<template #icon>
<icon-check-circle-fill />
</template>
<span>{{ expiresTagText }}</span>
</a-tag>
</template>
</template>
<template #description>
{{ description }}
<slot></slot>
</template>
</a-card-meta>
</a-space>
<template #actions>
<a-switch v-if="actionType === 'switch'" v-model="open" />
<a-space v-else-if="actionType === 'button'">
<template v-if="isExpires">
<a-button type="outline" @click="renew">
{{ expiresText }}
</a-button>
</template>
<template v-else>
<a-button v-if="open" @click="handleToggle">
{{ closeTxt }}
</a-button>
<a-button v-else-if="!open" type="outline" @click="handleToggle">
{{ openTxt }}
</a-button>
</template>
</a-space>
<div v-else>
<a-space>
<a-button @click="toggle(false)">
{{ closeTxt }}
</a-button>
<a-button type="primary" @click="toggle(true)">
{{ openTxt }}
</a-button>
</a-space>
</div>
</template>
</a-card>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { useToggle } from '@vueuse/core';
const props = defineProps({
loading: {
type: Boolean,
default: false,
},
title: {
type: String,
default: '',
},
description: {
type: String,
default: '',
},
actionType: {
type: String,
default: '',
},
defaultValue: {
type: Boolean,
default: false,
},
openTxt: {
type: String,
default: '',
},
closeTxt: {
type: String,
default: '',
},
expiresText: {
type: String,
default: '',
},
icon: {
type: String,
default: '',
},
showTag: {
type: Boolean,
default: true,
},
tagText: {
type: String,
default: '',
},
expires: {
type: Boolean,
default: false,
},
expiresTagText: {
type: String,
default: '',
},
});
const [open, toggle] = useToggle(props.defaultValue);
const handleToggle = () => {
toggle();
};
const isExpires = ref(props.expires);
const renew = () => {
isExpires.value = false;
};
</script>
<style scoped lang="less">
.card-wrap {
height: 100%;
transition: all 0.3s;
border: 1px solid var(--color-neutral-3);
border-radius: 4px;
&:hover {
transform: translateY(-4px);
// box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.1);
}
:deep(.arco-card) {
height: 100%;
border-radius: 4px;
.arco-card-body {
height: 100%;
.arco-space {
width: 100%;
height: 100%;
.arco-space-item {
height: 100%;
&:last-child {
flex: 1;
}
.arco-card-meta {
height: 100%;
display: flex;
flex-flow: column;
.arco-card-meta-content {
flex: 1;
.arco-card-meta-description {
margin-top: 8px;
color: rgb(var(--gray-6));
line-height: 20px;
font-size: 12px;
}
}
.arco-card-meta-footer {
margin-top: 0;
}
}
}
}
}
}
:deep(.arco-card-meta-title) {
display: flex;
align-items: center;
// To prevent the shaking
line-height: 28px;
}
:deep(.arco-skeleton-line) {
&:last-child {
display: flex;
justify-content: flex-end;
margin-top: 20px;
}
}
}
</style>

View file

@ -1,115 +0,0 @@
<template>
<div class="list-wrap">
<a-typography-title class="block-title" :heading="6">
{{ $t('cardList.tab.title.content') }}
</a-typography-title>
<a-row class="list-row" :gutter="24">
<a-col
:xs="12"
:sm="12"
:md="12"
:lg="6"
:xl="6"
:xxl="6"
class="list-col"
>
<div class="card-wrap empty-wrap">
<a-card :bordered="false" hoverable>
<a-result :status="null" :title="$t('cardList.content.action')">
<template #icon>
<icon-plus style="font-size: 20px" />
</template>
</a-result>
</a-card>
</div>
</a-col>
<a-col
v-for="item in renderData"
:key="item.id"
class="list-col"
:xs="12"
:sm="12"
:md="12"
:lg="6"
:xl="6"
:xxl="6"
>
<CardWrap
:loading="loading"
:title="item.title"
:description="item.description"
:default-value="item.enable"
:action-type="item.actionType"
:icon="item.icon"
:open-txt="$t('cardList.content.inspection')"
:close-txt="$t('cardList.content.delete')"
:show-tag="false"
>
<a-descriptions
style="margin-top: 16px"
:data="item.data"
layout="inline-horizontal"
:column="2"
/>
<template #skeleton>
<a-skeleton :animation="true">
<a-skeleton-line
:widths="['50%', '50%', '100%', '40%']"
:rows="4"
/>
<a-skeleton-line :widths="['40%']" :rows="1" />
</a-skeleton>
</template>
</CardWrap>
</a-col>
</a-row>
</div>
</template>
<script lang="ts" setup>
import { queryInspectionList, ServiceRecord } from '@/api/list';
import useRequest from '@/hooks/request';
import CardWrap from './card-wrap.vue';
const defaultValue: ServiceRecord[] = new Array(3).fill({});
const { loading, response: renderData } = useRequest<ServiceRecord[]>(
queryInspectionList,
defaultValue
);
</script>
<style scoped lang="less">
.card-wrap {
height: 100%;
transition: all 0.3s;
border: 1px solid var(--color-neutral-3);
&:hover {
transform: translateY(-4px);
}
:deep(.arco-card-meta-description) {
color: rgb(var(--gray-6));
.arco-descriptions-item-label-inline {
font-weight: normal;
font-size: 12px;
color: rgb(var(--gray-6));
}
.arco-descriptions-item-value-inline {
color: rgb(var(--gray-8));
}
}
}
.empty-wrap {
height: 200px;
border-radius: 4px;
:deep(.arco-card) {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
border-radius: 4px;
.arco-result-title {
color: rgb(var(--gray-6));
}
}
}
</style>

View file

@ -1,51 +0,0 @@
<template>
<div class="list-wrap">
<a-typography-title class="block-title" :heading="6">
{{ $t('cardList.tab.title.preset') }}
</a-typography-title>
<a-row class="list-row" :gutter="24">
<a-col
v-for="item in renderData"
:key="item.id"
:xs="12"
:sm="12"
:md="12"
:lg="6"
:xl="6"
:xxl="6"
class="list-col"
style="min-height: 140px"
>
<CardWrap
:loading="loading"
:title="item.title"
:description="item.description"
:default-value="item.enable"
:action-type="item.actionType"
:tag-text="$t('cardList.preset.tag')"
>
<template #skeleton>
<a-skeleton :animation="true">
<a-skeleton-line :widths="['100%', '40%']" :rows="2" />
<a-skeleton-line :widths="['40%']" :rows="1" />
</a-skeleton>
</template>
</CardWrap>
</a-col>
</a-row>
</div>
</template>
<script lang="ts" setup>
import { queryRulesPresetList, ServiceRecord } from '@/api/list';
import useRequest from '@/hooks/request';
import CardWrap from './card-wrap.vue';
const defaultValue: ServiceRecord[] = new Array(6).fill({});
const { loading, response: renderData } = useRequest<ServiceRecord[]>(
queryRulesPresetList,
defaultValue
);
</script>
<style scoped lang="less"></style>

View file

@ -1,57 +0,0 @@
<template>
<div class="list-wrap">
<a-typography-title class="block-title" :heading="6">
{{ $t('cardList.tab.title.service') }}
</a-typography-title>
<a-row class="list-row" :gutter="24">
<a-col
v-for="item in renderData"
:key="item.id"
:xs="12"
:sm="12"
:md="12"
:lg="6"
:xl="6"
:xxl="6"
class="list-col"
style="min-height: 162px"
>
<CardWrap
:loading="loading"
:title="item.title"
:description="item.description"
:default-value="item.enable"
:action-type="item.actionType"
:expires="item.expires"
:open-txt="$t('cardList.service.open')"
:close-txt="$t('cardList.service.cancel')"
:expires-text="$t('cardList.service.renew')"
:tag-text="$t('cardList.service.tag')"
:expires-tag-text="$t('cardList.service.expiresTag')"
:icon="item.icon"
>
<template #skeleton>
<a-skeleton :animation="true">
<a-skeleton-line :widths="['100%', '40%', '100%']" :rows="3" />
<a-skeleton-line :widths="['40%']" :rows="1" />
</a-skeleton>
</template>
</CardWrap>
</a-col>
</a-row>
</div>
</template>
<script lang="ts" setup>
import { queryTheServiceList, ServiceRecord } from '@/api/list';
import useRequest from '@/hooks/request';
import CardWrap from './card-wrap.vue';
const defaultValue: ServiceRecord[] = new Array(4).fill({});
const { loading, response: renderData } = useRequest<ServiceRecord[]>(
queryTheServiceList,
defaultValue
);
</script>
<style scoped lang="less"></style>

View file

@ -1,186 +0,0 @@
import Mock from 'mockjs';
import setupMock, { successResponseWrap } from '@/utils/setup-mock';
import { ServiceRecord } from '@/api/list';
const qualityInspectionList: ServiceRecord[] = [
{
id: 1,
name: 'quality',
title: '视频类-历史导入',
description: '2021-10-12 00:00:00',
data: [
{
label: '待质检数',
value: '120',
},
{
label: '积压时长',
value: '60s',
},
{
label: '待抽检数',
value: '0',
},
],
},
{
id: 2,
name: 'quality',
title: '图文类-图片版权',
description: '2021-12-11 18:30:00',
data: [
{
label: '待质检数',
value: '120',
},
{
label: '积压时长',
value: '60s',
},
{
label: '待抽检数',
value: '0',
},
],
},
{
id: 3,
name: 'quality',
title: '图文类-高清图片',
description: '2021-10-15 08:10:00',
data: [
{
label: '待质检数',
value: '120',
},
{
label: '积压时长',
value: '60s',
},
{
label: '待抽检数',
value: '0',
},
],
},
];
const theServiceList: ServiceRecord[] = [
{
id: 1,
icon: 'code',
title: '漏斗分析',
description:
'用户行为分析之漏斗分析模型是企业实现精细化运营、进行用户行为分析的重要数据分析模型。',
enable: true,
actionType: 'button',
},
{
id: 2,
icon: 'edit',
title: '用户分布',
description:
'快速诊断用户人群,地域细分情况,了解数据分布的集中度,以及主要的数据分布的区间段是什么。',
enable: true,
actionType: 'button',
expires: true,
},
{
id: 3,
icon: 'user',
title: '资源分发',
description:
'移动端动态化资源分发解决方案。提供稳定大流量服务支持、灵活定制的分发圈选规则,通过离线化预加载。',
enable: false,
actionType: 'button',
},
{
id: 4,
icon: 'user',
title: '用户画像分析',
description:
'用户画像就是将典型用户信息标签化,根据用户特征、业务场景和用户行为等信息,构建一个标签化的用户模型。',
enable: true,
actionType: 'button',
},
];
const rulesPresetList: ServiceRecord[] = [
{
id: 1,
title: '内容屏蔽规则',
description:
'用户在执行特定的内容分发任务时,可使用内容屏蔽规则根据特定标签,过滤内容集合。',
enable: true,
actionType: 'switch',
},
{
id: 2,
title: '内容置顶规则',
description:
'该规则支持用户在执行特定内容分发任务时,对固定的几条内容置顶。',
enable: true,
actionType: 'switch',
},
{
id: 3,
title: '内容加权规则',
description: '选定内容加权规则后可自定义从不同内容集合获取内容的概率。',
enable: false,
actionType: 'switch',
},
{
id: 4,
title: '内容分发规则',
description: '内容分发时对某些内容需要固定在C端展示的位置。',
enable: true,
actionType: 'switch',
},
{
id: 5,
title: '违禁内容识别',
description: '精准识别赌博、刀枪、毒品、造假、贩假等违规物品和违规行为。',
enable: false,
actionType: 'switch',
},
{
id: 6,
title: '多语言文字符号识别',
description:
'精准识别英语、维语、藏语、蒙古语、朝鲜语等多种语言以及emoji表情形态的语义识别。',
enable: false,
actionType: 'switch',
},
];
setupMock({
setup() {
// Quality Inspection
Mock.mock(new RegExp('/api/list/quality-inspection'), () => {
return successResponseWrap(
qualityInspectionList.map((_, index) => ({
...qualityInspectionList[index % qualityInspectionList.length],
id: Mock.Random.guid(),
}))
);
});
// the service
Mock.mock(new RegExp('/api/list/the-service'), () => {
return successResponseWrap(
theServiceList.map((_, index) => ({
...theServiceList[index % theServiceList.length],
id: Mock.Random.guid(),
}))
);
});
// rules preset
Mock.mock(new RegExp('/api/list/rules-preset'), () => {
return successResponseWrap(
rulesPresetList.map((_, index) => ({
...rulesPresetList[index % rulesPresetList.length],
id: Mock.Random.guid(),
}))
);
});
},
});

View file

@ -1,204 +0,0 @@
<template>
<div class="card-wrap">
<a-card v-if="loading" :bordered="false" hoverable>
<slot name="skeleton"></slot>
</a-card>
<a-card v-else :bordered="false" hoverable>
<a-space align="start">
<a-avatar
v-if="icon"
:size="24"
style="margin-right: 8px; background-color: #626aea"
>
<icon-filter />
</a-avatar>
<a-card-meta>
<template #title>
<a-typography-text style="margin-right: 10px">
{{ title }}
</a-typography-text>
<template v-if="showTag">
<a-tag
v-if="open && isExpires === false"
size="small"
color="green"
>
<template #icon>
<icon-check-circle-fill />
</template>
<span>{{ tagText }}</span>
</a-tag>
<a-tag v-else-if="isExpires" size="small" color="red">
<template #icon>
<icon-check-circle-fill />
</template>
<span>{{ expiresTagText }}</span>
</a-tag>
</template>
</template>
<template #description>
{{ description }}
<slot></slot>
</template>
</a-card-meta>
</a-space>
<template #actions>
<a-switch v-if="actionType === 'switch'" v-model="open" />
<a-space v-else-if="actionType === 'button'">
<template v-if="isExpires">
<a-button type="outline" @click="renew">
{{ expiresText }}
</a-button>
</template>
<template v-else>
<a-button v-if="open" @click="handleToggle">
{{ closeTxt }}
</a-button>
<a-button v-else-if="!open" type="outline" @click="handleToggle">
{{ openTxt }}
</a-button>
</template>
</a-space>
<div v-else>
<a-space>
<a-button @click="toggle(false)">
{{ closeTxt }}
</a-button>
<a-button type="primary" @click="toggle(true)">
{{ openTxt }}
</a-button>
</a-space>
</div>
</template>
</a-card>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { useToggle } from '@vueuse/core';
const props = defineProps({
loading: {
type: Boolean,
default: false,
},
title: {
type: String,
default: '',
},
description: {
type: String,
default: '',
},
actionType: {
type: String,
default: '',
},
defaultValue: {
type: Boolean,
default: false,
},
openTxt: {
type: String,
default: '',
},
closeTxt: {
type: String,
default: '',
},
expiresText: {
type: String,
default: '',
},
icon: {
type: String,
default: '',
},
showTag: {
type: Boolean,
default: true,
},
tagText: {
type: String,
default: '',
},
expires: {
type: Boolean,
default: false,
},
expiresTagText: {
type: String,
default: '',
},
});
const [open, toggle] = useToggle(props.defaultValue);
const handleToggle = () => {
toggle();
};
const isExpires = ref(props.expires);
const renew = () => {
isExpires.value = false;
};
</script>
<style scoped lang="less">
.card-wrap {
height: 100%;
transition: all 0.3s;
border: 1px solid var(--color-neutral-3);
border-radius: 4px;
&:hover {
transform: translateY(-4px);
// box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.1);
}
:deep(.arco-card) {
height: 100%;
border-radius: 4px;
.arco-card-body {
height: 100%;
.arco-space {
width: 100%;
height: 100%;
.arco-space-item {
height: 100%;
&:last-child {
flex: 1;
}
.arco-card-meta {
height: 100%;
display: flex;
flex-flow: column;
.arco-card-meta-content {
flex: 1;
.arco-card-meta-description {
margin-top: 8px;
color: rgb(var(--gray-6));
line-height: 20px;
font-size: 12px;
}
}
.arco-card-meta-footer {
margin-top: 0;
}
}
}
}
}
}
:deep(.arco-card-meta-title) {
display: flex;
align-items: center;
// To prevent the shaking
line-height: 28px;
}
:deep(.arco-skeleton-line) {
&:last-child {
display: flex;
justify-content: flex-end;
margin-top: 20px;
}
}
}
</style>

View file

@ -1,115 +0,0 @@
<template>
<div class="list-wrap">
<a-typography-title class="block-title" :heading="6">
{{ $t('cardList.tab.title.content') }}
</a-typography-title>
<a-row class="list-row" :gutter="24">
<a-col
:xs="12"
:sm="12"
:md="12"
:lg="6"
:xl="6"
:xxl="6"
class="list-col"
>
<div class="card-wrap empty-wrap">
<a-card :bordered="false" hoverable>
<a-result :status="null" :title="$t('cardList.content.action')">
<template #icon>
<icon-plus style="font-size: 20px" />
</template>
</a-result>
</a-card>
</div>
</a-col>
<a-col
v-for="item in renderData"
:key="item.id"
class="list-col"
:xs="12"
:sm="12"
:md="12"
:lg="6"
:xl="6"
:xxl="6"
>
<CardWrap
:loading="loading"
:title="item.title"
:description="item.description"
:default-value="item.enable"
:action-type="item.actionType"
:icon="item.icon"
:open-txt="$t('cardList.content.inspection')"
:close-txt="$t('cardList.content.delete')"
:show-tag="false"
>
<a-descriptions
style="margin-top: 16px"
:data="item.data"
layout="inline-horizontal"
:column="2"
/>
<template #skeleton>
<a-skeleton :animation="true">
<a-skeleton-line
:widths="['50%', '50%', '100%', '40%']"
:rows="4"
/>
<a-skeleton-line :widths="['40%']" :rows="1" />
</a-skeleton>
</template>
</CardWrap>
</a-col>
</a-row>
</div>
</template>
<script lang="ts" setup>
import { queryInspectionList, ServiceRecord } from '@/api/list';
import useRequest from '@/hooks/request';
import CardWrap from './card-wrap.vue';
const defaultValue: ServiceRecord[] = new Array(3).fill({});
const { loading, response: renderData } = useRequest<ServiceRecord[]>(
queryInspectionList,
defaultValue
);
</script>
<style scoped lang="less">
.card-wrap {
height: 100%;
transition: all 0.3s;
border: 1px solid var(--color-neutral-3);
&:hover {
transform: translateY(-4px);
}
:deep(.arco-card-meta-description) {
color: rgb(var(--gray-6));
.arco-descriptions-item-label-inline {
font-weight: normal;
font-size: 12px;
color: rgb(var(--gray-6));
}
.arco-descriptions-item-value-inline {
color: rgb(var(--gray-8));
}
}
}
.empty-wrap {
height: 200px;
border-radius: 4px;
:deep(.arco-card) {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
border-radius: 4px;
.arco-result-title {
color: rgb(var(--gray-6));
}
}
}
</style>

View file

@ -1,51 +0,0 @@
<template>
<div class="list-wrap">
<a-typography-title class="block-title" :heading="6">
{{ $t('cardList.tab.title.preset') }}
</a-typography-title>
<a-row class="list-row" :gutter="24">
<a-col
v-for="item in renderData"
:key="item.id"
:xs="12"
:sm="12"
:md="12"
:lg="6"
:xl="6"
:xxl="6"
class="list-col"
style="min-height: 140px"
>
<CardWrap
:loading="loading"
:title="item.title"
:description="item.description"
:default-value="item.enable"
:action-type="item.actionType"
:tag-text="$t('cardList.preset.tag')"
>
<template #skeleton>
<a-skeleton :animation="true">
<a-skeleton-line :widths="['100%', '40%']" :rows="2" />
<a-skeleton-line :widths="['40%']" :rows="1" />
</a-skeleton>
</template>
</CardWrap>
</a-col>
</a-row>
</div>
</template>
<script lang="ts" setup>
import { queryRulesPresetList, ServiceRecord } from '@/api/list';
import useRequest from '@/hooks/request';
import CardWrap from './card-wrap.vue';
const defaultValue: ServiceRecord[] = new Array(6).fill({});
const { loading, response: renderData } = useRequest<ServiceRecord[]>(
queryRulesPresetList,
defaultValue
);
</script>
<style scoped lang="less"></style>

View file

@ -1,57 +0,0 @@
<template>
<div class="list-wrap">
<a-typography-title class="block-title" :heading="6">
{{ $t('cardList.tab.title.service') }}
</a-typography-title>
<a-row class="list-row" :gutter="24">
<a-col
v-for="item in renderData"
:key="item.id"
:xs="12"
:sm="12"
:md="12"
:lg="6"
:xl="6"
:xxl="6"
class="list-col"
style="min-height: 162px"
>
<CardWrap
:loading="loading"
:title="item.title"
:description="item.description"
:default-value="item.enable"
:action-type="item.actionType"
:expires="item.expires"
:open-txt="$t('cardList.service.open')"
:close-txt="$t('cardList.service.cancel')"
:expires-text="$t('cardList.service.renew')"
:tag-text="$t('cardList.service.tag')"
:expires-tag-text="$t('cardList.service.expiresTag')"
:icon="item.icon"
>
<template #skeleton>
<a-skeleton :animation="true">
<a-skeleton-line :widths="['100%', '40%', '100%']" :rows="3" />
<a-skeleton-line :widths="['40%']" :rows="1" />
</a-skeleton>
</template>
</CardWrap>
</a-col>
</a-row>
</div>
</template>
<script lang="ts" setup>
import { queryTheServiceList, ServiceRecord } from '@/api/list';
import useRequest from '@/hooks/request';
import CardWrap from './card-wrap.vue';
const defaultValue: ServiceRecord[] = new Array(4).fill({});
const { loading, response: renderData } = useRequest<ServiceRecord[]>(
queryTheServiceList,
defaultValue
);
</script>
<style scoped lang="less"></style>

View file

@ -1,186 +0,0 @@
import Mock from 'mockjs';
import setupMock, { successResponseWrap } from '@/utils/setup-mock';
import { ServiceRecord } from '@/api/list';
const qualityInspectionList: ServiceRecord[] = [
{
id: 1,
name: 'quality',
title: '视频类-历史导入',
description: '2021-10-12 00:00:00',
data: [
{
label: '待质检数',
value: '120',
},
{
label: '积压时长',
value: '60s',
},
{
label: '待抽检数',
value: '0',
},
],
},
{
id: 2,
name: 'quality',
title: '图文类-图片版权',
description: '2021-12-11 18:30:00',
data: [
{
label: '待质检数',
value: '120',
},
{
label: '积压时长',
value: '60s',
},
{
label: '待抽检数',
value: '0',
},
],
},
{
id: 3,
name: 'quality',
title: '图文类-高清图片',
description: '2021-10-15 08:10:00',
data: [
{
label: '待质检数',
value: '120',
},
{
label: '积压时长',
value: '60s',
},
{
label: '待抽检数',
value: '0',
},
],
},
];
const theServiceList: ServiceRecord[] = [
{
id: 1,
icon: 'code',
title: '漏斗分析',
description:
'用户行为分析之漏斗分析模型是企业实现精细化运营、进行用户行为分析的重要数据分析模型。',
enable: true,
actionType: 'button',
},
{
id: 2,
icon: 'edit',
title: '用户分布',
description:
'快速诊断用户人群,地域细分情况,了解数据分布的集中度,以及主要的数据分布的区间段是什么。',
enable: true,
actionType: 'button',
expires: true,
},
{
id: 3,
icon: 'user',
title: '资源分发',
description:
'移动端动态化资源分发解决方案。提供稳定大流量服务支持、灵活定制的分发圈选规则,通过离线化预加载。',
enable: false,
actionType: 'button',
},
{
id: 4,
icon: 'user',
title: '用户画像分析',
description:
'用户画像就是将典型用户信息标签化,根据用户特征、业务场景和用户行为等信息,构建一个标签化的用户模型。',
enable: true,
actionType: 'button',
},
];
const rulesPresetList: ServiceRecord[] = [
{
id: 1,
title: '内容屏蔽规则',
description:
'用户在执行特定的内容分发任务时,可使用内容屏蔽规则根据特定标签,过滤内容集合。',
enable: true,
actionType: 'switch',
},
{
id: 2,
title: '内容置顶规则',
description:
'该规则支持用户在执行特定内容分发任务时,对固定的几条内容置顶。',
enable: true,
actionType: 'switch',
},
{
id: 3,
title: '内容加权规则',
description: '选定内容加权规则后可自定义从不同内容集合获取内容的概率。',
enable: false,
actionType: 'switch',
},
{
id: 4,
title: '内容分发规则',
description: '内容分发时对某些内容需要固定在C端展示的位置。',
enable: true,
actionType: 'switch',
},
{
id: 5,
title: '违禁内容识别',
description: '精准识别赌博、刀枪、毒品、造假、贩假等违规物品和违规行为。',
enable: false,
actionType: 'switch',
},
{
id: 6,
title: '多语言文字符号识别',
description:
'精准识别英语、维语、藏语、蒙古语、朝鲜语等多种语言以及emoji表情形态的语义识别。',
enable: false,
actionType: 'switch',
},
];
setupMock({
setup() {
// Quality Inspection
Mock.mock(new RegExp('/api/list/quality-inspection'), () => {
return successResponseWrap(
qualityInspectionList.map((_, index) => ({
...qualityInspectionList[index % qualityInspectionList.length],
id: Mock.Random.guid(),
}))
);
});
// the service
Mock.mock(new RegExp('/api/list/the-service'), () => {
return successResponseWrap(
theServiceList.map((_, index) => ({
...theServiceList[index % theServiceList.length],
id: Mock.Random.guid(),
}))
);
});
// rules preset
Mock.mock(new RegExp('/api/list/rules-preset'), () => {
return successResponseWrap(
rulesPresetList.map((_, index) => ({
...rulesPresetList[index % rulesPresetList.length],
id: Mock.Random.guid(),
}))
);
});
},
});

View file

@ -1,204 +0,0 @@
<template>
<div class="card-wrap">
<a-card v-if="loading" :bordered="false" hoverable>
<slot name="skeleton"></slot>
</a-card>
<a-card v-else :bordered="false" hoverable>
<a-space align="start">
<a-avatar
v-if="icon"
:size="24"
style="margin-right: 8px; background-color: #626aea"
>
<icon-filter />
</a-avatar>
<a-card-meta>
<template #title>
<a-typography-text style="margin-right: 10px">
{{ title }}
</a-typography-text>
<template v-if="showTag">
<a-tag
v-if="open && isExpires === false"
size="small"
color="green"
>
<template #icon>
<icon-check-circle-fill />
</template>
<span>{{ tagText }}</span>
</a-tag>
<a-tag v-else-if="isExpires" size="small" color="red">
<template #icon>
<icon-check-circle-fill />
</template>
<span>{{ expiresTagText }}</span>
</a-tag>
</template>
</template>
<template #description>
{{ description }}
<slot></slot>
</template>
</a-card-meta>
</a-space>
<template #actions>
<a-switch v-if="actionType === 'switch'" v-model="open" />
<a-space v-else-if="actionType === 'button'">
<template v-if="isExpires">
<a-button type="outline" @click="renew">
{{ expiresText }}
</a-button>
</template>
<template v-else>
<a-button v-if="open" @click="handleToggle">
{{ closeTxt }}
</a-button>
<a-button v-else-if="!open" type="outline" @click="handleToggle">
{{ openTxt }}
</a-button>
</template>
</a-space>
<div v-else>
<a-space>
<a-button @click="toggle(false)">
{{ closeTxt }}
</a-button>
<a-button type="primary" @click="toggle(true)">
{{ openTxt }}
</a-button>
</a-space>
</div>
</template>
</a-card>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { useToggle } from '@vueuse/core';
const props = defineProps({
loading: {
type: Boolean,
default: false,
},
title: {
type: String,
default: '',
},
description: {
type: String,
default: '',
},
actionType: {
type: String,
default: '',
},
defaultValue: {
type: Boolean,
default: false,
},
openTxt: {
type: String,
default: '',
},
closeTxt: {
type: String,
default: '',
},
expiresText: {
type: String,
default: '',
},
icon: {
type: String,
default: '',
},
showTag: {
type: Boolean,
default: true,
},
tagText: {
type: String,
default: '',
},
expires: {
type: Boolean,
default: false,
},
expiresTagText: {
type: String,
default: '',
},
});
const [open, toggle] = useToggle(props.defaultValue);
const handleToggle = () => {
toggle();
};
const isExpires = ref(props.expires);
const renew = () => {
isExpires.value = false;
};
</script>
<style scoped lang="less">
.card-wrap {
height: 100%;
transition: all 0.3s;
border: 1px solid var(--color-neutral-3);
border-radius: 4px;
&:hover {
transform: translateY(-4px);
// box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.1);
}
:deep(.arco-card) {
height: 100%;
border-radius: 4px;
.arco-card-body {
height: 100%;
.arco-space {
width: 100%;
height: 100%;
.arco-space-item {
height: 100%;
&:last-child {
flex: 1;
}
.arco-card-meta {
height: 100%;
display: flex;
flex-flow: column;
.arco-card-meta-content {
flex: 1;
.arco-card-meta-description {
margin-top: 8px;
color: rgb(var(--gray-6));
line-height: 20px;
font-size: 12px;
}
}
.arco-card-meta-footer {
margin-top: 0;
}
}
}
}
}
}
:deep(.arco-card-meta-title) {
display: flex;
align-items: center;
// To prevent the shaking
line-height: 28px;
}
:deep(.arco-skeleton-line) {
&:last-child {
display: flex;
justify-content: flex-end;
margin-top: 20px;
}
}
}
</style>

View file

@ -1,115 +0,0 @@
<template>
<div class="list-wrap">
<a-typography-title class="block-title" :heading="6">
{{ $t('cardList.tab.title.content') }}
</a-typography-title>
<a-row class="list-row" :gutter="24">
<a-col
:xs="12"
:sm="12"
:md="12"
:lg="6"
:xl="6"
:xxl="6"
class="list-col"
>
<div class="card-wrap empty-wrap">
<a-card :bordered="false" hoverable>
<a-result :status="null" :title="$t('cardList.content.action')">
<template #icon>
<icon-plus style="font-size: 20px" />
</template>
</a-result>
</a-card>
</div>
</a-col>
<a-col
v-for="item in renderData"
:key="item.id"
class="list-col"
:xs="12"
:sm="12"
:md="12"
:lg="6"
:xl="6"
:xxl="6"
>
<CardWrap
:loading="loading"
:title="item.title"
:description="item.description"
:default-value="item.enable"
:action-type="item.actionType"
:icon="item.icon"
:open-txt="$t('cardList.content.inspection')"
:close-txt="$t('cardList.content.delete')"
:show-tag="false"
>
<a-descriptions
style="margin-top: 16px"
:data="item.data"
layout="inline-horizontal"
:column="2"
/>
<template #skeleton>
<a-skeleton :animation="true">
<a-skeleton-line
:widths="['50%', '50%', '100%', '40%']"
:rows="4"
/>
<a-skeleton-line :widths="['40%']" :rows="1" />
</a-skeleton>
</template>
</CardWrap>
</a-col>
</a-row>
</div>
</template>
<script lang="ts" setup>
import { queryInspectionList, ServiceRecord } from '@/api/list';
import useRequest from '@/hooks/request';
import CardWrap from './card-wrap.vue';
const defaultValue: ServiceRecord[] = new Array(3).fill({});
const { loading, response: renderData } = useRequest<ServiceRecord[]>(
queryInspectionList,
defaultValue
);
</script>
<style scoped lang="less">
.card-wrap {
height: 100%;
transition: all 0.3s;
border: 1px solid var(--color-neutral-3);
&:hover {
transform: translateY(-4px);
}
:deep(.arco-card-meta-description) {
color: rgb(var(--gray-6));
.arco-descriptions-item-label-inline {
font-weight: normal;
font-size: 12px;
color: rgb(var(--gray-6));
}
.arco-descriptions-item-value-inline {
color: rgb(var(--gray-8));
}
}
}
.empty-wrap {
height: 200px;
border-radius: 4px;
:deep(.arco-card) {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
border-radius: 4px;
.arco-result-title {
color: rgb(var(--gray-6));
}
}
}
</style>

View file

@ -1,51 +0,0 @@
<template>
<div class="list-wrap">
<a-typography-title class="block-title" :heading="6">
{{ $t('cardList.tab.title.preset') }}
</a-typography-title>
<a-row class="list-row" :gutter="24">
<a-col
v-for="item in renderData"
:key="item.id"
:xs="12"
:sm="12"
:md="12"
:lg="6"
:xl="6"
:xxl="6"
class="list-col"
style="min-height: 140px"
>
<CardWrap
:loading="loading"
:title="item.title"
:description="item.description"
:default-value="item.enable"
:action-type="item.actionType"
:tag-text="$t('cardList.preset.tag')"
>
<template #skeleton>
<a-skeleton :animation="true">
<a-skeleton-line :widths="['100%', '40%']" :rows="2" />
<a-skeleton-line :widths="['40%']" :rows="1" />
</a-skeleton>
</template>
</CardWrap>
</a-col>
</a-row>
</div>
</template>
<script lang="ts" setup>
import { queryRulesPresetList, ServiceRecord } from '@/api/list';
import useRequest from '@/hooks/request';
import CardWrap from './card-wrap.vue';
const defaultValue: ServiceRecord[] = new Array(6).fill({});
const { loading, response: renderData } = useRequest<ServiceRecord[]>(
queryRulesPresetList,
defaultValue
);
</script>
<style scoped lang="less"></style>

View file

@ -1,57 +0,0 @@
<template>
<div class="list-wrap">
<a-typography-title class="block-title" :heading="6">
{{ $t('cardList.tab.title.service') }}
</a-typography-title>
<a-row class="list-row" :gutter="24">
<a-col
v-for="item in renderData"
:key="item.id"
:xs="12"
:sm="12"
:md="12"
:lg="6"
:xl="6"
:xxl="6"
class="list-col"
style="min-height: 162px"
>
<CardWrap
:loading="loading"
:title="item.title"
:description="item.description"
:default-value="item.enable"
:action-type="item.actionType"
:expires="item.expires"
:open-txt="$t('cardList.service.open')"
:close-txt="$t('cardList.service.cancel')"
:expires-text="$t('cardList.service.renew')"
:tag-text="$t('cardList.service.tag')"
:expires-tag-text="$t('cardList.service.expiresTag')"
:icon="item.icon"
>
<template #skeleton>
<a-skeleton :animation="true">
<a-skeleton-line :widths="['100%', '40%', '100%']" :rows="3" />
<a-skeleton-line :widths="['40%']" :rows="1" />
</a-skeleton>
</template>
</CardWrap>
</a-col>
</a-row>
</div>
</template>
<script lang="ts" setup>
import { queryTheServiceList, ServiceRecord } from '@/api/list';
import useRequest from '@/hooks/request';
import CardWrap from './card-wrap.vue';
const defaultValue: ServiceRecord[] = new Array(4).fill({});
const { loading, response: renderData } = useRequest<ServiceRecord[]>(
queryTheServiceList,
defaultValue
);
</script>
<style scoped lang="less"></style>

View file

@ -1,186 +0,0 @@
import Mock from 'mockjs';
import setupMock, { successResponseWrap } from '@/utils/setup-mock';
import { ServiceRecord } from '@/api/list';
const qualityInspectionList: ServiceRecord[] = [
{
id: 1,
name: 'quality',
title: '视频类-历史导入',
description: '2021-10-12 00:00:00',
data: [
{
label: '待质检数',
value: '120',
},
{
label: '积压时长',
value: '60s',
},
{
label: '待抽检数',
value: '0',
},
],
},
{
id: 2,
name: 'quality',
title: '图文类-图片版权',
description: '2021-12-11 18:30:00',
data: [
{
label: '待质检数',
value: '120',
},
{
label: '积压时长',
value: '60s',
},
{
label: '待抽检数',
value: '0',
},
],
},
{
id: 3,
name: 'quality',
title: '图文类-高清图片',
description: '2021-10-15 08:10:00',
data: [
{
label: '待质检数',
value: '120',
},
{
label: '积压时长',
value: '60s',
},
{
label: '待抽检数',
value: '0',
},
],
},
];
const theServiceList: ServiceRecord[] = [
{
id: 1,
icon: 'code',
title: '漏斗分析',
description:
'用户行为分析之漏斗分析模型是企业实现精细化运营、进行用户行为分析的重要数据分析模型。',
enable: true,
actionType: 'button',
},
{
id: 2,
icon: 'edit',
title: '用户分布',
description:
'快速诊断用户人群,地域细分情况,了解数据分布的集中度,以及主要的数据分布的区间段是什么。',
enable: true,
actionType: 'button',
expires: true,
},
{
id: 3,
icon: 'user',
title: '资源分发',
description:
'移动端动态化资源分发解决方案。提供稳定大流量服务支持、灵活定制的分发圈选规则,通过离线化预加载。',
enable: false,
actionType: 'button',
},
{
id: 4,
icon: 'user',
title: '用户画像分析',
description:
'用户画像就是将典型用户信息标签化,根据用户特征、业务场景和用户行为等信息,构建一个标签化的用户模型。',
enable: true,
actionType: 'button',
},
];
const rulesPresetList: ServiceRecord[] = [
{
id: 1,
title: '内容屏蔽规则',
description:
'用户在执行特定的内容分发任务时,可使用内容屏蔽规则根据特定标签,过滤内容集合。',
enable: true,
actionType: 'switch',
},
{
id: 2,
title: '内容置顶规则',
description:
'该规则支持用户在执行特定内容分发任务时,对固定的几条内容置顶。',
enable: true,
actionType: 'switch',
},
{
id: 3,
title: '内容加权规则',
description: '选定内容加权规则后可自定义从不同内容集合获取内容的概率。',
enable: false,
actionType: 'switch',
},
{
id: 4,
title: '内容分发规则',
description: '内容分发时对某些内容需要固定在C端展示的位置。',
enable: true,
actionType: 'switch',
},
{
id: 5,
title: '违禁内容识别',
description: '精准识别赌博、刀枪、毒品、造假、贩假等违规物品和违规行为。',
enable: false,
actionType: 'switch',
},
{
id: 6,
title: '多语言文字符号识别',
description:
'精准识别英语、维语、藏语、蒙古语、朝鲜语等多种语言以及emoji表情形态的语义识别。',
enable: false,
actionType: 'switch',
},
];
setupMock({
setup() {
// Quality Inspection
Mock.mock(new RegExp('/api/list/quality-inspection'), () => {
return successResponseWrap(
qualityInspectionList.map((_, index) => ({
...qualityInspectionList[index % qualityInspectionList.length],
id: Mock.Random.guid(),
}))
);
});
// the service
Mock.mock(new RegExp('/api/list/the-service'), () => {
return successResponseWrap(
theServiceList.map((_, index) => ({
...theServiceList[index % theServiceList.length],
id: Mock.Random.guid(),
}))
);
});
// rules preset
Mock.mock(new RegExp('/api/list/rules-preset'), () => {
return successResponseWrap(
rulesPresetList.map((_, index) => ({
...rulesPresetList[index % rulesPresetList.length],
id: Mock.Random.guid(),
}))
);
});
},
});

View file

@ -1,204 +0,0 @@
<template>
<div class="card-wrap">
<a-card v-if="loading" :bordered="false" hoverable>
<slot name="skeleton"></slot>
</a-card>
<a-card v-else :bordered="false" hoverable>
<a-space align="start">
<a-avatar
v-if="icon"
:size="24"
style="margin-right: 8px; background-color: #626aea"
>
<icon-filter />
</a-avatar>
<a-card-meta>
<template #title>
<a-typography-text style="margin-right: 10px">
{{ title }}
</a-typography-text>
<template v-if="showTag">
<a-tag
v-if="open && isExpires === false"
size="small"
color="green"
>
<template #icon>
<icon-check-circle-fill />
</template>
<span>{{ tagText }}</span>
</a-tag>
<a-tag v-else-if="isExpires" size="small" color="red">
<template #icon>
<icon-check-circle-fill />
</template>
<span>{{ expiresTagText }}</span>
</a-tag>
</template>
</template>
<template #description>
{{ description }}
<slot></slot>
</template>
</a-card-meta>
</a-space>
<template #actions>
<a-switch v-if="actionType === 'switch'" v-model="open" />
<a-space v-else-if="actionType === 'button'">
<template v-if="isExpires">
<a-button type="outline" @click="renew">
{{ expiresText }}
</a-button>
</template>
<template v-else>
<a-button v-if="open" @click="handleToggle">
{{ closeTxt }}
</a-button>
<a-button v-else-if="!open" type="outline" @click="handleToggle">
{{ openTxt }}
</a-button>
</template>
</a-space>
<div v-else>
<a-space>
<a-button @click="toggle(false)">
{{ closeTxt }}
</a-button>
<a-button type="primary" @click="toggle(true)">
{{ openTxt }}
</a-button>
</a-space>
</div>
</template>
</a-card>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { useToggle } from '@vueuse/core';
const props = defineProps({
loading: {
type: Boolean,
default: false,
},
title: {
type: String,
default: '',
},
description: {
type: String,
default: '',
},
actionType: {
type: String,
default: '',
},
defaultValue: {
type: Boolean,
default: false,
},
openTxt: {
type: String,
default: '',
},
closeTxt: {
type: String,
default: '',
},
expiresText: {
type: String,
default: '',
},
icon: {
type: String,
default: '',
},
showTag: {
type: Boolean,
default: true,
},
tagText: {
type: String,
default: '',
},
expires: {
type: Boolean,
default: false,
},
expiresTagText: {
type: String,
default: '',
},
});
const [open, toggle] = useToggle(props.defaultValue);
const handleToggle = () => {
toggle();
};
const isExpires = ref(props.expires);
const renew = () => {
isExpires.value = false;
};
</script>
<style scoped lang="less">
.card-wrap {
height: 100%;
transition: all 0.3s;
border: 1px solid var(--color-neutral-3);
border-radius: 4px;
&:hover {
transform: translateY(-4px);
// box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.1);
}
:deep(.arco-card) {
height: 100%;
border-radius: 4px;
.arco-card-body {
height: 100%;
.arco-space {
width: 100%;
height: 100%;
.arco-space-item {
height: 100%;
&:last-child {
flex: 1;
}
.arco-card-meta {
height: 100%;
display: flex;
flex-flow: column;
.arco-card-meta-content {
flex: 1;
.arco-card-meta-description {
margin-top: 8px;
color: rgb(var(--gray-6));
line-height: 20px;
font-size: 12px;
}
}
.arco-card-meta-footer {
margin-top: 0;
}
}
}
}
}
}
:deep(.arco-card-meta-title) {
display: flex;
align-items: center;
// To prevent the shaking
line-height: 28px;
}
:deep(.arco-skeleton-line) {
&:last-child {
display: flex;
justify-content: flex-end;
margin-top: 20px;
}
}
}
</style>

View file

@ -1,115 +0,0 @@
<template>
<div class="list-wrap">
<a-typography-title class="block-title" :heading="6">
{{ $t('cardList.tab.title.content') }}
</a-typography-title>
<a-row class="list-row" :gutter="24">
<a-col
:xs="12"
:sm="12"
:md="12"
:lg="6"
:xl="6"
:xxl="6"
class="list-col"
>
<div class="card-wrap empty-wrap">
<a-card :bordered="false" hoverable>
<a-result :status="null" :title="$t('cardList.content.action')">
<template #icon>
<icon-plus style="font-size: 20px" />
</template>
</a-result>
</a-card>
</div>
</a-col>
<a-col
v-for="item in renderData"
:key="item.id"
class="list-col"
:xs="12"
:sm="12"
:md="12"
:lg="6"
:xl="6"
:xxl="6"
>
<CardWrap
:loading="loading"
:title="item.title"
:description="item.description"
:default-value="item.enable"
:action-type="item.actionType"
:icon="item.icon"
:open-txt="$t('cardList.content.inspection')"
:close-txt="$t('cardList.content.delete')"
:show-tag="false"
>
<a-descriptions
style="margin-top: 16px"
:data="item.data"
layout="inline-horizontal"
:column="2"
/>
<template #skeleton>
<a-skeleton :animation="true">
<a-skeleton-line
:widths="['50%', '50%', '100%', '40%']"
:rows="4"
/>
<a-skeleton-line :widths="['40%']" :rows="1" />
</a-skeleton>
</template>
</CardWrap>
</a-col>
</a-row>
</div>
</template>
<script lang="ts" setup>
import { queryInspectionList, ServiceRecord } from '@/api/list';
import useRequest from '@/hooks/request';
import CardWrap from './card-wrap.vue';
const defaultValue: ServiceRecord[] = new Array(3).fill({});
const { loading, response: renderData } = useRequest<ServiceRecord[]>(
queryInspectionList,
defaultValue
);
</script>
<style scoped lang="less">
.card-wrap {
height: 100%;
transition: all 0.3s;
border: 1px solid var(--color-neutral-3);
&:hover {
transform: translateY(-4px);
}
:deep(.arco-card-meta-description) {
color: rgb(var(--gray-6));
.arco-descriptions-item-label-inline {
font-weight: normal;
font-size: 12px;
color: rgb(var(--gray-6));
}
.arco-descriptions-item-value-inline {
color: rgb(var(--gray-8));
}
}
}
.empty-wrap {
height: 200px;
border-radius: 4px;
:deep(.arco-card) {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
border-radius: 4px;
.arco-result-title {
color: rgb(var(--gray-6));
}
}
}
</style>

View file

@ -1,51 +0,0 @@
<template>
<div class="list-wrap">
<a-typography-title class="block-title" :heading="6">
{{ $t('cardList.tab.title.preset') }}
</a-typography-title>
<a-row class="list-row" :gutter="24">
<a-col
v-for="item in renderData"
:key="item.id"
:xs="12"
:sm="12"
:md="12"
:lg="6"
:xl="6"
:xxl="6"
class="list-col"
style="min-height: 140px"
>
<CardWrap
:loading="loading"
:title="item.title"
:description="item.description"
:default-value="item.enable"
:action-type="item.actionType"
:tag-text="$t('cardList.preset.tag')"
>
<template #skeleton>
<a-skeleton :animation="true">
<a-skeleton-line :widths="['100%', '40%']" :rows="2" />
<a-skeleton-line :widths="['40%']" :rows="1" />
</a-skeleton>
</template>
</CardWrap>
</a-col>
</a-row>
</div>
</template>
<script lang="ts" setup>
import { queryRulesPresetList, ServiceRecord } from '@/api/list';
import useRequest from '@/hooks/request';
import CardWrap from './card-wrap.vue';
const defaultValue: ServiceRecord[] = new Array(6).fill({});
const { loading, response: renderData } = useRequest<ServiceRecord[]>(
queryRulesPresetList,
defaultValue
);
</script>
<style scoped lang="less"></style>

View file

@ -1,57 +0,0 @@
<template>
<div class="list-wrap">
<a-typography-title class="block-title" :heading="6">
{{ $t('cardList.tab.title.service') }}
</a-typography-title>
<a-row class="list-row" :gutter="24">
<a-col
v-for="item in renderData"
:key="item.id"
:xs="12"
:sm="12"
:md="12"
:lg="6"
:xl="6"
:xxl="6"
class="list-col"
style="min-height: 162px"
>
<CardWrap
:loading="loading"
:title="item.title"
:description="item.description"
:default-value="item.enable"
:action-type="item.actionType"
:expires="item.expires"
:open-txt="$t('cardList.service.open')"
:close-txt="$t('cardList.service.cancel')"
:expires-text="$t('cardList.service.renew')"
:tag-text="$t('cardList.service.tag')"
:expires-tag-text="$t('cardList.service.expiresTag')"
:icon="item.icon"
>
<template #skeleton>
<a-skeleton :animation="true">
<a-skeleton-line :widths="['100%', '40%', '100%']" :rows="3" />
<a-skeleton-line :widths="['40%']" :rows="1" />
</a-skeleton>
</template>
</CardWrap>
</a-col>
</a-row>
</div>
</template>
<script lang="ts" setup>
import { queryTheServiceList, ServiceRecord } from '@/api/list';
import useRequest from '@/hooks/request';
import CardWrap from './card-wrap.vue';
const defaultValue: ServiceRecord[] = new Array(4).fill({});
const { loading, response: renderData } = useRequest<ServiceRecord[]>(
queryTheServiceList,
defaultValue
);
</script>
<style scoped lang="less"></style>

View file

@ -1,186 +0,0 @@
import Mock from 'mockjs';
import setupMock, { successResponseWrap } from '@/utils/setup-mock';
import { ServiceRecord } from '@/api/list';
const qualityInspectionList: ServiceRecord[] = [
{
id: 1,
name: 'quality',
title: '视频类-历史导入',
description: '2021-10-12 00:00:00',
data: [
{
label: '待质检数',
value: '120',
},
{
label: '积压时长',
value: '60s',
},
{
label: '待抽检数',
value: '0',
},
],
},
{
id: 2,
name: 'quality',
title: '图文类-图片版权',
description: '2021-12-11 18:30:00',
data: [
{
label: '待质检数',
value: '120',
},
{
label: '积压时长',
value: '60s',
},
{
label: '待抽检数',
value: '0',
},
],
},
{
id: 3,
name: 'quality',
title: '图文类-高清图片',
description: '2021-10-15 08:10:00',
data: [
{
label: '待质检数',
value: '120',
},
{
label: '积压时长',
value: '60s',
},
{
label: '待抽检数',
value: '0',
},
],
},
];
const theServiceList: ServiceRecord[] = [
{
id: 1,
icon: 'code',
title: '漏斗分析',
description:
'用户行为分析之漏斗分析模型是企业实现精细化运营、进行用户行为分析的重要数据分析模型。',
enable: true,
actionType: 'button',
},
{
id: 2,
icon: 'edit',
title: '用户分布',
description:
'快速诊断用户人群,地域细分情况,了解数据分布的集中度,以及主要的数据分布的区间段是什么。',
enable: true,
actionType: 'button',
expires: true,
},
{
id: 3,
icon: 'user',
title: '资源分发',
description:
'移动端动态化资源分发解决方案。提供稳定大流量服务支持、灵活定制的分发圈选规则,通过离线化预加载。',
enable: false,
actionType: 'button',
},
{
id: 4,
icon: 'user',
title: '用户画像分析',
description:
'用户画像就是将典型用户信息标签化,根据用户特征、业务场景和用户行为等信息,构建一个标签化的用户模型。',
enable: true,
actionType: 'button',
},
];
const rulesPresetList: ServiceRecord[] = [
{
id: 1,
title: '内容屏蔽规则',
description:
'用户在执行特定的内容分发任务时,可使用内容屏蔽规则根据特定标签,过滤内容集合。',
enable: true,
actionType: 'switch',
},
{
id: 2,
title: '内容置顶规则',
description:
'该规则支持用户在执行特定内容分发任务时,对固定的几条内容置顶。',
enable: true,
actionType: 'switch',
},
{
id: 3,
title: '内容加权规则',
description: '选定内容加权规则后可自定义从不同内容集合获取内容的概率。',
enable: false,
actionType: 'switch',
},
{
id: 4,
title: '内容分发规则',
description: '内容分发时对某些内容需要固定在C端展示的位置。',
enable: true,
actionType: 'switch',
},
{
id: 5,
title: '违禁内容识别',
description: '精准识别赌博、刀枪、毒品、造假、贩假等违规物品和违规行为。',
enable: false,
actionType: 'switch',
},
{
id: 6,
title: '多语言文字符号识别',
description:
'精准识别英语、维语、藏语、蒙古语、朝鲜语等多种语言以及emoji表情形态的语义识别。',
enable: false,
actionType: 'switch',
},
];
setupMock({
setup() {
// Quality Inspection
Mock.mock(new RegExp('/api/list/quality-inspection'), () => {
return successResponseWrap(
qualityInspectionList.map((_, index) => ({
...qualityInspectionList[index % qualityInspectionList.length],
id: Mock.Random.guid(),
}))
);
});
// the service
Mock.mock(new RegExp('/api/list/the-service'), () => {
return successResponseWrap(
theServiceList.map((_, index) => ({
...theServiceList[index % theServiceList.length],
id: Mock.Random.guid(),
}))
);
});
// rules preset
Mock.mock(new RegExp('/api/list/rules-preset'), () => {
return successResponseWrap(
rulesPresetList.map((_, index) => ({
...rulesPresetList[index % rulesPresetList.length],
id: Mock.Random.guid(),
}))
);
});
},
});

View file

@ -1,204 +0,0 @@
<template>
<div class="card-wrap">
<a-card v-if="loading" :bordered="false" hoverable>
<slot name="skeleton"></slot>
</a-card>
<a-card v-else :bordered="false" hoverable>
<a-space align="start">
<a-avatar
v-if="icon"
:size="24"
style="margin-right: 8px; background-color: #626aea"
>
<icon-filter />
</a-avatar>
<a-card-meta>
<template #title>
<a-typography-text style="margin-right: 10px">
{{ title }}
</a-typography-text>
<template v-if="showTag">
<a-tag
v-if="open && isExpires === false"
size="small"
color="green"
>
<template #icon>
<icon-check-circle-fill />
</template>
<span>{{ tagText }}</span>
</a-tag>
<a-tag v-else-if="isExpires" size="small" color="red">
<template #icon>
<icon-check-circle-fill />
</template>
<span>{{ expiresTagText }}</span>
</a-tag>
</template>
</template>
<template #description>
{{ description }}
<slot></slot>
</template>
</a-card-meta>
</a-space>
<template #actions>
<a-switch v-if="actionType === 'switch'" v-model="open" />
<a-space v-else-if="actionType === 'button'">
<template v-if="isExpires">
<a-button type="outline" @click="renew">
{{ expiresText }}
</a-button>
</template>
<template v-else>
<a-button v-if="open" @click="handleToggle">
{{ closeTxt }}
</a-button>
<a-button v-else-if="!open" type="outline" @click="handleToggle">
{{ openTxt }}
</a-button>
</template>
</a-space>
<div v-else>
<a-space>
<a-button @click="toggle(false)">
{{ closeTxt }}
</a-button>
<a-button type="primary" @click="toggle(true)">
{{ openTxt }}
</a-button>
</a-space>
</div>
</template>
</a-card>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { useToggle } from '@vueuse/core';
const props = defineProps({
loading: {
type: Boolean,
default: false,
},
title: {
type: String,
default: '',
},
description: {
type: String,
default: '',
},
actionType: {
type: String,
default: '',
},
defaultValue: {
type: Boolean,
default: false,
},
openTxt: {
type: String,
default: '',
},
closeTxt: {
type: String,
default: '',
},
expiresText: {
type: String,
default: '',
},
icon: {
type: String,
default: '',
},
showTag: {
type: Boolean,
default: true,
},
tagText: {
type: String,
default: '',
},
expires: {
type: Boolean,
default: false,
},
expiresTagText: {
type: String,
default: '',
},
});
const [open, toggle] = useToggle(props.defaultValue);
const handleToggle = () => {
toggle();
};
const isExpires = ref(props.expires);
const renew = () => {
isExpires.value = false;
};
</script>
<style scoped lang="less">
.card-wrap {
height: 100%;
transition: all 0.3s;
border: 1px solid var(--color-neutral-3);
border-radius: 4px;
&:hover {
transform: translateY(-4px);
// box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.1);
}
:deep(.arco-card) {
height: 100%;
border-radius: 4px;
.arco-card-body {
height: 100%;
.arco-space {
width: 100%;
height: 100%;
.arco-space-item {
height: 100%;
&:last-child {
flex: 1;
}
.arco-card-meta {
height: 100%;
display: flex;
flex-flow: column;
.arco-card-meta-content {
flex: 1;
.arco-card-meta-description {
margin-top: 8px;
color: rgb(var(--gray-6));
line-height: 20px;
font-size: 12px;
}
}
.arco-card-meta-footer {
margin-top: 0;
}
}
}
}
}
}
:deep(.arco-card-meta-title) {
display: flex;
align-items: center;
// To prevent the shaking
line-height: 28px;
}
:deep(.arco-skeleton-line) {
&:last-child {
display: flex;
justify-content: flex-end;
margin-top: 20px;
}
}
}
</style>

View file

@ -1,115 +0,0 @@
<template>
<div class="list-wrap">
<a-typography-title class="block-title" :heading="6">
{{ $t('cardList.tab.title.content') }}
</a-typography-title>
<a-row class="list-row" :gutter="24">
<a-col
:xs="12"
:sm="12"
:md="12"
:lg="6"
:xl="6"
:xxl="6"
class="list-col"
>
<div class="card-wrap empty-wrap">
<a-card :bordered="false" hoverable>
<a-result :status="null" :title="$t('cardList.content.action')">
<template #icon>
<icon-plus style="font-size: 20px" />
</template>
</a-result>
</a-card>
</div>
</a-col>
<a-col
v-for="item in renderData"
:key="item.id"
class="list-col"
:xs="12"
:sm="12"
:md="12"
:lg="6"
:xl="6"
:xxl="6"
>
<CardWrap
:loading="loading"
:title="item.title"
:description="item.description"
:default-value="item.enable"
:action-type="item.actionType"
:icon="item.icon"
:open-txt="$t('cardList.content.inspection')"
:close-txt="$t('cardList.content.delete')"
:show-tag="false"
>
<a-descriptions
style="margin-top: 16px"
:data="item.data"
layout="inline-horizontal"
:column="2"
/>
<template #skeleton>
<a-skeleton :animation="true">
<a-skeleton-line
:widths="['50%', '50%', '100%', '40%']"
:rows="4"
/>
<a-skeleton-line :widths="['40%']" :rows="1" />
</a-skeleton>
</template>
</CardWrap>
</a-col>
</a-row>
</div>
</template>
<script lang="ts" setup>
import { queryInspectionList, ServiceRecord } from '@/api/list';
import useRequest from '@/hooks/request';
import CardWrap from './card-wrap.vue';
const defaultValue: ServiceRecord[] = new Array(3).fill({});
const { loading, response: renderData } = useRequest<ServiceRecord[]>(
queryInspectionList,
defaultValue
);
</script>
<style scoped lang="less">
.card-wrap {
height: 100%;
transition: all 0.3s;
border: 1px solid var(--color-neutral-3);
&:hover {
transform: translateY(-4px);
}
:deep(.arco-card-meta-description) {
color: rgb(var(--gray-6));
.arco-descriptions-item-label-inline {
font-weight: normal;
font-size: 12px;
color: rgb(var(--gray-6));
}
.arco-descriptions-item-value-inline {
color: rgb(var(--gray-8));
}
}
}
.empty-wrap {
height: 200px;
border-radius: 4px;
:deep(.arco-card) {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
border-radius: 4px;
.arco-result-title {
color: rgb(var(--gray-6));
}
}
}
</style>

View file

@ -1,51 +0,0 @@
<template>
<div class="list-wrap">
<a-typography-title class="block-title" :heading="6">
{{ $t('cardList.tab.title.preset') }}
</a-typography-title>
<a-row class="list-row" :gutter="24">
<a-col
v-for="item in renderData"
:key="item.id"
:xs="12"
:sm="12"
:md="12"
:lg="6"
:xl="6"
:xxl="6"
class="list-col"
style="min-height: 140px"
>
<CardWrap
:loading="loading"
:title="item.title"
:description="item.description"
:default-value="item.enable"
:action-type="item.actionType"
:tag-text="$t('cardList.preset.tag')"
>
<template #skeleton>
<a-skeleton :animation="true">
<a-skeleton-line :widths="['100%', '40%']" :rows="2" />
<a-skeleton-line :widths="['40%']" :rows="1" />
</a-skeleton>
</template>
</CardWrap>
</a-col>
</a-row>
</div>
</template>
<script lang="ts" setup>
import { queryRulesPresetList, ServiceRecord } from '@/api/list';
import useRequest from '@/hooks/request';
import CardWrap from './card-wrap.vue';
const defaultValue: ServiceRecord[] = new Array(6).fill({});
const { loading, response: renderData } = useRequest<ServiceRecord[]>(
queryRulesPresetList,
defaultValue
);
</script>
<style scoped lang="less"></style>

View file

@ -1,57 +0,0 @@
<template>
<div class="list-wrap">
<a-typography-title class="block-title" :heading="6">
{{ $t('cardList.tab.title.service') }}
</a-typography-title>
<a-row class="list-row" :gutter="24">
<a-col
v-for="item in renderData"
:key="item.id"
:xs="12"
:sm="12"
:md="12"
:lg="6"
:xl="6"
:xxl="6"
class="list-col"
style="min-height: 162px"
>
<CardWrap
:loading="loading"
:title="item.title"
:description="item.description"
:default-value="item.enable"
:action-type="item.actionType"
:expires="item.expires"
:open-txt="$t('cardList.service.open')"
:close-txt="$t('cardList.service.cancel')"
:expires-text="$t('cardList.service.renew')"
:tag-text="$t('cardList.service.tag')"
:expires-tag-text="$t('cardList.service.expiresTag')"
:icon="item.icon"
>
<template #skeleton>
<a-skeleton :animation="true">
<a-skeleton-line :widths="['100%', '40%', '100%']" :rows="3" />
<a-skeleton-line :widths="['40%']" :rows="1" />
</a-skeleton>
</template>
</CardWrap>
</a-col>
</a-row>
</div>
</template>
<script lang="ts" setup>
import { queryTheServiceList, ServiceRecord } from '@/api/list';
import useRequest from '@/hooks/request';
import CardWrap from './card-wrap.vue';
const defaultValue: ServiceRecord[] = new Array(4).fill({});
const { loading, response: renderData } = useRequest<ServiceRecord[]>(
queryTheServiceList,
defaultValue
);
</script>
<style scoped lang="less"></style>

View file

@ -1,186 +0,0 @@
import Mock from 'mockjs';
import setupMock, { successResponseWrap } from '@/utils/setup-mock';
import { ServiceRecord } from '@/api/list';
const qualityInspectionList: ServiceRecord[] = [
{
id: 1,
name: 'quality',
title: '视频类-历史导入',
description: '2021-10-12 00:00:00',
data: [
{
label: '待质检数',
value: '120',
},
{
label: '积压时长',
value: '60s',
},
{
label: '待抽检数',
value: '0',
},
],
},
{
id: 2,
name: 'quality',
title: '图文类-图片版权',
description: '2021-12-11 18:30:00',
data: [
{
label: '待质检数',
value: '120',
},
{
label: '积压时长',
value: '60s',
},
{
label: '待抽检数',
value: '0',
},
],
},
{
id: 3,
name: 'quality',
title: '图文类-高清图片',
description: '2021-10-15 08:10:00',
data: [
{
label: '待质检数',
value: '120',
},
{
label: '积压时长',
value: '60s',
},
{
label: '待抽检数',
value: '0',
},
],
},
];
const theServiceList: ServiceRecord[] = [
{
id: 1,
icon: 'code',
title: '漏斗分析',
description:
'用户行为分析之漏斗分析模型是企业实现精细化运营、进行用户行为分析的重要数据分析模型。',
enable: true,
actionType: 'button',
},
{
id: 2,
icon: 'edit',
title: '用户分布',
description:
'快速诊断用户人群,地域细分情况,了解数据分布的集中度,以及主要的数据分布的区间段是什么。',
enable: true,
actionType: 'button',
expires: true,
},
{
id: 3,
icon: 'user',
title: '资源分发',
description:
'移动端动态化资源分发解决方案。提供稳定大流量服务支持、灵活定制的分发圈选规则,通过离线化预加载。',
enable: false,
actionType: 'button',
},
{
id: 4,
icon: 'user',
title: '用户画像分析',
description:
'用户画像就是将典型用户信息标签化,根据用户特征、业务场景和用户行为等信息,构建一个标签化的用户模型。',
enable: true,
actionType: 'button',
},
];
const rulesPresetList: ServiceRecord[] = [
{
id: 1,
title: '内容屏蔽规则',
description:
'用户在执行特定的内容分发任务时,可使用内容屏蔽规则根据特定标签,过滤内容集合。',
enable: true,
actionType: 'switch',
},
{
id: 2,
title: '内容置顶规则',
description:
'该规则支持用户在执行特定内容分发任务时,对固定的几条内容置顶。',
enable: true,
actionType: 'switch',
},
{
id: 3,
title: '内容加权规则',
description: '选定内容加权规则后可自定义从不同内容集合获取内容的概率。',
enable: false,
actionType: 'switch',
},
{
id: 4,
title: '内容分发规则',
description: '内容分发时对某些内容需要固定在C端展示的位置。',
enable: true,
actionType: 'switch',
},
{
id: 5,
title: '违禁内容识别',
description: '精准识别赌博、刀枪、毒品、造假、贩假等违规物品和违规行为。',
enable: false,
actionType: 'switch',
},
{
id: 6,
title: '多语言文字符号识别',
description:
'精准识别英语、维语、藏语、蒙古语、朝鲜语等多种语言以及emoji表情形态的语义识别。',
enable: false,
actionType: 'switch',
},
];
setupMock({
setup() {
// Quality Inspection
Mock.mock(new RegExp('/api/list/quality-inspection'), () => {
return successResponseWrap(
qualityInspectionList.map((_, index) => ({
...qualityInspectionList[index % qualityInspectionList.length],
id: Mock.Random.guid(),
}))
);
});
// the service
Mock.mock(new RegExp('/api/list/the-service'), () => {
return successResponseWrap(
theServiceList.map((_, index) => ({
...theServiceList[index % theServiceList.length],
id: Mock.Random.guid(),
}))
);
});
// rules preset
Mock.mock(new RegExp('/api/list/rules-preset'), () => {
return successResponseWrap(
rulesPresetList.map((_, index) => ({
...rulesPresetList[index % rulesPresetList.length],
id: Mock.Random.guid(),
}))
);
});
},
});

View file

@ -1,204 +0,0 @@
<template>
<div class="card-wrap">
<a-card v-if="loading" :bordered="false" hoverable>
<slot name="skeleton"></slot>
</a-card>
<a-card v-else :bordered="false" hoverable>
<a-space align="start">
<a-avatar
v-if="icon"
:size="24"
style="margin-right: 8px; background-color: #626aea"
>
<icon-filter />
</a-avatar>
<a-card-meta>
<template #title>
<a-typography-text style="margin-right: 10px">
{{ title }}
</a-typography-text>
<template v-if="showTag">
<a-tag
v-if="open && isExpires === false"
size="small"
color="green"
>
<template #icon>
<icon-check-circle-fill />
</template>
<span>{{ tagText }}</span>
</a-tag>
<a-tag v-else-if="isExpires" size="small" color="red">
<template #icon>
<icon-check-circle-fill />
</template>
<span>{{ expiresTagText }}</span>
</a-tag>
</template>
</template>
<template #description>
{{ description }}
<slot></slot>
</template>
</a-card-meta>
</a-space>
<template #actions>
<a-switch v-if="actionType === 'switch'" v-model="open" />
<a-space v-else-if="actionType === 'button'">
<template v-if="isExpires">
<a-button type="outline" @click="renew">
{{ expiresText }}
</a-button>
</template>
<template v-else>
<a-button v-if="open" @click="handleToggle">
{{ closeTxt }}
</a-button>
<a-button v-else-if="!open" type="outline" @click="handleToggle">
{{ openTxt }}
</a-button>
</template>
</a-space>
<div v-else>
<a-space>
<a-button @click="toggle(false)">
{{ closeTxt }}
</a-button>
<a-button type="primary" @click="toggle(true)">
{{ openTxt }}
</a-button>
</a-space>
</div>
</template>
</a-card>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { useToggle } from '@vueuse/core';
const props = defineProps({
loading: {
type: Boolean,
default: false,
},
title: {
type: String,
default: '',
},
description: {
type: String,
default: '',
},
actionType: {
type: String,
default: '',
},
defaultValue: {
type: Boolean,
default: false,
},
openTxt: {
type: String,
default: '',
},
closeTxt: {
type: String,
default: '',
},
expiresText: {
type: String,
default: '',
},
icon: {
type: String,
default: '',
},
showTag: {
type: Boolean,
default: true,
},
tagText: {
type: String,
default: '',
},
expires: {
type: Boolean,
default: false,
},
expiresTagText: {
type: String,
default: '',
},
});
const [open, toggle] = useToggle(props.defaultValue);
const handleToggle = () => {
toggle();
};
const isExpires = ref(props.expires);
const renew = () => {
isExpires.value = false;
};
</script>
<style scoped lang="less">
.card-wrap {
height: 100%;
transition: all 0.3s;
border: 1px solid var(--color-neutral-3);
border-radius: 4px;
&:hover {
transform: translateY(-4px);
// box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.1);
}
:deep(.arco-card) {
height: 100%;
border-radius: 4px;
.arco-card-body {
height: 100%;
.arco-space {
width: 100%;
height: 100%;
.arco-space-item {
height: 100%;
&:last-child {
flex: 1;
}
.arco-card-meta {
height: 100%;
display: flex;
flex-flow: column;
.arco-card-meta-content {
flex: 1;
.arco-card-meta-description {
margin-top: 8px;
color: rgb(var(--gray-6));
line-height: 20px;
font-size: 12px;
}
}
.arco-card-meta-footer {
margin-top: 0;
}
}
}
}
}
}
:deep(.arco-card-meta-title) {
display: flex;
align-items: center;
// To prevent the shaking
line-height: 28px;
}
:deep(.arco-skeleton-line) {
&:last-child {
display: flex;
justify-content: flex-end;
margin-top: 20px;
}
}
}
</style>

View file

@ -1,115 +0,0 @@
<template>
<div class="list-wrap">
<a-typography-title class="block-title" :heading="6">
{{ $t('cardList.tab.title.content') }}
</a-typography-title>
<a-row class="list-row" :gutter="24">
<a-col
:xs="12"
:sm="12"
:md="12"
:lg="6"
:xl="6"
:xxl="6"
class="list-col"
>
<div class="card-wrap empty-wrap">
<a-card :bordered="false" hoverable>
<a-result :status="null" :title="$t('cardList.content.action')">
<template #icon>
<icon-plus style="font-size: 20px" />
</template>
</a-result>
</a-card>
</div>
</a-col>
<a-col
v-for="item in renderData"
:key="item.id"
class="list-col"
:xs="12"
:sm="12"
:md="12"
:lg="6"
:xl="6"
:xxl="6"
>
<CardWrap
:loading="loading"
:title="item.title"
:description="item.description"
:default-value="item.enable"
:action-type="item.actionType"
:icon="item.icon"
:open-txt="$t('cardList.content.inspection')"
:close-txt="$t('cardList.content.delete')"
:show-tag="false"
>
<a-descriptions
style="margin-top: 16px"
:data="item.data"
layout="inline-horizontal"
:column="2"
/>
<template #skeleton>
<a-skeleton :animation="true">
<a-skeleton-line
:widths="['50%', '50%', '100%', '40%']"
:rows="4"
/>
<a-skeleton-line :widths="['40%']" :rows="1" />
</a-skeleton>
</template>
</CardWrap>
</a-col>
</a-row>
</div>
</template>
<script lang="ts" setup>
import { queryInspectionList, ServiceRecord } from '@/api/list';
import useRequest from '@/hooks/request';
import CardWrap from './card-wrap.vue';
const defaultValue: ServiceRecord[] = new Array(3).fill({});
const { loading, response: renderData } = useRequest<ServiceRecord[]>(
queryInspectionList,
defaultValue
);
</script>
<style scoped lang="less">
.card-wrap {
height: 100%;
transition: all 0.3s;
border: 1px solid var(--color-neutral-3);
&:hover {
transform: translateY(-4px);
}
:deep(.arco-card-meta-description) {
color: rgb(var(--gray-6));
.arco-descriptions-item-label-inline {
font-weight: normal;
font-size: 12px;
color: rgb(var(--gray-6));
}
.arco-descriptions-item-value-inline {
color: rgb(var(--gray-8));
}
}
}
.empty-wrap {
height: 200px;
border-radius: 4px;
:deep(.arco-card) {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
border-radius: 4px;
.arco-result-title {
color: rgb(var(--gray-6));
}
}
}
</style>

View file

@ -1,51 +0,0 @@
<template>
<div class="list-wrap">
<a-typography-title class="block-title" :heading="6">
{{ $t('cardList.tab.title.preset') }}
</a-typography-title>
<a-row class="list-row" :gutter="24">
<a-col
v-for="item in renderData"
:key="item.id"
:xs="12"
:sm="12"
:md="12"
:lg="6"
:xl="6"
:xxl="6"
class="list-col"
style="min-height: 140px"
>
<CardWrap
:loading="loading"
:title="item.title"
:description="item.description"
:default-value="item.enable"
:action-type="item.actionType"
:tag-text="$t('cardList.preset.tag')"
>
<template #skeleton>
<a-skeleton :animation="true">
<a-skeleton-line :widths="['100%', '40%']" :rows="2" />
<a-skeleton-line :widths="['40%']" :rows="1" />
</a-skeleton>
</template>
</CardWrap>
</a-col>
</a-row>
</div>
</template>
<script lang="ts" setup>
import { queryRulesPresetList, ServiceRecord } from '@/api/list';
import useRequest from '@/hooks/request';
import CardWrap from './card-wrap.vue';
const defaultValue: ServiceRecord[] = new Array(6).fill({});
const { loading, response: renderData } = useRequest<ServiceRecord[]>(
queryRulesPresetList,
defaultValue
);
</script>
<style scoped lang="less"></style>

View file

@ -1,57 +0,0 @@
<template>
<div class="list-wrap">
<a-typography-title class="block-title" :heading="6">
{{ $t('cardList.tab.title.service') }}
</a-typography-title>
<a-row class="list-row" :gutter="24">
<a-col
v-for="item in renderData"
:key="item.id"
:xs="12"
:sm="12"
:md="12"
:lg="6"
:xl="6"
:xxl="6"
class="list-col"
style="min-height: 162px"
>
<CardWrap
:loading="loading"
:title="item.title"
:description="item.description"
:default-value="item.enable"
:action-type="item.actionType"
:expires="item.expires"
:open-txt="$t('cardList.service.open')"
:close-txt="$t('cardList.service.cancel')"
:expires-text="$t('cardList.service.renew')"
:tag-text="$t('cardList.service.tag')"
:expires-tag-text="$t('cardList.service.expiresTag')"
:icon="item.icon"
>
<template #skeleton>
<a-skeleton :animation="true">
<a-skeleton-line :widths="['100%', '40%', '100%']" :rows="3" />
<a-skeleton-line :widths="['40%']" :rows="1" />
</a-skeleton>
</template>
</CardWrap>
</a-col>
</a-row>
</div>
</template>
<script lang="ts" setup>
import { queryTheServiceList, ServiceRecord } from '@/api/list';
import useRequest from '@/hooks/request';
import CardWrap from './card-wrap.vue';
const defaultValue: ServiceRecord[] = new Array(4).fill({});
const { loading, response: renderData } = useRequest<ServiceRecord[]>(
queryTheServiceList,
defaultValue
);
</script>
<style scoped lang="less"></style>

View file

@ -1,186 +0,0 @@
import Mock from 'mockjs';
import setupMock, { successResponseWrap } from '@/utils/setup-mock';
import { ServiceRecord } from '@/api/list';
const qualityInspectionList: ServiceRecord[] = [
{
id: 1,
name: 'quality',
title: '视频类-历史导入',
description: '2021-10-12 00:00:00',
data: [
{
label: '待质检数',
value: '120',
},
{
label: '积压时长',
value: '60s',
},
{
label: '待抽检数',
value: '0',
},
],
},
{
id: 2,
name: 'quality',
title: '图文类-图片版权',
description: '2021-12-11 18:30:00',
data: [
{
label: '待质检数',
value: '120',
},
{
label: '积压时长',
value: '60s',
},
{
label: '待抽检数',
value: '0',
},
],
},
{
id: 3,
name: 'quality',
title: '图文类-高清图片',
description: '2021-10-15 08:10:00',
data: [
{
label: '待质检数',
value: '120',
},
{
label: '积压时长',
value: '60s',
},
{
label: '待抽检数',
value: '0',
},
],
},
];
const theServiceList: ServiceRecord[] = [
{
id: 1,
icon: 'code',
title: '漏斗分析',
description:
'用户行为分析之漏斗分析模型是企业实现精细化运营、进行用户行为分析的重要数据分析模型。',
enable: true,
actionType: 'button',
},
{
id: 2,
icon: 'edit',
title: '用户分布',
description:
'快速诊断用户人群,地域细分情况,了解数据分布的集中度,以及主要的数据分布的区间段是什么。',
enable: true,
actionType: 'button',
expires: true,
},
{
id: 3,
icon: 'user',
title: '资源分发',
description:
'移动端动态化资源分发解决方案。提供稳定大流量服务支持、灵活定制的分发圈选规则,通过离线化预加载。',
enable: false,
actionType: 'button',
},
{
id: 4,
icon: 'user',
title: '用户画像分析',
description:
'用户画像就是将典型用户信息标签化,根据用户特征、业务场景和用户行为等信息,构建一个标签化的用户模型。',
enable: true,
actionType: 'button',
},
];
const rulesPresetList: ServiceRecord[] = [
{
id: 1,
title: '内容屏蔽规则',
description:
'用户在执行特定的内容分发任务时,可使用内容屏蔽规则根据特定标签,过滤内容集合。',
enable: true,
actionType: 'switch',
},
{
id: 2,
title: '内容置顶规则',
description:
'该规则支持用户在执行特定内容分发任务时,对固定的几条内容置顶。',
enable: true,
actionType: 'switch',
},
{
id: 3,
title: '内容加权规则',
description: '选定内容加权规则后可自定义从不同内容集合获取内容的概率。',
enable: false,
actionType: 'switch',
},
{
id: 4,
title: '内容分发规则',
description: '内容分发时对某些内容需要固定在C端展示的位置。',
enable: true,
actionType: 'switch',
},
{
id: 5,
title: '违禁内容识别',
description: '精准识别赌博、刀枪、毒品、造假、贩假等违规物品和违规行为。',
enable: false,
actionType: 'switch',
},
{
id: 6,
title: '多语言文字符号识别',
description:
'精准识别英语、维语、藏语、蒙古语、朝鲜语等多种语言以及emoji表情形态的语义识别。',
enable: false,
actionType: 'switch',
},
];
setupMock({
setup() {
// Quality Inspection
Mock.mock(new RegExp('/api/list/quality-inspection'), () => {
return successResponseWrap(
qualityInspectionList.map((_, index) => ({
...qualityInspectionList[index % qualityInspectionList.length],
id: Mock.Random.guid(),
}))
);
});
// the service
Mock.mock(new RegExp('/api/list/the-service'), () => {
return successResponseWrap(
theServiceList.map((_, index) => ({
...theServiceList[index % theServiceList.length],
id: Mock.Random.guid(),
}))
);
});
// rules preset
Mock.mock(new RegExp('/api/list/rules-preset'), () => {
return successResponseWrap(
rulesPresetList.map((_, index) => ({
...rulesPresetList[index % rulesPresetList.length],
id: Mock.Random.guid(),
}))
);
});
},
});

View file

@ -1,37 +0,0 @@
import Mock from 'mockjs';
import qs from 'query-string';
import setupMock, { successResponseWrap } from '@/utils/setup-mock';
import { GetParams } from '@/types/global';
const { Random } = Mock;
const data = Mock.mock({
'list|55': [
{
'id|8': /[A-Z][a-z][-][0-9]/,
'number|2-3': /[0-9]/,
'name|4-8': /[A-Z]/,
'mode|1': ['FM', 'AM', 'LSB'],
'freq|1': ['438.500', '438.500', '438.500'],
'contentType|1': ['img', 'horizontalVideo', 'verticalVideo'],
'count|2-3': /[0-9]/,
'status|1': ['online', 'offline'],
'filterType|1': ['artificial', 'rules'],
'createdTime': Random.datetime(),
},
],
});
setupMock({
setup() {
Mock.mock(new RegExp('/api/list/policy'), (params: GetParams) => {
const { current = 1, pageSize = 10 } = qs.parseUrl(params.url).query;
const p = current as number;
const ps = pageSize as number;
return successResponseWrap({
list: data.list.slice((p - 1) * ps, p * ps),
total: 55,
});
});
},
});

View file

@ -1,204 +0,0 @@
<template>
<div class="card-wrap">
<a-card v-if="loading" :bordered="false" hoverable>
<slot name="skeleton"></slot>
</a-card>
<a-card v-else :bordered="false" hoverable>
<a-space align="start">
<a-avatar
v-if="icon"
:size="24"
style="margin-right: 8px; background-color: #626aea"
>
<icon-filter />
</a-avatar>
<a-card-meta>
<template #title>
<a-typography-text style="margin-right: 10px">
{{ title }}
</a-typography-text>
<template v-if="showTag">
<a-tag
v-if="open && isExpires === false"
size="small"
color="green"
>
<template #icon>
<icon-check-circle-fill />
</template>
<span>{{ tagText }}</span>
</a-tag>
<a-tag v-else-if="isExpires" size="small" color="red">
<template #icon>
<icon-check-circle-fill />
</template>
<span>{{ expiresTagText }}</span>
</a-tag>
</template>
</template>
<template #description>
{{ description }}
<slot></slot>
</template>
</a-card-meta>
</a-space>
<template #actions>
<a-switch v-if="actionType === 'switch'" v-model="open" />
<a-space v-else-if="actionType === 'button'">
<template v-if="isExpires">
<a-button type="outline" @click="renew">
{{ expiresText }}
</a-button>
</template>
<template v-else>
<a-button v-if="open" @click="handleToggle">
{{ closeTxt }}
</a-button>
<a-button v-else-if="!open" type="outline" @click="handleToggle">
{{ openTxt }}
</a-button>
</template>
</a-space>
<div v-else>
<a-space>
<a-button @click="toggle(false)">
{{ closeTxt }}
</a-button>
<a-button type="primary" @click="toggle(true)">
{{ openTxt }}
</a-button>
</a-space>
</div>
</template>
</a-card>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { useToggle } from '@vueuse/core';
const props = defineProps({
loading: {
type: Boolean,
default: false,
},
title: {
type: String,
default: '',
},
description: {
type: String,
default: '',
},
actionType: {
type: String,
default: '',
},
defaultValue: {
type: Boolean,
default: false,
},
openTxt: {
type: String,
default: '',
},
closeTxt: {
type: String,
default: '',
},
expiresText: {
type: String,
default: '',
},
icon: {
type: String,
default: '',
},
showTag: {
type: Boolean,
default: true,
},
tagText: {
type: String,
default: '',
},
expires: {
type: Boolean,
default: false,
},
expiresTagText: {
type: String,
default: '',
},
});
const [open, toggle] = useToggle(props.defaultValue);
const handleToggle = () => {
toggle();
};
const isExpires = ref(props.expires);
const renew = () => {
isExpires.value = false;
};
</script>
<style scoped lang="less">
.card-wrap {
height: 100%;
transition: all 0.3s;
border: 1px solid var(--color-neutral-3);
border-radius: 4px;
&:hover {
transform: translateY(-4px);
// box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.1);
}
:deep(.arco-card) {
height: 100%;
border-radius: 4px;
.arco-card-body {
height: 100%;
.arco-space {
width: 100%;
height: 100%;
.arco-space-item {
height: 100%;
&:last-child {
flex: 1;
}
.arco-card-meta {
height: 100%;
display: flex;
flex-flow: column;
.arco-card-meta-content {
flex: 1;
.arco-card-meta-description {
margin-top: 8px;
color: rgb(var(--gray-6));
line-height: 20px;
font-size: 12px;
}
}
.arco-card-meta-footer {
margin-top: 0;
}
}
}
}
}
}
:deep(.arco-card-meta-title) {
display: flex;
align-items: center;
// To prevent the shaking
line-height: 28px;
}
:deep(.arco-skeleton-line) {
&:last-child {
display: flex;
justify-content: flex-end;
margin-top: 20px;
}
}
}
</style>

View file

@ -1,115 +0,0 @@
<template>
<div class="list-wrap">
<a-typography-title class="block-title" :heading="6">
{{ $t('cardList.tab.title.content') }}
</a-typography-title>
<a-row class="list-row" :gutter="24">
<a-col
:xs="12"
:sm="12"
:md="12"
:lg="6"
:xl="6"
:xxl="6"
class="list-col"
>
<div class="card-wrap empty-wrap">
<a-card :bordered="false" hoverable>
<a-result :status="null" :title="$t('cardList.content.action')">
<template #icon>
<icon-plus style="font-size: 20px" />
</template>
</a-result>
</a-card>
</div>
</a-col>
<a-col
v-for="item in renderData"
:key="item.id"
class="list-col"
:xs="12"
:sm="12"
:md="12"
:lg="6"
:xl="6"
:xxl="6"
>
<CardWrap
:loading="loading"
:title="item.title"
:description="item.description"
:default-value="item.enable"
:action-type="item.actionType"
:icon="item.icon"
:open-txt="$t('cardList.content.inspection')"
:close-txt="$t('cardList.content.delete')"
:show-tag="false"
>
<a-descriptions
style="margin-top: 16px"
:data="item.data"
layout="inline-horizontal"
:column="2"
/>
<template #skeleton>
<a-skeleton :animation="true">
<a-skeleton-line
:widths="['50%', '50%', '100%', '40%']"
:rows="4"
/>
<a-skeleton-line :widths="['40%']" :rows="1" />
</a-skeleton>
</template>
</CardWrap>
</a-col>
</a-row>
</div>
</template>
<script lang="ts" setup>
import { queryInspectionList, ServiceRecord } from '@/api/list';
import useRequest from '@/hooks/request';
import CardWrap from './card-wrap.vue';
const defaultValue: ServiceRecord[] = new Array(3).fill({});
const { loading, response: renderData } = useRequest<ServiceRecord[]>(
queryInspectionList,
defaultValue
);
</script>
<style scoped lang="less">
.card-wrap {
height: 100%;
transition: all 0.3s;
border: 1px solid var(--color-neutral-3);
&:hover {
transform: translateY(-4px);
}
:deep(.arco-card-meta-description) {
color: rgb(var(--gray-6));
.arco-descriptions-item-label-inline {
font-weight: normal;
font-size: 12px;
color: rgb(var(--gray-6));
}
.arco-descriptions-item-value-inline {
color: rgb(var(--gray-8));
}
}
}
.empty-wrap {
height: 200px;
border-radius: 4px;
:deep(.arco-card) {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
border-radius: 4px;
.arco-result-title {
color: rgb(var(--gray-6));
}
}
}
</style>

View file

@ -1,51 +0,0 @@
<template>
<div class="list-wrap">
<a-typography-title class="block-title" :heading="6">
{{ $t('cardList.tab.title.preset') }}
</a-typography-title>
<a-row class="list-row" :gutter="24">
<a-col
v-for="item in renderData"
:key="item.id"
:xs="12"
:sm="12"
:md="12"
:lg="6"
:xl="6"
:xxl="6"
class="list-col"
style="min-height: 140px"
>
<CardWrap
:loading="loading"
:title="item.title"
:description="item.description"
:default-value="item.enable"
:action-type="item.actionType"
:tag-text="$t('cardList.preset.tag')"
>
<template #skeleton>
<a-skeleton :animation="true">
<a-skeleton-line :widths="['100%', '40%']" :rows="2" />
<a-skeleton-line :widths="['40%']" :rows="1" />
</a-skeleton>
</template>
</CardWrap>
</a-col>
</a-row>
</div>
</template>
<script lang="ts" setup>
import { queryRulesPresetList, ServiceRecord } from '@/api/list';
import useRequest from '@/hooks/request';
import CardWrap from './card-wrap.vue';
const defaultValue: ServiceRecord[] = new Array(6).fill({});
const { loading, response: renderData } = useRequest<ServiceRecord[]>(
queryRulesPresetList,
defaultValue
);
</script>
<style scoped lang="less"></style>

View file

@ -1,57 +0,0 @@
<template>
<div class="list-wrap">
<a-typography-title class="block-title" :heading="6">
{{ $t('cardList.tab.title.service') }}
</a-typography-title>
<a-row class="list-row" :gutter="24">
<a-col
v-for="item in renderData"
:key="item.id"
:xs="12"
:sm="12"
:md="12"
:lg="6"
:xl="6"
:xxl="6"
class="list-col"
style="min-height: 162px"
>
<CardWrap
:loading="loading"
:title="item.title"
:description="item.description"
:default-value="item.enable"
:action-type="item.actionType"
:expires="item.expires"
:open-txt="$t('cardList.service.open')"
:close-txt="$t('cardList.service.cancel')"
:expires-text="$t('cardList.service.renew')"
:tag-text="$t('cardList.service.tag')"
:expires-tag-text="$t('cardList.service.expiresTag')"
:icon="item.icon"
>
<template #skeleton>
<a-skeleton :animation="true">
<a-skeleton-line :widths="['100%', '40%', '100%']" :rows="3" />
<a-skeleton-line :widths="['40%']" :rows="1" />
</a-skeleton>
</template>
</CardWrap>
</a-col>
</a-row>
</div>
</template>
<script lang="ts" setup>
import { queryTheServiceList, ServiceRecord } from '@/api/list';
import useRequest from '@/hooks/request';
import CardWrap from './card-wrap.vue';
const defaultValue: ServiceRecord[] = new Array(4).fill({});
const { loading, response: renderData } = useRequest<ServiceRecord[]>(
queryTheServiceList,
defaultValue
);
</script>
<style scoped lang="less"></style>

View file

@ -1,186 +0,0 @@
import Mock from 'mockjs';
import setupMock, { successResponseWrap } from '@/utils/setup-mock';
import { ServiceRecord } from '@/api/list';
const qualityInspectionList: ServiceRecord[] = [
{
id: 1,
name: 'quality',
title: '视频类-历史导入',
description: '2021-10-12 00:00:00',
data: [
{
label: '待质检数',
value: '120',
},
{
label: '积压时长',
value: '60s',
},
{
label: '待抽检数',
value: '0',
},
],
},
{
id: 2,
name: 'quality',
title: '图文类-图片版权',
description: '2021-12-11 18:30:00',
data: [
{
label: '待质检数',
value: '120',
},
{
label: '积压时长',
value: '60s',
},
{
label: '待抽检数',
value: '0',
},
],
},
{
id: 3,
name: 'quality',
title: '图文类-高清图片',
description: '2021-10-15 08:10:00',
data: [
{
label: '待质检数',
value: '120',
},
{
label: '积压时长',
value: '60s',
},
{
label: '待抽检数',
value: '0',
},
],
},
];
const theServiceList: ServiceRecord[] = [
{
id: 1,
icon: 'code',
title: '漏斗分析',
description:
'用户行为分析之漏斗分析模型是企业实现精细化运营、进行用户行为分析的重要数据分析模型。',
enable: true,
actionType: 'button',
},
{
id: 2,
icon: 'edit',
title: '用户分布',
description:
'快速诊断用户人群,地域细分情况,了解数据分布的集中度,以及主要的数据分布的区间段是什么。',
enable: true,
actionType: 'button',
expires: true,
},
{
id: 3,
icon: 'user',
title: '资源分发',
description:
'移动端动态化资源分发解决方案。提供稳定大流量服务支持、灵活定制的分发圈选规则,通过离线化预加载。',
enable: false,
actionType: 'button',
},
{
id: 4,
icon: 'user',
title: '用户画像分析',
description:
'用户画像就是将典型用户信息标签化,根据用户特征、业务场景和用户行为等信息,构建一个标签化的用户模型。',
enable: true,
actionType: 'button',
},
];
const rulesPresetList: ServiceRecord[] = [
{
id: 1,
title: '内容屏蔽规则',
description:
'用户在执行特定的内容分发任务时,可使用内容屏蔽规则根据特定标签,过滤内容集合。',
enable: true,
actionType: 'switch',
},
{
id: 2,
title: '内容置顶规则',
description:
'该规则支持用户在执行特定内容分发任务时,对固定的几条内容置顶。',
enable: true,
actionType: 'switch',
},
{
id: 3,
title: '内容加权规则',
description: '选定内容加权规则后可自定义从不同内容集合获取内容的概率。',
enable: false,
actionType: 'switch',
},
{
id: 4,
title: '内容分发规则',
description: '内容分发时对某些内容需要固定在C端展示的位置。',
enable: true,
actionType: 'switch',
},
{
id: 5,
title: '违禁内容识别',
description: '精准识别赌博、刀枪、毒品、造假、贩假等违规物品和违规行为。',
enable: false,
actionType: 'switch',
},
{
id: 6,
title: '多语言文字符号识别',
description:
'精准识别英语、维语、藏语、蒙古语、朝鲜语等多种语言以及emoji表情形态的语义识别。',
enable: false,
actionType: 'switch',
},
];
setupMock({
setup() {
// Quality Inspection
Mock.mock(new RegExp('/api/list/quality-inspection'), () => {
return successResponseWrap(
qualityInspectionList.map((_, index) => ({
...qualityInspectionList[index % qualityInspectionList.length],
id: Mock.Random.guid(),
}))
);
});
// the service
Mock.mock(new RegExp('/api/list/the-service'), () => {
return successResponseWrap(
theServiceList.map((_, index) => ({
...theServiceList[index % theServiceList.length],
id: Mock.Random.guid(),
}))
);
});
// rules preset
Mock.mock(new RegExp('/api/list/rules-preset'), () => {
return successResponseWrap(
rulesPresetList.map((_, index) => ({
...rulesPresetList[index % rulesPresetList.length],
id: Mock.Random.guid(),
}))
);
});
},
});