登录页面完善

This commit is contained in:
BianLzhaoMin 2025-09-10 16:38:48 +08:00
parent cc59f5f7f8
commit 148396860f
9 changed files with 2220 additions and 143 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

View File

@ -0,0 +1,204 @@
<template>
<div class="add-and-edit-form">
<!-- 基本信息表单 -->
<TitleTip title="基本信息" />
<el-form
ref="addAndEditForm"
label-width="120px"
:model="addAndEditForm"
:rules="addAndEditFormRules"
>
<el-row>
<el-col :span="12">
<el-form-item label="组件名称" prop="name">
<el-input v-model="addAndEditForm.name" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="分类" prop="type">
<el-input v-model="addAndEditForm.type" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="类型" prop="type">
<el-input v-model="addAndEditForm.type" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="jar包" prop="file">
<UploadFileFormData
:limit="1"
:file-size="10"
:file-type="['jpg', 'png', 'jpeg']"
:file-list.sync="addAndEditForm.file"
:is-uploaded="addAndEditForm.file.length >= 1"
/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="文档" prop="file">
<UploadFileFormData
:limit="1"
:file-size="10"
:file-type="['jpg', 'png', 'jpeg']"
:file-list.sync="addAndEditForm.file"
:is-uploaded="addAndEditForm.file.length >= 1"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="封面" prop="cover">
<UploadFileFormData
:limit="1"
:file-size="10"
:file-type="['jpg', 'png', 'jpeg']"
:file-list.sync="addAndEditForm.cover"
:is-uploaded="addAndEditForm.cover.length >= 1"
/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="版本" prop="version">
<el-input v-model="addAndEditForm.version" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="应用系统">
<el-input v-model="addAndEditForm.belongProduct" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="组件介绍" prop="description">
<el-input
clearable
type="textarea"
placeholder="请输入组件介绍"
:autosize="{ minRows: 3, maxRows: 6 }"
v-model="addAndEditForm.description"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
<!-- 底部按钮 -->
<el-row class="add-and-edit-form-footer">
<el-button size="mini" type="info" @click="handleCancel">
取消
</el-button>
<el-button size="mini" type="primary" @click="handleSave">
保存
</el-button>
</el-row>
</div>
</template>
<script>
import TitleTip from '@/components/TitleTip'
import UploadFileFormData from '@/components/UploadFileFormData'
export default {
name: 'AddAndEditForm',
components: { TitleTip, UploadFileFormData },
data() {
return {
currentTab: '1', // Tab
//
addAndEditForm: {
name: '', //
type: '', //
file: [], //
cover: [], //
version: '', //
belongProduct: '', //
description: '', //
},
//
addAndEditFormRules: {
name: [
{ required: true, message: '请输入名称', trigger: 'blur' },
],
type: [
{ required: true, message: '请输入类型', trigger: 'blur' },
],
file: [
{ required: true, message: '请上传附件', trigger: 'blur' },
],
cover: [
{ required: true, message: '请上传封面', trigger: 'blur' },
],
version: [
{
required: true,
message: '请输入版本',
trigger: 'blur',
},
],
description: [
{
required: true,
message: '请输入描述',
trigger: 'blur',
},
],
},
}
},
methods: {
//
handleCancel() {
//
this.$refs.addAndEditForm?.resetFields()
this.$emit('closeDialog', false)
},
//
async handleSave() {
this.$message.closeAll()
try {
await this.$refs.addAndEditForm.validate()
this.$message.success('保存成功')
this.$emit('closeDialog', true)
} catch (error) {
//
this.$message.error('请完善所有必填项后再保存')
}
},
},
}
</script>
<style lang="scss" scoped>
.add-and-edit-form {
width: 100%;
height: 100%;
padding-bottom: 70px;
.add-and-edit-form-footer {
position: fixed;
bottom: 0;
right: 0;
width: 100%;
height: 60px;
padding: 10px;
border-top: 1px solid #e5e6e7;
background-color: #fff;
display: flex;
justify-content: center;
align-items: center;
}
}
</style>

View File

