项目应用首页
This commit is contained in:
parent
894795616c
commit
3202aa73b4
2
sf-ui/.gitignore
vendored
Normal file
2
sf-ui/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/node_modules
|
||||
/dist
|
44
sf-ui/src/api/system/application.js
Normal file
44
sf-ui/src/api/system/application.js
Normal file
@ -0,0 +1,44 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询应用列列表
|
||||
export function getListApi(query) {
|
||||
return request({
|
||||
url: '/index/list/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询应用列详细
|
||||
export function getListDetail(id) {
|
||||
return request({
|
||||
url: '/index/list/' + id,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 新增应用列
|
||||
export function addList(data) {
|
||||
return request({
|
||||
url: '/index/list',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改应用列
|
||||
export function updateList(data) {
|
||||
return request({
|
||||
url: '/index/list',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除应用列
|
||||
export function delList(id) {
|
||||
return request({
|
||||
url: '/index/list/' + id,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
@ -1,5 +1,8 @@
|
||||
<template>
|
||||
<div class="navbar">
|
||||
<!-- <div style="float: left; line-height: 50px;" class="sidebar-logo-container">
|
||||
<Logo :collapse="true" />
|
||||
</div> -->
|
||||
<hamburger id="hamburger-container" :is-active="sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" />
|
||||
|
||||
<breadcrumb id="breadcrumb-container" class="breadcrumb-container" v-if="!topNav"/>
|
||||
@ -9,19 +12,19 @@
|
||||
<template v-if="device!=='mobile'">
|
||||
<search id="header-search" class="right-menu-item" />
|
||||
|
||||
<el-tooltip content="源码地址" effect="dark" placement="bottom">
|
||||
<!-- <el-tooltip content="源码地址" effect="dark" placement="bottom">
|
||||
<ruo-yi-git id="ruoyi-git" class="right-menu-item hover-effect" />
|
||||
</el-tooltip>
|
||||
|
||||
<el-tooltip content="文档地址" effect="dark" placement="bottom">
|
||||
<ruo-yi-doc id="ruoyi-doc" class="right-menu-item hover-effect" />
|
||||
</el-tooltip>
|
||||
</el-tooltip> -->
|
||||
|
||||
<screenfull id="screenfull" class="right-menu-item hover-effect" />
|
||||
|
||||
<el-tooltip content="布局大小" effect="dark" placement="bottom">
|
||||
<!-- <el-tooltip content="布局大小" effect="dark" placement="bottom">
|
||||
<size-select id="size-select" class="right-menu-item hover-effect" />
|
||||
</el-tooltip>
|
||||
</el-tooltip> -->
|
||||
|
||||
</template>
|
||||
|
||||
@ -48,6 +51,7 @@
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import Logo from "../components/Sidebar/Logo";
|
||||
import Breadcrumb from '@/components/Breadcrumb'
|
||||
import TopNav from '@/components/TopNav'
|
||||
import Hamburger from '@/components/Hamburger'
|
||||
@ -59,6 +63,7 @@ import RuoYiDoc from '@/components/RuoYi/Doc'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Logo,
|
||||
Breadcrumb,
|
||||
TopNav,
|
||||
Hamburger,
|
||||
|
@ -111,7 +111,7 @@ export default {
|
||||
value: val
|
||||
})
|
||||
if (!val) {
|
||||
this.$store.dispatch('app/toggleSideBarHide', false);
|
||||
// this.$store.dispatch('app/toggleSideBarHide', false);
|
||||
this.$store.commit("SET_SIDEBAR_ROUTERS", this.$store.state.permission.defaultRoutes);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
export { default as AppMain } from './AppMain'
|
||||
export { default as Navbar } from './Navbar'
|
||||
export { default as NavbarNew } from './NavbarNew'
|
||||
export { default as Settings } from './Settings'
|
||||
export { default as Sidebar } from './Sidebar/index.vue'
|
||||
export { default as TagsView } from './TagsView/index.vue'
|
||||
|
@ -24,11 +24,15 @@ router.beforeEach((to, from, next) => {
|
||||
// 判断当前用户是否已拉取完user_info信息
|
||||
store.dispatch('GetInfo').then(() => {
|
||||
isRelogin.show = false
|
||||
store.dispatch('GenerateRoutes').then(accessRoutes => {
|
||||
// 根据roles权限生成可访问的路由表
|
||||
router.addRoutes(accessRoutes) // 动态添加可访问路由表
|
||||
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成
|
||||
})
|
||||
if (to.path === '/index') {
|
||||
next()
|
||||
} else {
|
||||
store.dispatch('GenerateRoutes').then(accessRoutes => {
|
||||
// 根据roles权限生成可访问的路由表
|
||||
router.addRoutes(accessRoutes) // 动态添加可访问路由表
|
||||
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成
|
||||
})
|
||||
}
|
||||
}).catch(err => {
|
||||
store.dispatch('LogOut').then(() => {
|
||||
Message.error(err)
|
||||
|
@ -68,7 +68,7 @@ export const constantRoutes = [
|
||||
children: [
|
||||
{
|
||||
path: 'index',
|
||||
component: () => import('@/views/index'),
|
||||
component: () => import('@/views/indexNew'),
|
||||
name: 'Index',
|
||||
meta: { title: '首页', icon: 'dashboard', affix: true }
|
||||
}
|
||||
|
115
sf-ui/src/views/components/home/card.vue
Normal file
115
sf-ui/src/views/components/home/card.vue
Normal file
@ -0,0 +1,115 @@
|
||||
<template>
|
||||
<el-row v-loading="loading" :gutter="20">
|
||||
<el-col v-for="item in list" :key="item.id" :span="8" class="card-col">
|
||||
<el-card :body-style="{ padding: '15px 0 0 0' }" shadow="hover">
|
||||
<div class="card-conainer">
|
||||
<div class="card-head">
|
||||
<el-link :underline="false" @click="$emit('del', item)">删除</el-link>
|
||||
</div>
|
||||
<div class="card-center">
|
||||
<image-preview :src="item.picture" :width="60" :height="60"/>
|
||||
<!-- <el-avatar
|
||||
class="icon"
|
||||
:src="'/dev-api/'+item.picture"
|
||||
fit="cover"
|
||||
:size="100"
|
||||
/> -->
|
||||
<div class="content ml20">
|
||||
<div class="title">{{item.appName}}</div>
|
||||
<div class="time">{{item.createTime}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<p class="desc">{{item.appDesc}}</p>
|
||||
</div>
|
||||
<div class="card-foot">
|
||||
<el-button class="card-btn" @click="$emit('update', item)">编辑</el-button>
|
||||
<el-divider class="card-divider" direction="vertical"></el-divider>
|
||||
<el-button class="card-btn" @click="$emit('enter', item)">进入</el-button>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
list: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
defImg: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.card-col {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.card-conainer {
|
||||
padding: 0 20px;
|
||||
.card-head {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.card-center {
|
||||
display: flex;
|
||||
.el-image {
|
||||
width: 60px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
.content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
.title {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.time {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
.desc {
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
height: 38px;
|
||||
display: -webkit-box; /* 兼容webkit内核浏览器 */
|
||||
-webkit-line-clamp: 2; /* 最多显示两行 */
|
||||
-webkit-box-orient: vertical; /* 设置或限制在一个块状元素显示的内容的排列方式 */
|
||||
overflow: hidden; /* 隐藏超出部分 */
|
||||
text-overflow: ellipsis; /* 显示省略号 */
|
||||
}
|
||||
}
|
||||
.card-foot {
|
||||
display: flex;
|
||||
border-top: 1px solid #DCDFE6;
|
||||
.card-btn {
|
||||
flex: 1;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
height: 50px;
|
||||
}
|
||||
.card-divider {
|
||||
height: 50px;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
60
sf-ui/src/views/components/home/list.vue
Normal file
60
sf-ui/src/views/components/home/list.vue
Normal file
@ -0,0 +1,60 @@
|
||||
<template>
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column type="index" width="55" align="center" />
|
||||
<el-table-column label="项目名" width="300" prop="appName" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="项目图片" width="100" prop="picture">
|
||||
<template slot-scope="scope">
|
||||
<image-preview :src="scope.row.picture" :width="50" :height="50"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="项目描述" prop="appDesc" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="创建时间" width="200" prop="createTime" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="操作" width="200" class-name="small-padding fixed-width">
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-edit"
|
||||
@click="$emit('enter', scope.row)"
|
||||
>进入</el-button>
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-edit"
|
||||
@click="$emit('update', scope.row)"
|
||||
>编辑</el-button>
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-delete"
|
||||
@click="$emit('del', scope.row)"
|
||||
>删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
list: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
291
sf-ui/src/views/indexNew.vue
Normal file
291
sf-ui/src/views/indexNew.vue
Normal file
@ -0,0 +1,291 @@
|
||||
<template>
|
||||
<div class="app-container home">
|
||||
|
||||
<div class="home-header">
|
||||
<div class="home-header-left">
|
||||
<h1>项目列表</h1>
|
||||
</div>
|
||||
<div class="home-header-right">
|
||||
<el-input
|
||||
v-model="queryParams.appName"
|
||||
class="search-input mr10"
|
||||
placeholder="请输入关键字"
|
||||
clearable
|
||||
@keyup.enter.native="getList"
|
||||
>
|
||||
<el-button slot="append" icon="el-icon-search" @click="getList"></el-button>
|
||||
</el-input>
|
||||
<el-button-group class="mr10">
|
||||
<el-button :type="curType === 'card' ? 'primary' : 'default'" icon="el-icon-postcard" @click="checkType('card')">卡片</el-button>
|
||||
<el-button :type="curType === 'list' ? 'primary' : 'default'" icon="el-icon-notebook-2" @click="checkType('list')">列表</el-button>
|
||||
</el-button-group>
|
||||
<el-button type="primary" @click="handleAdd(null)">新增项目</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <transition name="slide-fade"> -->
|
||||
<component :is="curType === 'card' ? 'CardView' : 'ListView'"
|
||||
:list="list"
|
||||
:loading="loading"
|
||||
@update="handleAdd"
|
||||
@del="handleDelete"
|
||||
@enter="handleEnter"
|
||||
/>
|
||||
<pagination
|
||||
v-show="total>0"
|
||||
:total="total"
|
||||
:page.sync="queryParams.pageNum"
|
||||
:limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
<!-- </transition> -->
|
||||
|
||||
<el-dialog :title="dialogTitle" :visible.sync="dialogFormVisible" center :before-close="dialogBeforeClose">
|
||||
<el-form ref="form" :model="editForm" :rules="rules">
|
||||
<el-form-item label="应用名称" label-width="120px" prop="appName">
|
||||
<el-input v-model="editForm.appName" autocomplete="off"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="应用描述" label-width="120px" prop="appDesc">
|
||||
<el-input v-model="editForm.appDesc" autocomplete="off" type="textarea" :rows="3"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="上传图片" label-width="120px" prop="picture">
|
||||
<ImageUpload v-model="editForm.picture" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="dialogClose">取 消</el-button>
|
||||
<el-button type="primary" :loading="submitLoading" @click="submitForm">保 存</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import path from 'path'
|
||||
import { isExternal } from '@/utils/validate'
|
||||
import CardView from './components/home/card';
|
||||
import ListView from './components/home/list';
|
||||
import { getListApi, getListDetail, delList, addList, updateList } from "@/api/system/application";
|
||||
export default {
|
||||
name: "Index",
|
||||
components: {
|
||||
CardView,
|
||||
ListView,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
curType: 'card',
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
},
|
||||
total: 0,
|
||||
list: [],
|
||||
dialogFormVisible: false,
|
||||
dialogTitle: '新增应用',
|
||||
// 表单校验
|
||||
rules: {
|
||||
appName: [
|
||||
{ required: true, message: "应用名称不能为空", trigger: "blur" }
|
||||
],
|
||||
appDesc: [
|
||||
{ required: true, message: "应用描述不能为空", trigger: "blur" }
|
||||
],
|
||||
},
|
||||
editForm: {
|
||||
id: null,
|
||||
appName: '',
|
||||
appDesc: '',
|
||||
picture: '',
|
||||
},
|
||||
submitLoading: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
routes() {
|
||||
return this.$store.state.permission.addRoutes;
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.$store.dispatch('app/toggleSideBarHide', true);
|
||||
this.getList();
|
||||
},
|
||||
watch: {
|
||||
$route(route) {
|
||||
this.$store.dispatch('app/toggleSideBarHide', route.path === '/index');
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/** 查询应用列列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
getListApi(this.queryParams).then(response => {
|
||||
console.log(response)
|
||||
this.list = response.rows;
|
||||
this.total = response.total;
|
||||
this.loading = false;
|
||||
}).catch(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
checkType(type) {
|
||||
this.curType = type;
|
||||
},
|
||||
dialogBeforeClose(done) {
|
||||
this.$refs.form.resetFields();
|
||||
done();
|
||||
},
|
||||
dialogClose() {
|
||||
this.$refs.form.resetFields();
|
||||
this.dialogFormVisible = false;
|
||||
},
|
||||
// getList(params) {
|
||||
// return new Promise((resolve, reject) => {
|
||||
// setTimeout(() => {
|
||||
// const num = Math.floor(Math.random() * 10);
|
||||
// const ls = new Array(num).fill(0).map((v,i) => {
|
||||
// return {
|
||||
// id: Math.random(),
|
||||
// name: `第${i}个项目名称`,
|
||||
// desc: `第${i}个项目,是一个排名第${i}的项目,是一个四川的项目,同时也是${i}行业相关的项目,并且还是一个充满智慧的项目。`,
|
||||
// createTime: `2024-04-${i + 1}`,
|
||||
// img: "https://img.yzcdn.cn/vant/cat.jpeg",
|
||||
// };
|
||||
// });
|
||||
// return resolve({
|
||||
// code: 200,
|
||||
// data: {
|
||||
// list: ls,
|
||||
// total: 86,
|
||||
// }
|
||||
// });
|
||||
// }, 1000);
|
||||
// });
|
||||
// },
|
||||
async handleEnter(row) {
|
||||
// TODO
|
||||
// 此处需要储存项目id,供后续的网关服务、部署服务使用
|
||||
let routes = this.routes;
|
||||
if (this.routes.length === 0) {
|
||||
routes = await this.$store.dispatch('GenerateRoutes');
|
||||
this.$router.addRoutes(routes)
|
||||
}
|
||||
const [first, secound] = routes;
|
||||
const route = this.resolvePath(first, first.path);
|
||||
this.$router.push(route);
|
||||
},
|
||||
resolvePath(route, basepath) {
|
||||
if (isExternal(basepath)) {
|
||||
return basepath;
|
||||
}
|
||||
const childRoute = route.children && route.children[0];
|
||||
if (childRoute) {
|
||||
return path.resolve(basepath, childRoute.path);
|
||||
}
|
||||
return path.resolve(basepath);
|
||||
},
|
||||
handleAdd(row) {
|
||||
if (!row) {
|
||||
this.editForm = {
|
||||
id: null,
|
||||
appName: '',
|
||||
appDesc: '',
|
||||
picture: '',
|
||||
}
|
||||
this.dialogTitle = '新增应用';
|
||||
} else {
|
||||
this.editForm = {
|
||||
id: row.id,
|
||||
appName: row.appName,
|
||||
appDesc: row.appDesc,
|
||||
picture: row.picture,
|
||||
}
|
||||
this.dialogTitle = '编辑应用';
|
||||
}
|
||||
this.dialogFormVisible = true;
|
||||
},
|
||||
async handleDelete(row) {
|
||||
this.$confirm('此操作将永久删除该应用, 是否继续?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
beforeClose: (action, instance, done) => {
|
||||
if (action === 'confirm') {
|
||||
instance.confirmButtonLoading = true;
|
||||
this.delFunc(row.id).then(done).finally(() => {
|
||||
instance.confirmButtonLoading = false;
|
||||
})
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
async delFunc(id) {
|
||||
try {
|
||||
const res = await delList(id);
|
||||
this.$message.success('删除成功');
|
||||
this.getList();
|
||||
return res;
|
||||
} catch(e) {
|
||||
this.$message.error('删除失败');
|
||||
return Promise.reject(e);
|
||||
}
|
||||
},
|
||||
/** 提交按钮 */
|
||||
async submitForm() {
|
||||
await this.$refs["form"].validate();
|
||||
|
||||
const data = Object.assign({},this.editForm);
|
||||
const request = data.id ? updateList : addList;
|
||||
const msg = data.id ? '修改' : '新增';
|
||||
this.submitLoading = true;
|
||||
try {
|
||||
const { code } = await request(data);
|
||||
this.$modal.msgSuccess(`${msg}成功!`);
|
||||
this.submitLoading = false;
|
||||
this.getList();
|
||||
this.dialogClose();
|
||||
} catch (error) {
|
||||
this.$modal.msgSuccess(`${msg}成功!`);
|
||||
this.submitLoading = false;
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.top-btn {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.home-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
.search-input {
|
||||
width: 240px;
|
||||
}
|
||||
}
|
||||
/* slide-fade 过渡效果的 CSS 类定义 */
|
||||
.slide-fade-enter-active,
|
||||
.slide-fade-leave-active {
|
||||
transition: all 0.8s ease;
|
||||
}
|
||||
.slide-fade-leave-active {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.slide-fade-enter-from,
|
||||
.slide-fade-leave-to {
|
||||
transform: translateX(-100%); /* 左滑出效果,若需右滑入则改为 translateX(100%) */
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.slide-fade-enter-to,
|
||||
.slide-fade-leave-from {
|
||||
transform: translateX(0);
|
||||
opacity: 1;
|
||||
}
|
||||
</style>
|
Loading…
x
Reference in New Issue
Block a user