引入tailwindCss
This commit is contained in:
@@ -1,359 +1,25 @@
|
||||
<template>
|
||||
<div class="ele-body ele-body-card">
|
||||
<a-card :bordered="false">
|
||||
<template #title>
|
||||
<SoundOutlined class="ele-text-danger" />
|
||||
<span class="gg-title ele-text-heading">公告</span>
|
||||
<a @click="openNew('/cms/article/374')" class="ele-text-heading"
|
||||
>系统内测中,如何获取体验账号?</a
|
||||
>
|
||||
</template>
|
||||
<template #extra>
|
||||
<a @click="openNew('/cms/category/92')" class="ele-text-placeholder"
|
||||
>更多<RightOutlined
|
||||
/></a>
|
||||
</template>
|
||||
</a-card>
|
||||
<!-- <profile-card />-->
|
||||
<LinkCard />
|
||||
<a-row :gutter="16" ref="wrapRef">
|
||||
<a-col :md="9">
|
||||
<App title="我的项目" />
|
||||
</a-col>
|
||||
<a-col :md="9">
|
||||
<Task title="我的工单" :categoryId="92" />
|
||||
</a-col>
|
||||
<a-col :md="6">
|
||||
<Article title="通知公告" :categoryId="92" />
|
||||
</a-col>
|
||||
<a-col :md="6">
|
||||
<Article title="公司动态" :categoryId="37" />
|
||||
</a-col>
|
||||
<a-col :md="6">
|
||||
<Article title="经验分享" :categoryId="93" />
|
||||
</a-col>
|
||||
<a-col :md="6">
|
||||
<Article title="API文档" :categoryId="90" />
|
||||
</a-col>
|
||||
<a-col :md="6">
|
||||
<Link linkType="实用工具" />
|
||||
</a-col>
|
||||
<!-- <a-col :md="12">-->
|
||||
<!-- <a-card title="商品管理" :bordered="false" />-->
|
||||
<!-- </a-col>-->
|
||||
</a-row>
|
||||
<!-- <a-row :gutter="16" ref="wrapRef">-->
|
||||
<!-- <a-col-->
|
||||
<!-- v-for="(item, index) in data"-->
|
||||
<!-- :key="item.name"-->
|
||||
<!-- :lg="item.lg"-->
|
||||
<!-- :md="item.md"-->
|
||||
<!-- :sm="item.sm"-->
|
||||
<!-- :xs="item.xs"-->
|
||||
<!-- >-->
|
||||
<!-- <component-->
|
||||
<!-- :is="item.name"-->
|
||||
<!-- :title="item.title"-->
|
||||
<!-- @remove="onRemove(index)"-->
|
||||
<!-- @edit="onEdit(index)"-->
|
||||
<!-- />-->
|
||||
<!-- </a-col>-->
|
||||
<!-- </a-row>-->
|
||||
<a-card :bordered="false" :body-style="{ padding: 0 }">
|
||||
<div class="ele-cell" style="line-height: 42px">
|
||||
<div
|
||||
class="ele-cell-content ele-text-primary workplace-bottom-btn"
|
||||
@click="add"
|
||||
>
|
||||
<PlusCircleOutlined /> 添加视图
|
||||
</div>
|
||||
<a-divider type="vertical" />
|
||||
<div
|
||||
class="ele-cell-content ele-text-primary workplace-bottom-btn"
|
||||
@click="reset"
|
||||
>
|
||||
<UndoOutlined /> 重置布局
|
||||
</div>
|
||||
</div>
|
||||
</a-card>
|
||||
<ele-modal
|
||||
:width="680"
|
||||
v-model:visible="visible"
|
||||
title="未添加的视图"
|
||||
:footer="null"
|
||||
>
|
||||
<a-row :gutter="16">
|
||||
<a-col
|
||||
v-for="item in notAddedData"
|
||||
:key="item.name"
|
||||
:md="8"
|
||||
:sm="12"
|
||||
:xs="24"
|
||||
>
|
||||
<div
|
||||
class="workplace-card-item ele-border-split"
|
||||
@click="addView(item)"
|
||||
>
|
||||
<div class="workplace-card-header ele-border-split">
|
||||
{{ item.title }}
|
||||
</div>
|
||||
<div class="workplace-card-body ele-text-placeholder">
|
||||
<plus-circle-outlined />
|
||||
</div>
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-empty v-if="!notAddedData.length" description="已添加所有视图" />
|
||||
</ele-modal>
|
||||
<statistics-card />
|
||||
<sale-card />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed, onMounted, onBeforeUnmount } from 'vue';
|
||||
import SortableJs from 'sortablejs';
|
||||
import type { Row as ARow } from 'ant-design-vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
import Article from './components/article-list.vue';
|
||||
import Link from './components/link-list.vue';
|
||||
import App from './components/app-list.vue';
|
||||
import Task from './components/task-card.vue';
|
||||
import {
|
||||
PlusCircleOutlined,
|
||||
SoundOutlined,
|
||||
RightOutlined
|
||||
} from '@ant-design/icons-vue';
|
||||
import { openNew } from '@/utils/common';
|
||||
const CACHE_KEY = 'workplace-layout';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useThemeStore } from '@/store/modules/theme';
|
||||
import StatisticsCard from './components/statistics-card.vue';
|
||||
import SaleCard from './components/sale-card.vue';
|
||||
import VisitHour from './components/visit-hour.vue';
|
||||
import HotSearch from './components/hot-search.vue';
|
||||
|
||||
interface ViewItem {
|
||||
name: string;
|
||||
title: string;
|
||||
lg: number;
|
||||
md: number;
|
||||
sm: number;
|
||||
xs: number;
|
||||
}
|
||||
|
||||
// 默认布局
|
||||
const DEFAULT: ViewItem[] = [
|
||||
{
|
||||
name: 'link',
|
||||
title: '网址导航',
|
||||
lg: 24,
|
||||
md: 24,
|
||||
sm: 24,
|
||||
xs: 24
|
||||
},
|
||||
{
|
||||
name: 'task-card',
|
||||
title: '我的工单',
|
||||
lg: 18,
|
||||
md: 24,
|
||||
sm: 24,
|
||||
xs: 24
|
||||
},
|
||||
// {
|
||||
// name: 'project-card',
|
||||
// title: '项目管理',
|
||||
// lg: 16,
|
||||
// md: 24,
|
||||
// sm: 24,
|
||||
// xs: 24
|
||||
// },
|
||||
{
|
||||
name: 'user-list',
|
||||
title: '小组成员',
|
||||
lg: 6,
|
||||
md: 24,
|
||||
sm: 24,
|
||||
xs: 24
|
||||
}
|
||||
// {
|
||||
// name: 'activities-card',
|
||||
// title: '最新动态',
|
||||
// lg: 6,
|
||||
// md: 24,
|
||||
// sm: 24,
|
||||
// xs: 24
|
||||
// },
|
||||
// {
|
||||
// name: 'goal-card',
|
||||
// title: '本月目标',
|
||||
// lg: 8,
|
||||
// md: 24,
|
||||
// sm: 24,
|
||||
// xs: 24
|
||||
// },
|
||||
// {
|
||||
// name: 'docs',
|
||||
// title: '知识库',
|
||||
// lg: 8,
|
||||
// md: 24,
|
||||
// sm: 24,
|
||||
// xs: 24
|
||||
// }
|
||||
];
|
||||
|
||||
// 获取缓存的顺序
|
||||
const cache = (() => {
|
||||
const str = localStorage.getItem(CACHE_KEY);
|
||||
try {
|
||||
return str ? JSON.parse(str) : null;
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
})();
|
||||
|
||||
const data = ref<ViewItem[]>([...(cache ?? DEFAULT)]);
|
||||
|
||||
const visible = ref(false);
|
||||
|
||||
const wrapRef = ref<InstanceType<typeof ARow> | null>(null);
|
||||
|
||||
let sortableIns: SortableJs | null = null;
|
||||
|
||||
// 未添加的数据
|
||||
const notAddedData = computed(() => {
|
||||
return DEFAULT.filter((d) => !data.value.some((t) => t.name === d.name));
|
||||
});
|
||||
|
||||
/* 添加 */
|
||||
const add = () => {
|
||||
visible.value = true;
|
||||
};
|
||||
|
||||
/* 重置布局 */
|
||||
const reset = () => {
|
||||
data.value = [...DEFAULT];
|
||||
cacheData();
|
||||
message.success('已重置');
|
||||
};
|
||||
|
||||
/* 缓存布局 */
|
||||
const cacheData = () => {
|
||||
localStorage.setItem(CACHE_KEY, JSON.stringify(data.value));
|
||||
};
|
||||
|
||||
/* 删除视图 */
|
||||
const onRemove = (index: number) => {
|
||||
data.value = data.value.filter((_d, i) => i !== index);
|
||||
cacheData();
|
||||
};
|
||||
|
||||
/* 编辑视图 */
|
||||
const onEdit = (index: number) => {
|
||||
data.value.map((d) => {
|
||||
if (d.name == 'user-list') {
|
||||
}
|
||||
});
|
||||
// message.info('点击了编辑');
|
||||
};
|
||||
|
||||
/* 添加视图 */
|
||||
const addView = (item) => {
|
||||
data.value.push(item);
|
||||
cacheData();
|
||||
message.success('已添加');
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
const isTouchDevice = 'ontouchstart' in document.documentElement;
|
||||
if (isTouchDevice) {
|
||||
return;
|
||||
}
|
||||
sortableIns = new SortableJs(wrapRef.value?.$el, {
|
||||
handle: '.ant-card-head',
|
||||
animation: 300,
|
||||
onUpdate: ({ oldIndex, newIndex }) => {
|
||||
if (typeof oldIndex === 'number' && typeof newIndex === 'number') {
|
||||
const temp = [...data.value];
|
||||
temp.splice(newIndex, 0, temp.splice(oldIndex, 1)[0]);
|
||||
data.value = temp;
|
||||
cacheData();
|
||||
}
|
||||
},
|
||||
setData: () => {}
|
||||
});
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
if (sortableIns) {
|
||||
sortableIns.destroy();
|
||||
}
|
||||
});
|
||||
// 是否开启响应式布局
|
||||
const themeStore = useThemeStore();
|
||||
const { styleResponsive } = storeToRefs(themeStore);
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import ActivitiesCard from './components/activities-card.vue';
|
||||
import TaskCard from './components/task-card.vue';
|
||||
import GoalCard from './components/goal-card.vue';
|
||||
import UserList from './components/count-user.vue';
|
||||
import Docs from './components/docs.vue';
|
||||
import LinkCard from './components/link-card.vue';
|
||||
import ProfileCard from './components/profile-card.vue';
|
||||
|
||||
export default {
|
||||
name: 'DashboardWorkplace',
|
||||
components: {
|
||||
LinkCard,
|
||||
UserList,
|
||||
ActivitiesCard,
|
||||
TaskCard,
|
||||
GoalCard,
|
||||
Docs,
|
||||
ProfileCard
|
||||
}
|
||||
name: 'DashboardAnalysis'
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.ele-body :deep(.ant-card-head) {
|
||||
cursor: move;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.ele-body :deep(.ant-row > .ant-col.sortable-chosen > .ant-card) {
|
||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.workplace-bottom-btn {
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.workplace-bottom-btn:hover {
|
||||
background: hsla(0, 0%, 60%, 0.05);
|
||||
}
|
||||
|
||||
/* 添加弹窗 */
|
||||
.workplace-card-item {
|
||||
margin-bottom: 15px;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-radius: 4px;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
transition: box-shadow 0.2s, background-color 0.2s;
|
||||
}
|
||||
|
||||
.workplace-card-item:hover {
|
||||
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.1);
|
||||
background: hsla(0, 0%, 60%, 0.05);
|
||||
}
|
||||
|
||||
.workplace-card-item .workplace-card-header {
|
||||
border-bottom-width: 1px;
|
||||
border-bottom-style: solid;
|
||||
padding: 8px;
|
||||
}
|
||||
.gg-title {
|
||||
padding: 0 5px;
|
||||
margin-right: 20px;
|
||||
}
|
||||
.workplace-card-body {
|
||||
font-size: 26px;
|
||||
padding: 24px 10px;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user