@ -0,0 +1,270 @@
<template>
<!-- 公共组件管理 -->
<div class="app-container">
<el-form
size="small"
:inline="true"
ref="queryForm"
:model="queryParams"
>
<el-form-item prop="name">
<el-input
clearable
placeholder="请输入名称"
v-model="queryParams.name"
@keyup.enter.native="onHandleQuery"
/>
</el-form-item>
<el-form-item prop="status">
<el-select
clearable
filterable
placeholder="选择类型"
v-model="queryParams.type"
>
<el-option value="1" label="智慧基建" />
<el-option value="2" label="智慧后勤" />
<el-option value="3" label="数智装备" />
</el-select>
</el-form-item>
<el-form-item>
<el-button
type="primary"
size="mini"
@click="onHandleQuery"
icon="el-icon-search"
>
查询
</el-button>
<el-button
size="mini"
icon="el-icon-refresh"
@click="onResetQuery"
>
重置
</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
plain
size="mini"
type="primary"
icon="el-icon-plus"
@click="onHandleAdd"
>
新增
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
plain
size="mini"
type="primary"
icon="el-icon-upload"
@click="onHandleImport"
>
导入
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
plain
size="mini"
type="primary"
icon="el-icon-download"
@click="onHandleExport"
>
导出
</el-button>
</el-col>
</el-row>
<!-- 表格 -->
<el-table :data="tableData" border>
<el-table-column
type="index"
label="序号"
width="50"
align="center"
/>
<el-table-column
align="center"
:key="column.prop"
:prop="column.prop"
:label="column.label"
v-for="column in columns"
>
<template slot-scope="scope">
<template v-if="column.prop === 'file'"> 附件 </template>
<template v-else>
{{ scope.row[column.prop] }}
</template>
</template>
</el-table-column>
<el-table-column align="center" label="操作">
<template slot-scope="scope">
<el-button
plain
size="mini"
type="success"
style="padding: 4px 8px"
@click="onHandleEdit(scope.row)"
>
编辑
</el-button>
<el-button
plain
size="mini"
type="danger"
style="padding: 4px 8px"
@click="onHandleDelete(scope.row)"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 新增和编辑表单 -->
<DialogModel
:dialogConfig="dialogConfig"
@closeDialogOuter="handleCloseDialogOuter"
>
<template #outerContent>
<AddAndEditForm @closeDialog="closeDialog" />
</template>
</DialogModel>
</div>
</template>
<script>
import AddAndEditForm from './components/addAndEditForm.vue'
import DialogModel from '@/components/DialogModel'
export default {
name: 'CommonCom',
components: {
AddAndEditForm,
DialogModel,
},
data() {
return {
tableData: [
{
name: '产品1',
type: '智慧基建',
version: '1.0.0',
file: 'https://www.baidu.com',
description: '描述',
createBy: 'admin',
},
{
name: '产品2',
type: '智慧后勤',
version: '1.0.0',
file: 'https://www.baidu.com',
description: '描述',
createBy: 'admin',
},
],
queryParams: {
name: undefined,
type: undefined,
},
columns: [
{
prop: 'name',
label: '名称',
},
{
prop: 'type',
label: '类型',
},
{
prop: 'version',
label: '版本',
},
{
prop: 'description',
label: '描述',
},
{
prop: 'createBy',
label: '创建人',
},
{
prop: 'createTime',
label: '创建时间',
},
],
dialogConfig: {
outerTitle: '新增',
outerVisible: false,
outerWidth: '70%',
minHeight: '50vh',
maxHeight: '90vh',
},
}
},
methods: {
onHandleQuery() {
console.log(this.queryParams)
},
onResetQuery() {
this.queryParams = {
name: undefined,
type: undefined,
}
},
onHandleAdd() {
console.log('新增')
this.dialogConfig.outerTitle = '新增'
this.dialogConfig.outerVisible = true
},
onHandleImport() {
console.log('导入')
},
onHandleExport() {
console.log('导出')
},
onHandleEdit(row) {
console.log('编辑', row)
this.dialogConfig.outerTitle = '编辑'
this.dialogConfig.outerVisible = true
},
onHandleDelete(row) {
console.log('删除', row)
},
//
handleCloseDialogOuter() {
this.dialogConfig.outerVisible = false
},
//
closeDialog(isSuccess) {
this.dialogConfig.outerVisible = false
if (isSuccess) {
this.onHandleQuery()
}
},
},
created() {
// this.onHandleQuery()
},
}
</script>
<style scoped>
.link-text {
color: #409eff;
text-decoration: none;
}
.link-text:hover {
color: #409eff;
text-decoration: underline;
}
</style>

View File

@ -0,0 +1,154 @@
<template>
<div class="add-and-edit-form">
<!-- 基本信息表单 -->
<TitleTip title="基本信息" />
<el-form
ref="addAndEditForm"
label-width="120px"
:model="addAndEditForm"
:rules="addAndEditFormRules"
>
<el-row>
<el-col :span="12">
<el-form-item label="名称" prop="name">
<el-input v-model="addAndEditForm.name" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="类型" prop="type">
<el-input v-model="addAndEditForm.type" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="管理员" prop="admin">
<el-input v-model="addAndEditForm.admin" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="描述" prop="description">
<el-input
clearable
type="textarea"
placeholder="请输入描述"
:autosize="{ minRows: 3, maxRows: 6 }"
v-model="addAndEditForm.description"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
<!-- 底部按钮 -->
<el-row class="add-and-edit-form-footer">
<el-button size="mini" type="info" @click="handleCancel">
取消
</el-button>
<el-button size="mini" type="primary" @click="handleSave">
保存
</el-button>
</el-row>
</div>
</template>
<script>
import TitleTip from '@/components/TitleTip'
import UploadFileFormData from '@/components/UploadFileFormData'
export default {
name: 'AddAndEditForm',
components: { TitleTip, UploadFileFormData },
data() {
return {
currentTab: '1', // Tab
//
addAndEditForm: {
name: '', //
type: '', //
file: [], //
cover: [], //
version: '', //
belongProduct: '', //
description: '', //
},
//
addAndEditFormRules: {
name: [
{ required: true, message: '请输入名称', trigger: 'blur' },
],
type: [
{ required: true, message: '请输入类型', trigger: 'blur' },
],
file: [
{ required: true, message: '请上传附件', trigger: 'blur' },
],
cover: [
{ required: true, message: '请上传封面', trigger: 'blur' },
],
version: [
{
required: true,
message: '请输入版本',
trigger: 'blur',
},
],
description: [
{
required: true,
message: '请输入描述',
trigger: 'blur',
},
],
},
}
},
methods: {
//
handleCancel() {
//
this.$refs.addAndEditForm?.resetFields()
this.$emit('closeDialog', false)
},
//
async handleSave() {
this.$message.closeAll()
try {
await this.$refs.addAndEditForm.validate()
this.$message.success('保存成功')
this.$emit('closeDialog', true)
} catch (error) {
//
this.$message.error('请完善所有必填项后再保存')
}
},
},
}
</script>
<style lang="scss" scoped>
.add-and-edit-form {
width: 100%;
height: 100%;
padding-bottom: 70px;
.add-and-edit-form-footer {
position: fixed;
bottom: 0;
right: 0;
width: 100%;
height: 60px;
padding: 10px;
border-top: 1px solid #e5e6e7;
background-color: #fff;
display: flex;
justify-content: center;
align-items: center;
}
}
</style>

