feat: 完成用户表单的CURD基本操作
This commit is contained in:
parent
d12c14f26f
commit
0736cdee4a
@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "myVue_3.2",
|
||||
"name": "my-vue-3.2",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
@ -11,7 +11,9 @@
|
||||
"dependencies": {
|
||||
"@element-plus/icons-vue": "^2.0.6",
|
||||
"axios": "^0.27.2",
|
||||
"cesium": "^1.95.0",
|
||||
"core-js": "^3.8.3",
|
||||
"dayjs": "^1.11.4",
|
||||
"driver.js": "^0.9.8",
|
||||
"element-plus": "1.3.0-beta.5",
|
||||
"lint-staged": "13.0.3",
|
||||
|
@ -4,4 +4,9 @@
|
||||
|
||||
<script setup></script>
|
||||
|
||||
<style lang="scss"></style>
|
||||
<style lang="scss">
|
||||
// .el-message
|
||||
.el-message-box__status {
|
||||
position: absolute !important;
|
||||
}
|
||||
</style>
|
||||
|
38
src/api/user.js
Normal file
38
src/api/user.js
Normal file
@ -0,0 +1,38 @@
|
||||
import request from './request'
|
||||
|
||||
export const getUser = (params) => {
|
||||
return request({
|
||||
url: '/users',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export const changeUserState = (uid, type) => {
|
||||
return request({
|
||||
url: `users/${uid}/state/${type}`,
|
||||
method: 'put'
|
||||
})
|
||||
}
|
||||
|
||||
export const addUser = (data) => {
|
||||
return request({
|
||||
url: 'users',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export const editUser = (data) => {
|
||||
return request({
|
||||
url: `users/${data.id}`,
|
||||
method: 'put',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export const deleteUser = (id) => {
|
||||
return request({
|
||||
url: `users/${id}`,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
11
src/main.js
11
src/main.js
@ -8,6 +8,9 @@ import * as ElementPlusIconsVue from '@element-plus/icons-vue'
|
||||
import 'element-plus/dist/index.css'
|
||||
import '@/router/premission'
|
||||
import i18n from './i18n/i18nIndex'
|
||||
import * as Cesium from '../node_modules/cesium/Source/Cesium'
|
||||
import '../node_modules/cesium/Source/Widgets/widgets.css'
|
||||
import filters from './utils/filters'
|
||||
|
||||
const app = createApp(App)
|
||||
SvgIcon(app)
|
||||
@ -17,3 +20,11 @@ app.use(store).use(router).use(i18n).mount('#app')
|
||||
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
|
||||
app.component(key, component)
|
||||
}
|
||||
|
||||
// 全局引入时间过滤设置
|
||||
filters(app)
|
||||
|
||||
// 全局引入 Cesium
|
||||
app.config.globalProperties.$Cesium = Cesium
|
||||
Cesium.Ion.defaultAccessToken =
|
||||
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIzZjhhMGMyNy0xOGJhLTQyNDItODdjMC1kYzdhZjU5M2RlNTYiLCJpZCI6MTAyNzI1LCJpYXQiOjE2NTg5MTQwMTV9.V8wOhhVUW0PvDJq7KIlzieoWhtZcbWXeYnrY2iZoJl8'
|
||||
|
22
src/utils/filters.js
Normal file
22
src/utils/filters.js
Normal file
@ -0,0 +1,22 @@
|
||||
const dayjs = require('dayjs')
|
||||
//
|
||||
const filterTimes = (val, format = 'YYYY-MM-DD') => {
|
||||
if (!isNull(val)) {
|
||||
val = parseInt(val) * 1000
|
||||
return dayjs(val).format(format)
|
||||
} else {
|
||||
return '--'
|
||||
}
|
||||
}
|
||||
// 判断外来的值是否为空
|
||||
export const isNull = (date) => {
|
||||
if (!date) return true
|
||||
if (JSON.stringify(date) === '{}') return true
|
||||
if (JSON.stringify(date) === '[]') return true
|
||||
}
|
||||
|
||||
export default (app) => {
|
||||
app.config.globalProperties.$filters = {
|
||||
filterTimes
|
||||
}
|
||||
}
|
43
src/views/reports/myMap.vue
Normal file
43
src/views/reports/myMap.vue
Normal file
@ -0,0 +1,43 @@
|
||||
<template>
|
||||
<div class="cesiumContainer"></div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
Viewer,
|
||||
createWorldTerrain,
|
||||
createOsmBuildings,
|
||||
Cartesian3,
|
||||
Math
|
||||
} from 'cesium'
|
||||
|
||||
// Your access token can be found at: https://cesium.com/ion/tokens.
|
||||
// This is the default access token
|
||||
|
||||
// Initialize the Cesium Viewer in the HTML element with the `cesiumContainer` ID.
|
||||
const viewer = new Viewer('cesiumContainer', {
|
||||
terrainProvider: createWorldTerrain()
|
||||
})
|
||||
|
||||
// Add Cesium OSM Buildings, a global 3D buildings layer.
|
||||
viewer.scene.primitives.add(createOsmBuildings())
|
||||
|
||||
// Fly the camera to San Francisco at the given longitude, latitude, and height.
|
||||
viewer.camera.flyTo({
|
||||
destination: Cartesian3.fromDegrees(-122.4175, 37.655, 400),
|
||||
orientation: {
|
||||
heading: Math.toRadians(0.0),
|
||||
pitch: Math.toRadians(-15.0)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.cesiumContainer {
|
||||
width: auto;
|
||||
height: auto;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
@ -1,7 +1,12 @@
|
||||
<template>
|
||||
<div>reports</div>
|
||||
<!-- <my-map /> -->
|
||||
<!-- <Testmap /> -->
|
||||
</template>
|
||||
|
||||
<script setup></script>
|
||||
<script setup>
|
||||
// import myMap from './myMap.vue'
|
||||
// import Testmap from './cesium/testMap.vue'
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
144
src/views/users/components/dialogIndex.vue
Normal file
144
src/views/users/components/dialogIndex.vue
Normal file
@ -0,0 +1,144 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:model-value="dialogVisible"
|
||||
:title="dialogTitle"
|
||||
width="30%"
|
||||
@close="handleClose"
|
||||
>
|
||||
<el-form
|
||||
ref="ruleFormRef"
|
||||
:model="ruleForm"
|
||||
:rules="rules"
|
||||
label-width="120px"
|
||||
status-icon
|
||||
>
|
||||
<el-form-item label="用户名" prop="username">
|
||||
<el-input v-model="ruleForm.username" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="密码"
|
||||
prop="password"
|
||||
v-if="dialogTitle === '添加用户'"
|
||||
>
|
||||
<el-input v-model="ruleForm.password" type="password" />
|
||||
</el-form-item>
|
||||
<el-form-item label="邮箱" prop="email">
|
||||
<el-input v-model="ruleForm.email" />
|
||||
</el-form-item>
|
||||
<el-form-item label="手机号" prop="mobile">
|
||||
<el-input v-model="ruleForm.mobile" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="handleClose">取消</el-button>
|
||||
<el-button type="primary" @click="handleConfirm">确认</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { defineEmits, ref, defineProps, watch } from 'vue'
|
||||
// import { defineEmits, ref, defineProps } from 'vue'
|
||||
import { addUser, editUser } from '@/api/user'
|
||||
import i18n from '@/i18n/i18nIndex'
|
||||
import { ElMessage } from 'element-plus'
|
||||
|
||||
const props = defineProps({
|
||||
dialogTitle: {
|
||||
type: String,
|
||||
default: '',
|
||||
required: true
|
||||
},
|
||||
dialogTableValue: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
}
|
||||
})
|
||||
|
||||
const ruleFormRef = ref(null)
|
||||
const ruleForm = ref({
|
||||
username: '',
|
||||
password: '',
|
||||
email: '',
|
||||
mobile: ''
|
||||
})
|
||||
|
||||
const rules = ref({
|
||||
username: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入用户名。',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
password: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入用户密码。',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
email: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入用户邮箱。',
|
||||
trigger: 'blur'
|
||||
},
|
||||
{
|
||||
type: 'email',
|
||||
message: '请输入正确的邮箱地址。',
|
||||
trigger: ['blur', 'change']
|
||||
}
|
||||
],
|
||||
mobile: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入用户手机号。',
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
// 监听对话框数值的改变
|
||||
watch(
|
||||
() => props.dialogTableValue,
|
||||
() => {
|
||||
// console.log(props.dialogTableValue)
|
||||
ruleForm.value = props.dialogTableValue
|
||||
},
|
||||
{ deep: true, immediate: true }
|
||||
)
|
||||
|
||||
const emits = defineEmits(['update:modelValue', 'initUserList'])
|
||||
|
||||
const handleClose = () => {
|
||||
emits('update:modelValue', false)
|
||||
}
|
||||
// 确认按钮
|
||||
const handleConfirm = () => {
|
||||
ruleFormRef.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
props.dialogTitle === '添加用户'
|
||||
? await addUser(ruleForm.value)
|
||||
: await editUser(ruleForm.value)
|
||||
ElMessage({
|
||||
// showClose: true,
|
||||
message: i18n.global.t('message.updeteSuccess'),
|
||||
type: 'success'
|
||||
})
|
||||
emits('initUserList')
|
||||
handleClose()
|
||||
} else {
|
||||
ElMessage({
|
||||
message: '请检查输入内容。',
|
||||
type: 'error'
|
||||
})
|
||||
return false
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
35
src/views/users/userOptions.js
Normal file
35
src/views/users/userOptions.js
Normal file
@ -0,0 +1,35 @@
|
||||
export const options = [
|
||||
// {
|
||||
// label: 'id',
|
||||
// prop: 'id'
|
||||
// },
|
||||
{
|
||||
label: 'username',
|
||||
prop: 'username'
|
||||
},
|
||||
{
|
||||
label: 'email',
|
||||
prop: 'email'
|
||||
},
|
||||
{
|
||||
label: 'mobile',
|
||||
prop: 'mobile'
|
||||
},
|
||||
{
|
||||
label: 'role_name',
|
||||
prop: 'role_name'
|
||||
},
|
||||
{
|
||||
label: 'mg_state',
|
||||
prop: 'mg_state'
|
||||
},
|
||||
{
|
||||
label: 'create_time',
|
||||
prop: 'create_time'
|
||||
},
|
||||
{
|
||||
label: 'action',
|
||||
prop: 'action',
|
||||
width: 200
|
||||
}
|
||||
]
|
@ -1,7 +1,175 @@
|
||||
<template>
|
||||
<div>users</div>
|
||||
<el-card>
|
||||
<!-- 顶部搜索 -->
|
||||
<el-row :gutter="20" class="header">
|
||||
<el-col :span="7">
|
||||
<el-input
|
||||
:placeholder="$t('table.placeholder')"
|
||||
clearable
|
||||
v-model="queryFrom.query"
|
||||
>
|
||||
</el-input>
|
||||
</el-col>
|
||||
<el-button type="primary" :icon="Search" @click="initGetUsersList">
|
||||
{{ $t('table.search') }}
|
||||
</el-button>
|
||||
<el-button type="primary" @click="handleDialogValue()">
|
||||
{{ $t('table.adduser') }}
|
||||
</el-button>
|
||||
</el-row>
|
||||
<!-- 表格内容 -->
|
||||
<el-table :data="tableData" stripe style="width: 100%">
|
||||
<el-table-column
|
||||
:width="item.width"
|
||||
:prop="item.prop"
|
||||
:label="$t(`table.${item.label}`)"
|
||||
v-for="(item, index) in options"
|
||||
:key="index"
|
||||
>
|
||||
<template v-slot="{ row }" v-if="item.prop === 'mg_state'">
|
||||
<el-switch v-model="row.mg_state" @change="changeState(row)" />
|
||||
</template>
|
||||
<template v-slot="{ row }" v-else-if="item.prop === 'create_time'">
|
||||
{{ $filters.filterTimes(row.create_time) }}
|
||||
</template>
|
||||
<template #default="{ row }" v-else-if="item.prop === 'action'">
|
||||
<el-button
|
||||
type="primary"
|
||||
:icon="Edit"
|
||||
circle
|
||||
@click="handleDialogValue(row)"
|
||||
/>
|
||||
<el-button
|
||||
type="danger"
|
||||
:icon="Delete"
|
||||
circle
|
||||
@click="delUser(row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
v-model:currentPage="queryFrom.pagenum"
|
||||
v-model:page-size="queryFrom.pagesize"
|
||||
:page-sizes="[2, 5, 10, 15]"
|
||||
:small="small"
|
||||
:disabled="disabled"
|
||||
:background="background"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="total"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
class="footer"
|
||||
/>
|
||||
</el-card>
|
||||
<Dialog
|
||||
v-model="dialogVisible"
|
||||
:dialogTitle="dialogTitle"
|
||||
v-if="dialogVisible"
|
||||
@initUserList="initGetUsersList"
|
||||
:dialogTableValue="dialogTableValue"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script></script>
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { Search, Edit, Delete } from '@element-plus/icons-vue'
|
||||
import { getUser, changeUserState, deleteUser } from '@/api/user'
|
||||
import { options } from './userOptions'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import Dialog from './components/dialogIndex.vue'
|
||||
import { isNull } from '@/utils/filters'
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
const i18n = useI18n()
|
||||
|
||||
const queryFrom = ref({
|
||||
query: '',
|
||||
pagenum: 1,
|
||||
pagesize: 2
|
||||
})
|
||||
|
||||
const total = ref(0)
|
||||
|
||||
const dialogVisible = ref(false)
|
||||
const dialogTitle = ref('')
|
||||
const dialogTableValue = ref({})
|
||||
|
||||
const tableData = ref([])
|
||||
const initGetUsersList = async () => {
|
||||
const res = await getUser(queryFrom.value)
|
||||
// console.log(res)
|
||||
total.value = res.total
|
||||
tableData.value = res.users
|
||||
}
|
||||
initGetUsersList()
|
||||
|
||||
// 分页器页码改变的方法
|
||||
const handleSizeChange = (pageSize) => {
|
||||
queryFrom.value.pagenum = 1
|
||||
queryFrom.value.pagesize = pageSize
|
||||
initGetUsersList()
|
||||
}
|
||||
|
||||
const handleCurrentChange = (pageNum) => {
|
||||
queryFrom.value.pagenum = pageNum
|
||||
initGetUsersList()
|
||||
}
|
||||
|
||||
// 改变用户状态开关
|
||||
const changeState = async (info) => {
|
||||
await changeUserState(info.id, info.mg_state)
|
||||
ElMessage({
|
||||
// showClose: true,
|
||||
message: i18n.t('message.updeteSuccess'),
|
||||
type: 'success'
|
||||
})
|
||||
}
|
||||
|
||||
// 用户数据操作
|
||||
const handleDialogValue = (row) => {
|
||||
if (isNull(row)) {
|
||||
dialogTitle.value = '添加用户'
|
||||
dialogTableValue.value = {}
|
||||
} else {
|
||||
dialogTitle.value = '编辑用户'
|
||||
dialogTableValue.value = JSON.parse(JSON.stringify(row))
|
||||
}
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
const delUser = (row) => {
|
||||
ElMessageBox.confirm('是否确认删除该用户?', '警告', {
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
// 删除成功后刷新数据
|
||||
.then(async () => {
|
||||
await deleteUser(row.id)
|
||||
ElMessage({
|
||||
type: 'success',
|
||||
message: '删除成功。'
|
||||
})
|
||||
initGetUsersList()
|
||||
})
|
||||
.catch(() => {
|
||||
ElMessage({
|
||||
type: 'info',
|
||||
message: '取消删除。'
|
||||
})
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.header {
|
||||
padding-bottom: 16px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.footer {
|
||||
padding-top: 16px;
|
||||
box-sizing: border-box;
|
||||
text-align: right;
|
||||
}
|
||||
</style>
|
||||
|
10
yarn.lock
10
yarn.lock
@ -2610,6 +2610,11 @@ case-sensitive-paths-webpack-plugin@^2.3.0:
|
||||
resolved "https://registry.npmmirror.com/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz#db64066c6422eed2e08cc14b986ca43796dbc6d4"
|
||||
integrity sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==
|
||||
|
||||
cesium@^1.95.0:
|
||||
version "1.95.0"
|
||||
resolved "https://registry.npmmirror.com/cesium/-/cesium-1.95.0.tgz#8a9036c58b9818406586259d3720a05f24e87a69"
|
||||
integrity sha512-59U0lZD/wmSJa4t9FcK1/sp6PyCpx7h8c4giLd8VM7LJDL6w0G0o4QGlZ4TSJTBe4VIClf+qPDUf47wyBu4YoA==
|
||||
|
||||
chalk@^1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.npmmirror.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
|
||||
@ -3187,6 +3192,11 @@ dayjs@^1.10.7:
|
||||
resolved "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.3.tgz#4754eb694a624057b9ad2224b67b15d552589258"
|
||||
integrity sha512-xxwlswWOlGhzgQ4TKzASQkUhqERI3egRNqgV4ScR8wlANA/A9tZ7miXa44vTTKEq5l7vWoL5G57bG3zA+Kow0A==
|
||||
|
||||
dayjs@^1.11.4:
|
||||
version "1.11.4"
|
||||
resolved "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.4.tgz#3b3c10ca378140d8917e06ebc13a4922af4f433e"
|
||||
integrity sha512-Zj/lPM5hOvQ1Bf7uAvewDaUcsJoI6JmNqmHhHl3nyumwe0XHwt8sWdOVAPACJzCebL8gQCi+K49w7iKWnGwX9g==
|
||||
|
||||
debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.9:
|
||||
version "2.6.9"
|
||||
resolved "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
||||
|
Loading…
x
Reference in New Issue
Block a user