fix: 完成首页静态展示内容

This commit is contained in:
MTrun 2021-12-19 19:19:46 +08:00
parent c1daa231b6
commit f37ed1f3d3
29 changed files with 565 additions and 138 deletions

View File

@ -5,9 +5,9 @@
:date-locale="dateZhCN"
:theme-overrides="getThemeOverrides"
>
<app-provider>
<AppProvider>
<router-view />
</app-provider>
</AppProvider>
</n-config-provider>
</template>

View File

@ -0,0 +1,3 @@
import AppleControlBtn from './index.vue';
export { AppleControlBtn };

View File

@ -0,0 +1,96 @@
<template>
<div class="go-apple-control-btn">
<template v-for="item in btnList" :key="item.key">
<div
class="btn"
:class="[item.key, disabled && 'disabled']"
@click="handleClick(item.key)"
>
<n-icon size="10" class="icon-base" :class="{ hover: !disabled }">
<component :is="item.icon" />
</n-icon>
</div>
</template>
</div>
</template>
<script lang="ts" setup>
import { renderIcon } from '@/utils/index'
import { icon } from '@/plugins'
const emit = defineEmits(['close', 'remove', 'resize'])
const props = defineProps({
disabled: {
type: Boolean,
default: false
}
})
const { CloseIcon, RemoveIcon, ResizeIcon } = icon.ionicons5
const btnList = [
{
title: '关闭',
key: 'close',
icon: CloseIcon
},
{
title: '缩小',
key: 'remove',
icon: RemoveIcon
},
{
title: '放大',
key: 'resize',
icon: ResizeIcon
}
]
const handleClick = (key: 'close' | 'remove' | 'resize') => {
console.log(key)
emit(key)
}
</script>
<style lang="scss" scoped>
@include go('apple-control-btn') {
display: flex;
&:hover {
.btn {
.hover {
cursor: pointer;
opacity: 1;
}
}
}
.btn {
display: flex;
align-items: center;
justify-content: center;
width: 14px;
height: 14px;
margin: 0 4px;
color: $--color-text;
font-weight: bold;
border-radius: 50%;
&.disabled {
pointer-events:none;
}
.icon-base {
opacity: 0;
}
.hover {
@extend .go-transition;
}
}
.close {
background-color: $--color-red;
}
.remove {
background-color: $--color-warn;
}
.resize {
background-color: $--color-success;
}
}
</style>

View File

@ -1,4 +1,3 @@
<template></template>
<script lang="ts">
import { useMessage } from 'naive-ui';

View File

@ -0,0 +1,3 @@
import Skeleton from './index.vue';
export { Skeleton };

View File

@ -0,0 +1,29 @@
<template>
<div v-show="load">
<div v-show="repeat == 1">
<n-skeleton v-bind="$attrs" />
</div>
<div v-show="repeat == 2">
<n-skeleton v-bind="$attrs" />
<n-skeleton v-bind="$attrs" style="width: 60%;" />
</div>
<div v-show="repeat > 2">
<n-skeleton v-bind="$attrs" :repeat="repeat - 2" />
<n-skeleton v-bind="$attrs" style="width: 60%;" />
<n-skeleton v-bind="$attrs" style="width: 50%;" />
</div>
</div>
</template>
<script lang="ts" setup>
defineProps({
repeat: {
type: Number,
default: 1
},
load: {
type: Boolean,
default: true
}
})
</script>

View File

@ -1,10 +1,7 @@
<template>
<router-view #default="{ Component, route }">
<n-collapse-transition appear>
<component :is="Component" :key="route.fullPath" />
</n-collapse-transition>
<!-- todo 暂时不生效待处理 -->
<!-- <transition name="v-modal" mode="out-in" appear>
<!-- todo 动画暂时不生效待处理 -->
<transition name="v-modal" mode="out-in" appear>
<component
v-if="route.noKeepAlive"
:is="Component"
@ -13,6 +10,6 @@
<keep-alive v-else>
<component :is="Component" :key="route.fullPath" />
</keep-alive>
</transition> -->
</transition>
</router-view>
</template>

View File