View File

@ -0,0 +1,271 @@
<template>
<!-- 文档中心管理 -->
<div class="app-container">
<el-form
size="small"
:inline="true"
ref="queryForm"
:model="queryParams"
>
<el-form-item prop="name">
<el-input
clearable
placeholder="请输入名称"
v-model="queryParams.name"
@keyup.enter.native="onHandleQuery"
/>
</el-form-item>
<el-form-item prop="status">
<el-select
clearable
filterable
placeholder="选择类型"
v-model="queryParams.type"
>
<el-option value="1" label="智慧基建" />
<el-option value="2" label="智慧后勤" />
<el-option value="3" label="数智装备" />
</el-select>
</el-form-item>
<el-form-item>
<el-button
type="primary"
size="mini"
@click="onHandleQuery"
icon="el-icon-search"
>
查询
</el-button>
<el-button
size="mini"
icon="el-icon-refresh"
@click="onResetQuery"
>
重置
</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
plain
size="mini"
type="primary"
icon="el-icon-plus"
@click="onHandleAdd"
>
新增
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
plain
size="mini"
type="primary"
icon="el-icon-upload"
@click="onHandleImport"
>
导入
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
plain
size="mini"
type="primary"
icon="el-icon-download"
@click="onHandleExport"
>
导出
</el-button>
</el-col>
</el-row>
<!-- 表格 -->
<el-table :data="tableData" border>
<el-table-column
type="index"
label="序号"
width="50"
align="center"
/>
<el-table-column
align="center"
:key="column.prop"
:prop="column.prop"
:label="column.label"
v-for="column in columns"
>
<template slot-scope="scope">
<template v-if="column.prop === 'file'"> 附件 </template>
<template v-else>
{{ scope.row[column.prop] }}
</template>
</template>
</el-table-column>
<el-table-column align="center" label="操作">
<template slot-scope="scope">
<el-button
plain
size="mini"
type="success"
style="padding: 4px 8px"
@click="onHandleEdit(scope.row)"
>
编辑
</el-button>
<el-button
plain
size="mini"
type="danger"
style="padding: 4px 8px"
@click="onHandleDelete(scope.row)"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 新增和编辑表单 -->
<DialogModel
:dialogConfig="dialogConfig"
@closeDialogOuter="handleCloseDialogOuter"
>
<template #outerContent>
<AddAndEditForm @closeDialog="closeDialog" />
</template>
</DialogModel>
</div>
</template>
<script>
import AddAndEditForm from './components/addAndEditForm.vue'
import DialogModel from '@/components/DialogModel'
export default {
name: 'DocsCenter',
components: {
AddAndEditForm,
DialogModel,
},
data() {
return {
tableData: [
{
name: '产品1',
type: '智慧基建',
version: '1.0.0',
admin: '张三',
description: '描述',
createBy: 'admin',
},
{
name: '产品2',
type: '智慧后勤',
version: '1.0.0',
admin: '张三',
description: '描述',
createBy: 'admin',
},
],
queryParams: {
name: undefined,
type: undefined,
},
columns: [
{
prop: 'name',
label: '名称',
},
{
prop: 'type',
label: '类型',
},
{
prop: 'admin',
label: '管理员',
},
{
prop: 'description',
label: '描述',
},
{
prop: 'createBy',
label: '创建人',
},
{
prop: 'createTime',
label: '创建时间',
},
],
dialogConfig: {
outerTitle: '新增',
outerVisible: false,
outerWidth: '70%',
minHeight: '50vh',
maxHeight: '90vh',
},
}
},
methods: {
onHandleQuery() {
console.log(this.queryParams)
},
onResetQuery() {
this.queryParams = {
name: undefined,
type: undefined,
}
},
onHandleAdd() {
console.log('新增')
this.dialogConfig.outerTitle = '新增'
this.dialogConfig.outerVisible = true
},
onHandleImport() {
console.log('导入')
},
onHandleExport() {
console.log('导出')
},
onHandleEdit(row) {
console.log('编辑', row)
this.dialogConfig.outerTitle = '编辑'
this.dialogConfig.outerVisible = true
},
onHandleDelete(row) {
console.log('删除', row)
},
//
handleCloseDialogOuter() {
this.dialogConfig.outerVisible = false
},
//
closeDialog(isSuccess) {
this.dialogConfig.outerVisible = false
if (isSuccess) {
this.onHandleQuery()
}
},
},
created() {
// this.onHandleQuery()
},
}
</script>
<style scoped>
.link-text {
color: #409eff;
text-decoration: none;
}
.link-text:hover {
color: #409eff;
text-decoration: underline;
}
</style>

View File

