feat: AI建议 & 许可证页面
This commit is contained in:
104
src/components/AIRepair/Panel.vue
Normal file
104
src/components/AIRepair/Panel.vue
Normal file
@@ -0,0 +1,104 @@
|
||||
<template>
|
||||
<div>
|
||||
<slot name="header"></slot>
|
||||
</div>
|
||||
<Transition
|
||||
name="collapse-transition"
|
||||
@beforeEnter="beforeEnter"
|
||||
@enter="enter"
|
||||
@afterEnter="afterEnter"
|
||||
@beforeLeave="beforeLeave"
|
||||
@leave="leave"
|
||||
@afterLeave="afterLeave"
|
||||
>
|
||||
<div v-if="props.expand">
|
||||
<slot name="body"></slot>
|
||||
</div>
|
||||
</Transition>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, defineProps, type RendererElement } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
expand: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
});
|
||||
|
||||
const beforeEnter = (el: RendererElement) => {
|
||||
if (!el.dataset) {
|
||||
el.dataset = {};
|
||||
}
|
||||
if (el.style.height) {
|
||||
el.dataset.height = el.style.height;
|
||||
}
|
||||
el.style.maxHeight = 0;
|
||||
};
|
||||
const enter = (el: RendererElement) => {
|
||||
requestAnimationFrame(() => {
|
||||
el.dataset.oldOverflow = el.style.overflow;
|
||||
if (el.dataset.height) {
|
||||
el.style.maxHeight = el.dataset.height;
|
||||
} else if (el.scrollHeight !== 0) {
|
||||
el.style.maxHeight = `${el.scrollHeight}px`;
|
||||
} else {
|
||||
el.style.maxHeight = 0;
|
||||
}
|
||||
el.style.overflow = 'hidden';
|
||||
});
|
||||
};
|
||||
const afterEnter = (el: RendererElement) => {
|
||||
el.style.maxHeight = '';
|
||||
el.style.overflow = el.dataset.oldOverflow;
|
||||
};
|
||||
const beforeLeave = (el: RendererElement) => {
|
||||
if (!el.dataset) {
|
||||
el.dataset = {};
|
||||
}
|
||||
el.dataset.oldOverflow = el.style.overflow;
|
||||
el.style.maxHeight = `${el.scrollHeight}px`;
|
||||
el.style.overflow = 'hidden';
|
||||
};
|
||||
const leave = (el: RendererElement) => {
|
||||
if (el.scrollHeight !== 0) {
|
||||
el.style.maxHeight = 0;
|
||||
}
|
||||
};
|
||||
const afterLeave = (el: RendererElement) => {
|
||||
el.style.maxHeight = '';
|
||||
el.style.overflow = el.dataset.oldOverflow;
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.v-enter-active,
|
||||
.v-leave-active {
|
||||
transition: opacity 0.5s ease;
|
||||
}
|
||||
|
||||
.v-enter-from,
|
||||
.v-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.collapse-transition {
|
||||
&-enter-from,
|
||||
&-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
&-enter-to,
|
||||
&-leave-from {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&-enter-active,
|
||||
&-leave-active {
|
||||
transition:
|
||||
max-height 0.3s cubic-bezier(0.5, 0.05, 0.5, 0.95),
|
||||
opacity 0.3s cubic-bezier(0.5, 0.05, 0.5, 0.95);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
46
src/components/AIRepair/Table.vue
Normal file
46
src/components/AIRepair/Table.vue
Normal file
@@ -0,0 +1,46 @@
|
||||
<template>
|
||||
<d-table :data="dataSource" @sort-change="handleSortChange" :header-bg="true">
|
||||
<d-column v-for="(column, index) in props.tableConfig" :field="column.field"
|
||||
:header="column.header" :sortable="column.sortable" :sort-method="column.sortMethod"></d-column>
|
||||
</d-table>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent, ref, onMounted } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
tableConfig: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
dataSource: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
|
||||
onMounted(() => {
|
||||
console.log('props', props);
|
||||
});
|
||||
|
||||
const handleSortChange = ({ field, direction }) => {
|
||||
console.log('field', field);
|
||||
console.log('direction', direction);
|
||||
};
|
||||
const sortDateMethod = (a, b) => {
|
||||
return a.date > b.date;
|
||||
};
|
||||
const sortNameMethod = (a, b) => {
|
||||
return a.lastName > b.lastName;
|
||||
};
|
||||
|
||||
return { props, handleSortChange, sortDateMethod, sortNameMethod };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
</style>
|
||||
@@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<div class="full-w" :style="{ height: `${height}px` }">
|
||||
<div class="g-header fixed z-20" ref="headerRef">
|
||||
<div class="g-header fixed z-20" ref="headerRef" :class="{'home-background': isHome, 'normal-background': !isHome}">
|
||||
<div class="g-toolbar w-full overflow-hidden" :class="[searchClass, route?.meta?.headerClassName]">
|
||||
<div class="g-toolbar-left flex-shrink items-center">
|
||||
<div class="flex-center gap-[16px]">
|
||||
<div class="flex-center gap-[16px]" v-if="!isHome">
|
||||
<!-- <g-icon v-if="!asideSetShow" @click="$emit('clickMenu')" name="gt-hamburger" size="20px" class="cursor-pointer hover:!text-black" color="#1D1F3A"></g-icon>-->
|
||||
<GLink class="g-toolbar-left-logo" :href="baseUrl" />
|
||||
<GLink class="g-toolbar-left-title" :href="baseUrl">可信代码库</GLink>
|
||||
@@ -11,7 +11,7 @@
|
||||
<!-- <Entrance v-if="isLogin" :is-mobile="isMobile" /> -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-1 flex items-center justify-end">
|
||||
<div class="flex-1 flex items-center justify-end" v-if="!isHome">
|
||||
<Search class="g-toolbar-left-search" v-if="!isMobile" :key="$route.fullPath"/>
|
||||
</div>
|
||||
<div class="g-toolbar-right gap-[12px] flex-grow-0 flex-shrink-0">
|
||||
@@ -101,6 +101,7 @@ const { height = 56 } = useElementSize(headerRef);
|
||||
const userInfo = useAccountStore();
|
||||
const { isLogin } = storeToRefs(userInfo);
|
||||
const showSearch = computed(() => route.name !== 'home' && route.name !== 'search');
|
||||
const isHome = computed(() => route.name === 'home');
|
||||
const handleLogin = (type) => {
|
||||
emitEvent('login', { type, triggerType: '主动注册' });
|
||||
};
|
||||
@@ -139,7 +140,12 @@ $header-bg: #fff;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
justify-content: space-between;
|
||||
background-color: $header-bg;
|
||||
.home-background {
|
||||
background-color: #fff0;
|
||||
}
|
||||
.normal-background {
|
||||
background-color: $header-bg;
|
||||
}
|
||||
:deep(.g-link) {
|
||||
color: $devui-text-weak;
|
||||
}
|
||||
|
||||
137
src/components/LicenseInfo/SidePanel.vue
Normal file
137
src/components/LicenseInfo/SidePanel.vue
Normal file
@@ -0,0 +1,137 @@
|
||||
<template>
|
||||
<d-layout class="dlayout">
|
||||
<d-header class="dheader">
|
||||
<div class="title">
|
||||
<h1>Apache License 2.0</h1>
|
||||
<d-icon style="cursor: pointer;" name="icon-close" @click="emit('close')"></d-icon>
|
||||
</div>
|
||||
<div class="sub-title">
|
||||
<span>分数</span>
|
||||
<span>3</span>
|
||||
<span>类型</span>
|
||||
<d-tag color="#3ac295" size="sm">获准的</d-tag>
|
||||
</div>
|
||||
</d-header>
|
||||
<d-content class="dcontent">
|
||||
<div class="content-title"></div>
|
||||
<div class="content-body">
|
||||
<d-row>
|
||||
<d-col :span="8">
|
||||
<div class="content-body-col">
|
||||
<span class="color-allow">允许的</span>
|
||||
<span>Commercial Use</span>
|
||||
<span>Modify</span>
|
||||
<span>Distribute</span>
|
||||
<span>Sublicense</span>
|
||||
<span>Private Use</span>
|
||||
</div>
|
||||
</d-col>
|
||||
<d-col :span="8">
|
||||
<div class="content-body-col">
|
||||
<span class="color-info">必要的</span>
|
||||
<span>Include Copyright</span>
|
||||
<span>Include License</span>
|
||||
<span>State changes</span>
|
||||
<span>Include Notice</span>
|
||||
</div>
|
||||
</d-col>
|
||||
<d-col :span="8">
|
||||
<div class="content-body-col">
|
||||
<span class="color-danger">受限的</span>
|
||||
<span>Place Warranty</span>
|
||||
<span>Hold Liable</span>
|
||||
<span>Use Trademark</span>
|
||||
</div>
|
||||
</d-col>
|
||||
</d-row>
|
||||
</div>
|
||||
</d-content>
|
||||
<d-footer class="dfooter">
|
||||
<div>
|
||||
<span>影响组件:</span>
|
||||
<span>request</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>当前版本:</span>
|
||||
<span>2.0</span>
|
||||
</div>
|
||||
</d-footer>
|
||||
</d-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, defineEmits } from 'vue';
|
||||
|
||||
const emit = defineEmits(['close']);
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import 'devui-theme/styles-var/devui-var.scss';
|
||||
|
||||
.dlayout {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: start;
|
||||
gap: 8px;
|
||||
padding: 12px;
|
||||
|
||||
.dheader, .dcontent{
|
||||
width: 100%;
|
||||
border-bottom: 1px solid gray;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.dfooter {
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
d-icon {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.sub-title {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.content-body-col {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.dfooter {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: start;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.side-panel {
|
||||
padding: 20px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.color-danger {
|
||||
color: $devui-danger;
|
||||
}
|
||||
|
||||
.color-info {
|
||||
color: $devui-warning;
|
||||
}
|
||||
|
||||
.color-allow {
|
||||
color: $devui-success;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user