@ -3,7 +3,7 @@ import App from './App.vue'
import router, { setupRouter } from '@/router'
import i18n from '@/i18n/index'
import { setupStore } from '@/store'
import { setupNaive, setupDirectives } from '@/plugins'
import { setupNaive, setupDirectives, setupCustomComponents } from '@/plugins'
import { AppProvider } from '@/components/Application'
import { setHtmlTheme } from '@/utils/style'
@ -15,9 +15,12 @@ async function appInit() {
// 注册全局常用的 naive-ui 组件
setupNaive(app)
// 注册全局自定义指令v-permission权限指令
// 注册全局自定义指令
setupDirectives(app)
// 注册全局自定义组件
setupCustomComponents(app)
// 挂载状态管理
setupStore(app)

View File

@ -1,7 +1,10 @@
import type { App } from 'vue'
import { Skeleton } from '@/components/Skeleton'
/**
*
* @param app
*/
export function setupCustomComponents() {
// app.component()
export function setupCustomComponents(app: App) {
app.component('Skeleton', Skeleton)
}

45
src/plugins/icon.ts Normal file
View File

@ -0,0 +1,45 @@
import {
Close as CloseIcon,
Remove as RemoveIcon,
Resize as ResizeIcon,
EllipsisHorizontalSharp as EllipsisHorizontalCircleSharpIcon,
CopyOutline as CopyIcon,
Trash as TrashIcon,
Pencil as PencilIcon,
Hammer as HammerIcon,
ApertureSharp as ApertureSharpIcon,
DownloadOutline as DownloadIcon,
Open as OpenIcon
} from '@vicons/ionicons5'
// ionicons5 在这里
const ionicons5 = {
// 关闭
CloseIcon,
// 移除(最小化)
RemoveIcon,
// 调整(最大化)
ResizeIcon,
// 省略号
EllipsisHorizontalCircleSharpIcon,
// 复制
CopyIcon,
// 删除(垃圾桶)
TrashIcon,
// 编辑1
PencilIcon,
// 编辑2锤子
HammerIcon,
// 预览
ApertureSharpIcon,
// 下载
DownloadIcon,
// 导出
OpenIcon
}
// https://www.xicons.org/#/ 还有很多
export const icon = {
ionicons5
}

View File

@ -1,3 +1,4 @@
export { setupNaive } from '@/plugins/naive';
export { setupDirectives } from '@/plugins/directives';
export { setupCustomComponents } from '@/plugins/customComponents';
export { setupNaive } from '@/plugins/naive'
export { setupDirectives } from '@/plugins/directives'
export { setupCustomComponents } from '@/plugins/customComponents'
export { icon } from '@/plugins/icon'

View File

@ -12,6 +12,7 @@ import {
NMessageProvider,
NDialogProvider,
NInput,
NImage,
NButton,
NForm,
NFormItem,
@ -97,6 +98,7 @@ const naive = create({
NCheckboxGroup,
NCheckbox,
NIcon,
NImage,
NLayout,
NLayoutHeader,
NLayoutContent,

View File

@ -53,7 +53,7 @@ export const asideWidth = '270'
export const asideCollapsedWidth = '60'
// 修改边框圆角
export const borderRadius = '8px'
export const borderRadius = '4px'
// 轮播间隔
export const carouselInterval = 4000

View File

@ -1,13 +1,22 @@
@import './var.scss';
$dark: (
// 文字颜色
color: $--color-text-4,
//背景
background-color: $--color-dark-bg-1,
//渐变背景
background-image:
linear-gradient(120deg, $--color-dark-bg-1 0%, $--color-dark-bg-1 100%),
// 斑点背景
background-point:
(
linear-gradient($--color-dark-bg-1 14px, transparent 0),
linear-gradient(90deg, transparent 14px, $--color-text-2 0)
),
//毛玻璃
filter-color: $--filter-color-login-dark,
// 物料市场背景
items-top-bg: linear-gradient(180deg, $--color-dark-bg-1, rgba(23, 23, 26, 0))
items-top-bg:
linear-gradient(180deg, $--color-dark-bg-1, rgba(23, 23, 26, 0))
);

View File

@ -1,11 +1,19 @@
@import './var.scss';
$light: (
// 文字颜色
color: $--color-text,
//背景
background_color: $--color-light-fill-3,
//渐变背景
background-image:
linear-gradient(120deg, $--color-text-1 0%, $--color-text-1 100%),
// 斑点背景
background-point:
(
linear-gradient($--color-light-fill-1 14px, transparent 0),
linear-gradient(90deg, transparent 14px, $--color-dark-bg-5 0)
),
//毛玻璃
filter-color: $--filter-color-login-light,
filter-color: $--filter-color-login-light
);

View File

@ -1,3 +1,21 @@
// 闪烁
.animation-twinkle {
animation: twinkle 2s ease;
animation-iteration-count: infinite;
opacity: 1;
}
@keyframes twinkle {
0% {
opacity: 1;
}
50% {
opacity: 0.5;
}
100% {
opacity: 1;
}
}
// 淡入淡出
.v-modal-enter {
animation: v-modal-in 0.2s ease;
@ -34,4 +52,4 @@
}
.list-complete-leave-active {
position: absolute;
}
}

View File

@ -9,6 +9,12 @@
}
}
@mixin deep() {
::v-deep *{
@content;
}
}
@mixin when($state) {
@at-root {
&.#{$state-prefix + $state} {
@ -46,10 +52,10 @@
}
}
//获取字体颜色
@mixin font-color($target) {
//获取斑点渐变颜色
@mixin background-point($target) {
@include themeify {
color: themed($target);
background-image: themed($target);
}
}
@ -58,4 +64,4 @@
@include themeify {
border-color: themed($target);
}
}
}

View File

@ -1,7 +1,26 @@
@import './var.scss';
@import './animation.scss';
@import './mixins/mixins.scss';
// extends
// 过度
.go-transition {
transition: all 0.2s;
}
.go-flex-center {
display: flex;
justify-content: center;
align-items: center;
}
.go-absolute-center {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
// 毛玻璃
.go-background-filter {
backdrop-filter: $--filter-blur-base;
@ -15,6 +34,12 @@
overflow: hidden;
}
// 背景斑点需配合 @mixin background-point 使用
.go-point-bg {
@include fetch-theme('background-color');
background-size: 15px 15px, 15px 15px;
}
// todo 使用 scss 循环写一套完整的
// margin
.go-mt-0 {
@ -41,4 +66,4 @@
.go-px-0 {
@extend .go-pt-0;
@extend .go-pb-0;
}
}

View File

@ -4,11 +4,11 @@ $--color-warn: #fcbc40;
$--color-success: #34c749;
// 文字
$--color-text: hsla(0, 0%, 100%, 1);
$--color-text-1: hsla(0, 0%, 100%, 0.9);
$--color-text-2: hsla(0, 0%, 100%, 0.7);
$--color-text-3: hsla(0, 0%, 100%, 0.5);
$--color-text-4: hsla(0, 0%, 100%, 0.3);
$--color-text: #1d2129;
$--color-text-1: #4e5969;
$--color-text-2: #86909c;
$--color-text-3: #c9cdd4;
$--color-text-4: #f2f3f5;
// 白色
$--color-light-fill: #fff;

View File

@ -1,4 +1,4 @@
import { h, DefineComponent } from 'vue'
import { h } from 'vue'
import { NIcon } from 'naive-ui'
/**
@ -18,6 +18,43 @@ export const renderIcon = (icon: any) => {
return () => h(NIcon, null, { default: () => h(icon) })
}
/**
* * render
* @param { Function } dialogFn dialog函数
* @param { Object} params
*/
export const goDialog = (
dialogFn: Function,
params: {
// 基本
type: 'delete'
message?: string
onPositiveCallback?: Function
onNegativeCallback?: Function
// 渲染函数
render?: boolean
contentFn?: Function
actionFn?: Function
}
) => {
const { type, message, onPositiveCallback, onNegativeCallback } = params
const tip = {
delete: '是否删除此数据'
}
dialogFn({
title: '提示',
content: message || tip[type] || '',
positiveText: '确定',
negativeText: '取消',
onPositiveClick: () => {
onPositiveCallback && onPositiveCallback()
},
onNegativeClick: () => {
onNegativeCallback && onNegativeCallback()
}
})
}
/**
* * vite 使 require
* @param name

View File

@ -1,105 +0,0 @@
<template>
<div class="go-items-list">
<n-grid
:x-gap="20"
:y-gap="20"
cols="2 s:2 m:3 l:4 xl:4 xxl:4"
responsive="screen"
>
<n-grid-item v-for="item in list" :key="item.id">
<n-card hoverable size="small">
<div class="list-content">
<n-space>
<n-button size="small">
<template #icon>
<n-icon>
<EllipsisHorizontalCircleSharpIcon />
</n-icon>
</template>
</n-button>
</n-space>
<div class="list-content-top"></div>
<n-image
object-fit="cover"
width="100"
src="https://gw.alipayobjects.com/zos/antfincdn/aPkFc8Sj7n/method-draw-image.svg"
:alt="item.title"
/>
</div>
<template #action>
<n-skeleton v-if="loading" round size="medium" />
<n-space v-else justify="space-between">
<n-text>
奔跑的模板
</n-text>
<!-- 工具 -->
<n-space>
<n-button size="small">
<template #icon>
<n-icon>
<EllipsisHorizontalCircleSharpIcon />
</n-icon>
</template>
</n-button>
<n-button size="small">
<template #icon>
<n-icon>
<CopyIcon />
</n-icon>
</template>
</n-button>
</n-space>
<!-- end -->
</n-space>
</template>
</n-card>
</n-grid-item>
</n-grid>
</div>
</template>
<script setup lang="ts">
import { reactive, ref } from 'vue'
import {
EllipsisHorizontalSharp as EllipsisHorizontalCircleSharpIcon,
CopyOutline as CopyIcon
} from '@vicons/ionicons5'
const loading = ref<boolean>(true)
setTimeout(() => {
loading.value = false
}, 200)
const list = reactive([
{
id: 1,
title: '物料1'
},
{
id: 2,
title: '物料1'
},
{
id: 3,
title: '物料1'
},
{
id: 4,
title: '物料1'
},
{
id: 5,
title: '物料1'
}
])
</script>
<style lang="scss" scoped>
$contentHeight: 250px;
@include go('items-list') {
.list-content {
position: relative;
height: $contentHeight;
}
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

View File

@ -0,0 +1,3 @@
import Card from './index.vue'
export { Card }

View File

@ -0,0 +1,176 @@
<template>
<div class="go-items-list-card">
<n-card hoverable size="small">
<div class="list-content">
<!-- 顶部按钮 -->
<n-space class="list-content-top">
<AppleControlBtn @close="deleteHanlde" />
</n-space>
<!-- 中间 -->
<div class="list-content-img">
<n-image
object-fit="contain"
height="200"
:src="requireUrl('.', '20211219181327.png')"
:alt="CardData.title"
/>
</div>
</div>
<template #action>
<Skeleton v-if="loading" :loading="loading" text round size="small" />
<n-space v-else justify="space-between">
<n-text>
{{ CardData.title || '' }}
</n-text>
<!-- 工具 -->
<n-space>
<n-text>
<n-badge class="animation-twinkle" dot :color="CardData.release ? '#34c749' : '#fcbc40'" />
{{ CardData.release ? '已发布' : '未发布' }}
</n-text>
<template v-for="item in fnBtnList" :key="item.key">
<template v-if="item.key === 'select'">
<n-dropdown
trigger="hover"
placement="bottom-start"
:options="selectOptions"
:show-arrow="true"
@select="handleSelect"
>
<n-button size="small">
<template #icon>
<component :is="item.icon" />
</template>
</n-button>
</n-dropdown>
</template>
<n-button v-else size="small">
<template #icon>
<component :is="item.icon" />
</template>
</n-button>
</template>
</n-space>
<!-- end -->
</n-space>
</template>
</n-card>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { renderIcon, goDialog } from '@/utils/index'
import { icon } from '@/plugins'
import { AppleControlBtn } from '@/components/AppleControlBtn'
import { useMessage, useDialog } from 'naive-ui'
const {
EllipsisHorizontalCircleSharpIcon,
CopyIcon,
TrashIcon,
PencilIcon,
ApertureSharpIcon,
DownloadIcon
} = icon.ionicons5
const loading = ref<boolean>(true)
const dialog = useDialog()
const message = useMessage()
defineProps({
CardData: Object
})
const fnBtnList = [
{
lable: '更多',
key: 'select',
icon: renderIcon(EllipsisHorizontalCircleSharpIcon)
}
]
const selectOptions = [
{
label: '预览',
key: 'preview',
icon: renderIcon(ApertureSharpIcon)
},
{
label: '复制',
key: 'copy',
icon: renderIcon(CopyIcon)
},
{
label: '重命名',
key: 'rename',
icon: renderIcon(PencilIcon)
},
{
label: '下载',
key: 'download',
icon: renderIcon(DownloadIcon)
},
{
type: 'divider',
key: 'd1'
},
{
label: '删除',
key: 'delete',
icon: renderIcon(TrashIcon)
}
]
const handleSelect = (key: string) => {
console.log(key)
}
const requireUrl = (path: string, name: string) => {
return new URL(`${path}/${name}`, import.meta.url).href
}
const deleteHanlde = () => {
goDialog(dialog.warning, {
type: 'delete',
onPositiveCallback: () => {
message.success('确定')
}
})
}
setTimeout(() => {
loading.value = false
}, 1500)
</script>
<style lang="scss" scoped>
$contentHeight: 200px;
@include go('items-list-card') {
position: relative;
.list-content {
margin-top: 20px;
margin-bottom: 5px;
border-radius: $--border-radius-base;
@include background-point('background-point');
@extend .go-point-bg;
&-top {
position: absolute;
top: 5px;
left: 10px;
height: 22px;
}
&-img {
height: $contentHeight;
@extend .go-flex-center;
@extend .go-border-radius;
@include deep() {
img {
@extend .go-border-radius;
}
}
}
}
}
</style>

View File

@ -0,0 +1,62 @@
<template>
<div class="go-items-list">
<n-grid
:x-gap="20"
:y-gap="20"
cols="2 s:2 m:3 l:4 xl:4 xxl:4"
responsive="screen"
>
<n-grid-item v-for="item in list" :key="item.id">
<Card :CardData="item" />
</n-grid-item>
</n-grid>
</div>
</template>
<script setup lang="ts">
import { reactive, ref } from 'vue'
import { Card } from '../Card/index'
import {
EllipsisHorizontalSharp as EllipsisHorizontalCircleSharpIcon,
CopyOutline as CopyIcon
} from '@vicons/ionicons5'
const loading = ref<boolean>(true)
setTimeout(() => {
loading.value = false
}, 500)
const list = reactive([
{
id: 1,
title: '物料1',
release: true
},
{
id: 2,
title: '物料1'
},
{
id: 3,
title: '物料1'
},
{
id: 4,
title: '物料1'
},
{
id: 5,
title: '物料1'
}
])
</script>
<style lang="scss" scoped>
$contentHeight: 250px;
@include go('items-list') {
.list-content {
position: relative;
height: $contentHeight;
}
}
</style>

7
src/views/project/items/index.d.ts vendored Normal file
View File

@ -0,0 +1,7 @@
export type CardType = {
id: number | string
title: string // 标题
lableId: string | number
label: string // 标签
release: number // 0未发布 | 1已发布
}

View File

@ -5,7 +5,7 @@
</template>
<script setup lang="ts">
import { List } from './List'
import { List } from './components/List'
</script>
<style lang="scss" scoped>

View File

@ -26,7 +26,7 @@ export default defineConfig({
preprocessorOptions: {
scss: {
javascriptEnabled: true,
additionalData: `@import "src/styles/common/style.scss";@import "src/styles/common/mixins/mixins.scss";`,
additionalData: `@import "src/styles/common/style.scss";`,
},
},
},