@ -0,0 +1,160 @@
<template>
<div class="add-and-edit-form">
<!-- 基本信息表单 -->
<TitleTip title="基本信息" />
<el-form
ref="addAndEditForm"
label-width="120px"
:model="addAndEditForm"
:rules="addAndEditFormRules"
>
<el-row>
<el-col :span="12">
<el-form-item label="名称" prop="name">
<el-input v-model="addAndEditForm.name" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="类型" prop="type">
<el-input v-model="addAndEditForm.type" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="标签名称" prop="name">
<el-input v-model="addAndEditForm.name" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="标签属性" prop="type">
<el-input v-model="addAndEditForm.type" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="描述" prop="description">
<el-input
clearable
type="textarea"
placeholder="请输入描述"
:autosize="{ minRows: 3, maxRows: 6 }"
v-model="addAndEditForm.description"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
<!-- 底部按钮 -->
<el-row class="add-and-edit-form-footer">
<el-button size="mini" type="info" @click="handleCancel">
取消
</el-button>
<el-button size="mini" type="primary" @click="handleSave">
保存
</el-button>
</el-row>
</div>
</template>
<script>
import TitleTip from '@/components/TitleTip'
import UploadFileFormData from '@/components/UploadFileFormData'
export default {
name: 'AddAndEditForm',
components: { TitleTip, UploadFileFormData },
data() {
return {
currentTab: '1', // Tab
//
addAndEditForm: {
name: '', //
type: '', //
file: [], //
cover: [], //
version: '', //
belongProduct: '', //
description: '', //
},
//
addAndEditFormRules: {
name: [
{ required: true, message: '请输入名称', trigger: 'blur' },
],
type: [
{ required: true, message: '请输入类型', trigger: 'blur' },
],
file: [
{ required: true, message: '请上传附件', trigger: 'blur' },
],
cover: [
{ required: true, message: '请上传封面', trigger: 'blur' },
],
version: [
{
required: true,
message: '请输入版本',
trigger: 'blur',
},
],
description: [
{
required: true,
message: '请输入描述',
trigger: 'blur',
},
],
},
}
},
methods: {
//
handleCancel() {
//
this.$refs.addAndEditForm?.resetFields()
this.$emit('closeDialog', false)
},
//
async handleSave() {
this.$message.closeAll()
try {
await this.$refs.addAndEditForm.validate()
this.$message.success('保存成功')
this.$emit('closeDialog', true)
} catch (error) {
//
this.$message.error('请完善所有必填项后再保存')
}
},
},
}
</script>
<style lang="scss" scoped>
.add-and-edit-form {
width: 100%;
height: 100%;
padding-bottom: 70px;
.add-and-edit-form-footer {
position: fixed;
bottom: 0;
right: 0;
width: 100%;
height: 60px;
padding: 10px;
border-top: 1px solid #e5e6e7;
background-color: #fff;
display: flex;
justify-content: center;
align-items: center;
}
}
</style>

View File

@ -0,0 +1,271 @@
<template>
<!-- 文档标签管理 -->
<div class="app-container">
<el-form
size="small"
:inline="true"
ref="queryForm"
:model="queryParams"
>
<el-form-item prop="name">
<el-input
clearable
placeholder="请输入名称"
v-model="queryParams.name"
@keyup.enter.native="onHandleQuery"
/>
</el-form-item>
<el-form-item prop="status">
<el-select
clearable
filterable
placeholder="选择类型"
v-model="queryParams.type"
>
<el-option value="1" label="智慧基建" />
<el-option value="2" label="智慧后勤" />
<el-option value="3" label="数智装备" />
</el-select>
</el-form-item>
<el-form-item>
<el-button
type="primary"
size="mini"
@click="onHandleQuery"
icon="el-icon-search"
>
查询
</el-button>
<el-button
size="mini"
icon="el-icon-refresh"
@click="onResetQuery"
>
重置
</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
plain
size="mini"
type="primary"
icon="el-icon-plus"
@click="onHandleAdd"
>
新增
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
plain
size="mini"
type="primary"
icon="el-icon-upload"
@click="onHandleImport"
>
导入
</el-button>
</el-col>
<el-col :span="1.5">
<el-button
plain
size="mini"
type="primary"
icon="el-icon-download"
@click="onHandleExport"
>
导出
</el-button>
</el-col>
</el-row>
<!-- 表格 -->
<el-table :data="tableData" border>
<el-table-column
type="index"
label="序号"
width="50"
align="center"
/>
<el-table-column
align="center"
:key="column.prop"
:prop="column.prop"
:label="column.label"
v-for="column in columns"
>
<template slot-scope="scope">
<template v-if="column.prop === 'file'"> 附件 </template>
<template v-else>
{{ scope.row[column.prop] }}
</template>
</template>
</el-table-column>
<el-table-column align="center" label="操作">
<template slot-scope="scope">
<el-button
plain
size="mini"
type="success"
style="padding: 4px 8px"
@click="onHandleEdit(scope.row)"
>
编辑
</el-button>
<el-button
plain
size="mini"
type="danger"
style="padding: 4px 8px"
@click="onHandleDelete(scope.row)"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 新增和编辑表单 -->
<DialogModel
:dialogConfig="dialogConfig"
@closeDialogOuter="handleCloseDialogOuter"
>
<template #outerContent>
<AddAndEditForm @closeDialog="closeDialog" />
</template>
</DialogModel>
</div>
</template>
<script>
import AddAndEditForm from './components/addAndEditForm.vue'
import DialogModel from '@/components/DialogModel'
export default {
name: 'DocsTags',
components: {
AddAndEditForm,
DialogModel,
},
data() {
return {
tableData: [
{
name: '产品1',
type: '智慧基建',
version: '1.0.0',
tags: '标签',
description: '描述',
createBy: 'admin',
},
{
name: '产品2',
type: '智慧后勤',
version: '1.0.0',
tags: '标签',
description: '描述',
createBy: 'admin',
},
],
queryParams: {
name: undefined,
type: undefined,
},
columns: [
{
prop: 'name',
label: '名称',
},
{
prop: 'type',
label: '类型',
},
{
prop: 'tags',
label: '标签',
},
{
prop: 'description',
label: '描述',
},
{
prop: 'createBy',
label: '创建人',
},
{
prop: 'createTime',
label: '创建时间',
},
],
dialogConfig: {
outerTitle: '新增',
outerVisible: false,
outerWidth: '70%',
minHeight: '50vh',
maxHeight: '90vh',
},
}
},
methods: {
onHandleQuery() {
console.log(this.queryParams)
},
onResetQuery() {
this.queryParams = {
name: undefined,
type: undefined,
}
},
onHandleAdd() {
console.log('新增')
this.dialogConfig.outerTitle = '新增'
this.dialogConfig.outerVisible = true
},
onHandleImport() {
console.log('导入')
},
onHandleExport() {
console.log('导出')
},
onHandleEdit(row) {
console.log('编辑', row)
this.dialogConfig.outerTitle = '编辑'
this.dialogConfig.outerVisible = true
},
onHandleDelete(row) {
console.log('删除', row)
},
//
handleCloseDialogOuter() {
this.dialogConfig.outerVisible = false
},
//
closeDialog(isSuccess) {
this.dialogConfig.outerVisible = false
if (isSuccess) {
this.onHandleQuery()
}
},
},
created() {
// this.onHandleQuery()
},
}
</script>
<style scoped>
.link-text {
color: #409eff;
text-decoration: none;
}
.link-text:hover {
color: #409eff;
text-decoration: underline;
}
</style>

