浏览代码

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

MTrun 3 年之前
父节点
当前提交
f37ed1f3d3

+ 2 - 2
src/App.vue

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

+ 3 - 0
src/components/AppleControlBtn/index.ts

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

+ 96 - 0
src/components/AppleControlBtn/index.vue

@@ -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>

+ 0 - 1
src/components/MessageContent/index.vue

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

+ 3 - 0
src/components/Skeleton/index.ts

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

+ 29 - 0
src/components/Skeleton/index.vue

@@ -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>

+ 3 - 6
src/layout/components/TransitionMain/index.vue

@@ -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>

+ 5 - 2
src/main.ts

@@ -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)
 

+ 5 - 2
src/plugins/customComponents.ts

@@ -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 - 0
src/plugins/icon.ts

@@ -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
+}

+ 4 - 3
src/plugins/index.ts

@@ -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'

+ 2 - 0
src/plugins/naive.ts

@@ -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,

+ 1 - 1
src/settings/designSetting.ts

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

+ 10 - 1
src/styles/common/_dark.scss

@@ -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))
 );

+ 9 - 1
src/styles/common/_light.scss

@@ -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
 );

+ 19 - 1
src/styles/common/animation.scss

@@ -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;
-}
+}

+ 10 - 4
src/styles/common/mixins/mixins.scss

@@ -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);
   }
-}
+}

+ 26 - 1
src/styles/common/style.scss

@@ -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;
-}
+}

+ 5 - 5
src/styles/common/var.scss

@@ -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;

+ 38 - 1
src/utils/index.ts

@@ -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

+ 0 - 105
src/views/project/items/List/index.vue

@@ -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>

二进制
src/views/project/items/components/Card/20211219181327.png


+ 3 - 0
src/views/project/items/components/Card/index.ts

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

+ 176 - 0
src/views/project/items/components/Card/index.vue

@@ -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>

+ 0 - 0
src/views/project/items/List/index.ts → src/views/project/items/components/List/index.ts


+ 62 - 0
src/views/project/items/components/List/index.vue

@@ -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 - 0
src/views/project/items/index.d.ts

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

+ 1 - 1
src/views/project/items/index.vue

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

+ 1 - 1
vite.config.ts

@@ -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";`,
       },
     },
   },