init commit & 混料程序模块
This commit is contained in:
29
src/views/atomViews/ListView.vue
Normal file
29
src/views/atomViews/ListView.vue
Normal file
@@ -0,0 +1,29 @@
|
||||
<!-- 这里单纯的配置表格页就好了-->
|
||||
<template>
|
||||
<div class="full-page w-full bg-slate-200">
|
||||
<BaseListTable :over-all="tableConfig.overAll" :table-config="tableConfig.props" :table-data="tableConfig.data" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// TODO:
|
||||
// 1. ListView 相关
|
||||
import BaseListTable from '@/components/BaseListTable.vue';
|
||||
|
||||
export default {
|
||||
name: 'ListView',
|
||||
components: { BaseListTable },
|
||||
props: {
|
||||
tableConfig: {
|
||||
type: Object,
|
||||
default: () => ({ props: [], data: [], overAll: undefined }),
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
methods: {},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
20
src/views/atomViews/ListViewWithDetail.vue
Normal file
20
src/views/atomViews/ListViewWithDetail.vue
Normal file
@@ -0,0 +1,20 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- 用于展示 http://rp.picaiba.com/am/2022-12-08/#id=l1p50r&p=%E6%96%B0%E5%A2%9E_%E7%BC%96%E8%BE%91_7&g=1 这样的页面 -->
|
||||
<!-- 1.详情字段较多
|
||||
2.展示列表
|
||||
3.列表和详情字段,需要分为两个或多个 tag(比如: 详情字段+检测工艺明细列表+包装工艺明细列表), 可点击在同一个页面切换 -->
|
||||
|
||||
<!-- 要有 只读模式 配置 -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
export default { name: '', props:{}, data() {return {}}, created() {}, mounted() {}, methods: {}}
|
||||
</script>
|
||||
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
17
src/views/atomViews/ListViewWithDetailSimple.vue
Normal file
17
src/views/atomViews/ListViewWithDetailSimple.vue
Normal file
@@ -0,0 +1,17 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- 用于展示 http://rp.picaiba.com/am/2022-12-08/#id=8eeu8x&p=%E6%9F%A5%E7%9C%8B%E6%A3%80%E6%B5%8B%E5%B7%A5%E8%89%BA&g=1 这样的页面 -->
|
||||
<!-- 1.详情字段较少
|
||||
2.展示列表 -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
export default { name: '', props:{}, data() {return {}}, created() {}, mounted() {}, methods: {}}
|
||||
</script>
|
||||
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
229
src/views/atomViews/ListViewWithHead.vue
Normal file
229
src/views/atomViews/ListViewWithHead.vue
Normal file
@@ -0,0 +1,229 @@
|
||||
<!-- 表格页加上搜索条件 -->
|
||||
<template>
|
||||
<div class="bg-white rounded-lg shadow-lg w-full h-full p-5">
|
||||
<!-- <head-form :form-config="headFormConfig" @headBtnClick="btnClick" /> -->
|
||||
<BaseSearchForm :head-config="headConfig" @btn-click="handleBtnClick" />
|
||||
|
||||
<BaseListTable
|
||||
:table-config="tableConfig.table"
|
||||
:column-config="tableConfig.column"
|
||||
:table-data="dataList"
|
||||
@operate-event="handleOperate"
|
||||
/>
|
||||
|
||||
<el-pagination
|
||||
class="mt-5 flex justify-end"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handlePageChange"
|
||||
:current-page.sync="page"
|
||||
:page-sizes="[1, 5, 10, 20, 50, 100]"
|
||||
:page-size="size"
|
||||
:total="totalPage"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
></el-pagination>
|
||||
<!-- :current-page.sync="currentPage"
|
||||
:page-size.sync="pageSize" -->
|
||||
|
||||
<base-dialog
|
||||
ref="edit-dialog"
|
||||
v-if="dialogVisible"
|
||||
:configs="dialogConfigs"
|
||||
@refreshDataList="getList"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import BaseListTable from "@/components/BaseListTable.vue";
|
||||
import BaseSearchForm from "@/components/BaseSearchForm.vue";
|
||||
import BaseDialog from "@/components/DialogWithMenu.vue";
|
||||
|
||||
export default {
|
||||
name: "ListViewWithHead",
|
||||
components: { BaseSearchForm, BaseListTable, BaseDialog },
|
||||
props: {
|
||||
tableConfig: {
|
||||
type: Object,
|
||||
default: () => ({
|
||||
/** 列配置, 即 props **/ columnConfig: [],
|
||||
/** 表格整体配置 */ tableConfig: undefined,
|
||||
}),
|
||||
},
|
||||
headConfig: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
/** 请求page接口的时候有些字段是必填的,没有会报500,把相关字段名传入这个prop: */
|
||||
listQueryExtra: {
|
||||
type: Array,
|
||||
default: () => ["key"],
|
||||
},
|
||||
initDataWhenLoad: { type: Boolean, default: true },
|
||||
/** dialog configs 或许可以从 tableConfig 计算出来 computed... */
|
||||
dialogConfigs: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dialogVisible: false,
|
||||
topBtnConfig: null,
|
||||
totalPage: 100,
|
||||
page: 1,
|
||||
size: 20, // 默认20
|
||||
dataList: [],
|
||||
};
|
||||
},
|
||||
inject: ["urls"],
|
||||
mounted() {
|
||||
this.initDataWhenLoad && this.getList();
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 转换服务器数据的中间层
|
||||
* 为了抹平真实服务器数据和我本地的测试服务器数据的差异
|
||||
**/
|
||||
prehandle_data(list) {
|
||||
/** 根据具体情况修改 */
|
||||
list.forEach((data) => {
|
||||
data.id = data._id;
|
||||
delete data._id;
|
||||
});
|
||||
return list;
|
||||
},
|
||||
|
||||
/** 获取 列表数据 */
|
||||
getList(listQuery = null) {
|
||||
if (!listQuery) {
|
||||
listQuery = {};
|
||||
listQuery.page = this.page;
|
||||
listQuery.size = this.size;
|
||||
}
|
||||
|
||||
console.log("[before http] url: ", this.urls);
|
||||
|
||||
const params = {
|
||||
page: listQuery.page,
|
||||
limit: listQuery.size,
|
||||
};
|
||||
if (this.listQueryExtra.length) {
|
||||
this.listQueryExtra.map((name) => {
|
||||
params[name] = "";
|
||||
});
|
||||
}
|
||||
this.$http
|
||||
.get(this.urls.page, {
|
||||
params,
|
||||
})
|
||||
.then(({ data: res }) => {
|
||||
console.log("[http response] res is: ", res);
|
||||
|
||||
// page 场景:
|
||||
if ("list" in res.data) {
|
||||
// real env:
|
||||
this.dataList = res.data.list.map((item) => ({
|
||||
...item,
|
||||
id: item._id ?? item.id,
|
||||
}));
|
||||
// this.dataList = res.data.records;
|
||||
this.totalPage = res.data.total;
|
||||
} else if ("records" in res.data) {
|
||||
// dev env:
|
||||
this.dataList = res.data.records.map((item) => ({
|
||||
...item,
|
||||
id: item._id ?? item.id,
|
||||
}));
|
||||
// this.dataList = res.data.records;
|
||||
this.totalPage = res.data.total;
|
||||
} else {
|
||||
this.dataList.splice(0);
|
||||
this.totalPage = 0;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/** 处理 HeadForm 的操作 */
|
||||
handleHeadformOperate(payload) {
|
||||
// 查询,导出,导入,等等
|
||||
console.log("headform operate: ", payload);
|
||||
},
|
||||
|
||||
/** 处理 表格操作 */
|
||||
handleOperate({ type, data }) {
|
||||
console.log("payload", type, data);
|
||||
// 编辑、删除、跳转路由、打开弹窗(动态component)都可以在配置里加上 url
|
||||
// payload: { type: string, data: string | number | object }
|
||||
switch (type) {
|
||||
case "delete": {
|
||||
// 确认是否删除
|
||||
return this.$confirm(`是否删除条目: ${data}`, "提示", {
|
||||
confirmButtonText: "确认",
|
||||
cancelButtonText: "我再想想",
|
||||
type: "warning",
|
||||
})
|
||||
.then(() => {
|
||||
// this.$http.delete(this.urls.base + `/${data}`).then((res) => {
|
||||
this.$http({
|
||||
url: this.urls.base,
|
||||
method: "DELETE",
|
||||
data: [`${data}`],
|
||||
}).then(({ data: res }) => {
|
||||
if (res.code === 0) {
|
||||
this.$message.success("删除成功!");
|
||||
|
||||
this.page = 1;
|
||||
this.size = 10;
|
||||
this.getList();
|
||||
}
|
||||
});
|
||||
})
|
||||
.catch((err) => {});
|
||||
}
|
||||
case "edit": {
|
||||
this.openDialog(data); /** data is ==> id */
|
||||
break;
|
||||
}
|
||||
case "view-detail-action":
|
||||
this.openDialog(data, true);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
handleBtnClick({ btnName, payload }) {
|
||||
console.log("[search] form handleBtnClick", btnName, payload);
|
||||
switch (btnName) {
|
||||
case "新增":
|
||||
this.openDialog();
|
||||
break;
|
||||
case "查询":
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
/** 导航器的操作 */
|
||||
handleSizeChange(val) {
|
||||
// val 是新值
|
||||
this.page = 1;
|
||||
this.size = val;
|
||||
this.getList();
|
||||
},
|
||||
|
||||
handlePageChange(val) {
|
||||
// val 是新值
|
||||
this.getList();
|
||||
},
|
||||
|
||||
/** 打开对话框 */
|
||||
openDialog(row_id, detail_mode) {
|
||||
this.dialogVisible = true;
|
||||
|
||||
this.$nextTick(() => {
|
||||
this.$refs["edit-dialog"].init(/** some args... */ row_id, detail_mode);
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
1
src/views/atomViews/README.md
Normal file
1
src/views/atomViews/README.md
Normal file
@@ -0,0 +1 @@
|
||||
主要的视图由 atomViews 里的通用视图组成
|
||||
96
src/views/main-content.vue
Normal file
96
src/views/main-content.vue
Normal file
@@ -0,0 +1,96 @@
|
||||
<template>
|
||||
<main :class="['aui-content', { 'aui-content--tabs': $route.meta.isTab }]">
|
||||
<!-- tab展示内容 -->
|
||||
<template v-if="$route.meta.isTab">
|
||||
<el-dropdown class="aui-content--tabs-tools">
|
||||
<i class="el-icon-arrow-down"></i>
|
||||
<el-dropdown-menu slot="dropdown" :show-timeout="0">
|
||||
<el-dropdown-item @click.native="tabRemoveHandle($store.state.contentTabsActiveName)">{{ $t('contentTabs.closeCurrent') }}</el-dropdown-item>
|
||||
<el-dropdown-item @click.native="tabsCloseOtherHandle()">{{ $t('contentTabs.closeOther') }}</el-dropdown-item>
|
||||
<el-dropdown-item @click.native="tabsCloseAllHandle()">{{ $t('contentTabs.closeAll') }}</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
<el-tabs v-model="$store.state.contentTabsActiveName" @tab-click="tabSelectedHandle" @tab-remove="tabRemoveHandle">
|
||||
<el-tab-pane
|
||||
v-for="item in $store.state.contentTabs"
|
||||
:key="item.name"
|
||||
:name="item.name"
|
||||
:label="item.title"
|
||||
:closable="item.name !== 'home'"
|
||||
:class="{ 'is-iframe': tabIsIframe(item.iframeURL) }">
|
||||
<template v-if="item.name === 'home'">
|
||||
<svg slot="label" class="icon-svg aui-content--tabs-icon-nav" aria-hidden="true"><use xlink:href="#icon-home"></use></svg>
|
||||
</template>
|
||||
<iframe v-if="tabIsIframe(item.iframeURL)" :src="item.iframeURL" width="100%" height="100%" frameborder="0" scrolling="yes"></iframe>
|
||||
<keep-alive v-else>
|
||||
<router-view v-if="item.name === $store.state.contentTabsActiveName" />
|
||||
</keep-alive>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</template>
|
||||
<!-- 其他方式, 展示内容 -->
|
||||
<template v-else>
|
||||
<keep-alive>
|
||||
<router-view />
|
||||
</keep-alive>
|
||||
</template>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { isURL } from '@/utils/validate'
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// tabs, 是否通过iframe展示
|
||||
tabIsIframe (url) {
|
||||
return isURL(url)
|
||||
},
|
||||
// tabs, 选中tab
|
||||
tabSelectedHandle (tab) {
|
||||
tab = this.$store.state.contentTabs.filter(item => item.name === tab.name)[0]
|
||||
if (tab) {
|
||||
this.$router.push({
|
||||
'name': tab.name,
|
||||
'params': { ...tab.params },
|
||||
'query': { ...tab.query }
|
||||
})
|
||||
}
|
||||
},
|
||||
// tabs, 删除tab
|
||||
tabRemoveHandle (tabName) {
|
||||
if (tabName === 'home') {
|
||||
return false
|
||||
}
|
||||
this.$store.state.contentTabs = this.$store.state.contentTabs.filter(item => item.name !== tabName)
|
||||
if (this.$store.state.contentTabs.length <= 0) {
|
||||
this.$store.state.sidebarMenuActiveName = this.$store.state.contentTabsActiveName = 'home'
|
||||
return false
|
||||
}
|
||||
// 当前选中tab被删除
|
||||
if (tabName === this.$store.state.contentTabsActiveName) {
|
||||
let tab = this.$store.state.contentTabs[this.$store.state.contentTabs.length - 1]
|
||||
this.$router.push({
|
||||
name: tab.name,
|
||||
params: { ...tab.params },
|
||||
query: { ...tab.query }
|
||||
})
|
||||
}
|
||||
},
|
||||
// tabs, 关闭其它
|
||||
tabsCloseOtherHandle () {
|
||||
this.$store.state.contentTabs = this.$store.state.contentTabs.filter(item => {
|
||||
return item.name === 'home' || item.name === this.$store.state.contentTabsActiveName
|
||||
})
|
||||
},
|
||||
// tabs, 关闭全部
|
||||
tabsCloseAllHandle () {
|
||||
this.$store.state.contentTabs = this.$store.state.contentTabs.filter(item => item.name === 'home')
|
||||
this.$router.push({ name: 'home' })
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
17
src/views/main-footer.vue
Normal file
17
src/views/main-footer.vue
Normal file
@@ -0,0 +1,17 @@
|
||||
<template>
|
||||
<div class="footerbar">
|
||||
© 中建材智能自动化研究院有限公司
|
||||
<!-- © {{ 'copyright.company' | i18nFilter }} -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.footerbar{
|
||||
width: 100%;
|
||||
height: 20px;
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
color: #C7C7C7;
|
||||
margin: 5px 0;
|
||||
}
|
||||
</style>
|
||||
97
src/views/main-navbar-update-password.vue
Normal file
97
src/views/main-navbar-update-password.vue
Normal file
@@ -0,0 +1,97 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:visible.sync="visible"
|
||||
:title="$t('updatePassword.title')"
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
:append-to-body="true">
|
||||
<el-form :model="dataForm" :rules="dataRule" ref="dataForm" @keyup.enter.native="dataFormSubmitHandle()" label-width="120px">
|
||||
<el-form-item :label="$t('updatePassword.username')">
|
||||
<span>{{ $store.state.user.name }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item prop="password" :label="$t('updatePassword.password')">
|
||||
<el-input v-model="dataForm.password" type="password" :placeholder="$t('updatePassword.password')"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="newPassword" :label="$t('updatePassword.newPassword')">
|
||||
<el-input v-model="dataForm.newPassword" type="password" :placeholder="$t('updatePassword.newPassword')"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="confirmPassword" :label="$t('updatePassword.confirmPassword')">
|
||||
<el-input v-model="dataForm.confirmPassword" type="password" :placeholder="$t('updatePassword.confirmPassword')"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template slot="footer">
|
||||
<el-button @click="visible = false">{{ $t('cancel') }}</el-button>
|
||||
<el-button type="primary" @click="dataFormSubmitHandle()">{{ $t('confirm') }}</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import debounce from 'lodash/debounce'
|
||||
import { clearLoginInfo } from '@/utils'
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
visible: false,
|
||||
dataForm: {
|
||||
password: '',
|
||||
newPassword: '',
|
||||
confirmPassword: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
dataRule () {
|
||||
var validateConfirmPassword = (rule, value, callback) => {
|
||||
if (this.dataForm.newPassword !== value) {
|
||||
return callback(new Error(this.$t('updatePassword.validate.confirmPassword')))
|
||||
}
|
||||
callback()
|
||||
}
|
||||
return {
|
||||
password: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
||||
],
|
||||
newPassword: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
||||
],
|
||||
confirmPassword: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' },
|
||||
{ validator: validateConfirmPassword, trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
init () {
|
||||
this.visible = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs['dataForm'].resetFields()
|
||||
})
|
||||
},
|
||||
// 表单提交
|
||||
dataFormSubmitHandle: debounce(function () {
|
||||
this.$refs['dataForm'].validate((valid) => {
|
||||
if (!valid) {
|
||||
return false
|
||||
}
|
||||
this.$http.put('/sys/user/password', this.dataForm).then(({ data: res }) => {
|
||||
if (res.code !== 0) {
|
||||
return this.$message.error(res.msg)
|
||||
}
|
||||
this.$message({
|
||||
message: this.$t('prompt.success'),
|
||||
type: 'success',
|
||||
duration: 500,
|
||||
onClose: () => {
|
||||
this.visible = false
|
||||
clearLoginInfo()
|
||||
this.$router.replace({ name: 'login' })
|
||||
}
|
||||
})
|
||||
}).catch(() => {})
|
||||
})
|
||||
}, 1000, { 'leading': true, 'trailing': false })
|
||||
}
|
||||
}
|
||||
</script>
|
||||
107
src/views/main-navbar.vue
Normal file
107
src/views/main-navbar.vue
Normal file
@@ -0,0 +1,107 @@
|
||||
<!--
|
||||
* @Author: zwq
|
||||
* @Date: 2022-08-22 14:57:51
|
||||
* @LastEditors: zwq
|
||||
* @LastEditTime: 2023-01-06 09:44:17
|
||||
* @Description:
|
||||
-->
|
||||
<template>
|
||||
<nav class="aui-navbar" :class="`aui-navbar--${$store.state.navbarLayoutType}`">
|
||||
<div class="aui-navbar__header">
|
||||
<h1 class="aui-navbar__brand" @click="$router.push({ name: 'home' })">
|
||||
<a class="aui-navbar__brand-lg" href="javascript:;">{{ $t('brand.lg') }}</a>
|
||||
<a class="aui-navbar__brand-mini" href="javascript:;">{{ $t('brand.mini') }}</a>
|
||||
</h1>
|
||||
</div>
|
||||
<div class="aui-navbar__body">
|
||||
<el-menu class="aui-navbar__menu mr-auto" mode="horizontal">
|
||||
<el-menu-item index="1" @click="$store.state.sidebarFold = !$store.state.sidebarFold">
|
||||
<svg class="icon-svg aui-navbar__icon-menu aui-navbar__icon-menu--switch" aria-hidden="true"><use xlink:href="#icon-outdent"></use></svg>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="2" @click="refresh()">
|
||||
<svg class="icon-svg aui-navbar__icon-menu aui-navbar__icon-menu--refresh" aria-hidden="true"><use xlink:href="#icon-sync"></use></svg>
|
||||
</el-menu-item>
|
||||
</el-menu>
|
||||
<el-menu class="aui-navbar__menu" mode="horizontal">
|
||||
<el-menu-item index="6" @click="$router.push({ name: 'home' })">
|
||||
<svg class="icon-svg aui-navbar__icon-menu" aria-hidden="true"><use xlink:href="#icon-home"></use></svg>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="4" @click="fullscreenHandle()">
|
||||
<svg class="icon-svg aui-navbar__icon-menu" aria-hidden="true"><use xlink:href="#icon-fullscreen"></use></svg>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="5" class="aui-navbar__avatar">
|
||||
<el-dropdown placement="bottom" :show-timeout="0">
|
||||
<span class="el-dropdown-link">
|
||||
<img src="~@/assets/img/avatar.png">
|
||||
<span>{{ $store.state.user.name }}</span>
|
||||
<i class="el-icon-arrow-down"></i>
|
||||
</span>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item @click.native="updatePasswordHandle()">
|
||||
<svg class="icon-svg aui-content--tabs-icon-nav" aria-hidden="true"><use xlink:href="#修改密码"></use></svg>
|
||||
{{ $t('updatePassword.title') }}</el-dropdown-item>
|
||||
<el-dropdown-item @click.native="logoutHandle()">
|
||||
<svg class="icon-svg aui-content--tabs-icon-nav" aria-hidden="true"><use xlink:href="#tuichu"></use></svg>
|
||||
{{ $t('logout') }}</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</el-menu-item>
|
||||
</el-menu>
|
||||
</div>
|
||||
<!-- 弹窗, 修改密码 -->
|
||||
<update-password v-if="updatePasswordVisible" ref="updatePassword"></update-password>
|
||||
</nav>
|
||||
</template>
|
||||
<script>
|
||||
import screenfull from 'screenfull'
|
||||
import UpdatePassword from './main-navbar-update-password'
|
||||
import { clearLoginInfo } from '@/utils'
|
||||
export default {
|
||||
inject: ['refresh'],
|
||||
data () {
|
||||
return {
|
||||
updatePasswordVisible: false,
|
||||
messageTip: false
|
||||
}
|
||||
},
|
||||
components: {
|
||||
UpdatePassword
|
||||
},
|
||||
methods: {
|
||||
// 全屏
|
||||
fullscreenHandle () {
|
||||
if (!screenfull.enabled) {
|
||||
return this.$message({
|
||||
message: this.$t('fullscreen.prompt'),
|
||||
type: 'warning',
|
||||
duration: 500
|
||||
})
|
||||
}
|
||||
screenfull.toggle()
|
||||
},
|
||||
// 修改密码
|
||||
updatePasswordHandle () {
|
||||
this.updatePasswordVisible = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs.updatePassword.init()
|
||||
})
|
||||
},
|
||||
// 退出
|
||||
logoutHandle () {
|
||||
this.$confirm(this.$t('prompt.info', { 'handle': this.$t('logout') }), this.$t('prompt.title'), {
|
||||
confirmButtonText: this.$t('confirm'),
|
||||
cancelButtonText: this.$t('cancel'),
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
this.$http.post('/logout').then(({ data: res }) => {
|
||||
if (res.code !== 0) {
|
||||
return this.$message.error(res.msg)
|
||||
}
|
||||
clearLoginInfo()
|
||||
this.$router.push({ name: 'login' })
|
||||
}).catch(() => {})
|
||||
}).catch(() => {})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
46
src/views/main-sidebar-sub-menu.vue
Normal file
46
src/views/main-sidebar-sub-menu.vue
Normal file
@@ -0,0 +1,46 @@
|
||||
<!--
|
||||
* @Author: zwq
|
||||
* @Date: 2023-01-04 10:29:40
|
||||
* @LastEditors: zwq
|
||||
* @LastEditTime: 2023-01-05 16:48:04
|
||||
* @Description:
|
||||
-->
|
||||
<template>
|
||||
<el-submenu v-if="menu.children && menu.children.length >= 1" :index="menu.id" :popper-append-to-body="false">
|
||||
<template slot="title">
|
||||
<svg class="icon-svg aui-sidebar__menu-icon" aria-hidden="true"><use :xlink:href="`#${menu.icon}`"></use></svg>
|
||||
<span>{{ menu.name }}</span>
|
||||
</template>
|
||||
<sub-menu v-for="item in menu.children" :key="item.id" :menu="item"></sub-menu>
|
||||
</el-submenu>
|
||||
<el-menu-item v-else :index="menu.id" @click="gotoRouteHandle(menu.id)">
|
||||
<svg class="icon-svg aui-sidebar__menu-icon-son" aria-hidden="true"><use xlink:href="#椭圆形"></use></svg>
|
||||
<!-- <svg class="icon-svg aui-sidebar__menu-icon" aria-hidden="true"><use :xlink:href="`#${menu.icon}`"></use></svg> -->
|
||||
<span>{{ menu.name }}</span>
|
||||
</el-menu-item>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SubMenu from './main-sidebar-sub-menu'
|
||||
export default {
|
||||
name: 'sub-menu',
|
||||
props: {
|
||||
menu: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
components: {
|
||||
SubMenu
|
||||
},
|
||||
methods: {
|
||||
// 通过menuId与动态(菜单)路由进行匹配跳转至指定路由
|
||||
gotoRouteHandle (menuId) {
|
||||
var route = window.SITE_CONFIG['dynamicMenuRoutes'].filter(item => item.meta.menuId === menuId)[0]
|
||||
if (route) {
|
||||
this.$router.push({ name: route.name })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
67
src/views/main-sidebar.vue
Normal file
67
src/views/main-sidebar.vue
Normal file
@@ -0,0 +1,67 @@
|
||||
<!--
|
||||
* @Author: zwq
|
||||
* @Date: 2023-01-04 10:29:40
|
||||
* @LastEditors: zwq
|
||||
* @LastEditTime: 2023-01-05 15:52:01
|
||||
* @Description:
|
||||
-->
|
||||
<template>
|
||||
<aside
|
||||
:class="['aui-sidebar', `aui-sidebar--${$store.state.sidebarLayoutSkin}`]"
|
||||
>
|
||||
<div class="aui-sidebar__inner">
|
||||
<el-menu
|
||||
:default-active="$store.state.sidebarMenuActiveName"
|
||||
:collapse="$store.state.sidebarFold"
|
||||
:unique-opened="true"
|
||||
:collapseTransition="false"
|
||||
class="aui-sidebar__menu"
|
||||
>
|
||||
<sub-menu
|
||||
v-for="menu in $store.state.sidebarMenuList"
|
||||
:key="menu.id"
|
||||
:menu="menu"
|
||||
/>
|
||||
</el-menu>
|
||||
</div>
|
||||
</aside>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SubMenu from "./main-sidebar-sub-menu";
|
||||
export default {
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
components: {
|
||||
SubMenu,
|
||||
},
|
||||
created() {
|
||||
this.$store.state.sidebarMenuList = this.getUnhiddenRoutesListFrom(
|
||||
window.SITE_CONFIG["menuList"]
|
||||
);
|
||||
},
|
||||
methods: {
|
||||
getUnhiddenRoutesListFrom(fullList) {
|
||||
const list = [];
|
||||
if (fullList.length) {
|
||||
fullList.forEach((menu) => {
|
||||
if (menu.sort !== 99) {
|
||||
/** 前后端约定,路由排序值为 99 时不在前端的侧边栏展示该路由 */
|
||||
const newRouteItem = JSON.parse(JSON.stringify(menu));
|
||||
if (menu.children) {
|
||||
newRouteItem.children = this.getUnhiddenRoutesListFrom(
|
||||
menu.children
|
||||
);
|
||||
}
|
||||
list.push(newRouteItem);
|
||||
} else {
|
||||
// console.log(menu.name, '是应该被隐藏的路由')
|
||||
}
|
||||
});
|
||||
}
|
||||
return list;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
121
src/views/main.vue
Normal file
121
src/views/main.vue
Normal file
@@ -0,0 +1,121 @@
|
||||
<template>
|
||||
<div
|
||||
v-loading.fullscreen.lock="loading"
|
||||
:element-loading-text="$t('loading')"
|
||||
:class="['aui-wrapper', { 'aui-sidebar--fold': $store.state.sidebarFold }]"
|
||||
>
|
||||
<template v-if="!loading">
|
||||
<main-navbar />
|
||||
<main-sidebar />
|
||||
<div class="aui-content__wrapper">
|
||||
<main-content v-if="!$store.state.contentIsNeedRefresh" />
|
||||
<main-footer />
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MainNavbar from "./main-navbar";
|
||||
import MainSidebar from "./main-sidebar";
|
||||
import MainContent from "./main-content";
|
||||
import MainFooter from "./main-footer";
|
||||
import debounce from "lodash/debounce";
|
||||
export default {
|
||||
provide() {
|
||||
return {
|
||||
// 刷新
|
||||
refresh() {
|
||||
this.$store.state.contentIsNeedRefresh = true;
|
||||
this.$nextTick(() => {
|
||||
this.$store.state.contentIsNeedRefresh = false;
|
||||
});
|
||||
},
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: true,
|
||||
};
|
||||
},
|
||||
components: {
|
||||
MainNavbar,
|
||||
MainSidebar,
|
||||
MainFooter,
|
||||
MainContent,
|
||||
},
|
||||
watch: {
|
||||
$route: "routeHandle",
|
||||
},
|
||||
created() {
|
||||
this.windowResizeHandle();
|
||||
this.routeHandle(this.$route);
|
||||
Promise.all([this.getUserInfo(), this.getPermissions()]).then(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
// 窗口改变大小
|
||||
windowResizeHandle() {
|
||||
this.$store.state.sidebarFold =
|
||||
document.documentElement["clientWidth"] <= 992 || false;
|
||||
window.addEventListener(
|
||||
"resize",
|
||||
debounce(() => {
|
||||
this.$store.state.sidebarFold =
|
||||
document.documentElement["clientWidth"] <= 992 || false;
|
||||
}, 150)
|
||||
);
|
||||
},
|
||||
// 路由, 监听
|
||||
routeHandle(route) {
|
||||
if (!route.meta.isTab) {
|
||||
return false;
|
||||
}
|
||||
var tab = this.$store.state.contentTabs.filter(
|
||||
(item) => item.name === route.name
|
||||
)[0];
|
||||
if (!tab) {
|
||||
tab = {
|
||||
...window.SITE_CONFIG["contentTabDefault"],
|
||||
...route.meta,
|
||||
name: route.name,
|
||||
params: { ...route.params },
|
||||
query: { ...route.query },
|
||||
};
|
||||
this.$store.state.contentTabs = this.$store.state.contentTabs.concat(
|
||||
tab
|
||||
);
|
||||
}
|
||||
this.$store.state.sidebarMenuActiveName = tab.menuId;
|
||||
this.$store.state.contentTabsActiveName = tab.name;
|
||||
},
|
||||
// 获取当前管理员信息
|
||||
getUserInfo() {
|
||||
return this.$http
|
||||
.get("/sys/user/info")
|
||||
.then(({ data: res }) => {
|
||||
if (res.code !== 0) {
|
||||
return this.$message.error(res.msg);
|
||||
}
|
||||
this.$store.state.user.id = res.data.id;
|
||||
this.$store.state.user.name = res.data.username;
|
||||
this.$store.state.user.superAdmin = res.data.superAdmin;
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
// 获取权限
|
||||
getPermissions() {
|
||||
return this.$http
|
||||
.get("/sys/menu/permissions")
|
||||
.then(({ data: res }) => {
|
||||
if (res.code !== 0) {
|
||||
return this.$message.error(res.msg);
|
||||
}
|
||||
window.SITE_CONFIG["permissions"] = res.data;
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
20
src/views/modules/home.vue
Normal file
20
src/views/modules/home.vue
Normal file
@@ -0,0 +1,20 @@
|
||||
<!--
|
||||
* @Author: zwq
|
||||
* @Date: 2023-01-04 10:29:40
|
||||
* @LastEditors: zwq
|
||||
* @LastEditTime: 2023-01-06 09:45:19
|
||||
* @Description:
|
||||
-->
|
||||
<template>
|
||||
<el-card shadow="never" class="aui-card--fill">
|
||||
<div class="mod-home">
|
||||
基础框架-1
|
||||
</div>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.mod-home {
|
||||
line-height: 1.5;
|
||||
}
|
||||
</style>
|
||||
106
src/views/modules/job/schedule-add-or-update.vue
Normal file
106
src/views/modules/job/schedule-add-or-update.vue
Normal file
@@ -0,0 +1,106 @@
|
||||
<template>
|
||||
<el-dialog :visible.sync="visible" :title="!dataForm.id ? $t('add') : $t('update')" :close-on-click-modal="false" :close-on-press-escape="false">
|
||||
<el-form :model="dataForm" :rules="dataRule" ref="dataForm" @keyup.enter.native="dataFormSubmitHandle()" label-width="120px">
|
||||
<el-form-item prop="beanName" :label="$t('schedule.beanName')">
|
||||
<el-input v-model="dataForm.beanName" :placeholder="$t('schedule.beanNameTips')"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="params" :label="$t('schedule.params')">
|
||||
<el-input v-model="dataForm.params" :placeholder="$t('schedule.params')"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="cronExpression" :label="$t('schedule.cronExpression')">
|
||||
<el-popover v-model="cronPopover">
|
||||
<cron @change="changeCron" @close="cronPopover=false" i18n="cn"></cron>
|
||||
<el-input slot="reference" @click="cronPopover=true" v-model="dataForm.cronExpression" :placeholder="$t('schedule.cronExpressionTips')"></el-input>
|
||||
</el-popover>
|
||||
</el-form-item>
|
||||
<el-form-item prop="remark" :label="$t('schedule.remark')">
|
||||
<el-input v-model="dataForm.remark" :placeholder="$t('schedule.remark')"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template slot="footer">
|
||||
<el-button @click="visible = false">{{ $t('cancel') }}</el-button>
|
||||
<el-button type="primary" @click="dataFormSubmitHandle()">{{ $t('confirm') }}</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import debounce from 'lodash/debounce'
|
||||
import { cron } from 'vue-cron'
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
visible: false,
|
||||
dataForm: {
|
||||
id: '',
|
||||
beanName: '',
|
||||
params: '',
|
||||
cronExpression: '',
|
||||
remark: '',
|
||||
status: 0
|
||||
},
|
||||
cronPopover: false
|
||||
}
|
||||
},
|
||||
components: {
|
||||
cron
|
||||
},
|
||||
computed: {
|
||||
dataRule () {
|
||||
return {
|
||||
beanName: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
||||
],
|
||||
cronExpression: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
init () {
|
||||
this.visible = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs['dataForm'].resetFields()
|
||||
if (this.dataForm.id) {
|
||||
this.getInfo()
|
||||
}
|
||||
})
|
||||
},
|
||||
changeCron (val) {
|
||||
this.dataForm.cronExpression = val
|
||||
},
|
||||
// 获取信息
|
||||
getInfo () {
|
||||
this.$http.get(`/sys/schedule/${this.dataForm.id}`).then(({ data: res }) => {
|
||||
if (res.code !== 0) {
|
||||
return this.$message.error(res.msg)
|
||||
}
|
||||
this.dataForm = res.data
|
||||
}).catch(() => {})
|
||||
},
|
||||
// 表单提交
|
||||
dataFormSubmitHandle: debounce(function () {
|
||||
this.$refs['dataForm'].validate((valid) => {
|
||||
if (!valid) {
|
||||
return false
|
||||
}
|
||||
this.$http[!this.dataForm.id ? 'post' : 'put']('/sys/schedule', this.dataForm).then(({ data: res }) => {
|
||||
if (res.code !== 0) {
|
||||
return this.$message.error(res.msg)
|
||||
}
|
||||
this.$message({
|
||||
message: this.$t('prompt.success'),
|
||||
type: 'success',
|
||||
duration: 500,
|
||||
onClose: () => {
|
||||
this.visible = false
|
||||
this.$emit('refreshDataList')
|
||||
}
|
||||
})
|
||||
}).catch(() => {})
|
||||
})
|
||||
}, 1000, { 'leading': true, 'trailing': false })
|
||||
}
|
||||
}
|
||||
</script>
|
||||
74
src/views/modules/job/schedule-log.vue
Normal file
74
src/views/modules/job/schedule-log.vue
Normal file
@@ -0,0 +1,74 @@
|
||||
<template>
|
||||
<el-dialog :visible.sync="visible" :title="$t('schedule.log')" :close-on-click-modal="false" :close-on-press-escape="false" width="75%">
|
||||
<el-form :inline="true" :model="dataForm" @keyup.enter.native="getDataList()">
|
||||
<el-form-item>
|
||||
<el-input v-model="dataForm.jobId" :placeholder="$t('schedule.jobId')" clearable></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="getDataList()">{{ $t('query') }}</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-table
|
||||
v-loading="dataListLoading"
|
||||
:data="dataList"
|
||||
border
|
||||
@sort-change="dataListSortChangeHandle"
|
||||
height="460"
|
||||
style="width: 100%;">
|
||||
<el-table-column prop="jobId" :label="$t('schedule.jobId')" header-align="center" align="center" width="80"></el-table-column>
|
||||
<el-table-column prop="beanName" :label="$t('schedule.beanName')" header-align="center" align="center"></el-table-column>
|
||||
<el-table-column prop="params" :label="$t('schedule.params')" header-align="center" align="center"></el-table-column>
|
||||
<el-table-column prop="status" :label="$t('schedule.status')" header-align="center" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.status === 1" size="small">{{ $t('schedule.statusLog1') }}</el-tag>
|
||||
<el-tag v-else type="danger" size="small" @click.native="showErrorInfo(scope.row.id)" style="cursor: pointer;">{{ $t('schedule.statusLog0') }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="times" :label="$t('schedule.times')" header-align="center" align="center"></el-table-column>
|
||||
<el-table-column prop="createDate" :label="$t('schedule.createDate')" header-align="center" align="center" width="180"></el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
:current-page="page"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
:page-size="limit"
|
||||
:total="total"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
@size-change="pageSizeChangeHandle"
|
||||
@current-change="pageCurrentChangeHandle">
|
||||
</el-pagination>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import mixinViewModule from '@/mixins/view-module'
|
||||
export default {
|
||||
mixins: [mixinViewModule],
|
||||
data () {
|
||||
return {
|
||||
visible: false,
|
||||
mixinViewModuleOptions: {
|
||||
getDataListURL: '/sys/scheduleLog/page',
|
||||
getDataListIsPage: true
|
||||
},
|
||||
dataForm: {
|
||||
jobId: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
init () {
|
||||
this.visible = true
|
||||
this.getDataList()
|
||||
},
|
||||
// 失败信息
|
||||
showErrorInfo (id) {
|
||||
this.$http.get(`/sys/scheduleLog/${id}`).then(({ data: res }) => {
|
||||
if (res.code !== 0) {
|
||||
return this.$message.error(res.msg)
|
||||
}
|
||||
this.$alert(res.data.error)
|
||||
}).catch(() => {})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
196
src/views/modules/job/schedule.vue
Normal file
196
src/views/modules/job/schedule.vue
Normal file
@@ -0,0 +1,196 @@
|
||||
<template>
|
||||
<el-card shadow="never" class="aui-card--fill">
|
||||
<div class="mod-job__schedule">
|
||||
<el-form :inline="true" :model="dataForm" @keyup.enter.native="getDataList()">
|
||||
<el-form-item>
|
||||
<el-input v-model="dataForm.beanName" :placeholder="$t('schedule.beanName')" clearable></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="getDataList()">{{ $t('query') }}</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button v-if="$hasPermission('sys:schedule:save')" type="primary" @click="addOrUpdateHandle()">{{ $t('add') }}</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button v-if="$hasPermission('sys:schedule:delete')" type="danger" @click="deleteHandle()">{{ $t('deleteBatch') }}</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button v-if="$hasPermission('sys:schedule:pause')" type="danger" @click="pauseHandle()">{{ $t('schedule.pauseBatch') }}</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button v-if="$hasPermission('sys:schedule:resume')" type="danger" @click="resumeHandle()">{{ $t('schedule.resumeBatch') }}</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button v-if="$hasPermission('sys:schedule:run')" type="danger" @click="runHandle()">{{ $t('schedule.runBatch') }}</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button v-if="$hasPermission('sys:schedule:log')" type="success" @click="logHandle()">{{ $t('schedule.log') }}</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-table
|
||||
v-loading="dataListLoading"
|
||||
:data="dataList"
|
||||
border
|
||||
@selection-change="dataListSelectionChangeHandle"
|
||||
@sort-change="dataListSortChangeHandle"
|
||||
style="width: 100%;">
|
||||
<el-table-column type="selection" header-align="center" align="center" width="50"></el-table-column>
|
||||
<el-table-column prop="beanName" :label="$t('schedule.beanName')" header-align="center" align="center"></el-table-column>
|
||||
<el-table-column prop="params" :label="$t('schedule.params')" header-align="center" align="center"></el-table-column>
|
||||
<el-table-column prop="cronExpression" :label="$t('schedule.cronExpression')" header-align="center" align="center"></el-table-column>
|
||||
<el-table-column prop="remark" :label="$t('schedule.remark')" header-align="center" align="center"></el-table-column>
|
||||
<el-table-column prop="status" :label="$t('schedule.status')" sortable="custom" header-align="center" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.status === 1" size="small">{{ $t('schedule.status1') }}</el-tag>
|
||||
<el-tag v-else size="small" type="danger">{{ $t('schedule.status0') }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('handle')" fixed="right" header-align="center" align="center" width="150">
|
||||
<template slot-scope="scope">
|
||||
<el-button v-if="$hasPermission('sys:schedule:update')" type="text" size="small" @click="addOrUpdateHandle(scope.row.id)">{{ $t('update') }}</el-button>
|
||||
<el-button v-if="$hasPermission('sys:schedule:pause')" type="text" size="small" @click="pauseHandle(scope.row.id)">{{ $t('schedule.pause') }}</el-button>
|
||||
<el-button v-if="$hasPermission('sys:schedule:resume')" type="text" size="small" @click="resumeHandle(scope.row.id)">{{ $t('schedule.resume') }}</el-button>
|
||||
<el-button v-if="$hasPermission('sys:schedule:run')" type="text" size="small" @click="runHandle(scope.row.id)">{{ $t('schedule.run') }}</el-button>
|
||||
<el-button v-if="$hasPermission('sys:schedule:delete')" type="text" size="small" @click="deleteHandle(scope.row.id)">{{ $t('delete') }}</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
:current-page="page"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
:page-size="limit"
|
||||
:total="total"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
@size-change="pageSizeChangeHandle"
|
||||
@current-change="pageCurrentChangeHandle">
|
||||
</el-pagination>
|
||||
<!-- 弹窗, 新增 / 修改 -->
|
||||
<add-or-update v-if="addOrUpdateVisible" ref="addOrUpdate" @refreshDataList="getDataList"></add-or-update>
|
||||
<!-- 弹窗, 日志列表 -->
|
||||
<log v-if="logVisible" ref="log"></log>
|
||||
</div>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import mixinViewModule from '@/mixins/view-module'
|
||||
import AddOrUpdate from './schedule-add-or-update'
|
||||
import Log from './schedule-log'
|
||||
export default {
|
||||
mixins: [mixinViewModule],
|
||||
data () {
|
||||
return {
|
||||
mixinViewModuleOptions: {
|
||||
getDataListURL: '/sys/schedule/page',
|
||||
getDataListIsPage: true,
|
||||
deleteURL: '/sys/schedule',
|
||||
deleteIsBatch: true
|
||||
},
|
||||
dataForm: {
|
||||
beanName: ''
|
||||
},
|
||||
logVisible: false
|
||||
}
|
||||
},
|
||||
components: {
|
||||
AddOrUpdate,
|
||||
Log
|
||||
},
|
||||
methods: {
|
||||
// 暂停
|
||||
pauseHandle (id) {
|
||||
if (!id && this.dataListSelections.length <= 0) {
|
||||
return this.$message({
|
||||
message: this.$t('prompt.deleteBatch'),
|
||||
type: 'warning',
|
||||
duration: 500
|
||||
})
|
||||
}
|
||||
this.$confirm(this.$t('prompt.info', { 'handle': this.$t('schedule.pause') }), this.$t('prompt.title'), {
|
||||
confirmButtonText: this.$t('confirm'),
|
||||
cancelButtonText: this.$t('cancel'),
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
this.$http.put('/sys/schedule/pause', id ? [id] : this.dataListSelections.map(item => item.id)).then(({ data: res }) => {
|
||||
if (res.code !== 0) {
|
||||
return this.$message.error(res.msg)
|
||||
}
|
||||
this.$message({
|
||||
message: this.$t('prompt.success'),
|
||||
type: 'success',
|
||||
duration: 500,
|
||||
onClose: () => {
|
||||
this.getDataList()
|
||||
}
|
||||
})
|
||||
}).catch(() => {})
|
||||
}).catch(() => {})
|
||||
},
|
||||
// 恢复
|
||||
resumeHandle (id) {
|
||||
if (!id && this.dataListSelections.length <= 0) {
|
||||
return this.$message({
|
||||
message: this.$t('prompt.deleteBatch'),
|
||||
type: 'warning',
|
||||
duration: 500
|
||||
})
|
||||
}
|
||||
this.$confirm(this.$t('prompt.info', { 'handle': this.$t('schedule.resume') }), this.$t('prompt.title'), {
|
||||
confirmButtonText: this.$t('confirm'),
|
||||
cancelButtonText: this.$t('cancel'),
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
this.$http.put('/sys/schedule/resume', id ? [id] : this.dataListSelections.map(item => item.id)).then(({ data: res }) => {
|
||||
if (res.code !== 0) {
|
||||
return this.$message.error(res.msg)
|
||||
}
|
||||
this.$message({
|
||||
message: this.$t('prompt.success'),
|
||||
type: 'success',
|
||||
duration: 500,
|
||||
onClose: () => {
|
||||
this.getDataList()
|
||||
}
|
||||
})
|
||||
}).catch(() => {})
|
||||
}).catch(() => {})
|
||||
},
|
||||
// 执行
|
||||
runHandle (id) {
|
||||
if (!id && this.dataListSelections.length <= 0) {
|
||||
return this.$message({
|
||||
message: this.$t('prompt.deleteBatch'),
|
||||
type: 'warning',
|
||||
duration: 500
|
||||
})
|
||||
}
|
||||
this.$confirm(this.$t('prompt.info', { 'handle': this.$t('schedule.run') }), this.$t('prompt.title'), {
|
||||
confirmButtonText: this.$t('confirm'),
|
||||
cancelButtonText: this.$t('cancel'),
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
this.$http.put('/sys/schedule/run', id ? [id] : this.dataListSelections.map(item => item.id)).then(({ data: res }) => {
|
||||
if (res.code !== 0) {
|
||||
return this.$message.error(res.msg)
|
||||
}
|
||||
this.$message({
|
||||
message: this.$t('prompt.success'),
|
||||
type: 'success',
|
||||
duration: 500,
|
||||
onClose: () => {
|
||||
this.getDataList()
|
||||
}
|
||||
})
|
||||
}).catch(() => {})
|
||||
}).catch(() => {})
|
||||
},
|
||||
// 日志列表
|
||||
logHandle () {
|
||||
this.logVisible = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs.log.init()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
225
src/views/modules/oss/oss-config.vue
Normal file
225
src/views/modules/oss/oss-config.vue
Normal file
@@ -0,0 +1,225 @@
|
||||
<template>
|
||||
<el-dialog :visible.sync="visible" :title="$t('oss.config')" :close-on-click-modal="false" :close-on-press-escape="false">
|
||||
<el-form :model="dataForm" :rules="dataRule" ref="dataForm" @keyup.enter.native="dataFormSubmitHandle()" label-width="120px">
|
||||
<el-form-item :label="$t('oss.type')" size="mini">
|
||||
<el-radio-group v-model="dataForm.type">
|
||||
<el-radio :label="1">{{ $t('oss.type1') }}</el-radio>
|
||||
<el-radio :label="2">{{ $t('oss.type2') }}</el-radio>
|
||||
<el-radio :label="3">{{ $t('oss.type3') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<template v-if="dataForm.type === 1">
|
||||
<el-form-item size="mini">
|
||||
<a href="https://s.qiniu.com/7Rfaym" target="_blank">免费申请(七牛)10GB储存空间</a>
|
||||
</el-form-item>
|
||||
<el-form-item prop="qiniuDomain" :label="$t('oss.qiniuDomain')">
|
||||
<el-input v-model="dataForm.qiniuDomain" :placeholder="$t('oss.qiniuDomainTips')"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="qiniuPrefix" :label="$t('oss.qiniuPrefix')">
|
||||
<el-input v-model="dataForm.qiniuPrefix" :placeholder="$t('oss.qiniuPrefixTips')"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="qiniuAccessKey" :label="$t('oss.qiniuAccessKey')">
|
||||
<el-input v-model="dataForm.qiniuAccessKey" :placeholder="$t('oss.qiniuAccessKeyTips')"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="qiniuSecretKey" :label="$t('oss.qiniuSecretKey')">
|
||||
<el-input v-model="dataForm.qiniuSecretKey" :placeholder="$t('oss.qiniuSecretKeyTips')"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="qiniuBucketName" :label="$t('oss.qiniuBucketName')">
|
||||
<el-input v-model="dataForm.qiniuBucketName" :placeholder="$t('oss.qiniuBucketNameTips')"></el-input>
|
||||
</el-form-item>
|
||||
</template>
|
||||
<template v-else-if="dataForm.type === 2">
|
||||
<el-form-item size="mini">
|
||||
<a href="https://www.aliyun.com/minisite/goods?userCode=y93lfwbg" target="_blank">免费领取阿里云优惠券</a>
|
||||
</el-form-item>
|
||||
<el-form-item prop="aliyunDomain" :label="$t('oss.aliyunDomain')">
|
||||
<el-input v-model="dataForm.aliyunDomain" :placeholder="$t('oss.aliyunDomainTips')"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="aliyunPrefix" :label="$t('oss.aliyunPrefix')">
|
||||
<el-input v-model="dataForm.aliyunPrefix" :placeholder="$t('oss.aliyunPrefixTips')"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="aliyunEndPoint" :label="$t('oss.aliyunEndPoint')">
|
||||
<el-input v-model="dataForm.aliyunEndPoint" :placeholder="$t('oss.aliyunEndPointTips')"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="aliyunAccessKeyId" :label="$t('oss.aliyunAccessKeyId')">
|
||||
<el-input v-model="dataForm.aliyunAccessKeyId" :placeholder="$t('oss.aliyunAccessKeyIdTips')"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="aliyunAccessKeySecret" :label="$t('oss.aliyunAccessKeySecret')">
|
||||
<el-input v-model="dataForm.aliyunAccessKeySecret" :placeholder="$t('oss.aliyunAccessKeySecretTips')"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="aliyunBucketName" :label="$t('oss.aliyunBucketName')">
|
||||
<el-input v-model="dataForm.aliyunBucketName" :placeholder="$t('oss.aliyunBucketNameTips')"></el-input>
|
||||
</el-form-item>
|
||||
</template>
|
||||
<template v-else-if="dataForm.type === 3">
|
||||
<el-form-item size="mini">
|
||||
<a href="https://curl.qcloud.com/zt3xdYbZ" target="_blank">免费领取腾讯云优惠券</a>
|
||||
</el-form-item>
|
||||
<el-form-item prop="qcloudDomain" :label="$t('oss.qcloudDomain')">
|
||||
<el-input v-model="dataForm.qcloudDomain" :placeholder="$t('oss.qcloudDomainTips')"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="qcloudPrefix" :label="$t('oss.qcloudPrefix')">
|
||||
<el-input v-model="dataForm.qcloudPrefix" :placeholder="$t('oss.qcloudPrefixTips')"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="qcloudAppId" :label="$t('oss.qcloudAppId')">
|
||||
<el-input v-model="dataForm.qcloudAppId" :placeholder="$t('oss.qcloudAppIdTips')"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="qcloudSecretId" :label="$t('oss.qcloudSecretId')">
|
||||
<el-input v-model="dataForm.qcloudSecretId" :placeholder="$t('oss.qcloudSecretIdTips')"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="qcloudSecretKey" :label="$t('oss.qcloudSecretKey')">
|
||||
<el-input v-model="dataForm.qcloudSecretKey" :placeholder="$t('oss.qcloudSecretKeyTips')"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="qcloudBucketName" :label="$t('oss.qcloudBucketName')">
|
||||
<el-input v-model="dataForm.qcloudBucketName" :placeholder="$t('oss.qcloudBucketNameTips')"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="qcloudRegion" :label="$t('oss.qcloudRegion')">
|
||||
<el-select v-model="dataForm.qcloudRegion" clearable :placeholder="$t('oss.qcloudRegionTips')" class="w-percent-100">
|
||||
<el-option value="ap-beijing-1" :label="$t('oss.qcloudRegionBeijing1')"></el-option>
|
||||
<el-option value="ap-beijing" :label="$t('oss.qcloudRegionBeijing')"></el-option>
|
||||
<el-option value="ap-shanghai" :label="$t('oss.qcloudRegionShanghai')"></el-option>
|
||||
<el-option value="ap-guangzhou" :label="$t('oss.qcloudRegionGuangzhou')"></el-option>
|
||||
<el-option value="ap-chengdu" :label="$t('oss.qcloudRegionChengdu')"></el-option>
|
||||
<el-option value="ap-chongqing" :label="$t('oss.qcloudRegionChongqing')"></el-option>
|
||||
<el-option value="ap-singapore" :label="$t('oss.qcloudRegionSingapore')"></el-option>
|
||||
<el-option value="ap-hongkong" :label="$t('oss.qcloudRegionHongkong')"></el-option>
|
||||
<el-option value="na-toronto" :label="$t('oss.qcloudRegionToronto')"></el-option>
|
||||
<el-option value="eu-frankfurt" :label="$t('oss.qcloudRegionFrankfurt')"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-form>
|
||||
<template slot="footer">
|
||||
<el-button @click="visible = false">{{ $t('cancel') }}</el-button>
|
||||
<el-button type="primary" @click="dataFormSubmitHandle()">{{ $t('confirm') }}</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import debounce from 'lodash/debounce'
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
visible: false,
|
||||
dataForm: {
|
||||
type: 0,
|
||||
qiniuDomain: '',
|
||||
qiniuPrefix: '',
|
||||
qiniuAccessKey: '',
|
||||
qiniuSecretKey: '',
|
||||
qiniuBucketName: '',
|
||||
aliyunDomain: '',
|
||||
aliyunPrefix: '',
|
||||
aliyunEndPoint: '',
|
||||
aliyunAccessKeyId: '',
|
||||
aliyunAccessKeySecret: '',
|
||||
aliyunBucketName: '',
|
||||
qcloudDomain: '',
|
||||
qcloudPrefix: '',
|
||||
qcloudAppId: 0,
|
||||
qcloudSecretId: '',
|
||||
qcloudSecretKey: '',
|
||||
qcloudBucketName: '',
|
||||
qcloudRegion: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
dataRule () {
|
||||
return {
|
||||
qiniuDomain: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
||||
],
|
||||
qiniuAccessKey: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
||||
],
|
||||
qiniuSecretKey: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
||||
],
|
||||
qiniuBucketName: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
||||
],
|
||||
aliyunDomain: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
||||
],
|
||||
aliyunEndPoint: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
||||
],
|
||||
aliyunAccessKeyId: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
||||
],
|
||||
aliyunAccessKeySecret: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
||||
],
|
||||
aliyunBucketName: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
||||
],
|
||||
qcloudDomain: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
||||
],
|
||||
qcloudAppId: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
||||
],
|
||||
qcloudSecretId: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
||||
],
|
||||
qcloudSecretKey: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
||||
],
|
||||
qcloudBucketName: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
||||
],
|
||||
qcloudRegion: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'dataForm.type' (val) {
|
||||
this.$refs['dataForm'].clearValidate()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
init () {
|
||||
this.visible = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs['dataForm'].resetFields()
|
||||
this.getInfo()
|
||||
})
|
||||
},
|
||||
// 获取信息
|
||||
getInfo () {
|
||||
this.$http.get('/sys/oss/info').then(({ data: res }) => {
|
||||
if (res.code !== 0) {
|
||||
return this.$message.error(res.msg)
|
||||
}
|
||||
this.dataForm = res.data
|
||||
}).catch(() => {})
|
||||
},
|
||||
// 表单提交
|
||||
dataFormSubmitHandle: debounce(function () {
|
||||
this.$refs['dataForm'].validate((valid) => {
|
||||
if (!valid) {
|
||||
return false
|
||||
}
|
||||
this.$http.post('/sys/oss', this.dataForm).then(({ data: res }) => {
|
||||
if (res.code !== 0) {
|
||||
return this.$message.error(res.msg)
|
||||
}
|
||||
this.$message({
|
||||
message: this.$t('prompt.success'),
|
||||
type: 'success',
|
||||
duration: 500,
|
||||
onClose: () => {
|
||||
this.visible = false
|
||||
this.$emit('refreshDataList')
|
||||
}
|
||||
})
|
||||
}).catch(() => {})
|
||||
})
|
||||
}, 1000, { 'leading': true, 'trailing': false })
|
||||
}
|
||||
}
|
||||
</script>
|
||||
65
src/views/modules/oss/oss-upload.vue
Normal file
65
src/views/modules/oss/oss-upload.vue
Normal file
@@ -0,0 +1,65 @@
|
||||
<template>
|
||||
<el-dialog :visible.sync="visible" :title="$t('oss.upload')" :close-on-click-modal="false" :close-on-press-escape="false">
|
||||
<el-upload
|
||||
:action="url"
|
||||
:file-list="fileList"
|
||||
drag
|
||||
multiple
|
||||
:before-upload="beforeUploadHandle"
|
||||
:on-success="successHandle"
|
||||
class="text-center">
|
||||
<i class="el-icon-upload"></i>
|
||||
<div class="el-upload__text" v-html="$t('upload.text')"></div>
|
||||
<div class="el-upload__tip" slot="tip">{{ $t('upload.tip', { 'format': 'jpg、png、gif' }) }}</div>
|
||||
</el-upload>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Cookies from 'js-cookie'
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
visible: false,
|
||||
url: '',
|
||||
num: 0,
|
||||
fileList: []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
init () {
|
||||
this.visible = true
|
||||
this.url = `${window.SITE_CONFIG['apiURL']}/sys/oss/upload?token=${Cookies.get('token')}`
|
||||
this.num = 0
|
||||
this.fileList = []
|
||||
},
|
||||
// 上传之前
|
||||
beforeUploadHandle (file) {
|
||||
if (file.type !== 'image/jpg' && file.type !== 'image/jpeg' && file.type !== 'image/png' && file.type !== 'image/gif') {
|
||||
this.$message.error(this.$t('upload.tip', { 'format': 'jpg、png、gif' }))
|
||||
return false
|
||||
}
|
||||
this.num++
|
||||
},
|
||||
// 上传成功
|
||||
successHandle (res, file, fileList) {
|
||||
if (res.code !== 0) {
|
||||
return this.$message.error(res.msg)
|
||||
}
|
||||
this.fileList = fileList
|
||||
this.num--
|
||||
if (this.num === 0) {
|
||||
this.$message({
|
||||
message: this.$t('prompt.success'),
|
||||
type: 'success',
|
||||
duration: 500,
|
||||
onClose: () => {
|
||||
this.visible = false
|
||||
this.$emit('refreshDataList')
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
88
src/views/modules/oss/oss.vue
Normal file
88
src/views/modules/oss/oss.vue
Normal file
@@ -0,0 +1,88 @@
|
||||
<template>
|
||||
<el-card shadow="never" class="aui-card--fill">
|
||||
<div class="mod-oss__oss">
|
||||
<el-form :inline="true" :model="dataForm">
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="configHandle()">{{ $t('oss.config') }}</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="uploadHandle()">{{ $t('oss.upload') }}</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="danger" @click="deleteHandle()">{{ $t('deleteBatch') }}</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-table
|
||||
v-loading="dataListLoading"
|
||||
:data="dataList"
|
||||
border
|
||||
@selection-change="dataListSelectionChangeHandle"
|
||||
@sort-change="dataListSortChangeHandle"
|
||||
style="width: 100%;">
|
||||
<el-table-column type="selection" header-align="center" align="center" width="50"></el-table-column>
|
||||
<el-table-column prop="url" :label="$t('oss.url')" header-align="center" align="center"></el-table-column>
|
||||
<el-table-column prop="createDate" :label="$t('oss.createDate')" sortable="custom" header-align="center" align="center" width="180"></el-table-column>
|
||||
<el-table-column :label="$t('handle')" fixed="right" header-align="center" align="center" width="150">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="small" @click="deleteHandle(scope.row.id)">{{ $t('delete') }}</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
:current-page="page"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
:page-size="limit"
|
||||
:total="total"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
@size-change="pageSizeChangeHandle"
|
||||
@current-change="pageCurrentChangeHandle">
|
||||
</el-pagination>
|
||||
<!-- 弹窗, 云存储配置 -->
|
||||
<config v-if="configVisible" ref="config"></config>
|
||||
<!-- 弹窗, 上传文件 -->
|
||||
<upload v-if="uploadVisible" ref="upload" @refreshDataList="getDataList"></upload>
|
||||
</div>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import mixinViewModule from '@/mixins/view-module'
|
||||
import Config from './oss-config'
|
||||
import Upload from './oss-upload'
|
||||
export default {
|
||||
mixins: [mixinViewModule],
|
||||
data () {
|
||||
return {
|
||||
mixinViewModuleOptions: {
|
||||
getDataListURL: '/sys/oss/page',
|
||||
getDataListIsPage: true,
|
||||
deleteURL: '/sys/oss',
|
||||
deleteIsBatch: true
|
||||
},
|
||||
dataForm: {},
|
||||
configVisible: false,
|
||||
uploadVisible: false
|
||||
}
|
||||
},
|
||||
components: {
|
||||
Config,
|
||||
Upload
|
||||
},
|
||||
methods: {
|
||||
// 云存储配置
|
||||
configHandle () {
|
||||
this.configVisible = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs.config.init()
|
||||
})
|
||||
},
|
||||
// 上传文件
|
||||
uploadHandle () {
|
||||
this.uploadVisible = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs.upload.init()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
154
src/views/modules/pms/blenderStep/config.js
Normal file
154
src/views/modules/pms/blenderStep/config.js
Normal file
@@ -0,0 +1,154 @@
|
||||
import TableOperaionComponent from '@/components/noTemplateComponents/operationComponent'
|
||||
import TableTextComponent from '@/components/noTemplateComponents/detailComponent'
|
||||
import StatusComponent from '@/components/noTemplateComponents/statusComponent'
|
||||
import InputArea from 'code-brick-zj'
|
||||
|
||||
export default function () {
|
||||
|
||||
const tableProps = [
|
||||
{ prop: 'name', label: '混料程序名称' },
|
||||
{ prop: 'code', label: '程序编码' },
|
||||
{ prop: 'version', label: '版本号' },
|
||||
{ prop: 'status', label: '状态', subcomponent: StatusComponent }, // subcomponent
|
||||
{ prop: 'remark', label: '备注' },
|
||||
{ prop: 'description', label: '详情', subcomponent: TableTextComponent },
|
||||
{
|
||||
prop: 'operations',
|
||||
name: '操作',
|
||||
fixed: 'right',
|
||||
width: 120,
|
||||
subcomponent: TableOperaionComponent,
|
||||
options: ['edit', 'delete']
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
const headFormFields = [
|
||||
{
|
||||
label: '混料程序名称',
|
||||
input: true,
|
||||
default: { value: '' }
|
||||
},
|
||||
{
|
||||
button: {
|
||||
type: 'primary',
|
||||
name: '查询'
|
||||
}
|
||||
},
|
||||
{
|
||||
button: {
|
||||
type: 'plain',
|
||||
name: '新增',
|
||||
permission: 'pms:blenderStep:save'
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
const dialogConfigs = {
|
||||
menu: [{ name: '混料程序' }, { name: '参数明细', onlyEditMode: true }],
|
||||
form: {
|
||||
url: '/pms/blenderStep',
|
||||
rows: [
|
||||
[
|
||||
{ input: true, label: '混料程序名称', prop: 'name', rules: { required: true, message: 'not empty', trigger: 'blur' }, elparams: { placeholder: '请输入混料程序名称' } },
|
||||
{ input: true, label: '程序编码', prop: 'code', rules: { required: true, message: 'not empty', trigger: 'blur' }, elparams: { placeholder: '请输入混料程序编码' } },
|
||||
{ input: true, label: '版本号', prop: 'version', elparams: { placeholder: '请输入版本号' } },
|
||||
],
|
||||
[
|
||||
// {
|
||||
// select: true,
|
||||
// label: '城市',
|
||||
// prop: 'city',
|
||||
// options: [
|
||||
// { label: '1', value: 1 },
|
||||
// { label: '2', value: 2 },
|
||||
// { label: '3', value: 3 },
|
||||
// ],
|
||||
// elparams: { placeholder: '请选择城市' }
|
||||
// },
|
||||
// { input: true, label: '程序号', prop: '', rules: { required: true, message: 'not empty', trigger: 'blur' }, elparams: { placeholder: '请输入混料程序号' } },
|
||||
],
|
||||
// [{ switch: true, label: '状态', prop: 'enabled', default: 0 }],
|
||||
[{ textarea: true, label: '备注', prop: 'remark', elparams: { placeholder: '备注' } }],
|
||||
],
|
||||
operations: [
|
||||
{ name: 'add', label: '保存', type: 'primary', showOnEdit: false },
|
||||
{ name: 'update', label: '更新', type: 'primary', showOnEdit: true },
|
||||
{ name: 'reset', label: '重置', type: 'warning', showAlways: true },
|
||||
// { name: 'cancel', label: '取消', showAlways: true },
|
||||
],
|
||||
},
|
||||
table: {
|
||||
// extraParams: ['stepId'],
|
||||
extraParams: 'stepId',
|
||||
props: [
|
||||
{ prop: 'sort', label: '步骤', isEditField: true },
|
||||
{ prop: 'name', label: '参数名称', isEditField: true },
|
||||
{ prop: 'description', label: '描述', isEditField: true },
|
||||
{ prop: 'value', label: '设定值', isEditField: true },
|
||||
{ prop: 'valueFloor', label: '值下限', isEditField: true },
|
||||
{ prop: 'valueTop', label: '值上限', isEditField: true },
|
||||
{
|
||||
prop: 'operations',
|
||||
name: '操作',
|
||||
fixed: 'right',
|
||||
width: 120,
|
||||
subcomponent: TableOperaionComponent,
|
||||
options: [
|
||||
{ name: 'edit', permission: 'pms:blender:edit' },
|
||||
{ name: 'delete', permission: 'pms:blender:delete' },
|
||||
]
|
||||
}
|
||||
],
|
||||
data: [
|
||||
// TOOD 暂时用不到,但获取可以考虑把拉取接口数据的函数迁移到此文件(没有太大必要)
|
||||
],
|
||||
},
|
||||
|
||||
subDialog: {
|
||||
extraParams: 'stepId',
|
||||
rows: [
|
||||
[
|
||||
{ input: true, label: '步骤', prop: 'sort', rules: { required: true, message: 'not empty', trigger: 'blur' }, elparams: { placeholder: '请输入步骤' } },
|
||||
{ input: true, label: '步骤描述', prop: 'description', rules: { required: true, message: 'not empty', trigger: 'blur' }, elparams: { placeholder: '请输入描述' } },
|
||||
], [
|
||||
{ input: true, label: '参数名称', prop: 'name', elparams: { placeholder: '请输入参数名称' } },
|
||||
{ input: true, label: '参数编码', prop: 'code', rules: { required: true, message: 'not empty', trigger: 'blur' }, elparams: { placeholder: '请输入描述' } },
|
||||
], [
|
||||
{ input: true, label: '参数值上限', prop: 'valueTop', elparams: { placeholder: '请输入参数值上限' } },
|
||||
{ input: true, label: '参数值下限', prop: 'valueFloor', elparams: { placeholder: '请输入参数值下限' } },
|
||||
],
|
||||
[
|
||||
{ input: true, label: '参数值', prop: 'value', elparams: { placeholder: '请输入参数值' } },
|
||||
]
|
||||
],
|
||||
operations: [
|
||||
{ name: 'add', label: '保存', type: 'primary', showOnEdit: false },
|
||||
{ name: 'update', label: '更新', type: 'primary', showOnEdit: true },
|
||||
// { name: 'reset', label: '重置', type: 'warning', showAlways: true },
|
||||
// { name: 'cancel', label: '取消', showAlways: true },
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
return {
|
||||
dialogConfigs,
|
||||
tableConfig: {
|
||||
table: null, // 此处可省略,el-table 上的配置项
|
||||
column: tableProps, // el-column-item 上的配置项
|
||||
},
|
||||
headFormConfigs: {
|
||||
rules: null, // 名称是由 BaseSearchForm.vue 组件固定的
|
||||
fields: headFormFields // 名称是由 BaseSearchForm.vue 组件固定的
|
||||
},
|
||||
urls: {
|
||||
base: '/pms/blenderStep',
|
||||
page: '/pms/blenderStep/page',
|
||||
subase: '/pms/blenderStepParam',
|
||||
subpage: '/pms/blenderStepParam/page',
|
||||
// more...
|
||||
}
|
||||
}
|
||||
}
|
||||
47
src/views/modules/pms/blenderStep/index.vue
Normal file
47
src/views/modules/pms/blenderStep/index.vue
Normal file
@@ -0,0 +1,47 @@
|
||||
<template>
|
||||
<ListViewWithHead :table-config="tableConfig" :head-config="headFormConfigs" :dialog-configs="dialogConfigs" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import initConfig from './config';
|
||||
import ListViewWithHead from '@/views/atomViews/ListViewWithHead.vue';
|
||||
|
||||
export default {
|
||||
name: 'BlenderView',
|
||||
components: { ListViewWithHead },
|
||||
provide() {
|
||||
return {
|
||||
urls: this.allUrls
|
||||
}
|
||||
}
|
||||
// urls: {
|
||||
// type: Object,
|
||||
// required: true,
|
||||
// default: () => ({
|
||||
// /** 列表 url **/ list: null,
|
||||
// /** 分页 url **/ page: null,
|
||||
// /** 编辑保存 url **/ edit: null,
|
||||
// /** 删除条目 url **/ delete: null,
|
||||
// /** 详情 url **/ detail: null,
|
||||
// /** 导出 url **/ export: null,
|
||||
// /** 导入 url **/ import: null,
|
||||
// /** 其他 url **/ other: null,
|
||||
// }),
|
||||
// },
|
||||
,
|
||||
data() {
|
||||
const { tableConfig, headFormConfigs, urls, dialogConfigs } = initConfig.call(this);
|
||||
return {
|
||||
tableConfig,
|
||||
headFormConfigs,
|
||||
allUrls: urls,
|
||||
dialogConfigs,
|
||||
};
|
||||
},
|
||||
created() {},
|
||||
mounted() {},
|
||||
methods: {},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
155
src/views/modules/sys/dept-add-or-update.vue
Normal file
155
src/views/modules/sys/dept-add-or-update.vue
Normal file
@@ -0,0 +1,155 @@
|
||||
<template>
|
||||
<el-form :model="dataForm" :rules="dataRule" ref="dataForm" @keyup.enter.native="dataFormSubmit()" label-width="120px">
|
||||
<el-form-item prop="name" :label="$t('dept.name')">
|
||||
<el-input v-model="dataForm.name" :placeholder="$t('dept.name')"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="parentName" :label="$t('dept.parentName')" class="dept-list">
|
||||
<el-popover v-model="deptListVisible" ref="deptListPopover" placement="bottom-start" trigger="click">
|
||||
<el-tree
|
||||
:data="deptList"
|
||||
:props="{ label: 'name', children: 'children' }"
|
||||
node-key="id"
|
||||
ref="deptListTree"
|
||||
:highlight-current="true"
|
||||
:expand-on-click-node="false"
|
||||
accordion
|
||||
@current-change="deptListTreeCurrentChangeHandle">
|
||||
</el-tree>
|
||||
</el-popover>
|
||||
<el-input v-model="dataForm.parentName" v-popover:deptListPopover :readonly="true" :placeholder="$t('dept.parentName')">
|
||||
<i
|
||||
v-if="$store.state.user.superAdmin === 1 && dataForm.pid !== '0'"
|
||||
slot="suffix"
|
||||
@click.stop="deptListTreeSetDefaultHandle()"
|
||||
class="el-icon-circle-close el-input__icon">
|
||||
</i>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="sort" :label="$t('dept.sort')">
|
||||
<el-input-number v-model="dataForm.sort" controls-position="right" :min="0" :label="$t('dept.sort')"></el-input-number>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import debounce from 'lodash/debounce'
|
||||
import basicAdd from '@/mixins/basic-add'
|
||||
export default {
|
||||
mixins: [basicAdd],
|
||||
data () {
|
||||
return {
|
||||
urlOptions: {
|
||||
submitURL: '/sys/dept/',
|
||||
infoURL: '/sys/dept'
|
||||
},
|
||||
visible: false,
|
||||
deptList: [],
|
||||
deptListVisible: false,
|
||||
dataForm: {
|
||||
id: '',
|
||||
name: '',
|
||||
pid: '',
|
||||
parentName: '',
|
||||
sort: 0
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
dataRule () {
|
||||
return {
|
||||
name: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
||||
],
|
||||
parentName: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'change' }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
init(id) {
|
||||
this.dataForm.id = id || "";
|
||||
this.visible = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs['dataForm'].resetFields()
|
||||
this.getDeptList().then(() => {
|
||||
if (this.dataForm.id) {
|
||||
this.getInfo()
|
||||
} else if (this.$store.state.user.superAdmin === 1) {
|
||||
this.deptListTreeSetDefaultHandle()
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
// 获取部门列表
|
||||
getDeptList () {
|
||||
return this.$http.get('/sys/dept/list').then(({ data: res }) => {
|
||||
if (res.code !== 0) {
|
||||
return this.$message.error(res.msg)
|
||||
}
|
||||
this.deptList = res.data
|
||||
}).catch(() => {})
|
||||
},
|
||||
// 获取信息
|
||||
getInfo () {
|
||||
this.$http.get(`/sys/dept/${this.dataForm.id}`).then(({ data: res }) => {
|
||||
if (res.code !== 0) {
|
||||
return this.$message.error(res.msg)
|
||||
}
|
||||
this.dataForm = {
|
||||
...this.dataForm,
|
||||
...res.data
|
||||
}
|
||||
if (this.dataForm.pid === '0') {
|
||||
return this.deptListTreeSetDefaultHandle()
|
||||
}
|
||||
this.$refs.deptListTree.setCurrentKey(this.dataForm.pid)
|
||||
}).catch(() => {})
|
||||
},
|
||||
// 上级部门树, 设置默认值
|
||||
deptListTreeSetDefaultHandle () {
|
||||
this.dataForm.pid = '0'
|
||||
this.dataForm.parentName = this.$t('dept.parentNameDefault')
|
||||
},
|
||||
// 上级部门树, 选中
|
||||
deptListTreeCurrentChangeHandle (data) {
|
||||
this.dataForm.pid = data.id
|
||||
this.dataForm.parentName = data.name
|
||||
this.deptListVisible = false
|
||||
},
|
||||
// 表单提交
|
||||
dataFormSubmit: debounce(function () {
|
||||
this.$refs['dataForm'].validate((valid) => {
|
||||
if (!valid) {
|
||||
return false
|
||||
}
|
||||
this.$http[!this.dataForm.id ? 'post' : 'put']('/sys/dept', this.dataForm).then(({ data: res }) => {
|
||||
if (res.code !== 0) {
|
||||
return this.$message.error(res.msg)
|
||||
}
|
||||
this.$message({
|
||||
message: this.$t('prompt.success'),
|
||||
type: 'success',
|
||||
duration: 500,
|
||||
onClose: () => {
|
||||
this.visible = false
|
||||
this.$emit('refreshDataList')
|
||||
}
|
||||
})
|
||||
}).catch(() => {})
|
||||
})
|
||||
}, 1000, { 'leading': true, 'trailing': false })
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.mod-sys__dept {
|
||||
.dept-list {
|
||||
.el-input__inner,
|
||||
.el-input__suffix {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
119
src/views/modules/sys/dept.vue
Normal file
119
src/views/modules/sys/dept.vue
Normal file
@@ -0,0 +1,119 @@
|
||||
<!--
|
||||
* @Author: zwq
|
||||
* @Date: 2023-01-04 10:29:40
|
||||
* @LastEditors: zwq
|
||||
* @LastEditTime: 2023-01-05 14:32:59
|
||||
* @Description:
|
||||
-->
|
||||
<template>
|
||||
<el-card shadow="never" class="aui-card--fill">
|
||||
<div class="mod-sys__dept">
|
||||
<search-bar :formConfigs="formConfig" ref="searchBarForm" @headBtnClick="buttonClick" />
|
||||
<base-table
|
||||
:table-props="tableProps"
|
||||
:page="listQuery.page"
|
||||
:limit="listQuery.limit"
|
||||
:table-data="tableData"
|
||||
row-key="id"
|
||||
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
|
||||
>
|
||||
<method-btn
|
||||
v-if="tableBtn.length"
|
||||
slot="handleBtn"
|
||||
:width="100"
|
||||
label="操作"
|
||||
:method-list="tableBtn"
|
||||
@clickBtn="handleClick"
|
||||
/>
|
||||
</base-table>
|
||||
<!-- 弹窗, 新增 / 修改 -->
|
||||
<base-dialog
|
||||
:dialogTitle="addOrEditTitle"
|
||||
:dialogVisible="addOrUpdateVisible"
|
||||
@cancel="handleCancel"
|
||||
@confirm="handleConfirm"
|
||||
:before-close="handleCancel"
|
||||
>
|
||||
<add-or-update ref="addOrUpdate" @successSubmit="successSubmit"></add-or-update>
|
||||
</base-dialog>
|
||||
</div>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import basicPage from "@/mixins/basic-page";
|
||||
import AddOrUpdate from "./dept-add-or-update";
|
||||
import i18n from "@/i18n";
|
||||
const tableProps = [
|
||||
{
|
||||
prop: "name",
|
||||
label: i18n.t("dept.name"),
|
||||
},
|
||||
{
|
||||
prop: "parentName",
|
||||
label: i18n.t("dept.parentName"),
|
||||
},
|
||||
{
|
||||
prop: "sort",
|
||||
label: i18n.t("dept.sort"),
|
||||
},
|
||||
];
|
||||
const tableBtn = [
|
||||
{
|
||||
type: "edit",
|
||||
btnName: "编辑",
|
||||
},
|
||||
{
|
||||
type: "delete",
|
||||
btnName: "删除",
|
||||
},
|
||||
];
|
||||
export default {
|
||||
mixins: [basicPage],
|
||||
data() {
|
||||
return {
|
||||
urlOptions: {
|
||||
getDataListURL: "/sys/dept/list",
|
||||
deleteURL: "/sys/dept",
|
||||
},
|
||||
tableProps,
|
||||
tableBtn,
|
||||
formConfig: [
|
||||
{
|
||||
type: "button",
|
||||
btnName: "新增",
|
||||
name: "add",
|
||||
color: "primary",
|
||||
plain: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
components: {
|
||||
AddOrUpdate,
|
||||
},
|
||||
methods: {
|
||||
// 获取数据列表
|
||||
getDataList() {
|
||||
this.dataListLoading = true;
|
||||
this.$http
|
||||
.get(this.urlOptions.getDataListURL, {
|
||||
params: this.listQuery,
|
||||
})
|
||||
.then(({ data: res }) => {
|
||||
this.dataListLoading = false;
|
||||
if (res.code !== 0) {
|
||||
this.tableData = [];
|
||||
this.listQuery.total = 0;
|
||||
return this.$message.error(res.msg);
|
||||
}
|
||||
this.tableData = res.data;
|
||||
this.listQuery.total = res.data.total;
|
||||
})
|
||||
.catch(() => {
|
||||
this.dataListLoading = false;
|
||||
});
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
103
src/views/modules/sys/dict-data-add-or-update.vue
Normal file
103
src/views/modules/sys/dict-data-add-or-update.vue
Normal file
@@ -0,0 +1,103 @@
|
||||
<template>
|
||||
<el-form :model="dataForm" :rules="dataRule" ref="dataForm" @keyup.enter.native="dataFormSubmitHandle()" label-width="120px">
|
||||
<el-form-item prop="dictValue" :label="$t('dict.dictValue')">
|
||||
<el-input v-model="dataForm.dictValue" :placeholder="$t('dict.dictValue')"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="dictLabel" :label="$t('dict.dictLabel')">
|
||||
<el-input v-model="dataForm.dictLabel" :placeholder="$t('dict.dictLabel')"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="sort" :label="$t('dict.sort')">
|
||||
<el-input-number v-model="dataForm.sort" controls-position="right" :min="0" :label="$t('dict.sort')"></el-input-number>
|
||||
</el-form-item>
|
||||
<el-form-item prop="remark" :label="$t('dict.remark')">
|
||||
<el-input v-model="dataForm.remark" :placeholder="$t('dict.remark')"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import debounce from 'lodash/debounce'
|
||||
import basicAdd from '@/mixins/basic-add'
|
||||
export default {
|
||||
mixins: [basicAdd],
|
||||
data () {
|
||||
return {
|
||||
urlOptions: {
|
||||
submitURL: '/sys/dict/data/',
|
||||
infoURL: '/sys/dict/data'
|
||||
},
|
||||
visible: false,
|
||||
dataForm: {
|
||||
id: '',
|
||||
dictTypeId: '',
|
||||
dictLabel: '',
|
||||
dictValue: '',
|
||||
sort: 0,
|
||||
remark: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
dataRule () {
|
||||
return {
|
||||
dictLabel: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
||||
],
|
||||
dictValue: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
||||
],
|
||||
sort: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
init(id,dictTypeId) {
|
||||
this.dataForm.id = id || "";
|
||||
this.dataForm.dictTypeId = dictTypeId || "";
|
||||
this.visible = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs['dataForm'].resetFields()
|
||||
if (this.dataForm.id) {
|
||||
this.getInfo()
|
||||
}
|
||||
})
|
||||
},
|
||||
// 获取信息
|
||||
getInfo () {
|
||||
this.$http.get(`/sys/dict/data/${this.dataForm.id}`).then(({ data: res }) => {
|
||||
if (res.code !== 0) {
|
||||
return this.$message.error(res.msg)
|
||||
}
|
||||
this.dataForm = {
|
||||
...this.dataForm,
|
||||
...res.data
|
||||
}
|
||||
}).catch(() => {})
|
||||
},
|
||||
// 表单提交
|
||||
dataFormSubmitHandle: debounce(function () {
|
||||
this.$refs['dataForm'].validate((valid) => {
|
||||
if (!valid) {
|
||||
return false
|
||||
}
|
||||
this.$http[!this.dataForm.id ? 'post' : 'put']('/sys/dict/data', this.dataForm).then(({ data: res }) => {
|
||||
if (res.code !== 0) {
|
||||
return this.$message.error(res.msg)
|
||||
}
|
||||
this.$message({
|
||||
message: this.$t('prompt.success'),
|
||||
type: 'success',
|
||||
duration: 500,
|
||||
onClose: () => {
|
||||
this.visible = false
|
||||
this.$emit('refreshDataList')
|
||||
}
|
||||
})
|
||||
}).catch(() => {})
|
||||
})
|
||||
}, 1000, { 'leading': true, 'trailing': false })
|
||||
}
|
||||
}
|
||||
</script>
|
||||
150
src/views/modules/sys/dict-data.vue
Normal file
150
src/views/modules/sys/dict-data.vue
Normal file
@@ -0,0 +1,150 @@
|
||||
<template>
|
||||
<el-card shadow="never" class="aui-card--fill">
|
||||
<div class="mod-sys__user">
|
||||
<search-bar :formConfigs="formConfig" ref="searchBarForm" @headBtnClick="buttonClick" />
|
||||
<base-table
|
||||
:table-props="tableProps"
|
||||
:page="listQuery.page"
|
||||
:limit="listQuery.limit"
|
||||
:table-data="tableData"
|
||||
>
|
||||
<method-btn
|
||||
v-if="tableBtn.length"
|
||||
slot="handleBtn"
|
||||
:width="100"
|
||||
label="操作"
|
||||
:method-list="tableBtn"
|
||||
@clickBtn="handleClick"
|
||||
/>
|
||||
</base-table>
|
||||
<pagination
|
||||
:limit.sync="listQuery.limit"
|
||||
:page.sync="listQuery.page"
|
||||
:total="listQuery.total"
|
||||
@pagination="getDataList"
|
||||
/>
|
||||
<!-- 弹窗, 新增 / 修改 -->
|
||||
<base-dialog
|
||||
:dialogTitle="addOrEditTitle"
|
||||
:dialogVisible="addOrUpdateVisible"
|
||||
@cancel="handleCancel"
|
||||
@confirm="handleConfirm"
|
||||
:before-close="handleCancel"
|
||||
>
|
||||
<add-or-update ref="addOrUpdate" @successSubmit="successSubmit"></add-or-update>
|
||||
</base-dialog>
|
||||
</div>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import basicPage from "@/mixins/basic-page";
|
||||
import AddOrUpdate from './dict-data-add-or-update'
|
||||
import i18n from "@/i18n";
|
||||
const tableProps = [
|
||||
{
|
||||
prop: "dictValue",
|
||||
label: i18n.t("dict.dictValue"),
|
||||
},
|
||||
{
|
||||
prop: "dictLabel",
|
||||
label: i18n.t("dict.dictLabel"),
|
||||
},
|
||||
{
|
||||
prop: "sort",
|
||||
label: i18n.t("dict.sort"),
|
||||
},
|
||||
{
|
||||
prop: "remark",
|
||||
label: i18n.t("dict.remark"),
|
||||
},
|
||||
{
|
||||
prop: "createDate",
|
||||
label: i18n.t("dict.createDate"),
|
||||
},
|
||||
];
|
||||
const tableBtn = [
|
||||
{
|
||||
type: "edit",
|
||||
btnName: "编辑",
|
||||
},
|
||||
{
|
||||
type: "delete",
|
||||
btnName: "删除",
|
||||
},
|
||||
];
|
||||
export default {
|
||||
mixins: [basicPage],
|
||||
data() {
|
||||
return {
|
||||
urlOptions: {
|
||||
getDataListURL: "/sys/dict/data/page",
|
||||
deleteURL: "/sys/dict/data",
|
||||
},
|
||||
tableProps,
|
||||
tableBtn,
|
||||
formConfig: [
|
||||
{
|
||||
type: "input",
|
||||
label: i18n.t("dict.dictValue"),
|
||||
placeholder: i18n.t("dict.dictValue"),
|
||||
param: "dictValue",
|
||||
},
|
||||
{
|
||||
type: "input",
|
||||
label: i18n.t("dict.dictLabel"),
|
||||
placeholder: i18n.t("dict.dictLabel"),
|
||||
param: "dictLabel",
|
||||
},
|
||||
{
|
||||
type: "button",
|
||||
btnName: "查询",
|
||||
name: "search",
|
||||
color: "primary",
|
||||
},
|
||||
{
|
||||
type: "button",
|
||||
btnName: "新增",
|
||||
name: "add",
|
||||
color: "primary",
|
||||
plain: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
components: {
|
||||
AddOrUpdate,
|
||||
},
|
||||
created () {
|
||||
this.listQuery.dictTypeId = this.$route.params.dictTypeId || '0'
|
||||
this.getDataList()
|
||||
},
|
||||
methods:{
|
||||
//search-bar点击
|
||||
buttonClick(val) {
|
||||
switch (val.btnName) {
|
||||
case "search":
|
||||
this.listQuery.dictValue = val.dictValue;
|
||||
this.listQuery.dictLabel = val.dictLabel;
|
||||
this.listQuery.page = 1;
|
||||
this.getDataList();
|
||||
break;
|
||||
case "add":
|
||||
this.addOrEditTitle = '新增'
|
||||
this.addOrUpdateVisible = true;
|
||||
this.addOrUpdateHandle()
|
||||
break;
|
||||
default:
|
||||
console.log(val)
|
||||
}
|
||||
},
|
||||
// 新增 / 修改
|
||||
addOrUpdateHandle (id) {
|
||||
this.addOrUpdateVisible = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs.addOrUpdate.init(id,this.listQuery.dictTypeId)
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
101
src/views/modules/sys/dict-type-add-or-update.vue
Normal file
101
src/views/modules/sys/dict-type-add-or-update.vue
Normal file
@@ -0,0 +1,101 @@
|
||||
<template>
|
||||
<el-form :model="dataForm" :rules="dataRule" ref="dataForm" @keyup.enter.native="dataFormSubmitHandle()" label-width="120px">
|
||||
<el-form-item prop="dictName" :label="$t('dict.dictName')">
|
||||
<el-input v-model="dataForm.dictName" :placeholder="$t('dict.dictName')"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="dictType" :label="$t('dict.dictType')">
|
||||
<el-input v-model="dataForm.dictType" :placeholder="$t('dict.dictType')"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="sort" :label="$t('dict.sort')">
|
||||
<el-input-number v-model="dataForm.sort" controls-position="right" :min="0" :label="$t('dict.sort')"></el-input-number>
|
||||
</el-form-item>
|
||||
<el-form-item prop="remark" :label="$t('dict.remark')">
|
||||
<el-input v-model="dataForm.remark" :placeholder="$t('dict.remark')"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import debounce from 'lodash/debounce'
|
||||
import basicAdd from '@/mixins/basic-add'
|
||||
export default {
|
||||
mixins: [basicAdd],
|
||||
data () {
|
||||
return {
|
||||
urlOptions: {
|
||||
submitURL: '/sys/dict/type/',
|
||||
infoURL: '/sys/dict/type'
|
||||
},
|
||||
visible: false,
|
||||
dataForm: {
|
||||
id: '',
|
||||
dictName: '',
|
||||
dictType: '',
|
||||
sort: 0,
|
||||
remark: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
dataRule () {
|
||||
return {
|
||||
dictName: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
||||
],
|
||||
dictType: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
||||
],
|
||||
sort: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
init(id) {
|
||||
this.dataForm.id = id || "";
|
||||
this.visible = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs['dataForm'].resetFields()
|
||||
if (this.dataForm.id) {
|
||||
this.getInfo()
|
||||
}
|
||||
})
|
||||
},
|
||||
// 获取信息
|
||||
getInfo () {
|
||||
this.$http.get(`/sys/dict/type/${this.dataForm.id}`).then(({ data: res }) => {
|
||||
if (res.code !== 0) {
|
||||
return this.$message.error(res.msg)
|
||||
}
|
||||
this.dataForm = {
|
||||
...this.dataForm,
|
||||
...res.data
|
||||
}
|
||||
}).catch(() => {})
|
||||
},
|
||||
// 表单提交
|
||||
dataFormSubmitHandle: debounce(function () {
|
||||
this.$refs['dataForm'].validate((valid) => {
|
||||
if (!valid) {
|
||||
return false
|
||||
}
|
||||
this.$http[!this.dataForm.id ? 'post' : 'put']('/sys/dict/type', this.dataForm).then(({ data: res }) => {
|
||||
if (res.code !== 0) {
|
||||
return this.$message.error(res.msg)
|
||||
}
|
||||
this.$message({
|
||||
message: this.$t('prompt.success'),
|
||||
type: 'success',
|
||||
duration: 500,
|
||||
onClose: () => {
|
||||
this.visible = false
|
||||
this.$emit('refreshDataList')
|
||||
}
|
||||
})
|
||||
}).catch(() => {})
|
||||
})
|
||||
}, 1000, { 'leading': true, 'trailing': false })
|
||||
}
|
||||
}
|
||||
</script>
|
||||
33
src/views/modules/sys/dict-type-to.vue
Normal file
33
src/views/modules/sys/dict-type-to.vue
Normal file
@@ -0,0 +1,33 @@
|
||||
<template>
|
||||
<span>
|
||||
<el-button type="text" size="small" @click="emitClick">{{ injectData.dictType }}</el-button>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { addDynamicRoute } from '@/router'
|
||||
export default {
|
||||
props: {
|
||||
injectData: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 子级
|
||||
emitClick () {
|
||||
// 路由参数
|
||||
const routeParams = {
|
||||
routeName: `${this.$route.name}__${this.injectData.id}`,
|
||||
title: `${this.$route.meta.title} - ${this.injectData.dictType}`,
|
||||
path: 'sys/dict-data',
|
||||
params: {
|
||||
dictTypeId: this.injectData.id
|
||||
}
|
||||
}
|
||||
// 动态路由
|
||||
addDynamicRoute(routeParams, this.$router)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
141
src/views/modules/sys/dict-type.vue
Normal file
141
src/views/modules/sys/dict-type.vue
Normal file
@@ -0,0 +1,141 @@
|
||||
<template>
|
||||
<el-card shadow="never" class="aui-card--fill">
|
||||
<div class="mod-sys__user">
|
||||
<search-bar :formConfigs="formConfig" ref="searchBarForm" @headBtnClick="buttonClick" />
|
||||
<base-table
|
||||
:table-props="tableProps"
|
||||
:page="listQuery.page"
|
||||
:limit="listQuery.limit"
|
||||
:table-data="tableData"
|
||||
>
|
||||
<method-btn
|
||||
v-if="tableBtn.length"
|
||||
slot="handleBtn"
|
||||
:width="100"
|
||||
label="操作"
|
||||
:method-list="tableBtn"
|
||||
@clickBtn="handleClick"
|
||||
/>
|
||||
</base-table>
|
||||
<pagination
|
||||
:limit.sync="listQuery.limit"
|
||||
:page.sync="listQuery.page"
|
||||
:total="listQuery.total"
|
||||
@pagination="getDataList"
|
||||
/>
|
||||
<!-- 弹窗, 新增 / 修改 -->
|
||||
<base-dialog
|
||||
:dialogTitle="addOrEditTitle"
|
||||
:dialogVisible="addOrUpdateVisible"
|
||||
@cancel="handleCancel"
|
||||
@confirm="handleConfirm"
|
||||
:before-close="handleCancel"
|
||||
>
|
||||
<add-or-update ref="addOrUpdate" @successSubmit="successSubmit"></add-or-update>
|
||||
</base-dialog>
|
||||
</div>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import basicPage from "@/mixins/basic-page";
|
||||
import AddOrUpdate from './dict-type-add-or-update'
|
||||
import toDictType from './dict-type-to'
|
||||
import i18n from "@/i18n";
|
||||
const tableProps = [
|
||||
{
|
||||
prop: "dictName",
|
||||
label: i18n.t("dict.dictName"),
|
||||
},
|
||||
{
|
||||
prop: "dictType",
|
||||
label: i18n.t("dict.dictType"),
|
||||
subcomponent: toDictType
|
||||
},
|
||||
{
|
||||
prop: "sort",
|
||||
label: i18n.t("dict.sort"),
|
||||
},
|
||||
{
|
||||
prop: "remark",
|
||||
label: i18n.t("dict.remark"),
|
||||
},
|
||||
{
|
||||
prop: "createDate",
|
||||
label: i18n.t("dict.createDate"),
|
||||
},
|
||||
];
|
||||
const tableBtn = [
|
||||
{
|
||||
type: "edit",
|
||||
btnName: "编辑",
|
||||
},
|
||||
{
|
||||
type: "delete",
|
||||
btnName: "删除",
|
||||
},
|
||||
];
|
||||
export default {
|
||||
mixins: [basicPage],
|
||||
data() {
|
||||
return {
|
||||
urlOptions: {
|
||||
getDataListURL: "/sys/dict/type/page",
|
||||
deleteURL: "/sys/dict/type",
|
||||
},
|
||||
tableProps,
|
||||
tableBtn,
|
||||
formConfig: [
|
||||
{
|
||||
type: "input",
|
||||
label: i18n.t("dict.dictName"),
|
||||
placeholder: i18n.t("dict.dictName"),
|
||||
param: "dictName",
|
||||
},
|
||||
{
|
||||
type: "input",
|
||||
label: i18n.t("dict.dictType"),
|
||||
placeholder: i18n.t("dict.dictType"),
|
||||
param: "dictType",
|
||||
},
|
||||
{
|
||||
type: "button",
|
||||
btnName: "查询",
|
||||
name: "search",
|
||||
color: "primary",
|
||||
},
|
||||
{
|
||||
type: "button",
|
||||
btnName: "新增",
|
||||
name: "add",
|
||||
color: "primary",
|
||||
plain: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
components: {
|
||||
AddOrUpdate,
|
||||
},
|
||||
methods:{
|
||||
//search-bar点击
|
||||
buttonClick(val) {
|
||||
switch (val.btnName) {
|
||||
case "search":
|
||||
this.listQuery.dictName = val.dictName;
|
||||
this.listQuery.dictType = val.dictType;
|
||||
this.listQuery.page = 1;
|
||||
this.getDataList();
|
||||
break;
|
||||
case "add":
|
||||
this.addOrEditTitle = '新增'
|
||||
this.addOrUpdateVisible = true;
|
||||
this.addOrUpdateHandle()
|
||||
break;
|
||||
default:
|
||||
console.log(val)
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
99
src/views/modules/sys/log-error.vue
Normal file
99
src/views/modules/sys/log-error.vue
Normal file
@@ -0,0 +1,99 @@
|
||||
<!--
|
||||
* @Author: zwq
|
||||
* @Date: 2023-01-04 10:29:40
|
||||
* @LastEditors: zwq
|
||||
* @LastEditTime: 2023-01-05 15:29:06
|
||||
* @Description:
|
||||
-->
|
||||
<template>
|
||||
<el-card shadow="never" class="aui-card--fill">
|
||||
<div class="mod-sys__user">
|
||||
<search-bar :formConfigs="formConfig" ref="searchBarForm" @headBtnClick="buttonClick" />
|
||||
<base-table
|
||||
:table-props="tableProps"
|
||||
:page="listQuery.page"
|
||||
:limit="listQuery.limit"
|
||||
:table-data="tableData"
|
||||
/>
|
||||
<pagination
|
||||
:limit.sync="listQuery.limit"
|
||||
:page.sync="listQuery.page"
|
||||
:total="listQuery.total"
|
||||
@pagination="getDataList"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import basicPage from "@/mixins/basic-page";
|
||||
import i18n from "@/i18n";
|
||||
import Cookies from 'js-cookie'
|
||||
import qs from 'qs'
|
||||
const tableProps = [
|
||||
{
|
||||
prop: "requestUri",
|
||||
label: i18n.t("logError.requestUri"),
|
||||
},
|
||||
{
|
||||
prop: "requestMethod",
|
||||
label: i18n.t("logError.requestMethod"),
|
||||
},
|
||||
{
|
||||
prop: "requestParams",
|
||||
label: i18n.t("logError.requestParams"),
|
||||
},
|
||||
{
|
||||
prop: "ip",
|
||||
label: i18n.t("logError.ip"),
|
||||
},
|
||||
{
|
||||
prop: "userAgent",
|
||||
label: i18n.t("logError.userAgent"),
|
||||
},
|
||||
{
|
||||
prop: "createDate",
|
||||
label: i18n.t("logError.createDate"),
|
||||
},
|
||||
];
|
||||
export default {
|
||||
mixins: [basicPage],
|
||||
data() {
|
||||
return {
|
||||
urlOptions: {
|
||||
getDataListURL: "/sys/log/error/page",
|
||||
exportUrl: "/sys/log/error/export",
|
||||
},
|
||||
tableProps,
|
||||
formConfig: [
|
||||
{
|
||||
type: "button",
|
||||
btnName: "导出",
|
||||
name: "export",
|
||||
color: "primary",
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
components: {},
|
||||
methods:{
|
||||
//search-bar点击
|
||||
buttonClick(val) {
|
||||
switch (val.btnName) {
|
||||
case "export":
|
||||
this.exportHandle();
|
||||
break;
|
||||
default:
|
||||
console.log(val)
|
||||
}
|
||||
},
|
||||
// 导出
|
||||
exportHandle () {
|
||||
var params = qs.stringify({
|
||||
'token': Cookies.get('token')
|
||||
})
|
||||
window.location.href = `${window.SITE_CONFIG['apiURL']}${this.urlOptions.exportURL}?${params}`
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
121
src/views/modules/sys/log-login.vue
Normal file
121
src/views/modules/sys/log-login.vue
Normal file
@@ -0,0 +1,121 @@
|
||||
<!--
|
||||
* @Author: zwq
|
||||
* @Date: 2023-01-04 10:29:40
|
||||
* @LastEditors: zwq
|
||||
* @LastEditTime: 2023-01-05 15:49:17
|
||||
* @Description:
|
||||
-->
|
||||
<template>
|
||||
<el-card shadow="never" class="aui-card--fill">
|
||||
<div class="mod-sys__user">
|
||||
<search-bar :formConfigs="formConfig" ref="searchBarForm" @headBtnClick="buttonClick" />
|
||||
<base-table
|
||||
:table-props="tableProps"
|
||||
:page="listQuery.page"
|
||||
:limit="listQuery.limit"
|
||||
:table-data="tableData"
|
||||
/>
|
||||
<pagination
|
||||
:limit.sync="listQuery.limit"
|
||||
:page.sync="listQuery.page"
|
||||
:total="listQuery.total"
|
||||
@pagination="getDataList"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import basicPage from "@/mixins/basic-page";
|
||||
import i18n from "@/i18n";
|
||||
import sysFilter from '@/filters/sys-filter'
|
||||
const tableProps = [
|
||||
{
|
||||
prop: "creatorName",
|
||||
label: i18n.t("logLogin.creatorName"),
|
||||
},
|
||||
{
|
||||
prop: "operation",
|
||||
label: i18n.t("logLogin.operation"),
|
||||
filter: sysFilter('logOperation'),
|
||||
},
|
||||
{
|
||||
prop: "status",
|
||||
label: i18n.t("logLogin.status"),
|
||||
filter: sysFilter('logStatus'),
|
||||
},
|
||||
{
|
||||
prop: "ip",
|
||||
label: i18n.t("logLogin.ip"),
|
||||
},
|
||||
{
|
||||
prop: "userAgent",
|
||||
label: i18n.t("logLogin.userAgent"),
|
||||
},
|
||||
{
|
||||
prop: "createDate",
|
||||
label: i18n.t("logLogin.createDate"),
|
||||
},
|
||||
];
|
||||
export default {
|
||||
mixins: [basicPage],
|
||||
data() {
|
||||
return {
|
||||
urlOptions: {
|
||||
getDataListURL: "/sys/log/login/page",
|
||||
deleteURL: "/sys/log/login",
|
||||
exportUrl: "/sys/log/login/export",
|
||||
},
|
||||
tableProps,
|
||||
formConfig: [
|
||||
{
|
||||
type: "input",
|
||||
label: i18n.t("logLogin.creatorName"),
|
||||
placeholder: i18n.t("logLogin.creatorName"),
|
||||
param: "creatorName",
|
||||
},
|
||||
{
|
||||
type: "select",
|
||||
label: "状态",
|
||||
selectOptions: [
|
||||
{ id: "0", name: i18n.t("logLogin.status0") },
|
||||
{ id: "1", name: i18n.t("logLogin.status1") },
|
||||
{ id: "2", name: i18n.t("logLogin.status2") },
|
||||
],
|
||||
param: "status",
|
||||
defaultSelect: "",
|
||||
onchange: true,
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
type: "button",
|
||||
btnName: "查询",
|
||||
name: "search",
|
||||
color: "primary",
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
components: {},
|
||||
methods:{
|
||||
//search-bar点击
|
||||
buttonClick(val) {
|
||||
switch (val.btnName) {
|
||||
case "search":
|
||||
this.listQuery.creatorName = val.creatorName;
|
||||
this.listQuery.status = val.status;
|
||||
this.listQuery.page = 1;
|
||||
this.getDataList();
|
||||
break;
|
||||
case "add":
|
||||
this.addOrEditTitle = '新增'
|
||||
this.addOrUpdateVisible = true;
|
||||
this.addOrUpdateHandle()
|
||||
break;
|
||||
default:
|
||||
console.log(val)
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
127
src/views/modules/sys/log-operation.vue
Normal file
127
src/views/modules/sys/log-operation.vue
Normal file
@@ -0,0 +1,127 @@
|
||||
<!--
|
||||
* @Author: zwq
|
||||
* @Date: 2023-01-04 10:29:40
|
||||
* @LastEditors: zwq
|
||||
* @LastEditTime: 2023-01-05 15:50:27
|
||||
* @Description:
|
||||
-->
|
||||
<template>
|
||||
<el-card shadow="never" class="aui-card--fill">
|
||||
<div class="mod-sys__user">
|
||||
<search-bar :formConfigs="formConfig" ref="searchBarForm" @headBtnClick="buttonClick" />
|
||||
<base-table
|
||||
:table-props="tableProps"
|
||||
:page="listQuery.page"
|
||||
:limit="listQuery.limit"
|
||||
:table-data="tableData"
|
||||
/>
|
||||
<pagination
|
||||
:limit.sync="listQuery.limit"
|
||||
:page.sync="listQuery.page"
|
||||
:total="listQuery.total"
|
||||
@pagination="getDataList"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import basicPage from "@/mixins/basic-page";
|
||||
import i18n from "@/i18n";
|
||||
import sysFilter from '@/filters/sys-filter'
|
||||
const tableProps = [
|
||||
{
|
||||
prop: "creatorName",
|
||||
label: i18n.t("logOperation.creatorName"),
|
||||
},
|
||||
{
|
||||
prop: "operation",
|
||||
label: i18n.t("logOperation.operation"),
|
||||
},
|
||||
{
|
||||
prop: "requestUri",
|
||||
label: i18n.t("logOperation.requestUri"),
|
||||
},
|
||||
{
|
||||
prop: "requestMethod",
|
||||
label: i18n.t("logOperation.requestMethod"),
|
||||
},
|
||||
{
|
||||
prop: "requestParams",
|
||||
label: i18n.t("logOperation.requestParams"),
|
||||
},
|
||||
{
|
||||
prop: "requestTime",
|
||||
label: i18n.t("logOperation.requestTime"),
|
||||
},
|
||||
{
|
||||
prop: "status",
|
||||
label: i18n.t("logOperation.status"),
|
||||
filter: sysFilter('logStatus'),
|
||||
},
|
||||
{
|
||||
prop: "ip",
|
||||
label: i18n.t("logOperation.ip"),
|
||||
},
|
||||
{
|
||||
prop: "userAgent",
|
||||
label: i18n.t("logOperation.userAgent"),
|
||||
},
|
||||
{
|
||||
prop: "createDate",
|
||||
label: i18n.t("logOperation.createDate"),
|
||||
},
|
||||
];
|
||||
export default {
|
||||
mixins: [basicPage],
|
||||
data() {
|
||||
return {
|
||||
urlOptions: {
|
||||
getDataListURL: "/sys/log/operation/page",
|
||||
exportUrl: "/sys/log/operation/export",
|
||||
},
|
||||
tableProps,
|
||||
formConfig: [
|
||||
{
|
||||
type: "select",
|
||||
label: "状态",
|
||||
selectOptions: [
|
||||
{ id: "0", name: i18n.t("logOperation.status0") },
|
||||
{ id: "1", name: i18n.t("logOperation.status1") },
|
||||
],
|
||||
param: "status",
|
||||
defaultSelect: "",
|
||||
onchange: true,
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
type: "button",
|
||||
btnName: "查询",
|
||||
name: "search",
|
||||
color: "primary",
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
components: {},
|
||||
methods:{
|
||||
//search-bar点击
|
||||
buttonClick(val) {
|
||||
switch (val.btnName) {
|
||||
case "search":
|
||||
this.listQuery.status = val.status;
|
||||
this.listQuery.page = 1;
|
||||
this.getDataList();
|
||||
break;
|
||||
case "add":
|
||||
this.addOrEditTitle = '新增'
|
||||
this.addOrUpdateVisible = true;
|
||||
this.addOrUpdateHandle()
|
||||
break;
|
||||
default:
|
||||
console.log(val)
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
222
src/views/modules/sys/menu-add-or-update.vue
Normal file
222
src/views/modules/sys/menu-add-or-update.vue
Normal file
@@ -0,0 +1,222 @@
|
||||
<template>
|
||||
<el-form :model="dataForm" :rules="dataRule" ref="dataForm" @keyup.enter.native="dataFormSubmitHandle()" label-width="120px">
|
||||
<el-form-item prop="type" :label="$t('menu.type')" size="mini">
|
||||
<el-radio-group v-model="dataForm.type" :disabled="!!dataForm.id">
|
||||
<el-radio :label="0">{{ $t('menu.type0') }}</el-radio>
|
||||
<el-radio :label="1">{{ $t('menu.type1') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item prop="name" :label="$t('menu.name')">
|
||||
<el-input v-model="dataForm.name" :placeholder="$t('menu.name')"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="parentName" :label="$t('menu.parentName')" class="menu-list">
|
||||
<el-popover v-model="menuListVisible" ref="menuListPopover" placement="bottom-start" trigger="click">
|
||||
<el-tree
|
||||
:data="menuList"
|
||||
:props="{ label: 'name', children: 'children' }"
|
||||
node-key="id"
|
||||
ref="menuListTree"
|
||||
:highlight-current="true"
|
||||
:expand-on-click-node="false"
|
||||
accordion
|
||||
@current-change="menuListTreeCurrentChangeHandle">
|
||||
</el-tree>
|
||||
</el-popover>
|
||||
<el-input v-model="dataForm.parentName" v-popover:menuListPopover :readonly="true" :placeholder="$t('menu.parentName')">
|
||||
<i v-if="dataForm.pid !== '0'" slot="suffix" @click.stop="deptListTreeSetDefaultHandle()" class="el-icon-circle-close el-input__icon"></i>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="dataForm.type === 0" prop="url" :label="$t('menu.url')">
|
||||
<el-input v-model="dataForm.url" :placeholder="$t('menu.url')"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="sort" :label="$t('menu.sort')">
|
||||
<el-input-number v-model="dataForm.sort" controls-position="right" :min="0" :label="$t('menu.sort')"></el-input-number>
|
||||
</el-form-item>
|
||||
<el-form-item prop="permissions" :label="$t('menu.permissions')">
|
||||
<el-input v-model="dataForm.permissions" :placeholder="$t('menu.permissionsTips')"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="dataForm.type === 0" prop="icon" :label="$t('menu.icon')" class="icon-list">
|
||||
<el-popover v-model="iconListVisible" ref="iconListPopover" placement="bottom-start" trigger="click" popper-class="mod-sys__menu-icon-popover">
|
||||
<div class="mod-sys__menu-icon-inner">
|
||||
<div class="mod-sys__menu-icon-list">
|
||||
<el-button
|
||||
v-for="(item, index) in iconList"
|
||||
:key="index"
|
||||
@click="iconListCurrentChangeHandle(item)"
|
||||
:class="{ 'is-active': dataForm.icon === item }">
|
||||
<svg class="icon-svg" aria-hidden="true"><use :xlink:href="`#${item}`"></use></svg>
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-popover>
|
||||
<el-input v-model="dataForm.icon" v-popover:iconListPopover :readonly="true" :placeholder="$t('menu.icon')"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import debounce from 'lodash/debounce'
|
||||
import { getIconList } from '@/utils'
|
||||
import basicAdd from '@/mixins/basic-add'
|
||||
export default {
|
||||
mixins: [basicAdd],
|
||||
data () {
|
||||
return {
|
||||
urlOptions: {
|
||||
submitURL: '/sys/menu/',
|
||||
infoURL: '/sys/menu'
|
||||
},
|
||||
visible: false,
|
||||
menuList: [],
|
||||
menuListVisible: false,
|
||||
iconList: [],
|
||||
iconListVisible: false,
|
||||
dataForm: {
|
||||
id: '',
|
||||
type: 0,
|
||||
name: '',
|
||||
pid: '0',
|
||||
parentName: '',
|
||||
url: '',
|
||||
permissions: '',
|
||||
sort: 0,
|
||||
icon: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
dataRule () {
|
||||
return {
|
||||
name: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
||||
],
|
||||
parentName: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'change' }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'dataForm.type' (val) {
|
||||
this.$refs['dataForm'].clearValidate()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
init(id) {
|
||||
this.dataForm.id = id || "";
|
||||
this.visible = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs['dataForm'].resetFields()
|
||||
this.iconList = getIconList()
|
||||
this.dataForm.parentName = this.$t('menu.parentNameDefault')
|
||||
this.getMenuList().then(() => {
|
||||
if (this.dataForm.id) {
|
||||
this.getInfo()
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
// 获取菜单列表
|
||||
getMenuList () {
|
||||
return this.$http.get('/sys/menu/list?type=0').then(({ data: res }) => {
|
||||
if (res.code !== 0) {
|
||||
return this.$message.error(res.msg)
|
||||
}
|
||||
this.menuList = res.data
|
||||
}).catch(() => {})
|
||||
},
|
||||
// 获取信息
|
||||
getInfo () {
|
||||
this.$http.get(`/sys/menu/${this.dataForm.id}`).then(({ data: res }) => {
|
||||
if (res.code !== 0) {
|
||||
return this.$message.error(res.msg)
|
||||
}
|
||||
this.dataForm = {
|
||||
...this.dataForm,
|
||||
...res.data
|
||||
}
|
||||
if (this.dataForm.pid === '0') {
|
||||
return this.deptListTreeSetDefaultHandle()
|
||||
}
|
||||
this.$refs.menuListTree.setCurrentKey(this.dataForm.pid)
|
||||
}).catch(() => {})
|
||||
},
|
||||
// 上级菜单树, 设置默认值
|
||||
deptListTreeSetDefaultHandle () {
|
||||
this.dataForm.pid = '0'
|
||||
this.dataForm.parentName = this.$t('menu.parentNameDefault')
|
||||
},
|
||||
// 上级菜单树, 选中
|
||||
menuListTreeCurrentChangeHandle (data) {
|
||||
this.dataForm.pid = data.id
|
||||
this.dataForm.parentName = data.name
|
||||
this.menuListVisible = false
|
||||
},
|
||||
// 图标, 选中
|
||||
iconListCurrentChangeHandle (icon) {
|
||||
this.dataForm.icon = icon
|
||||
this.iconListVisible = false
|
||||
},
|
||||
// 表单提交
|
||||
dataFormSubmitHandle: debounce(function () {
|
||||
this.$refs['dataForm'].validate((valid) => {
|
||||
if (!valid) {
|
||||
return false
|
||||
}
|
||||
this.$http[!this.dataForm.id ? 'post' : 'put']('/sys/menu', this.dataForm).then(({ data: res }) => {
|
||||
if (res.code !== 0) {
|
||||
return this.$message.error(res.msg)
|
||||
}
|
||||
this.$message({
|
||||
message: this.$t('prompt.success'),
|
||||
type: 'success',
|
||||
duration: 500,
|
||||
onClose: () => {
|
||||
this.visible = false
|
||||
this.$emit('refreshDataList')
|
||||
}
|
||||
})
|
||||
}).catch(() => {})
|
||||
})
|
||||
}, 1000, { 'leading': true, 'trailing': false })
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.mod-sys__menu {
|
||||
.menu-list,
|
||||
.icon-list {
|
||||
.el-input__inner,
|
||||
.el-input__suffix {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
&-icon-popover {
|
||||
width: 458px;
|
||||
overflow: hidden;
|
||||
}
|
||||
&-icon-inner {
|
||||
width: 478px;
|
||||
max-height: 258px;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
}
|
||||
&-icon-list {
|
||||
width: 458px;
|
||||
padding: 0;
|
||||
margin: -8px 0 0 -8px;
|
||||
> .el-button {
|
||||
padding: 8px;
|
||||
margin: 8px 0 0 8px;
|
||||
> span {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
133
src/views/modules/sys/menu.vue
Normal file
133
src/views/modules/sys/menu.vue
Normal file
@@ -0,0 +1,133 @@
|
||||
<!--
|
||||
* @Author: zwq
|
||||
* @Date: 2023-01-04 10:29:40
|
||||
* @LastEditors: zwq
|
||||
* @LastEditTime: 2023-01-05 15:47:14
|
||||
* @Description:
|
||||
-->
|
||||
<template>
|
||||
<el-card shadow="never" class="aui-card--fill">
|
||||
<div class="mod-sys__dept">
|
||||
<search-bar :formConfigs="formConfig" ref="searchBarForm" @headBtnClick="buttonClick" />
|
||||
<base-table
|
||||
:table-props="tableProps"
|
||||
:page="listQuery.page"
|
||||
:limit="listQuery.limit"
|
||||
:table-data="tableData"
|
||||
row-key="id"
|
||||
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
|
||||
>
|
||||
<method-btn
|
||||
v-if="tableBtn.length"
|
||||
slot="handleBtn"
|
||||
:width="100"
|
||||
label="操作"
|
||||
:method-list="tableBtn"
|
||||
@clickBtn="handleClick"
|
||||
/>
|
||||
</base-table>
|
||||
<!-- 弹窗, 新增 / 修改 -->
|
||||
<base-dialog
|
||||
:dialogTitle="addOrEditTitle"
|
||||
:dialogVisible="addOrUpdateVisible"
|
||||
@cancel="handleCancel"
|
||||
@confirm="handleConfirm"
|
||||
:before-close="handleCancel"
|
||||
>
|
||||
<add-or-update ref="addOrUpdate" @successSubmit="successSubmit"></add-or-update>
|
||||
</base-dialog>
|
||||
</div>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import basicPage from "@/mixins/basic-page";
|
||||
import AddOrUpdate from './menu-add-or-update'
|
||||
import i18n from "@/i18n";
|
||||
import sysFilter from '@/filters/sys-filter'
|
||||
const tableProps = [
|
||||
{
|
||||
prop: "name",
|
||||
label: i18n.t("menu.name"),
|
||||
},
|
||||
{
|
||||
prop: "icon",
|
||||
label: i18n.t("menu.icon"),
|
||||
},
|
||||
{
|
||||
prop: "type",
|
||||
label: i18n.t("menu.type"),
|
||||
filter: sysFilter('menuType'),
|
||||
},
|
||||
{
|
||||
prop: "sort",
|
||||
label: i18n.t("menu.sort"),
|
||||
},
|
||||
{
|
||||
prop: "url",
|
||||
label: i18n.t("menu.url"),
|
||||
},
|
||||
{
|
||||
prop: "permissions",
|
||||
label: i18n.t("menu.permissions"),
|
||||
},
|
||||
];
|
||||
const tableBtn = [
|
||||
{
|
||||
type: "edit",
|
||||
btnName: "编辑",
|
||||
},
|
||||
{
|
||||
type: "delete",
|
||||
btnName: "删除",
|
||||
},
|
||||
];
|
||||
export default {
|
||||
mixins: [basicPage],
|
||||
data() {
|
||||
return {
|
||||
urlOptions: {
|
||||
getDataListURL: '/sys/menu/list',
|
||||
deleteURL: '/sys/menu'
|
||||
},
|
||||
tableProps,
|
||||
tableBtn,
|
||||
formConfig: [
|
||||
{
|
||||
type: "button",
|
||||
btnName: "新增",
|
||||
name: "add",
|
||||
color: "primary",
|
||||
plain: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
components: {
|
||||
AddOrUpdate,
|
||||
},
|
||||
methods: {
|
||||
// 获取数据列表
|
||||
getDataList() {
|
||||
this.dataListLoading = true;
|
||||
this.$http
|
||||
.get(this.urlOptions.getDataListURL, {
|
||||
params: this.listQuery,
|
||||
})
|
||||
.then(({ data: res }) => {
|
||||
this.dataListLoading = false;
|
||||
if (res.code !== 0) {
|
||||
this.tableData = [];
|
||||
this.listQuery.total = 0;
|
||||
return this.$message.error(res.msg);
|
||||
}
|
||||
this.tableData = res.data;
|
||||
this.listQuery.total = res.data.total;
|
||||
})
|
||||
.catch(() => {
|
||||
this.dataListLoading = false;
|
||||
});
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
101
src/views/modules/sys/params-add-or-update.vue
Normal file
101
src/views/modules/sys/params-add-or-update.vue
Normal file
@@ -0,0 +1,101 @@
|
||||
<!--
|
||||
* @Author: zwq
|
||||
* @Date: 2023-01-04 10:29:40
|
||||
* @LastEditors: zwq
|
||||
* @LastEditTime: 2023-01-05 14:40:11
|
||||
* @Description:
|
||||
-->
|
||||
<template>
|
||||
<el-form :model="dataForm" :rules="dataRule" ref="dataForm" @keyup.enter.native="dataFormSubmitHandle()" label-width="120px">
|
||||
<el-form-item prop="paramCode" :label="$t('params.paramCode')">
|
||||
<el-input v-model="dataForm.paramCode" :placeholder="$t('params.paramCode')"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="paramValue" :label="$t('params.paramValue')">
|
||||
<el-input v-model="dataForm.paramValue" :placeholder="$t('params.paramValue')"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="remark" :label="$t('params.remark')">
|
||||
<el-input v-model="dataForm.remark" :placeholder="$t('params.remark')"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import debounce from 'lodash/debounce'
|
||||
import basicAdd from '@/mixins/basic-add'
|
||||
export default {
|
||||
mixins: [basicAdd],
|
||||
data () {
|
||||
return {
|
||||
urlOptions: {
|
||||
submitURL: '/sys/params/',
|
||||
infoURL: '/sys/params'
|
||||
},
|
||||
visible: false,
|
||||
dataForm: {
|
||||
id: '',
|
||||
paramCode: '',
|
||||
paramValue: '',
|
||||
remark: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
dataRule () {
|
||||
return {
|
||||
paramCode: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
||||
],
|
||||
paramValue: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
init(id) {
|
||||
this.dataForm.id = id || "";
|
||||
this.visible = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs['dataForm'].resetFields()
|
||||
if (this.dataForm.id) {
|
||||
this.getInfo()
|
||||
}
|
||||
})
|
||||
},
|
||||
// 获取信息
|
||||
getInfo () {
|
||||
this.$http.get(`/sys/params/${this.dataForm.id}`).then(({ data: res }) => {
|
||||
if (res.code !== 0) {
|
||||
return this.$message.error(res.msg)
|
||||
}
|
||||
this.dataForm = {
|
||||
...this.dataForm,
|
||||
...res.data
|
||||
}
|
||||
}).catch(() => {})
|
||||
},
|
||||
// 表单提交
|
||||
dataFormSubmitHandle: debounce(function () {
|
||||
this.$refs['dataForm'].validate((valid) => {
|
||||
if (!valid) {
|
||||
return false
|
||||
}
|
||||
this.$http[!this.dataForm.id ? 'post' : 'put']('/sys/params', this.dataForm).then(({ data: res }) => {
|
||||
if (res.code !== 0) {
|
||||
return this.$message.error(res.msg)
|
||||
}
|
||||
this.$message({
|
||||
message: this.$t('prompt.success'),
|
||||
type: 'success',
|
||||
duration: 500,
|
||||
onClose: () => {
|
||||
this.visible = false
|
||||
this.$emit('refreshDataList')
|
||||
}
|
||||
})
|
||||
}).catch(() => {})
|
||||
})
|
||||
}, 1000, { 'leading': true, 'trailing': false })
|
||||
}
|
||||
}
|
||||
</script>
|
||||
124
src/views/modules/sys/params.vue
Normal file
124
src/views/modules/sys/params.vue
Normal file
@@ -0,0 +1,124 @@
|
||||
<template>
|
||||
<el-card shadow="never" class="aui-card--fill">
|
||||
<div class="mod-sys__user">
|
||||
<search-bar :formConfigs="formConfig" ref="searchBarForm" @headBtnClick="buttonClick" />
|
||||
<base-table
|
||||
:table-props="tableProps"
|
||||
:page="listQuery.page"
|
||||
:limit="listQuery.limit"
|
||||
:table-data="tableData"
|
||||
>
|
||||
<method-btn
|
||||
v-if="tableBtn.length"
|
||||
slot="handleBtn"
|
||||
:width="100"
|
||||
label="操作"
|
||||
:method-list="tableBtn"
|
||||
@clickBtn="handleClick"
|
||||
/>
|
||||
</base-table>
|
||||
<pagination
|
||||
:limit.sync="listQuery.limit"
|
||||
:page.sync="listQuery.page"
|
||||
:total="listQuery.total"
|
||||
@pagination="getDataList"
|
||||
/>
|
||||
<!-- 弹窗, 新增 / 修改 -->
|
||||
<base-dialog
|
||||
:dialogTitle="addOrEditTitle"
|
||||
:dialogVisible="addOrUpdateVisible"
|
||||
@cancel="handleCancel"
|
||||
@confirm="handleConfirm"
|
||||
:before-close="handleCancel"
|
||||
>
|
||||
<add-or-update ref="addOrUpdate" @successSubmit="successSubmit"></add-or-update>
|
||||
</base-dialog>
|
||||
</div>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import basicPage from "@/mixins/basic-page";
|
||||
import AddOrUpdate from './params-add-or-update'
|
||||
import i18n from "@/i18n";
|
||||
const tableProps = [
|
||||
{
|
||||
prop: "paramCode",
|
||||
label: i18n.t("params.paramCode"),
|
||||
},
|
||||
{
|
||||
prop: "paramValue",
|
||||
label: i18n.t("params.paramValue"),
|
||||
},
|
||||
{
|
||||
prop: "remark",
|
||||
label: i18n.t("params.remark"),
|
||||
},
|
||||
];
|
||||
const tableBtn = [
|
||||
{
|
||||
type: "edit",
|
||||
btnName: "编辑",
|
||||
},
|
||||
{
|
||||
type: "delete",
|
||||
btnName: "删除",
|
||||
},
|
||||
];
|
||||
export default {
|
||||
mixins: [basicPage],
|
||||
data() {
|
||||
return {
|
||||
urlOptions: {
|
||||
getDataListURL: "/sys/params/page",
|
||||
deleteURL: "/sys/params",
|
||||
},
|
||||
tableProps,
|
||||
tableBtn,
|
||||
formConfig: [
|
||||
{
|
||||
type: "input",
|
||||
label: i18n.t("params.paramCode"),
|
||||
placeholder: i18n.t("params.paramCode"),
|
||||
param: "paramCode",
|
||||
},
|
||||
{
|
||||
type: "button",
|
||||
btnName: "查询",
|
||||
name: "search",
|
||||
color: "primary",
|
||||
},
|
||||
{
|
||||
type: "button",
|
||||
btnName: "新增",
|
||||
name: "add",
|
||||
color: "primary",
|
||||
plain: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
components: {
|
||||
AddOrUpdate,
|
||||
},
|
||||
methods:{
|
||||
//search-bar点击
|
||||
buttonClick(val) {
|
||||
switch (val.btnName) {
|
||||
case "search":
|
||||
this.listQuery.paramCode = val.paramCode;
|
||||
this.listQuery.page = 1;
|
||||
this.getDataList();
|
||||
break;
|
||||
case "add":
|
||||
this.addOrEditTitle = '新增'
|
||||
this.addOrUpdateVisible = true;
|
||||
this.addOrUpdateHandle()
|
||||
break;
|
||||
default:
|
||||
console.log(val)
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
148
src/views/modules/sys/role-add-or-update.vue
Normal file
148
src/views/modules/sys/role-add-or-update.vue
Normal file
@@ -0,0 +1,148 @@
|
||||
<template>
|
||||
<el-form :model="dataForm" :rules="dataRule" ref="dataForm" @keyup.enter.native="dataFormSubmitHandle()" label-width="120px">
|
||||
<el-form-item prop="name" :label="$t('role.name')">
|
||||
<el-input v-model="dataForm.name" :placeholder="$t('role.name')"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="remark" :label="$t('role.remark')">
|
||||
<el-input v-model="dataForm.remark" :placeholder="$t('role.remark')"></el-input>
|
||||
</el-form-item>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item size="mini" :label="$t('role.menuList')">
|
||||
<el-tree
|
||||
:data="menuList"
|
||||
:props="{ label: 'name', children: 'children' }"
|
||||
node-key="id"
|
||||
ref="menuListTree"
|
||||
accordion
|
||||
show-checkbox>
|
||||
</el-tree>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item size="mini" :label="$t('role.deptList')">
|
||||
<el-tree
|
||||
:data="deptList"
|
||||
:props="{ label: 'name', children: 'children' }"
|
||||
node-key="id"
|
||||
ref="deptListTree"
|
||||
accordion
|
||||
show-checkbox>
|
||||
</el-tree>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import debounce from 'lodash/debounce'
|
||||
import basicAdd from '@/mixins/basic-add'
|
||||
export default {
|
||||
mixins: [basicAdd],
|
||||
data () {
|
||||
return {
|
||||
urlOptions: {
|
||||
submitURL: '/sys/role/',
|
||||
infoURL: '/sys/role'
|
||||
},
|
||||
visible: false,
|
||||
menuList: [],
|
||||
deptList: [],
|
||||
dataForm: {
|
||||
id: '',
|
||||
name: '',
|
||||
menuIdList: [],
|
||||
deptIdList: [],
|
||||
remark: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
dataRule () {
|
||||
return {
|
||||
name: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
init(id) {
|
||||
this.dataForm.id = id || "";
|
||||
this.$nextTick(() => {
|
||||
this.$refs['dataForm'].resetFields()
|
||||
this.$refs.menuListTree.setCheckedKeys([])
|
||||
this.$refs.deptListTree.setCheckedKeys([])
|
||||
Promise.all([
|
||||
this.getMenuList(),
|
||||
this.getDeptList()
|
||||
]).then(() => {
|
||||
if (this.dataForm.id) {
|
||||
this.getInfo()
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
// 获取菜单列表
|
||||
getMenuList () {
|
||||
return this.$http.get('/sys/menu/select').then(({ data: res }) => {
|
||||
if (res.code !== 0) {
|
||||
return this.$message.error(res.msg)
|
||||
}
|
||||
this.menuList = res.data
|
||||
}).catch(() => {})
|
||||
},
|
||||
// 获取部门列表
|
||||
getDeptList () {
|
||||
return this.$http.get('/sys/dept/list').then(({ data: res }) => {
|
||||
if (res.code !== 0) {
|
||||
return this.$message.error(res.msg)
|
||||
}
|
||||
this.deptList = res.data
|
||||
}).catch(() => {})
|
||||
},
|
||||
// 获取信息
|
||||
getInfo () {
|
||||
this.$http.get(`/sys/role/${this.dataForm.id}`).then(({ data: res }) => {
|
||||
if (res.code !== 0) {
|
||||
return this.$message.error(res.msg)
|
||||
}
|
||||
this.dataForm = {
|
||||
...this.dataForm,
|
||||
...res.data
|
||||
}
|
||||
this.dataForm.menuIdList.forEach(item => this.$refs.menuListTree.setChecked(item, true))
|
||||
this.$refs.deptListTree.setCheckedKeys(this.dataForm.deptIdList)
|
||||
}).catch(() => {})
|
||||
},
|
||||
// 表单提交
|
||||
dataFormSubmitHandle: debounce(function () {
|
||||
this.$refs['dataForm'].validate((valid) => {
|
||||
if (!valid) {
|
||||
return false
|
||||
}
|
||||
this.dataForm.menuIdList = [
|
||||
...this.$refs.menuListTree.getHalfCheckedKeys(),
|
||||
...this.$refs.menuListTree.getCheckedKeys()
|
||||
]
|
||||
this.dataForm.deptIdList = this.$refs.deptListTree.getCheckedKeys()
|
||||
this.$http[!this.dataForm.id ? 'post' : 'put']('/sys/role', this.dataForm).then(({ data: res }) => {
|
||||
if (res.code !== 0) {
|
||||
return this.$message.error(res.msg)
|
||||
}
|
||||
this.$message({
|
||||
message: this.$t('prompt.success'),
|
||||
type: 'success',
|
||||
duration: 500,
|
||||
onClose: () => {
|
||||
this.visible = false
|
||||
this.$emit('refreshDataList')
|
||||
}
|
||||
})
|
||||
}).catch(() => {})
|
||||
})
|
||||
}, 1000, { 'leading': true, 'trailing': false })
|
||||
}
|
||||
}
|
||||
</script>
|
||||
124
src/views/modules/sys/role.vue
Normal file
124
src/views/modules/sys/role.vue
Normal file
@@ -0,0 +1,124 @@
|
||||
<template>
|
||||
<el-card shadow="never" class="aui-card--fill">
|
||||
<div class="mod-sys__user">
|
||||
<search-bar :formConfigs="formConfig" ref="searchBarForm" @headBtnClick="buttonClick" />
|
||||
<base-table
|
||||
:table-props="tableProps"
|
||||
:page="listQuery.page"
|
||||
:limit="listQuery.limit"
|
||||
:table-data="tableData"
|
||||
>
|
||||
<method-btn
|
||||
v-if="tableBtn.length"
|
||||
slot="handleBtn"
|
||||
:width="100"
|
||||
label="操作"
|
||||
:method-list="tableBtn"
|
||||
@clickBtn="handleClick"
|
||||
/>
|
||||
</base-table>
|
||||
<pagination
|
||||
:limit.sync="listQuery.limit"
|
||||
:page.sync="listQuery.page"
|
||||
:total="listQuery.total"
|
||||
@pagination="getDataList"
|
||||
/>
|
||||
<!-- 弹窗, 新增 / 修改 -->
|
||||
<base-dialog
|
||||
:dialogTitle="addOrEditTitle"
|
||||
:dialogVisible="addOrUpdateVisible"
|
||||
@cancel="handleCancel"
|
||||
@confirm="handleConfirm"
|
||||
:before-close="handleCancel"
|
||||
>
|
||||
<add-or-update ref="addOrUpdate" @successSubmit="successSubmit"></add-or-update>
|
||||
</base-dialog>
|
||||
</div>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import basicPage from "@/mixins/basic-page";
|
||||
import AddOrUpdate from './role-add-or-update'
|
||||
import i18n from "@/i18n";
|
||||
const tableProps = [
|
||||
{
|
||||
prop: "name",
|
||||
label: i18n.t("role.name"),
|
||||
},
|
||||
{
|
||||
prop: "remark",
|
||||
label: i18n.t("role.remark"),
|
||||
},
|
||||
{
|
||||
prop: "createDate",
|
||||
label: i18n.t("role.createDate"),
|
||||
},
|
||||
];
|
||||
const tableBtn = [
|
||||
{
|
||||
type: "edit",
|
||||
btnName: "编辑",
|
||||
},
|
||||
{
|
||||
type: "delete",
|
||||
btnName: "删除",
|
||||
},
|
||||
];
|
||||
export default {
|
||||
mixins: [basicPage],
|
||||
data() {
|
||||
return {
|
||||
urlOptions: {
|
||||
getDataListURL: '/sys/role/page',
|
||||
deleteURL: '/sys/role',
|
||||
},
|
||||
tableProps,
|
||||
tableBtn,
|
||||
formConfig: [
|
||||
{
|
||||
type: "input",
|
||||
label: i18n.t("role.name"),
|
||||
placeholder: i18n.t("role.name"),
|
||||
param: "name",
|
||||
},
|
||||
{
|
||||
type: "button",
|
||||
btnName: "查询",
|
||||
name: "search",
|
||||
color: "primary",
|
||||
},
|
||||
{
|
||||
type: "button",
|
||||
btnName: "新增",
|
||||
name: "add",
|
||||
color: "primary",
|
||||
plain: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
components: {
|
||||
AddOrUpdate,
|
||||
},
|
||||
methods:{
|
||||
//search-bar点击
|
||||
buttonClick(val) {
|
||||
switch (val.btnName) {
|
||||
case "search":
|
||||
this.listQuery.name = val.name;
|
||||
this.listQuery.page = 1;
|
||||
this.getDataList();
|
||||
break;
|
||||
case "add":
|
||||
this.addOrEditTitle = '新增'
|
||||
this.addOrUpdateVisible = true;
|
||||
this.addOrUpdateHandle()
|
||||
break;
|
||||
default:
|
||||
console.log(val)
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
213
src/views/modules/sys/user-add-or-update.vue
Normal file
213
src/views/modules/sys/user-add-or-update.vue
Normal file
@@ -0,0 +1,213 @@
|
||||
<template>
|
||||
<el-form :model="dataForm" :rules="dataRule" ref="dataForm" @keyup.enter.native="dataFormSubmit()" label-width="120px">
|
||||
<el-form-item prop="username" :label="$t('user.username')">
|
||||
<el-input v-model="dataForm.username" :placeholder="$t('user.username')"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="deptName" :label="$t('user.deptName')">
|
||||
<ren-dept-tree v-model="dataForm.deptId" :placeholder="$t('dept.title')" :dept-name.sync="dataForm.deptName"></ren-dept-tree>
|
||||
</el-form-item>
|
||||
<el-form-item prop="password" :label="$t('user.password')" :class="{ 'is-required': !dataForm.id }">
|
||||
<el-input v-model="dataForm.password" type="password" :placeholder="$t('user.password')"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="confirmPassword" :label="$t('user.confirmPassword')" :class="{ 'is-required': !dataForm.id }">
|
||||
<el-input v-model="dataForm.confirmPassword" type="password" :placeholder="$t('user.confirmPassword')"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="realName" :label="$t('user.realName')">
|
||||
<el-input v-model="dataForm.realName" :placeholder="$t('user.realName')"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="gender" :label="$t('user.gender')">
|
||||
<ren-radio-group v-model="dataForm.gender" dict-type="gender"></ren-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item prop="email" :label="$t('user.email')">
|
||||
<el-input v-model="dataForm.email" :placeholder="$t('user.email')"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="mobile" :label="$t('user.mobile')">
|
||||
<el-input v-model="dataForm.mobile" :placeholder="$t('user.mobile')"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="roleIdList" :label="$t('user.roleIdList')" class="role-list">
|
||||
<el-select v-model="dataForm.roleIdList" multiple :placeholder="$t('user.roleIdList')">
|
||||
<el-option v-for="role in roleList" :key="role.id" :label="role.name" :value="role.id"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item prop="status" :label="$t('user.status')" size="mini">
|
||||
<el-radio-group v-model="dataForm.status">
|
||||
<el-radio :label="0">{{ $t('user.status0') }}</el-radio>
|
||||
<el-radio :label="1">{{ $t('user.status1') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import debounce from 'lodash/debounce'
|
||||
import { isEmail, isMobile } from '@/utils/validate'
|
||||
import basicAdd from '@/mixins/basic-add'
|
||||
export default {
|
||||
mixins: [basicAdd],
|
||||
data () {
|
||||
return {
|
||||
urlOptions: {
|
||||
submitURL: '/sys/user/',
|
||||
infoURL: '/sys/user'
|
||||
},
|
||||
visible: false,
|
||||
roleList: [],
|
||||
roleIdListDefault: [],
|
||||
dataForm: {
|
||||
id: '',
|
||||
username: '',
|
||||
deptId: '',
|
||||
deptName: '',
|
||||
password: '',
|
||||
confirmPassword: '',
|
||||
realName: '',
|
||||
gender: 0,
|
||||
email: '',
|
||||
mobile: '',
|
||||
roleIdList: [],
|
||||
status: 1
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
dataRule () {
|
||||
var validatePassword = (rule, value, callback) => {
|
||||
if (!this.dataForm.id && !/\S/.test(value)) {
|
||||
return callback(new Error(this.$t('validate.required')))
|
||||
}
|
||||
callback()
|
||||
}
|
||||
var validateConfirmPassword = (rule, value, callback) => {
|
||||
if (!this.dataForm.id && !/\S/.test(value)) {
|
||||
return callback(new Error(this.$t('validate.required')))
|
||||
}
|
||||
if (this.dataForm.password !== value) {
|
||||
return callback(new Error(this.$t('user.validate.confirmPassword')))
|
||||
}
|
||||
callback()
|
||||
}
|
||||
var validateEmail = (rule, value, callback) => {
|
||||
if (value && !isEmail(value)) {
|
||||
return callback(new Error(this.$t('validate.format', { 'attr': this.$t('user.email') })))
|
||||
}
|
||||
callback()
|
||||
}
|
||||
var validateMobile = (rule, value, callback) => {
|
||||
if (value && !isMobile(value)) {
|
||||
return callback(new Error(this.$t('validate.format', { 'attr': this.$t('user.mobile') })))
|
||||
}
|
||||
callback()
|
||||
}
|
||||
return {
|
||||
username: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
||||
],
|
||||
deptName: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'change' }
|
||||
],
|
||||
password: [
|
||||
{ validator: validatePassword, trigger: 'blur' }
|
||||
],
|
||||
confirmPassword: [
|
||||
{ validator: validateConfirmPassword, trigger: 'blur' }
|
||||
],
|
||||
realName: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
||||
],
|
||||
email: [
|
||||
{ validator: validateEmail, trigger: 'blur' }
|
||||
],
|
||||
mobile: [
|
||||
{ validator: validateMobile, trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
init(id) {
|
||||
this.dataForm.id = id || "";
|
||||
this.visible = true
|
||||
this.dataForm.deptId = ''
|
||||
this.$nextTick(() => {
|
||||
this.$refs['dataForm'].resetFields()
|
||||
this.roleIdListDefault = []
|
||||
Promise.all([
|
||||
this.getRoleList()
|
||||
]).then(() => {
|
||||
if (this.dataForm.id) {
|
||||
this.getInfo()
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
// 获取角色列表
|
||||
getRoleList () {
|
||||
return this.$http.get('/sys/role/list').then(({ data: res }) => {
|
||||
if (res.code !== 0) {
|
||||
return this.$message.error(res.msg)
|
||||
}
|
||||
this.roleList = res.data
|
||||
}).catch(() => {})
|
||||
},
|
||||
// 获取信息
|
||||
getInfo () {
|
||||
this.$http.get(`/sys/user/${this.dataForm.id}`).then(({ data: res }) => {
|
||||
if (res.code !== 0) {
|
||||
return this.$message.error(res.msg)
|
||||
}
|
||||
this.dataForm = {
|
||||
...this.dataForm,
|
||||
...res.data,
|
||||
roleIdList: []
|
||||
}
|
||||
// 角色配置, 区分是否为默认角色
|
||||
for (var i = 0; i < res.data.roleIdList.length; i++) {
|
||||
if (this.roleList.filter(item => item.id === res.data.roleIdList[i])[0]) {
|
||||
this.dataForm.roleIdList.push(res.data.roleIdList[i])
|
||||
continue
|
||||
}
|
||||
this.roleIdListDefault.push(res.data.roleIdList[i])
|
||||
}
|
||||
}).catch(() => {})
|
||||
},
|
||||
// 表单提交
|
||||
dataFormSubmit: debounce(function () {
|
||||
this.$refs['dataForm'].validate((valid) => {
|
||||
if (!valid) {
|
||||
return false
|
||||
}
|
||||
this.$http[!this.dataForm.id ? 'post' : 'put']('/sys/user', {
|
||||
...this.dataForm,
|
||||
roleIdList: [
|
||||
...this.dataForm.roleIdList,
|
||||
...this.roleIdListDefault
|
||||
]
|
||||
}).then(({ data: res }) => {
|
||||
if (res.code !== 0) {
|
||||
return this.$message.error(res.msg)
|
||||
}
|
||||
this.$message({
|
||||
message: this.$t('prompt.success'),
|
||||
type: 'success',
|
||||
duration: 500,
|
||||
onClose: () => {
|
||||
this.visible = false
|
||||
this.$emit('refreshDataList')
|
||||
}
|
||||
})
|
||||
}).catch(() => {})
|
||||
})
|
||||
}, 1000, { 'leading': true, 'trailing': false })
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.mod-sys__user {
|
||||
.role-list {
|
||||
.el-select {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
144
src/views/modules/sys/user.vue
Normal file
144
src/views/modules/sys/user.vue
Normal file
@@ -0,0 +1,144 @@
|
||||
<template>
|
||||
<el-card shadow="never" class="aui-card--fill">
|
||||
<div class="mod-sys__user">
|
||||
<search-bar :formConfigs="formConfig" ref="searchBarForm" @headBtnClick="buttonClick" />
|
||||
<base-table
|
||||
:table-props="tableProps"
|
||||
:page="listQuery.page"
|
||||
:limit="listQuery.limit"
|
||||
:table-data="tableData"
|
||||
>
|
||||
<method-btn
|
||||
v-if="tableBtn.length"
|
||||
slot="handleBtn"
|
||||
:width="100"
|
||||
label="操作"
|
||||
:method-list="tableBtn"
|
||||
@clickBtn="handleClick"
|
||||
/>
|
||||
</base-table>
|
||||
<pagination
|
||||
:limit.sync="listQuery.limit"
|
||||
:page.sync="listQuery.page"
|
||||
:total="listQuery.total"
|
||||
@pagination="getDataList"
|
||||
/>
|
||||
<!-- 弹窗, 新增 / 修改 -->
|
||||
<base-dialog
|
||||
:dialogTitle="addOrEditTitle"
|
||||
:dialogVisible="addOrUpdateVisible"
|
||||
@cancel="handleCancel"
|
||||
@confirm="handleConfirm"
|
||||
:before-close="handleCancel"
|
||||
>
|
||||
<add-or-update ref="addOrUpdate" @successSubmit="successSubmit"></add-or-update>
|
||||
</base-dialog>
|
||||
</div>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import basicPage from "@/mixins/basic-page";
|
||||
import AddOrUpdate from "./user-add-or-update";
|
||||
import i18n from "@/i18n";
|
||||
import sysFilter from '@/filters/sys-filter'
|
||||
const tableProps = [
|
||||
{
|
||||
prop: "username",
|
||||
label: i18n.t("user.username"),
|
||||
},
|
||||
{
|
||||
prop: "deptName",
|
||||
label: i18n.t("user.deptName"),
|
||||
},
|
||||
{
|
||||
prop: "email",
|
||||
label: i18n.t("user.email"),
|
||||
},
|
||||
{
|
||||
prop: "mobile",
|
||||
label: i18n.t("user.mobile"),
|
||||
},
|
||||
{
|
||||
prop: "gender",
|
||||
label: i18n.t("user.gender"),
|
||||
filter: sysFilter('sex'),
|
||||
},
|
||||
{
|
||||
prop: "status",
|
||||
label: i18n.t("user.status"),
|
||||
filter: sysFilter('userStatus'),
|
||||
},
|
||||
{
|
||||
prop: "createDate",
|
||||
label: i18n.t("user.createDate"),
|
||||
},
|
||||
];
|
||||
const tableBtn = [
|
||||
{
|
||||
type: "edit",
|
||||
btnName: "编辑",
|
||||
},
|
||||
{
|
||||
type: "delete",
|
||||
btnName: "删除",
|
||||
},
|
||||
];
|
||||
export default {
|
||||
mixins: [basicPage],
|
||||
data() {
|
||||
return {
|
||||
urlOptions: {
|
||||
getDataListURL: "/sys/user/page",
|
||||
deleteURL: "/sys/user",
|
||||
exportUrl: "/sys/user/export",
|
||||
},
|
||||
tableProps,
|
||||
tableBtn,
|
||||
formConfig: [
|
||||
{
|
||||
type: "input",
|
||||
label: i18n.t("user.username"),
|
||||
placeholder: i18n.t("user.username"),
|
||||
param: "username",
|
||||
},
|
||||
{
|
||||
type: "button",
|
||||
btnName: "查询",
|
||||
name: "search",
|
||||
color: "primary",
|
||||
},
|
||||
{
|
||||
type: "button",
|
||||
btnName: "新增",
|
||||
name: "add",
|
||||
color: "primary",
|
||||
plain: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
components: {
|
||||
AddOrUpdate,
|
||||
},
|
||||
methods:{
|
||||
//search-bar点击
|
||||
buttonClick(val) {
|
||||
switch (val.btnName) {
|
||||
case "search":
|
||||
this.listQuery.username = val.username;
|
||||
this.listQuery.page = 1;
|
||||
this.getDataList();
|
||||
break;
|
||||
case "add":
|
||||
this.addOrEditTitle = '新增'
|
||||
this.addOrUpdateVisible = true;
|
||||
this.addOrUpdateHandle()
|
||||
break;
|
||||
default:
|
||||
console.log(val)
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
19
src/views/pages/404.vue
Normal file
19
src/views/pages/404.vue
Normal file
@@ -0,0 +1,19 @@
|
||||
<template>
|
||||
<div class="aui-wrapper aui-page__not-found">
|
||||
<div class="aui-content__wrapper">
|
||||
<div class="aui-content">
|
||||
<h2 class="title">400</h2>
|
||||
<p class="desc" v-html="$t('notFound.desc')"></p>
|
||||
<div class="btn-bar">
|
||||
<el-button @click="$router.go(-1)">{{ $t('notFound.back') }}</el-button>
|
||||
<el-button type="primary" @click="$router.push({ name: 'home' })">{{ $t('notFound.home') }}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
}
|
||||
</script>
|
||||
110
src/views/pages/login copy.vue
Normal file
110
src/views/pages/login copy.vue
Normal file
@@ -0,0 +1,110 @@
|
||||
<template>
|
||||
<div class="aui-wrapper aui-page__login">
|
||||
<div class="aui-content__wrapper">
|
||||
<main class="aui-content">
|
||||
<div class="login-header">
|
||||
<h2 class="login-brand">{{ $t('brand.lg') }}</h2>
|
||||
</div>
|
||||
<div class="login-body">
|
||||
<h3 class="login-title">{{ $t('login.title') }}</h3>
|
||||
<el-form :model="dataForm" :rules="dataRule" ref="dataForm" @keyup.enter.native="dataFormSubmitHandle()" status-icon>
|
||||
<el-form-item prop="username">
|
||||
<el-input v-model="dataForm.username" :placeholder="$t('login.username')">
|
||||
<span slot="prefix" class="el-input__icon">
|
||||
<svg class="icon-svg" aria-hidden="true"><use xlink:href="#icon-user"></use></svg>
|
||||
</span>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="password">
|
||||
<el-input v-model="dataForm.password" type="password" :placeholder="$t('login.password')">
|
||||
<span slot="prefix" class="el-input__icon">
|
||||
<svg class="icon-svg" aria-hidden="true"><use xlink:href="#icon-lock"></use></svg>
|
||||
</span>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="captcha">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="14">
|
||||
<el-input v-model="dataForm.captcha" :placeholder="$t('login.captcha')">
|
||||
<span slot="prefix" class="el-input__icon">
|
||||
<svg class="icon-svg" aria-hidden="true"><use xlink:href="#icon-safetycertificate"></use></svg>
|
||||
</span>
|
||||
</el-input>
|
||||
</el-col>
|
||||
<el-col :span="10" class="login-captcha">
|
||||
<img :src="captchaPath" @click="getCaptcha()">
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="dataFormSubmitHandle()" class="w-percent-100">{{ $t('login.title') }}</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="login-footer">
|
||||
<p>{{ $t('login.copyright') }}</p>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Cookies from 'js-cookie'
|
||||
import debounce from 'lodash/debounce'
|
||||
import { getUUID } from '@/utils'
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
captchaPath: '',
|
||||
dataForm: {
|
||||
username: 'admin',
|
||||
password: 'admin',
|
||||
uuid: 'string',
|
||||
captcha: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
dataRule () {
|
||||
return {
|
||||
username: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
||||
],
|
||||
password: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
||||
],
|
||||
captcha: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.getCaptcha()
|
||||
},
|
||||
methods: {
|
||||
// 获取验证码
|
||||
getCaptcha () {
|
||||
this.dataForm.uuid = getUUID()
|
||||
this.captchaPath = `${window.SITE_CONFIG['apiURL']}/captcha?uuid=${this.dataForm.uuid}`
|
||||
},
|
||||
// 表单提交
|
||||
dataFormSubmitHandle: debounce(function () {
|
||||
this.$refs['dataForm'].validate((valid) => {
|
||||
if (!valid) {
|
||||
return false
|
||||
}
|
||||
this.$http.post('/login', this.dataForm).then(({ data: res }) => {
|
||||
if (res.code !== 0) {
|
||||
this.getCaptcha()
|
||||
return this.$message.error(res.msg)
|
||||
}
|
||||
Cookies.set('token', res.data.token)
|
||||
this.$router.replace({ name: 'home' })
|
||||
}).catch(() => {})
|
||||
})
|
||||
}, 1000, { 'leading': true, 'trailing': false })
|
||||
}
|
||||
}
|
||||
</script>
|
||||
441
src/views/pages/login.vue
Normal file
441
src/views/pages/login.vue
Normal file
@@ -0,0 +1,441 @@
|
||||
<template>
|
||||
<div class="login-container">
|
||||
<div
|
||||
class="login-background"
|
||||
:style="{
|
||||
backgroundImage: 'url(' + (coverImgUrl ? coverImgUrl : baseImg) + ')',
|
||||
backgroundSize: '100% 100%',
|
||||
backgroundRepeat: 'no-repeat',
|
||||
}"
|
||||
>
|
||||
<div class="login-background-container">
|
||||
<div class="back-title">
|
||||
Wel<span>come</span>
|
||||
<p>
|
||||
<span class="back-title-point" />>>>项目名称<<<
|
||||
</p>
|
||||
</div>
|
||||
<img
|
||||
:src="require('../../assets/img/login.gif')"
|
||||
style="width: 90%; margin-left: 5%"
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<el-form
|
||||
ref="dataForm"
|
||||
:model="dataForm"
|
||||
:rules="dataRule"
|
||||
class="login-form"
|
||||
autocomplete="on"
|
||||
label-position="left"
|
||||
>
|
||||
<div class="title-container">
|
||||
<h3 class="title" :title="'标题'">
|
||||
<img
|
||||
src="../../assets/img/cnbm.png"
|
||||
style="width: 1em; height: 1em; position: relative; top: .15em; margin-right: 12px"
|
||||
alt=""
|
||||
/>
|
||||
<!-- {{ "title" | i18nFilter }} -->
|
||||
中建材智能自动化院
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<el-form-item prop="username" style="margin: 0px 8.3%">
|
||||
<el-input
|
||||
ref="username"
|
||||
v-model="dataForm.username"
|
||||
:placeholder="'请输入用户名'"
|
||||
name="username"
|
||||
type="text"
|
||||
tabindex="1"
|
||||
autocomplete="on"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-tooltip
|
||||
v-model="capsTooltip"
|
||||
content="Caps lock is On"
|
||||
placement="right"
|
||||
manual
|
||||
>
|
||||
<el-form-item prop="password" style="margin: 8px 8.3%">
|
||||
<el-input
|
||||
:key="passwordType"
|
||||
ref="password"
|
||||
v-model="dataForm.password"
|
||||
:type="passwordType"
|
||||
:placeholder="'请输入密码'"
|
||||
name="password"
|
||||
tabindex="2"
|
||||
autocomplete="on"
|
||||
@keyup.native="checkCapslock"
|
||||
@blur="capsTooltip = false"
|
||||
@keyup.enter.native="dataFormSubmitHandle"
|
||||
/>
|
||||
<span class="show-pwd" @click="showPwd">
|
||||
<!-- <svg-icon
|
||||
:icon-class="passwordType === 'password' ? 'eye' : 'eye-open'"
|
||||
/> -->
|
||||
</span>
|
||||
</el-form-item>
|
||||
</el-tooltip>
|
||||
|
||||
<el-form-item prop="captcha" style="margin: 0px 8.3%">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="14">
|
||||
<el-input
|
||||
v-model="dataForm.captcha"
|
||||
:placeholder="$t('login.captcha')"
|
||||
>
|
||||
<!-- <span slot="prefix" class="el-input__icon">
|
||||
<svg class="icon-svg" aria-hidden="true">
|
||||
<use xlink:href="#icon-safetycertificate"></use>
|
||||
</svg>
|
||||
</span> -->
|
||||
</el-input>
|
||||
</el-col>
|
||||
<el-col :span="10" class="login-captcha">
|
||||
<img :src="captchaPath" @click="getCaptcha()" />
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
<!-- <lang-select class="login-language" /> -->
|
||||
|
||||
<el-button
|
||||
:loading="loading"
|
||||
type="primary"
|
||||
style="width: 83.4%; height: 6vh; background-color: #0B58FF; margin: 0px 8.3%; margin-top: 5vh"
|
||||
@click.native.prevent="dataFormSubmitHandle"
|
||||
>
|
||||
<!-- {{ "login.logIn" | i18nFilter }} -->
|
||||
登录
|
||||
</el-button>
|
||||
<el-row class="login-footer">
|
||||
<el-row class="login-language">
|
||||
<el-col
|
||||
:span="2"
|
||||
:offset="8"
|
||||
:class="['login-language-box', language === 'zh' ? 'isActive' : '']"
|
||||
@click.native="changeLanguage('zh')"
|
||||
>
|
||||
中文
|
||||
</el-col>
|
||||
<el-col :span="1" :offset="1" style="color: #DCDFE6">|</el-col>
|
||||
<el-col
|
||||
:span="2"
|
||||
:offset="1"
|
||||
:class="['login-language-box', language === 'en' ? 'isActive' : '']"
|
||||
@click.native="changeLanguage('en')"
|
||||
>
|
||||
English
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="login-copyright">
|
||||
<!-- {{ "copyright.copyright" | i18nFilter }}:{{
|
||||
"copyright.company" | i18nFilter
|
||||
}} {{ "copyright.version" | i18nFilter }}:1.0 -->
|
||||
版权所有: ©中建材智能自动化研究院有限公司 2023 v1.0
|
||||
</el-row>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Cookies from "js-cookie";
|
||||
import debounce from "lodash/debounce";
|
||||
import { getUUID } from "@/utils";
|
||||
|
||||
export default {
|
||||
name: "Login",
|
||||
data() {
|
||||
return {
|
||||
baseImg: require("../../assets/img/login-back.png"),
|
||||
coverImgUrl: "",
|
||||
dataForm: {
|
||||
username: "admin",
|
||||
password: "admin",
|
||||
uuid: "string",
|
||||
captcha: "",
|
||||
},
|
||||
captchaPath: "",
|
||||
passwordType: "password",
|
||||
capsTooltip: false,
|
||||
loading: false,
|
||||
redirect: undefined,
|
||||
otherQuery: {},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
language() {
|
||||
return "zh";
|
||||
},
|
||||
dataRule() {
|
||||
return {
|
||||
username: [
|
||||
{
|
||||
required: true,
|
||||
message: this.$t("validate.required"),
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
password: [
|
||||
{
|
||||
required: true,
|
||||
message: this.$t("validate.required"),
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
captcha: [
|
||||
{
|
||||
required: true,
|
||||
message: this.$t("validate.required"),
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
created() {
|
||||
this.getCaptcha();
|
||||
},
|
||||
|
||||
methods: {
|
||||
// 检查大写
|
||||
checkCapslock() {},
|
||||
// 显示密码
|
||||
showPwd() {},
|
||||
// 改变语言环境
|
||||
changeLanguage(lang) {},
|
||||
// 获取验证码
|
||||
getCaptcha() {
|
||||
this.dataForm.uuid = getUUID();
|
||||
this.captchaPath = `${window.SITE_CONFIG["apiURL"]}/captcha?uuid=${this.dataForm.uuid}`;
|
||||
},
|
||||
// 表单提交
|
||||
dataFormSubmitHandle: debounce(
|
||||
function() {
|
||||
this.$refs["dataForm"].validate((valid) => {
|
||||
if (!valid) {
|
||||
return false;
|
||||
}
|
||||
this.$http
|
||||
.post("/login", this.dataForm)
|
||||
.then(({ data: res }) => {
|
||||
if (res.code !== 0) {
|
||||
this.getCaptcha();
|
||||
return this.$message.error(res.msg);
|
||||
}
|
||||
Cookies.set("token", res.data.token);
|
||||
this.$router.replace({ name: "home" });
|
||||
})
|
||||
.catch(() => {});
|
||||
});
|
||||
},
|
||||
1000,
|
||||
{ leading: true, trailing: false }
|
||||
),
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
/* 修复input 背景不协调 和光标变色 */
|
||||
/* Detail see https://github.com/PanJiaChen/vue-element-admin/pull/927 */
|
||||
|
||||
// $bg:#283443;
|
||||
$light_gray: #fff;
|
||||
$cursor: #161616;
|
||||
|
||||
@supports (-webkit-mask: none) and (not (cater-color: $cursor)) {
|
||||
.login-container .el-input input {
|
||||
color: $cursor;
|
||||
height: 6vh !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* reset element-ui css */
|
||||
.login-container {
|
||||
.el-input {
|
||||
display: inline-block;
|
||||
height: 47px;
|
||||
width: 85%;
|
||||
|
||||
input {
|
||||
background: transparent;
|
||||
border: 0px;
|
||||
-webkit-appearance: none;
|
||||
border-radius: 0px;
|
||||
padding: 12px 5px 12px 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.el-form-item {
|
||||
border: 1px solid #d7d8d9;
|
||||
border-radius: 5px;
|
||||
color: #454545;
|
||||
height: 6vh;
|
||||
.el-form-item__content {
|
||||
height: calc(6vh - 2px);
|
||||
line-height: 6vh;
|
||||
.el-input {
|
||||
height: calc(6vh - 2px);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
// $bg:#2d3a4b;
|
||||
$dark_gray: #889aa4;
|
||||
$light_gray: #eee;
|
||||
$cursor: #161616;
|
||||
|
||||
.login-container {
|
||||
min-height: 100%;
|
||||
width: 100%;
|
||||
background-size: cover;
|
||||
// background-color: $bg;
|
||||
overflow: hidden;
|
||||
.login-background {
|
||||
position: absolute;
|
||||
width: 60%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
.login-background-container {
|
||||
width: 95%;
|
||||
.back-title {
|
||||
color: #26b9de;
|
||||
font-size: 88px;
|
||||
margin-left: 17%;
|
||||
span {
|
||||
color: #fff;
|
||||
}
|
||||
p {
|
||||
font-size: 22px;
|
||||
letter-spacing: 1px;
|
||||
.back-title-point {
|
||||
display: inline-block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 8px;
|
||||
background-color: #26b9de;
|
||||
margin-right: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.login-form {
|
||||
position: absolute;
|
||||
width: 40%;
|
||||
max-width: 100%;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
padding: 0 6.67%;
|
||||
margin: 0 auto;
|
||||
overflow: hidden;
|
||||
background: rgba($color: #fff, $alpha: 1);
|
||||
backdrop-filter: blur(10px);
|
||||
box-shadow: 5px 5px 5px rgba($color: #000000, $alpha: 0.1);
|
||||
.login-footer {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
margin-bottom: 5vh;
|
||||
}
|
||||
.login-language {
|
||||
font-size: 15px;
|
||||
text-align: center;
|
||||
color: $cursor;
|
||||
margin-bottom: 12px;
|
||||
.login-language-box {
|
||||
cursor: pointer;
|
||||
}
|
||||
.isActive {
|
||||
color: #0b58ff;
|
||||
cursor: auto;
|
||||
}
|
||||
}
|
||||
.login-copyright {
|
||||
text-align: center;
|
||||
color: #c7c7c7;
|
||||
font-size: 15px;
|
||||
line-height: 28px;
|
||||
padding: 0 16%;
|
||||
}
|
||||
}
|
||||
|
||||
.tips {
|
||||
font-size: 14px;
|
||||
color: #fff;
|
||||
margin-bottom: 10px;
|
||||
|
||||
span {
|
||||
&:first-of-type {
|
||||
margin-right: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.svg-container {
|
||||
padding: 6px 5px 6px 15px;
|
||||
color: #000;
|
||||
vertical-align: middle;
|
||||
width: 30px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.title-container {
|
||||
position: relative;
|
||||
margin-top: 18vh;
|
||||
|
||||
.title {
|
||||
font-size: 34px;
|
||||
line-height: 6vh;
|
||||
margin: 0px auto 40px auto;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
word-break: break-all;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 3;
|
||||
-webkit-box-orient: vertical;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.show-pwd {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 0;
|
||||
font-size: 16px;
|
||||
color: $dark_gray;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.thirdparty-button {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 6px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 470px) {
|
||||
.thirdparty-button {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user