View File

@ -1,90 +1,175 @@
<template>
<div class="login">
<el-form
ref="loginForm"
:model="loginForm"
:rules="loginRules"
class="login-form"
>
<h3 class="title">{{ title }}</h3>
<el-form-item prop="username">
<el-input
v-model="loginForm.username"
type="text"
auto-complete="off"
placeholder="账号"
>
<svg-icon
slot="prefix"
icon-class="user"
class="el-input__icon input-icon"
/>
</el-input>
</el-form-item>
<el-form-item prop="password">
<el-input
v-model="loginForm.password"
type="password"
auto-complete="off"
placeholder="密码"
show-password
@keyup.enter.native="handleLogin"
>
<svg-icon
slot="prefix"
icon-class="password"
class="el-input__icon input-icon"
/>
</el-input>
</el-form-item>
<el-form-item prop="code" v-if="captchaEnabled">
<el-input
v-model="loginForm.code"
auto-complete="off"
placeholder="验证码"
style="width: 63%"
@keyup.enter.native="handleLogin"
>
<svg-icon
slot="prefix"
icon-class="validCode"
class="el-input__icon input-icon"
/>
</el-input>
<div class="login-code">
<img
:src="codeUrl"
@click="getCode"
class="login-code-img"
/>
</div>
</el-form-item>
<el-checkbox
v-model="loginForm.rememberMe"
style="margin: 0px 0px 25px 0px"
>记住密码</el-checkbox
>
<el-form-item style="width: 100%">
<el-button
:loading="loading"
size="medium"
type="primary"
style="width: 100%"
@click.native.prevent="handleLogin"
>
<span v-if="!loading"> </span>
<span v-else> 中...</span>
</el-button>
<div style="float: right" v-if="register">
<router-link class="link-type" :to="'/register'"
>立即注册</router-link
<div class="login-content">
<div class="login-container">
<!-- 左侧背景区域 -->
<div class="login-left">
<!-- <div class="background-image">
<img
alt="背景图"
src="../assets/images/login-new-background.png"
/>
</div> -->
</div>
<!-- 右侧登录表单区域 -->
<div class="login-right">
<div class="login-form-container">
<h2 class="welcome-title">欢迎登录公共服务平台</h2>
<!-- 登录方式切换 -->
<div class="login-type-switch">
<span
:class="[
'switch-item',
{ active: loginType === 'password' },
]"
@click="switchLoginType('password')"
>
密码登录
</span>
<span class="divider">|</span>
<span
:class="[
'switch-item',
{ active: loginType === 'sms' },
]"
@click="switchLoginType('sms')"
>
验证码登录
</span>
</div>
<!-- 登录表单 -->
<el-form
ref="loginForm"
:model="loginForm"
:rules="loginRules"
class="login-form"
>
<!-- 密码登录表单 -->
<template v-if="loginType === 'password'">
<el-form-item prop="username">
<el-input
v-model="loginForm.username"
type="text"
auto-complete="off"
placeholder="请输入用户名"
class="custom-input"
>
<i
slot="prefix"
class="el-input__icon el-icon-user"
></i>
</el-input>
</el-form-item>
<el-form-item prop="password">
<el-input
v-model="loginForm.password"
type="password"
auto-complete="off"
placeholder="请输入密码"
show-password
class="custom-input"
@keyup.enter.native="handleLogin"
>
<i
slot="prefix"
class="el-input__icon el-icon-lock"
/>
</el-input>
</el-form-item>
<el-form-item prop="code" v-if="captchaEnabled">
<div class="code-input-group">
<el-input
v-model="loginForm.code"
auto-complete="off"
placeholder="请输入右侧校验码"
class="custom-input code-input"
@keyup.enter.native="handleLogin"
>
<i
slot="prefix"
class="el-input__icon el-icon-message"
/>
</el-input>
<div class="login-code">
<img
:src="codeUrl"
@click="getCode"
class="login-code-img"
/>
</div>
</div>
</el-form-item>
<div class="form-options">
<el-checkbox v-model="loginForm.rememberMe"
>记住密码</el-checkbox
>
<a href="#" class="forgot-password">忘记密码</a>
</div>
</template>
<!-- 验证码登录表单 -->
<template v-else>
<el-form-item prop="mobile">
<el-input
v-model="loginForm.mobile"
type="text"
auto-complete="off"
placeholder="请输入手机号"
class="custom-input"
>
<i
slot="prefix"
class="el-input__icon el-icon-phone"
></i>
</el-input>
</el-form-item>
<el-form-item prop="smsCode">
<div class="sms-input-group">
<el-input
v-model="loginForm.smsCode"
auto-complete="off"
placeholder="请输入验证码"
class="custom-input sms-input"
@keyup.enter.native="handleLogin"
>
<i
slot="prefix"
class="el-input__icon el-icon-key"
></i>
</el-input>
<el-button
class="sms-button"
:disabled="smsCountdown > 0"
@click="sendSmsCode"
>
{{
smsCountdown > 0
? `${smsCountdown}s`
: '获取验证码'
}}
</el-button>
</div>
</el-form-item>
</template>
<!-- 登录按钮 -->
<el-form-item class="login-button-item">
<el-button
:loading="loading"
size="large"
type="primary"
class="login-button"
@click.native.prevent="handleLogin"
>
<span v-if="!loading">登录</span>
<span v-else>登录中...</span>
</el-button>
</el-form-item>
</el-form>
</div>
</el-form-item>
</el-form>
<!-- 底部 -->
<div class="el-login-footer">
<span>Copyright © 2018-2025 ruoyi.vip All Rights Reserved.</span>
</div>
</div>
</div>
</template>
@ -100,9 +185,12 @@ export default {
return {
title: process.env.VUE_APP_TITLE,
codeUrl: '',
loginType: 'password', // password sms
loginForm: {
username: 'admin',
password: 'admin123',
mobile: '',
smsCode: '',
rememberMe: false,
code: '',
uuid: '',
@ -122,6 +210,25 @@ export default {
message: '请输入您的密码',
},
],
mobile: [
{
required: true,
trigger: 'blur',
message: '请输入手机号',
},
{
pattern: /^1[3-9]\d{9}$/,
message: '请输入正确的手机号',
trigger: 'blur',
},
],
smsCode: [
{
required: true,
trigger: 'blur',
message: '请输入验证码',
},
],
code: [
{
required: true,
@ -136,6 +243,8 @@ export default {
//
register: false,
redirect: undefined,
//
smsCountdown: 0,
}
},
watch: {
@ -151,6 +260,40 @@ export default {
this.getCookie()
},
methods: {
//
switchLoginType(type) {
this.loginType = type
//
this.$nextTick(() => {
this.$refs.loginForm.clearValidate()
})
},
//
sendSmsCode() {
if (!this.loginForm.mobile) {
this.$message.warning('请先输入手机号')
return
}
if (!/^1[3-9]\d{9}$/.test(this.loginForm.mobile)) {
this.$message.warning('请输入正确的手机号')
return
}
// API
//
this.$message.success('验证码已发送')
this.startCountdown()
},
//
startCountdown() {
this.smsCountdown = 60
const timer = setInterval(() => {
this.smsCountdown--
if (this.smsCountdown <= 0) {
clearInterval(timer)
}
}, 1000)
},
getCode() {
getCodeImg().then((res) => {
this.captchaEnabled =
@ -180,23 +323,42 @@ export default {
this.$refs.loginForm.validate((valid) => {
if (valid) {
this.loading = true
if (this.loginForm.rememberMe) {
Cookies.set('username', this.loginForm.username, {
expires: 30,
})
Cookies.set(
'password',
encrypt(this.loginForm.password),
{ expires: 30 },
)
Cookies.set('rememberMe', this.loginForm.rememberMe, {
expires: 30,
})
//
if (this.loginType === 'password') {
//
if (this.loginForm.rememberMe) {
Cookies.set('username', this.loginForm.username, {
expires: 30,
})
Cookies.set(
'password',
encrypt(this.loginForm.password),
{ expires: 30 },
)
Cookies.set(
'rememberMe',
this.loginForm.rememberMe,
{
expires: 30,
},
)
} else {
Cookies.remove('username')
Cookies.remove('password')
Cookies.remove('rememberMe')
}
} else {
Cookies.remove('username')
Cookies.remove('password')
Cookies.remove('rememberMe')
//
//
console.log(
'短信验证码登录',
this.loginForm.mobile,
this.loginForm.smsCode,
)
}
//
this.$store
.dispatch('Login', this.loginForm)
.then(() => {
@ -206,7 +368,10 @@ export default {
})
.catch(() => {
this.loading = false
if (this.captchaEnabled) {
if (
this.captchaEnabled &&
this.loginType === 'password'
) {
this.getCode()
}
})
@ -218,65 +383,365 @@ export default {
</script>
<style rel="stylesheet/scss" lang="scss">
.login {
.login-content {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
height: 100%;
background-image: url('../assets/images/login-background.jpg');
background-size: cover;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.title {
margin: 0px auto 30px auto;
text-align: center;
color: #707070;
.login-container {
display: flex;
height: 80%;
width: 80%;
background: #f5f7fa;
overflow: hidden;
border-radius: 10px;
box-shadow: 0 0 10px 0 rgba(205, 43, 211, 0.658);
}
.login-form {
border-radius: 6px;
background: #ffffff;
width: 400px;
padding: 25px 25px 5px 25px;
z-index: 1;
.el-input {
height: 38px;
input {
height: 38px;
//
.login-left {
flex: 1;
position: relative;
display: flex;
align-items: center;
justify-content: center;
// background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
background: url('../assets/images/login-new-background.png') no-repeat
center center;
background-size: 100% 100%;
overflow: hidden;
.background-image {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
.input-icon {
height: 39px;
width: 14px;
margin-left: 2px;
.version-text {
position: absolute;
top: 30px;
left: 30px;
color: rgba(255, 255, 255, 0.8);
font-size: 14px;
font-weight: 500;
z-index: 2;
}
}
.login-tip {
font-size: 13px;
text-align: center;
color: #bfbfbf;
}
.login-code {
width: 33%;
height: 38px;
float: right;
img {
cursor: pointer;
vertical-align: middle;
//
.login-right {
// flex: 0 0 700px;
width: 38%;
display: flex;
align-items: center;
justify-content: center;
background: #ffffff;
position: relative;
.login-form-container {
margin: 0 auto;
width: 85%;
padding: 20px;
.welcome-title {
font-size: 28px;
font-weight: 600;
color: #2c3e50;
text-align: center;
margin-bottom: 40px;
letter-spacing: 1px;
}
.login-type-switch {
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 40px;
.switch-item {
padding: 8px 20px;
cursor: pointer;
font-size: 16px;
color: #909399;
transition: all 0.3s ease;
position: relative;
&.active {
color: #409eff;
font-weight: 600;
&::after {
content: '';
position: absolute;
bottom: -8px;
left: 50%;
transform: translateX(-50%);
width: 30px;
height: 3px;
background: linear-gradient(90deg, #409eff, #67c23a);
border-radius: 2px;
}
}
&:hover {
color: #409eff;
}
}
.divider {
margin: 0 15px;
color: #dcdfe6;
font-size: 16px;
}
}
}
}
.el-login-footer {
height: 40px;
line-height: 40px;
//
.login-form {
.el-form-item {
margin-bottom: 25px;
&.login-button-item {
margin-bottom: 0;
margin-top: 30px;
}
}
.custom-input {
.el-input__inner {
height: 50px;
line-height: 50px;
border: 2px solid #e4e7ed;
border-radius: 8px;
padding-left: 45px;
font-size: 16px;
transition: all 0.3s ease;
background: #fafbfc;
&:focus {
border-color: #409eff;
background: #ffffff;
box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.1);
}
&::placeholder {
color: #c0c4cc;
}
}
.el-input__prefix {
left: 15px;
top: 50%;
transform: translateY(-50%);
.el-input__icon {
font-size: 18px;
color: #909399;
}
}
}
.code-input-group {
display: flex;
gap: 12px;
.code-input {
flex: 1;
}
.login-code {
position: relative;
width: 120px;
height: 50px;
border: 2px solid #e4e7ed;
border-radius: 8px;
overflow: hidden;
cursor: pointer;
transition: all 0.3s ease;
&:hover {
border-color: #409eff;
}
.login-code-img {
width: 100%;
height: 100%;
object-fit: cover;
}
.refresh-icon {
position: absolute;
top: 50%;
right: 8px;
transform: translateY(-50%);
color: #909399;
font-size: 14px;
background: rgba(255, 255, 255, 0.8);
padding: 2px;
border-radius: 2px;
}
}
}
.sms-input-group {
display: flex;
gap: 12px;
.sms-input {
flex: 1;
}
.sms-button {
width: 120px;
height: 50px;
border-radius: 8px;
font-size: 14px;
border: 2px solid #409eff;
background: #409eff;
color: #ffffff;
transition: all 0.3s ease;
&:hover:not(:disabled) {
background: #66b1ff;
border-color: #66b1ff;
}
&:disabled {
background: #c0c4cc;
border-color: #c0c4cc;
color: #ffffff;
}
}
}
.form-options {
display: flex;
justify-content: space-between;
align-items: center;
margin: 20px 0;
.el-checkbox {
.el-checkbox__label {
color: #606266;
font-size: 14px;
}
}
.forgot-password {
color: #409eff;
text-decoration: none;
font-size: 14px;
transition: color 0.3s ease;
&:hover {
color: #66b1ff;
}
}
}
.login-button {
width: 100%;
height: 50px;
background: linear-gradient(135deg, #409eff 0%, #67c23a 100%);
border: none;
border-radius: 8px;
font-size: 16px;
font-weight: 600;
letter-spacing: 1px;
transition: all 0.3s ease;
box-shadow: 0 4px 15px rgba(64, 158, 255, 0.3);
&:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(64, 158, 255, 0.4);
}
&:active {
transform: translateY(0);
}
}
}
//
.login-footer {
position: fixed;
bottom: 0;
width: 100%;
left: 0;
right: 0;
height: 50px;
line-height: 50px;
text-align: center;
color: #fff;
font-family: Arial;
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(10px);
border-top: 1px solid #e4e7ed;
color: #909399;
font-size: 12px;
letter-spacing: 1px;
z-index: 1000;
}
.login-code-img {
height: 38px;
//
@media (max-width: 768px) {
.login-container {
flex-direction: column;
}
.login-left {
flex: 0 0 200px;
}
.login-right {
flex: 1;
.login-form-container {
width: 100%;
padding: 20px;
}
}
}
//
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.login-form-container {
animation: fadeInUp 0.6s ease-out;
}
//
.custom-input .el-input__inner:focus {
animation: pulse 0.3s ease-in-out;
}
@keyframes pulse {
0% {
transform: scale(1);
}
50% {
transform: scale(1.02);
}
100% {
transform: scale(1);
}
}
</style>

282
src/views/login_old.vue Normal file
View File

@ -0,0 +1,282 @@
<template>
<div class="login">
<el-form
ref="loginForm"
:model="loginForm"
:rules="loginRules"
class="login-form"
>
<h3 class="title">{{ title }}</h3>
<el-form-item prop="username">
<el-input
v-model="loginForm.username"
type="text"
auto-complete="off"
placeholder="账号"
>
<svg-icon
slot="prefix"
icon-class="user"
class="el-input__icon input-icon"
/>
</el-input>
</el-form-item>
<el-form-item prop="password">
<el-input
v-model="loginForm.password"
type="password"
auto-complete="off"
placeholder="密码"
show-password
@keyup.enter.native="handleLogin"
>
<svg-icon
slot="prefix"
icon-class="password"
class="el-input__icon input-icon"
/>
</el-input>
</el-form-item>
<el-form-item prop="code" v-if="captchaEnabled">
<el-input
v-model="loginForm.code"
auto-complete="off"
placeholder="验证码"
style="width: 63%"
@keyup.enter.native="handleLogin"
>
<svg-icon
slot="prefix"
icon-class="validCode"
class="el-input__icon input-icon"
/>
</el-input>
<div class="login-code">
<img
:src="codeUrl"
@click="getCode"
class="login-code-img"
/>
</div>
</el-form-item>
<el-checkbox
v-model="loginForm.rememberMe"
style="margin: 0px 0px 25px 0px"
>记住密码</el-checkbox
>
<el-form-item style="width: 100%">
<el-button
:loading="loading"
size="medium"
type="primary"
style="width: 100%"
@click.native.prevent="handleLogin"
>
<span v-if="!loading"> </span>
<span v-else> 中...</span>
</el-button>
<div style="float: right" v-if="register">
<router-link class="link-type" :to="'/register'"
>立即注册</router-link
>
</div>
</el-form-item>
</el-form>
<!-- 底部 -->
<div class="el-login-footer">
<span>Copyright © 2018-2025 ruoyi.vip All Rights Reserved.</span>
</div>
</div>
</template>
<script>
import { getCodeImg } from '@/api/login'
import Cookies from 'js-cookie'
import { encrypt, decrypt } from '@/utils/jsencrypt'
export default {
name: 'Login',
data() {
return {
title: process.env.VUE_APP_TITLE,
codeUrl: '',
loginForm: {
username: 'admin',
password: 'admin123',
rememberMe: false,
code: '',
uuid: '',
},
loginRules: {
username: [
{
required: true,
trigger: 'blur',
message: '请输入您的账号',
},
],
password: [
{
required: true,
trigger: 'blur',
message: '请输入您的密码',
},
],
code: [
{
required: true,
trigger: 'change',
message: '请输入验证码',
},
],
},
loading: false,
//
captchaEnabled: true,
//
register: false,
redirect: undefined,
}
},
watch: {
$route: {
handler: function (route) {
this.redirect = route.query && route.query.redirect
},
immediate: true,
},
},
created() {
this.getCode()
this.getCookie()
},
methods: {
getCode() {
getCodeImg().then((res) => {
this.captchaEnabled =
res.captchaEnabled === undefined ? true : res.captchaEnabled
if (this.captchaEnabled) {
this.codeUrl = 'data:image/gif;base64,' + res.img
this.loginForm.uuid = res.uuid
}
})
},
getCookie() {
const username = Cookies.get('username')
const password = Cookies.get('password')
const rememberMe = Cookies.get('rememberMe')
this.loginForm = {
username:
username === undefined ? this.loginForm.username : username,
password:
password === undefined
? this.loginForm.password
: decrypt(password),
rememberMe:
rememberMe === undefined ? false : Boolean(rememberMe),
}
},
handleLogin() {
this.$refs.loginForm.validate((valid) => {
if (valid) {
this.loading = true
if (this.loginForm.rememberMe) {
Cookies.set('username', this.loginForm.username, {
expires: 30,
})
Cookies.set(
'password',
encrypt(this.loginForm.password),
{ expires: 30 },
)
Cookies.set('rememberMe', this.loginForm.rememberMe, {
expires: 30,
})
} else {
Cookies.remove('username')
Cookies.remove('password')
Cookies.remove('rememberMe')
}
this.$store
.dispatch('Login', this.loginForm)
.then(() => {
this.$router
.push({ path: this.redirect || '/' })
.catch(() => {})
})
.catch(() => {
this.loading = false
if (this.captchaEnabled) {
this.getCode()
}
})
}
})
},
},
}
</script>
<style rel="stylesheet/scss" lang="scss">
.login {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
background-image: url('../assets/images/login-background.jpg');
background-size: cover;
}
.title {
margin: 0px auto 30px auto;
text-align: center;
color: #707070;
}
.login-form {
border-radius: 6px;
background: #ffffff;
width: 400px;
padding: 25px 25px 5px 25px;
z-index: 1;
.el-input {
height: 38px;
input {
height: 38px;
}
}
.input-icon {
height: 39px;
width: 14px;
margin-left: 2px;
}
}
.login-tip {
font-size: 13px;
text-align: center;
color: #bfbfbf;
}
.login-code {
width: 33%;
height: 38px;
float: right;
img {
cursor: pointer;
vertical-align: middle;
}
}
.el-login-footer {
height: 40px;
line-height: 40px;
position: fixed;
bottom: 0;
width: 100%;
text-align: center;
color: #fff;
font-family: Arial;
font-size: 12px;
letter-spacing: 1px;
}
.login-code-img {
height: 38px;
}
</style>