mirror of
https://gitee.com/ssssssss-team/magic-boot.git
synced 2026-08-16 00:00:34 +08:00
在线用户,验证码,bug修复,代码优化
This commit is contained in:
@@ -23,10 +23,6 @@
|
||||
border: 1px solid #efefef
|
||||
}
|
||||
body{
|
||||
--el-dialog__wrapper-bottom: 15vh;
|
||||
--el-dialog__wrapper-top: 15vh;
|
||||
--el-dialog__body-max-height: 60vh;
|
||||
|
||||
--mb-main-color: #409EFF;
|
||||
--mb-sidebar-width: 240px;
|
||||
--mb-main-icon-color: #909399;
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
import {ref, reactive, getCurrentInstance, defineExpose } from 'vue'
|
||||
const { proxy } = getCurrentInstance()
|
||||
const rules = reactive(getRules())
|
||||
const formData = ref(getFormData())
|
||||
const formData = ref(initFormData())
|
||||
const dataForm = ref()
|
||||
const props = defineProps({
|
||||
form: {
|
||||
@@ -42,14 +42,14 @@
|
||||
proxy.$common.setDefaultValue(props.form.props, 'labelPosition', 'right')
|
||||
proxy.$common.setDefaultValue(props.form.props, 'labelWidth', '120px')
|
||||
|
||||
if(props.detail.formData){
|
||||
if(props.detail && props.detail.formData){
|
||||
if(props.detail.handlerFormData){
|
||||
props.detail.handlerFormData(props.detail.formData)
|
||||
}
|
||||
formData.value = props.detail.formData
|
||||
}
|
||||
|
||||
if(props.detail.request){
|
||||
if(props.detail && props.detail.request){
|
||||
|
||||
}
|
||||
|
||||
@@ -65,16 +65,21 @@
|
||||
return _rules
|
||||
}
|
||||
|
||||
function getFormData() {
|
||||
function initFormData() {
|
||||
var data = {}
|
||||
props.form.rows.forEach(row => {
|
||||
row.cols.forEach(col => {
|
||||
data[col.name] = col.defaultValue === null ? col.defaultValue : col.defaultValue || ''
|
||||
// data[col.name] = col.defaultValue === null ? col.defaultValue : col.defaultValue || ''
|
||||
data[col.name] = undefined
|
||||
})
|
||||
})
|
||||
return data
|
||||
}
|
||||
|
||||
function getFormData(){
|
||||
return formData.value
|
||||
}
|
||||
|
||||
function save(d) {
|
||||
dataForm.value.validate((valid) => {
|
||||
if (valid) {
|
||||
@@ -87,7 +92,7 @@
|
||||
type: 'success',
|
||||
duration: 2000
|
||||
})
|
||||
if(props.detail.formData){
|
||||
if(props.detail && props.detail.formData){
|
||||
props.detail.formData = {}
|
||||
}
|
||||
d.hide()
|
||||
@@ -109,6 +114,6 @@
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({ save, getDetail })
|
||||
defineExpose({ save, getDetail, getFormData })
|
||||
|
||||
</script>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
|
||||
<mb-search v-if="table.where" :where="table.where" :no-reset="search.noReset" @search="reload" />
|
||||
<mb-search v-if="table.where" :where="table.where" :no-reset="search && search.noReset" @search="reload" />
|
||||
|
||||
<el-row class="toolbar-container">
|
||||
<div v-for="(it, i) in tools" :key="i">
|
||||
|
||||
@@ -1,10 +1,22 @@
|
||||
<template>
|
||||
<el-dialog :fullscreen="fullscreen" :width="width" :title="title" v-model="dialogVisible" :close-on-click-modal="false" :key="dialogKey" :append-to-body="true" draggable @opened="opened">
|
||||
<el-dialog
|
||||
v-model="dialogVisible"
|
||||
:custom-class="customClass"
|
||||
:fullscreen="fullscreen"
|
||||
:width="width"
|
||||
:title="title"
|
||||
:close-on-click-modal="false"
|
||||
:destroy-on-close="destroyOnClose"
|
||||
:append-to-body="true"
|
||||
draggable
|
||||
@open="$emit('open')"
|
||||
@close="$emit('close')"
|
||||
>
|
||||
<slot name="content" />
|
||||
<template #footer>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<slot name="btns">
|
||||
<el-button @click="dialogVisible = false">
|
||||
<el-button @click="hide">
|
||||
关闭
|
||||
</el-button>
|
||||
<el-button type="primary" :loading="confirmLoading" @click="confirmClick">
|
||||
@@ -17,9 +29,8 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
emits: ['confirm-click'],
|
||||
emits: ['confirm-click', 'open', 'close'],
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
@@ -33,11 +44,7 @@ export default {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
opened: {
|
||||
type: Function,
|
||||
default: () => {}
|
||||
},
|
||||
autoKey: {
|
||||
destroyOnClose: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
@@ -46,19 +53,20 @@ export default {
|
||||
return {
|
||||
dialogVisible: false,
|
||||
confirmLoading: false,
|
||||
dialogKey: 'mbDialog',
|
||||
customClass: 'mbDialog' + this.$common.uuid()
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
dialogVisible(value) {
|
||||
if(value){
|
||||
this.addStyle()
|
||||
}else{
|
||||
this.removeStyle()
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
if (this.fullscreen) {
|
||||
document.body.style.setProperty('--el-dialog__wrapper-bottom', '0vh')
|
||||
document.body.style.setProperty('--el-dialog__wrapper-top', '0vh')
|
||||
document.body.style.setProperty('--el-dialog__body-max-height', '100vh')
|
||||
} else {
|
||||
document.body.style.setProperty('--el-dialog__wrapper-bottom', '15vh')
|
||||
document.body.style.setProperty('--el-dialog__wrapper-top', '15vh')
|
||||
document.body.style.setProperty('--el-dialog__body-max-height', '60vh')
|
||||
}
|
||||
this.addStyle()
|
||||
},
|
||||
methods: {
|
||||
confirmClick() {
|
||||
@@ -71,33 +79,43 @@ export default {
|
||||
this.confirmLoading = false
|
||||
},
|
||||
show() {
|
||||
if(this.autoKey){
|
||||
this.dialogKey = Math.random()
|
||||
}
|
||||
this.dialogVisible = true
|
||||
},
|
||||
hide() {
|
||||
this.dialogVisible = false
|
||||
},
|
||||
addStyle(){
|
||||
var componentStyle = document.createElement("style");
|
||||
var cc = this.customClass
|
||||
if (this.fullscreen) {
|
||||
componentStyle.innerHTML = `
|
||||
.${cc}{
|
||||
margin-top: 0vh;
|
||||
margin-bottom: 0vh;
|
||||
}
|
||||
.${cc} .el-dialog__body{
|
||||
max-height: 100vh;
|
||||
}
|
||||
`
|
||||
} else {
|
||||
componentStyle.innerHTML = `
|
||||
.${cc}{
|
||||
margin-top: 10vh;
|
||||
margin-bottom: 10vh;
|
||||
}
|
||||
.${cc} .el-dialog__body{
|
||||
max-height: 60vh;
|
||||
overflow: auto;
|
||||
}
|
||||
`
|
||||
}
|
||||
componentStyle.id = cc
|
||||
document.head.appendChild(componentStyle);
|
||||
},
|
||||
removeStyle(){
|
||||
document.getElementById(this.customClass) && document.getElementById(this.customClass).remove()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.el-dialog__wrapper{
|
||||
padding-bottom: var(--el-dialog__wrapper-bottom);
|
||||
padding-top: var(--el-dialog__wrapper-top);
|
||||
overflow: hidden;
|
||||
}
|
||||
.el-dialog__wrapper >>> .el-dialog{
|
||||
margin-top: 0vh!important;
|
||||
}
|
||||
.el-dialog__wrapper >>> .el-dialog__body{
|
||||
max-height: var(--el-dialog__body-max-height);
|
||||
overflow: auto;
|
||||
padding: 25px!important;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
<template>
|
||||
<el-radio-group v-model="modelValue" v-bind="props.props">
|
||||
<el-radio-button v-for="it in options" :label="it.value" :disabled="it.disabled" :name="it.disabled">{{ it.label }}</el-radio-button>
|
||||
</el-radio-group>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { watch } from 'vue'
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const props = defineProps({
|
||||
modelValue: String,
|
||||
options: Array
|
||||
})
|
||||
watch(() => props.modelValue, (value) => {
|
||||
emit('update:modelValue', value)
|
||||
})
|
||||
</script>
|
||||
@@ -1,3 +0,0 @@
|
||||
<template>
|
||||
|
||||
</template>
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
<script setup>
|
||||
|
||||
import { nextTick, watch } from 'vue'
|
||||
import { nextTick, watch, onMounted } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
where: {
|
||||
@@ -60,7 +60,7 @@ watch(() => props.where,() => {
|
||||
console.log(props.where)
|
||||
})
|
||||
|
||||
const emit = defineEmits(['search'])
|
||||
const emit = defineEmits(['search', 'mounted'])
|
||||
|
||||
function input(input){
|
||||
if(input){
|
||||
@@ -101,6 +101,10 @@ function reset() {
|
||||
nextTick(() => emit('search'))
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
emit('mounted')
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<el-table-column
|
||||
v-bind="col.props"
|
||||
:key="col.field"
|
||||
:label="col.label"
|
||||
:prop="col.field"
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
<template>
|
||||
<el-checkbox-group
|
||||
v-model="modelValue"
|
||||
:size="size"
|
||||
:disabled="disabled"
|
||||
:min="min"
|
||||
:max="max"
|
||||
:text-color="textColor"
|
||||
:fill="fill"
|
||||
@change="change"
|
||||
>
|
||||
<el-checkbox-button v-if="button" v-for="it in options" v-bind="it" :label="it[valueField]">
|
||||
{{ it[labelField] }}
|
||||
</el-checkbox-button>
|
||||
<el-checkbox v-if="!button" v-for="it in options" v-bind="it" :label="it[valueField]">
|
||||
{{ it[labelField] }}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {watch, ref, getCurrentInstance} from "vue";
|
||||
import request from '@/scripts/request'
|
||||
const emit = defineEmits(['update:modelValue', 'change'])
|
||||
const { proxy } = getCurrentInstance()
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
type: String,
|
||||
button: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
options: Array,
|
||||
url: String,
|
||||
params: Object,
|
||||
method: {
|
||||
type: String,
|
||||
default: 'get'
|
||||
},
|
||||
labelField: {
|
||||
type: String,
|
||||
default: 'label'
|
||||
},
|
||||
valueField: {
|
||||
type: String,
|
||||
default: 'value'
|
||||
},
|
||||
size: String,
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
min: Number,
|
||||
max: Number,
|
||||
textColor: {
|
||||
type: String,
|
||||
default: '#fff'
|
||||
},
|
||||
fill: {
|
||||
type: String,
|
||||
default: '#409EFF'
|
||||
}
|
||||
})
|
||||
|
||||
const options = ref([])
|
||||
|
||||
if(props.type){
|
||||
options.value = proxy.$common.getDictType(props.type)
|
||||
}else if(props.url){
|
||||
request({
|
||||
url: props.url,
|
||||
method: props.method,
|
||||
params: props.params,
|
||||
data: props.params
|
||||
}).then(res => {
|
||||
options.value = res.data.list || res.data
|
||||
})
|
||||
}else if(props.options){
|
||||
options.value = props.options
|
||||
}
|
||||
|
||||
function change(value){
|
||||
emit('change', value)
|
||||
}
|
||||
|
||||
watch(() => props.modelValue, (value) => {
|
||||
console.log(value)
|
||||
emit('update:modelValue', value)
|
||||
})
|
||||
</script>
|
||||
+3
-6
@@ -12,7 +12,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { watch } from 'vue'
|
||||
import { watch, ref } from 'vue'
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const props = defineProps({
|
||||
modelValue: String,
|
||||
@@ -23,11 +23,7 @@
|
||||
},
|
||||
format: {
|
||||
type: String,
|
||||
default: 'yyyy-MM-dd'
|
||||
},
|
||||
valueFormat: {
|
||||
type: String,
|
||||
default: 'yyyy-MM-dd'
|
||||
default: 'YYYY-MM-DD'
|
||||
},
|
||||
startPlaceholder: {
|
||||
type: String,
|
||||
@@ -39,6 +35,7 @@
|
||||
},
|
||||
props: Object
|
||||
})
|
||||
const valueFormat = ref(props.format)
|
||||
watch(() => props.modelValue, (value) => {
|
||||
emit('update:modelValue', value)
|
||||
})
|
||||
@@ -0,0 +1,86 @@
|
||||
<template>
|
||||
<el-radio-group
|
||||
v-model="modelValue"
|
||||
:size="size"
|
||||
:disabled="disabled"
|
||||
:text-color="textColor"
|
||||
:fill="fill"
|
||||
@change="change"
|
||||
>
|
||||
<el-radio-button v-if="button" v-for="it in options" v-bind="it" :label="it[valueField]">
|
||||
{{ it[labelField] }}
|
||||
</el-radio-button>
|
||||
<el-radio v-if="!button" v-for="it in options" v-bind="it" :label="it[valueField]">
|
||||
{{ it[labelField] }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {watch, ref, getCurrentInstance} from "vue";
|
||||
import request from '@/scripts/request'
|
||||
const emit = defineEmits(['update:modelValue', 'change'])
|
||||
const { proxy } = getCurrentInstance()
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: String | Number | Boolean,
|
||||
type: String,
|
||||
button: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
options: Array,
|
||||
url: String,
|
||||
params: Object,
|
||||
method: {
|
||||
type: String,
|
||||
default: 'get'
|
||||
},
|
||||
labelField: {
|
||||
type: String,
|
||||
default: 'label'
|
||||
},
|
||||
valueField: {
|
||||
type: String,
|
||||
default: 'value'
|
||||
},
|
||||
size: String,
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
textColor: {
|
||||
type: String,
|
||||
default: '#fff'
|
||||
},
|
||||
fill: {
|
||||
type: String,
|
||||
default: '#409EFF'
|
||||
}
|
||||
})
|
||||
|
||||
const options = ref([])
|
||||
|
||||
if(props.type){
|
||||
options.value = proxy.$common.getDictType(props.type)
|
||||
}else if(props.url){
|
||||
request({
|
||||
url: props.url,
|
||||
method: props.method,
|
||||
params: props.params,
|
||||
data: props.params
|
||||
}).then(res => {
|
||||
options.value = res.data.list || res.data
|
||||
})
|
||||
}else if(props.options){
|
||||
options.value = props.options
|
||||
}
|
||||
|
||||
function change(value){
|
||||
emit('change', value)
|
||||
}
|
||||
|
||||
watch(() => props.modelValue, (value) => {
|
||||
emit('update:modelValue', value)
|
||||
})
|
||||
</script>
|
||||
+6
-3
@@ -11,9 +11,12 @@
|
||||
import { watch } from 'vue'
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const props = defineProps({
|
||||
modelValue: String,
|
||||
activeValue: String,
|
||||
inactiveValue: String,
|
||||
modelValue: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
activeValue: Boolean | String | Number,
|
||||
inactiveValue: Boolean | String | Number,
|
||||
props: Object
|
||||
})
|
||||
watch(() => props.modelValue, (value) => {
|
||||
+10
-2
@@ -26,11 +26,11 @@
|
||||
|
||||
<script setup>
|
||||
|
||||
import { watch, ref, reactive, defineExpose, nextTick, getCurrentInstance, onBeforeMount } from 'vue'
|
||||
import { watch, ref, reactive, defineExpose, nextTick, getCurrentInstance, onBeforeMount, onMounted } from 'vue'
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
|
||||
const emit = defineEmits(['update:select-values', 'check-change', 'node-click'])
|
||||
const emit = defineEmits(['update:select-values', 'check-change', 'node-click', 'mounted'])
|
||||
|
||||
const props = defineProps({
|
||||
url: {
|
||||
@@ -75,6 +75,10 @@ const props = defineProps({
|
||||
}
|
||||
})
|
||||
|
||||
watch(() => props.checkedIds, (value) => {
|
||||
console.log(value)
|
||||
})
|
||||
|
||||
const tree = ref()
|
||||
const treeData = ref([])
|
||||
const searchData = ref([])
|
||||
@@ -91,6 +95,10 @@ onBeforeMount(async () => {
|
||||
await loadTreeData()
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
emit('mounted')
|
||||
})
|
||||
|
||||
watch(() => props.selectValues, async () => {
|
||||
await loadTreeData()
|
||||
checkedAll(searchData.value, false)
|
||||
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1647393180960" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3075" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M522.854 33.884L902.47 164.732c14.1 4.85 23.54 18.113 23.54 33.011v402.218c-10.714 238.49-386.18 383.703-402.118 389.764A34.91 34.91 0 0 1 511.505 992c-4.217 0-8.439-0.767-12.387-2.275C483.147 983.664 107.648 838.452 97 601.502V197.743c0-14.898 9.442-28.16 23.503-33.011L500.121 33.884a35.24 35.24 0 0 1 22.733 0z m243.984 299.804c-29.29-29.29-76.777-29.29-106.066 0L459.246 535.213l-95.46-95.46c-29.289-29.289-76.776-29.289-106.065 0-29.29 29.29-29.29 76.777 0 106.067l148.492 148.492c14.645 14.645 33.839 21.967 53.033 21.967l1.152-0.009c18.808-0.287 37.53-7.606 51.881-21.958l254.559-254.558c29.289-29.29 29.289-76.777 0-106.066z" fill="#909399" p-id="3076"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
@@ -56,7 +56,6 @@ import Sidebar from './sidebar/sidebar.vue'
|
||||
import { logout } from '@/scripts/auth'
|
||||
import { getCurrentInstance } from 'vue'
|
||||
const { proxy } = getCurrentInstance()
|
||||
console.log(proxy.$global.user.info.headPortrait)
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@@ -117,4 +116,4 @@ console.log(proxy.$global.user.info.headPortrait)
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -47,6 +47,8 @@ export function login(data){
|
||||
var token = res.data
|
||||
setToken(token)
|
||||
resolve(token)
|
||||
}).catch((e) => {
|
||||
reject(e)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
<template>
|
||||
<mb-form ref="magicForm" v-bind="formOptions" />
|
||||
<el-button @click="getFormData">获取表单数据</el-button>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, getCurrentInstance } from 'vue'
|
||||
const { proxy } = getCurrentInstance()
|
||||
const magicForm = ref()
|
||||
const formOptions = reactive({
|
||||
form: {
|
||||
request: {
|
||||
url: "user/save",
|
||||
method: "post"
|
||||
},
|
||||
rows: [{
|
||||
gutter: 24,
|
||||
cols: [{
|
||||
span: 12,
|
||||
name: 'input',
|
||||
label: 'input'
|
||||
},{
|
||||
span: 12,
|
||||
name: 'switch',
|
||||
component: 'switch',
|
||||
label: 'switch',
|
||||
props: {
|
||||
activeValue: '1',
|
||||
inactiveValue: '0'
|
||||
}
|
||||
},{
|
||||
span: 12,
|
||||
name: 'checkbox',
|
||||
component: 'checkbox',
|
||||
label: 'checkbox',
|
||||
props: {
|
||||
type: 'office_type'
|
||||
}
|
||||
},{
|
||||
span: 12,
|
||||
name: 'checkboxButton',
|
||||
component: 'checkbox',
|
||||
label: 'checkboxButton',
|
||||
props: {
|
||||
type: 'office_type',
|
||||
button: true
|
||||
}
|
||||
},{
|
||||
span: 12,
|
||||
name: 'radio',
|
||||
component: 'radio',
|
||||
label: 'radio',
|
||||
props: {
|
||||
type: 'is_login'
|
||||
}
|
||||
},{
|
||||
span: 12,
|
||||
name: 'radioButton',
|
||||
component: 'radio',
|
||||
label: 'radioButton',
|
||||
props: {
|
||||
type: 'is_login',
|
||||
button: true
|
||||
}
|
||||
},{
|
||||
span: 12,
|
||||
name: 'date',
|
||||
component: 'date',
|
||||
label: 'date',
|
||||
props: {
|
||||
type: 'date'
|
||||
}
|
||||
},{
|
||||
span: 12,
|
||||
name: 'datetime',
|
||||
component: 'date',
|
||||
label: 'datetime',
|
||||
props: {
|
||||
type: 'datetime',
|
||||
format: 'YYYY-MM-DD HH:mm:ss'
|
||||
}
|
||||
},{
|
||||
span: 12,
|
||||
name: 'daterange',
|
||||
component: 'date',
|
||||
label: 'daterange',
|
||||
props: {
|
||||
type: 'daterange'
|
||||
}
|
||||
},{
|
||||
span: 12,
|
||||
name: 'datetimerange',
|
||||
component: 'date',
|
||||
label: 'datetimerange',
|
||||
props: {
|
||||
type: 'datetimerange',
|
||||
format: 'YYYY-MM-DD HH:mm:ss'
|
||||
}
|
||||
},{
|
||||
component: 'treeselect',
|
||||
span: 12,
|
||||
name: 'treeselect',
|
||||
label: 'treeselect',
|
||||
rules: [{ required: true, message: '请选择组织机构', trigger: 'change' }],
|
||||
props: {
|
||||
url: 'user/offices'
|
||||
}
|
||||
}, {
|
||||
component: 'select',
|
||||
span: 12,
|
||||
name: 'select',
|
||||
label: 'select',
|
||||
rules: [{ required: true, message: '请选择角色', trigger: 'change' }],
|
||||
props: {
|
||||
url: 'role/all',
|
||||
placeholder: '请选择角色',
|
||||
el: { multiple: true }
|
||||
}
|
||||
},{
|
||||
span: 12,
|
||||
name: 'head',
|
||||
component: 'upload-image',
|
||||
label: '头像',
|
||||
rules: [{ required: true, message: '请选择头像', trigger: 'change' }]
|
||||
}]
|
||||
}]
|
||||
}
|
||||
})
|
||||
function getFormData(){
|
||||
console.log(magicForm.value.getFormData())
|
||||
}
|
||||
</script>
|
||||
@@ -51,25 +51,25 @@ const listOptions = reactive({
|
||||
cols: [
|
||||
{
|
||||
field: 'username',
|
||||
title: '登录名称',
|
||||
label: '登录名称',
|
||||
sortable: 'custom'
|
||||
}, {
|
||||
field: 'name',
|
||||
title: '姓名/昵称',
|
||||
label: '姓名/昵称',
|
||||
sortable: 'custom'
|
||||
}, {
|
||||
field: 'officeName',
|
||||
title: '所属机构'
|
||||
label: '所属机构'
|
||||
}, {
|
||||
field: 'roles',
|
||||
title: '角色'
|
||||
label: '角色'
|
||||
}, {
|
||||
field: 'phone',
|
||||
title: '手机号',
|
||||
label: '手机号',
|
||||
sortable: 'custom'
|
||||
}, {
|
||||
field: 'isLogin',
|
||||
title: '禁止登录',
|
||||
label: '禁止登录',
|
||||
type: 'switch',
|
||||
width: 100,
|
||||
change: (row) => {
|
||||
@@ -80,17 +80,17 @@ const listOptions = reactive({
|
||||
}
|
||||
}, {
|
||||
field: 'createDate',
|
||||
title: '创建时间',
|
||||
label: '创建时间',
|
||||
width: 180
|
||||
}, {
|
||||
title: '操作',
|
||||
label: '操作',
|
||||
type: 'btns',
|
||||
width: 140,
|
||||
fixed: 'right',
|
||||
btns: [
|
||||
{
|
||||
permission: 'user:save',
|
||||
title: '修改',
|
||||
label: '修改',
|
||||
type: 'text',
|
||||
icon: 'ElEdit',
|
||||
click: (row) => {
|
||||
@@ -101,7 +101,7 @@ const listOptions = reactive({
|
||||
}
|
||||
}, {
|
||||
permission: 'user:delete',
|
||||
title: '删除',
|
||||
label: '删除',
|
||||
type: 'text',
|
||||
icon: 'ElDelete',
|
||||
click: (row) => {
|
||||
@@ -136,6 +136,12 @@ const formOptions = reactive({
|
||||
rows: [{
|
||||
gutter: 24,
|
||||
cols: [{
|
||||
span: 12,
|
||||
name: 'head',
|
||||
component: 'upload-image',
|
||||
label: '头像',
|
||||
rules: [{ required: true, message: '请选择头像', trigger: 'change' }]
|
||||
},{
|
||||
span: 12,
|
||||
name: 'username',
|
||||
label: '登录名称',
|
||||
@@ -170,7 +176,6 @@ const formOptions = reactive({
|
||||
span: 12,
|
||||
name: 'officeId',
|
||||
label: '组织机构',
|
||||
defaultValue: null,
|
||||
rules: [{ required: true, message: '请选择组织机构', trigger: 'change' }],
|
||||
props: {
|
||||
url: 'user/offices'
|
||||
@@ -180,7 +185,6 @@ const formOptions = reactive({
|
||||
span: 12,
|
||||
name: 'roles',
|
||||
label: '选择角色',
|
||||
defaultValue: null,
|
||||
rules: [{ required: true, message: '请选择角色', trigger: 'change' }],
|
||||
props: {
|
||||
url: 'role/all',
|
||||
|
||||
@@ -12,6 +12,11 @@
|
||||
<mb-icon icon="password"/>
|
||||
<input class="magic-input" ref="password" v-model="loginForm.password" type="password" placeholder="密码" name="password" tabindex="2" auto-complete="on" @keyup.enter.native="handleLogin" />
|
||||
</div>
|
||||
<div class="magic-login-row">
|
||||
<mb-icon icon="verification-code"/>
|
||||
<input class="magic-input code" ref="code" v-model="loginForm.code" placeholder="验证码" name="code" tabindex="3" @keyup.enter.native="handleLogin" />
|
||||
<img class="code-img" :src="codeImg" @click="refreshCode">
|
||||
</div>
|
||||
<div class="magic-login-row">
|
||||
<button :loading="loading" class="magic-button" type="primary" size="medium" @click.native.prevent="handleLogin">登录</button>
|
||||
</div>
|
||||
@@ -24,12 +29,20 @@
|
||||
import { reactive, ref, getCurrentInstance } from 'vue'
|
||||
import { login } from '@/scripts/auth'
|
||||
const { proxy } = getCurrentInstance()
|
||||
|
||||
const codeImg = ref(import.meta.env.VITE_APP_BASE_API + '/security/verification/code')
|
||||
const loginForm = reactive({
|
||||
username: '',
|
||||
password: ''
|
||||
password: '',
|
||||
code: ''
|
||||
})
|
||||
const loading = ref(false)
|
||||
function refreshCode(){
|
||||
proxy.$get('/security/verification/code').then(res => {
|
||||
codeImg.value = 'data:image/png;base64,' + res.data.img
|
||||
loginForm.uuid = res.data.uuid
|
||||
})
|
||||
}
|
||||
refreshCode()
|
||||
function handleLogin() {
|
||||
if(!loginForm.username){
|
||||
proxy.$message({
|
||||
@@ -47,12 +60,21 @@
|
||||
showClose: true
|
||||
})
|
||||
return
|
||||
}else if(!loginForm.code){
|
||||
proxy.$message({
|
||||
message: '请输入验证码',
|
||||
type: 'error',
|
||||
duration: 2000,
|
||||
showClose: true
|
||||
})
|
||||
return
|
||||
}else{
|
||||
loading.value = true
|
||||
login(loginForm).then((res) => {
|
||||
proxy.$router.push({ path: '/home' })
|
||||
loading.value = false
|
||||
}).catch(() => {
|
||||
refreshCode()
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
@@ -63,6 +85,15 @@
|
||||
*{
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.code{
|
||||
width: 283px;
|
||||
float: left;
|
||||
margin-right: 15px;
|
||||
}
|
||||
.code-img{
|
||||
border: 1px solid #D9D9D9;
|
||||
border-radius: 4px;
|
||||
}
|
||||
input{
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@@ -28,12 +28,26 @@
|
||||
},
|
||||
{
|
||||
field: 'type',
|
||||
label: '登录状态'
|
||||
label: '登录状态',
|
||||
templet: (row) => {
|
||||
return row.type == '成功' ? '<b style="color: #409EFF">成功</b>' : '<b style="color: red">失败</b>'
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'ip',
|
||||
label: 'ip'
|
||||
},
|
||||
{
|
||||
field: 'browser',
|
||||
label: '浏览器'
|
||||
},
|
||||
{
|
||||
field: 'os',
|
||||
label: '系统',
|
||||
props: {
|
||||
"show-overflow-tooltip": true
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'createDate',
|
||||
label: '操作时间'
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
<template>
|
||||
<mb-list ref="magicList" v-bind="listOptions" />
|
||||
<!-- <mb-dialog ref="magicDialog" title="提示" width="600px" @confirm-click="disable">-->
|
||||
<!-- <template #content>-->
|
||||
<!-- <el-row :gutter="24">-->
|
||||
<!-- <el-col :span="24">-->
|
||||
<!-- 确定要踢“{{currRow.username}}”下线并临时封禁吗?-->
|
||||
<!-- </el-col>-->
|
||||
<!-- <el-col :span="24">-->
|
||||
<!-- <mb-radio v-model="time" :options="options"></mb-radio>-->
|
||||
<!-- </el-col>-->
|
||||
<!-- </el-row>-->
|
||||
<!-- </template>-->
|
||||
<!-- </mb-dialog>-->
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {reactive, ref, getCurrentInstance} from "vue";
|
||||
const { proxy } = getCurrentInstance()
|
||||
const magicList = ref()
|
||||
// const magicDialog = ref()
|
||||
// const currRow = ref()
|
||||
// const time = ref(0)
|
||||
// const options = reactive([{
|
||||
// label: '不封禁',
|
||||
// value: 0
|
||||
// },{
|
||||
// label: '1分钟',
|
||||
// value: 60
|
||||
// },{
|
||||
// label: '10分钟',
|
||||
// value: 10 * 60
|
||||
// },{
|
||||
// label: '1小时',
|
||||
// value: 1 * 60 *60
|
||||
// },{
|
||||
// label: '5小时',
|
||||
// value: 5 * 60 *60
|
||||
// },{
|
||||
// label: '永久',
|
||||
// value: -1
|
||||
// }])
|
||||
const listOptions = reactive({
|
||||
table: {
|
||||
url: 'online/list',
|
||||
where: {
|
||||
username: {
|
||||
label: '登录名称',
|
||||
},
|
||||
ip: {
|
||||
label: 'IP',
|
||||
}
|
||||
},
|
||||
cols: [
|
||||
{
|
||||
field: 'username',
|
||||
label: '登录名称'
|
||||
}, {
|
||||
field: 'officeName',
|
||||
label: '所属机构'
|
||||
}, {
|
||||
field: 'ip',
|
||||
label: 'IP'
|
||||
}, {
|
||||
field: 'browser',
|
||||
label: '浏览器'
|
||||
}, {
|
||||
field: 'os',
|
||||
label: '操作系统',
|
||||
props: {
|
||||
"show-overflow-tooltip": true
|
||||
}
|
||||
}, {
|
||||
field: 'createDate',
|
||||
label: '登录时间'
|
||||
}, {
|
||||
label: '操作',
|
||||
type: 'btns',
|
||||
width: 140,
|
||||
fixed: 'right',
|
||||
btns: [
|
||||
{
|
||||
permission: 'online:logout',
|
||||
label: '踢人',
|
||||
type: 'text',
|
||||
icon: 'ElBicycle',
|
||||
click: (row) => {
|
||||
// currRow.value = row
|
||||
// magicDialog.value.show()
|
||||
proxy.$alert(`确定要踢“${row.username}”下线吗?`, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
callback: (action) => {
|
||||
if (action === 'confirm') {
|
||||
proxy.$get('online/logout',{ token: row.token }).then(() => {
|
||||
magicList.value.reload()
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
// function disable(){
|
||||
// proxy.$get('online/logout',{ id: currRow.value.id, time: time.value }).then(() => {
|
||||
// magicDialog.value.hide()
|
||||
// magicList.value.reload()
|
||||
// })
|
||||
// }
|
||||
</script>
|
||||
@@ -40,7 +40,10 @@
|
||||
},
|
||||
{
|
||||
field: 'userAgent',
|
||||
label: '用户代理'
|
||||
label: '用户代理',
|
||||
props: {
|
||||
"show-overflow-tooltip": true
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'username',
|
||||
|
||||
@@ -196,7 +196,10 @@ const tableOptions = reactive({
|
||||
type: 'text',
|
||||
icon: 'ElUserFilled',
|
||||
click: (row) => {
|
||||
proxy.$router.push({ path: `/system/user/user-list?officeId=${row.id}` })
|
||||
proxy.$router.push({
|
||||
path: '/system/user/user-list',
|
||||
query: { officeId: row.id }
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -13,11 +13,21 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<div class="left">
|
||||
<mb-tree url="office/tree" :el="{ 'expand-on-click-node': false,'show-checkbox': true }" :checked-ids="[tableOptions.where.officeId]" :expand="false" :search="true" search-width="100%" :checked="false" @check-change="checkChange" />
|
||||
<mb-tree
|
||||
url="office/tree"
|
||||
:el="{ 'expand-on-click-node': false,'show-checkbox': true }"
|
||||
:checked-ids="[tableOptions.where.officeId]"
|
||||
:expand="false"
|
||||
:search="true"
|
||||
search-width="100%"
|
||||
:checked="false"
|
||||
@check-change="checkChange"
|
||||
@mounted="treeMounted"
|
||||
/>
|
||||
</div>
|
||||
<div class="right">
|
||||
|
||||
<mb-search :where="tableOptions.where" @search="reloadTable">
|
||||
<mb-search :where="tableOptions.where" @search="reloadTable" @mounted="searchMounted">
|
||||
<template #btns>
|
||||
<el-button :loading="downloadLoading" class="filter-item" icon="ElDownload" @click="handleDownload">
|
||||
导出
|
||||
@@ -71,13 +81,13 @@ const tableOptions = reactive({
|
||||
roleId: {
|
||||
type: 'select',
|
||||
label: '角色',
|
||||
value: proxy.$route.query.roleId,
|
||||
value: '',
|
||||
properties: {
|
||||
url: 'role/all',
|
||||
el: { multiple: true }
|
||||
}
|
||||
},
|
||||
officeId: proxy.$route.query.officeId
|
||||
officeId: ''
|
||||
},
|
||||
cols: [
|
||||
{
|
||||
@@ -159,20 +169,17 @@ const userFormDialog = ref()
|
||||
const table = ref()
|
||||
const userForm = ref()
|
||||
|
||||
// onMounted(() => {
|
||||
// setTimeout(function(){
|
||||
// nextTick(() => {
|
||||
// console.log(proxy.$route.query.roleId)
|
||||
// if(proxy.$route.query.roleId){
|
||||
// tableOptions.where.roleId.value = proxy.$route.query.roleId
|
||||
// }
|
||||
// if(proxy.$route.query.officeId){
|
||||
// tableOptions.where.officeId = proxy.$route.query.officeId
|
||||
// }
|
||||
// })
|
||||
function searchMounted(){
|
||||
if(proxy.$route.query.roleId){
|
||||
tableOptions.where.roleId.value = proxy.$route.query.roleId
|
||||
}
|
||||
}
|
||||
|
||||
// },1000)
|
||||
// })
|
||||
function treeMounted(){
|
||||
if(proxy.$route.query.officeId){
|
||||
tableOptions.where.officeId = proxy.$route.query.officeId
|
||||
}
|
||||
}
|
||||
|
||||
function checkChange(values) {
|
||||
tableOptions.where.officeId = values
|
||||
|
||||
Reference in New Issue
Block a user