feat:用户管理

environments/test/deployments/1
saatana 4 years ago
parent 537bc8d07e
commit 47e13a9dfb

@ -4,9 +4,7 @@ const mock = (data) =>
resolve(data);
}, Math.random() * 1500 + 500);
});
export const findUserList = (data) => {
return mock({
content: [
let list = [
{
id: 1,
username: 'user001',
@ -34,7 +32,27 @@ export const findUserList = (data) => {
loginTime: Date.now(),
enabled: false,
},
],
totalElements: 3,
});
];
export const findUserList = (data) => {
return mock({ content: list, totalElements: list.length });
};
export const createUser = (data) => {
data = {
id: new Date().getTime(),
...data,
};
list.push(data);
return mock(data);
};
export const updateUser = (data) => {
let old = list.find((item) => item.id === data.id);
Object.assign(old, data);
return mock(old);
};
export const removeUser = (ids) => {
list = list.filter((item) => !ids.includes(item.id));
return mock(true);
};
export const getUserDetail = (id) => {
return mock(list.find((item) => item.id === id));
};

@ -32,6 +32,11 @@
},
multiple: {
type: Boolean,
defualt: false,
},
disabled: {
type: Boolean,
defualt: false,
},
limit: {
type: Number,
@ -122,9 +127,13 @@
{unref(imgList).map((item, index) => (
<div class="img-li">
<ElImage src={item?.response?.data} alt={item.name} />
{!props.disabled ? (
<div class="img-li-cover" onClick={() => handleDeleteImage(index)}>
<ElIcon class="upload-del-icon" name="delete-bin-fill" size="20" />
</div>
) : (
''
)}
</div>
))}
{props.limit != unref(imgList).length ? (

@ -24,6 +24,12 @@
width: 100%;
height: @layout-main-height;
padding: @layout-space-large;
&.form-container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
}
}
}

@ -38,6 +38,16 @@ export default [
hidden: true,
},
},
{
path: 'detail/:id',
name: 'UserDetail',
component: () => import('@/views/system/user/form.vue'),
meta: {
title: '用户详情',
icon: 'user-1-fill',
hidden: true,
},
},
],
},
],

@ -1,34 +1,76 @@
import * as api from '@/api/system/user.js';
import { ElMessage } from '@/plugins/element-plus';
import { ElMessage, ElMessageBox } from '@/plugins/element-plus';
const state = () => ({
loading: false,
list: [],
total: 0,
page: { pageIndex: 1, length: 10 },
opts: {
sex: [
{ label: '男', value: 1 },
{ label: '女', value: 0 },
],
init: false,
sex: [],
},
});
const getters = {};
const mutations = {
setLoading: (state, data) => (state.loading = data),
setList: (state, data) => (state.list = data),
setTotal: (state, data) => (state.total = data),
setOpts: (state, data) => (state.opts = data),
};
const actions = {
search: async ({ commit }, data) => {
commit('setLoading', true);
let res = await api.findUserList(data);
search: async ({ state, commit }, data = {}) => {
let res = await api.findUserList({ ...state.page, ...data });
if (res) {
commit('setList', res.content);
commit('setTotal', res.totalElements);
} else {
ElMessage.error('查询用户失败');
ElMessage.error('查询失败');
commit('setList', []);
}
commit('setLoading', false);
return res;
},
load: async ({ commit }) => {
commit('setOpts', {
init: true,
sex: [
{ label: '男', value: 1 },
{ label: '女', value: 0 },
],
});
},
detail: async ({ state }, id) => {
let res = await api.getUserDetail(id);
if (!res) {
ElMessage.error('加载详情失败');
}
return res;
},
save: async ({ dispatch }, data) => {
let save = data.id ? api.updateUser : api.createUser;
let res = await save(data);
if (res) {
ElMessage.success('保存成功');
dispatch('search');
} else {
ElMessage.error('保存失败');
}
return res;
},
remove: async ({ dispatch }, ids) => {
if (!ids.length) {
ElMessage.warning('请选择要删除的数据');
} else {
try {
await ElMessageBox.confirm('数据删除后无法恢复,确定要删除吗?', '危险操作');
let res = await api.removeUser(ids);
if (res) {
ElMessage.success('删除成功');
dispatch('search');
} else {
ElMessage.error('删除失败');
}
} catch (e) {
console.info('取消删除', e);
}
}
},
};
export default {

@ -1,20 +1,115 @@
<template>
<div class="form-container">
<el-form :model="form" :rules="rules" label-width="100px">
<el-form
class="form-content"
ref="refsForm"
v-loading="loading"
:model="form"
:rules="rules"
label-width="100px"
:disabled="route.name === 'UserDetail'"
>
<el-form-item label="用户名" prop="username">
<el-input v-model="form.username" />
</el-form-item>
<el-form-item label="昵称" prop="nickname">
<el-input v-model="form.nickname" />
</el-form-item>
<el-form-item label="性别" prop="sex">
<el-radio-group :opts="opts.sex" v-model="form.sex" />
</el-form-item>
<el-form-item label="头像" prop="avatar">
<el-upload-image :disabled="route.name === 'UserDetail'" v-model="form.avatar" />
</el-form-item>
<el-form-item label="状态" prop="enabled">
<el-switch
v-model="form.enabled"
active-text="启用"
inactive-text="禁用"
:active-value="true"
:inactive-value="false"
/>
</el-form-item>
</el-form>
<div class="form-footer">
<template v-if="route.name !== 'UserDetail'">
<el-button @click="handleCancel"></el-button>
<el-button type="primary" @click="handleSave" :disabled="loading" :loading="submitting">保存</el-button>
</template>
<el-button @click="handleClose" v-else></el-button>
</div>
</div>
</template>
<script setup>
/* 全局 */
const store = useStore();
const route = useRoute();
const router = useRouter();
const { proxy } = getCurrentInstance();
/* 表单 */
const loading = ref(false);
const submitting = ref(false);
const refsForm = ref(null);
const form = reactive({
username: null,
nickname: null,
sex: 0,
avatar: null,
enabled: true,
});
const rules = reactive({
username: [{ required: true }],
username: [{ required: true, message: '用户名不能为空' }],
nickname: [{ required: true, message: '昵称不能为空' }],
sex: [{ required: true, message: '性别不能为空' }],
avatar: [{ required: true, message: '头像不能为空' }],
enabled: [{ required: true, message: '状态不能为空' }],
});
const opts = computed(() => store.state.user.opts);
if (!unref(opts).init) {
store.dispatch('user/load');
}
/* 详情 */
watch(
() => [route.name, route.params.id],
async (value) => {
// watch
if (['UpdateUser', 'UserDetail'].includes(value[0]) && value[1]) {
loading.value = true;
let res = await store.dispatch('user/detail', +value[1]);
if (res) {
Object.assign(form, res);
}
loading.value = false;
}
},
{ immediate: true }
);
/* 交互 */
const handleSave = async () => {
submitting.value = true;
try {
await unref(refsForm).validate();
let res = await store.dispatch('user/save', unref(form));
if (res) {
handleClose();
}
} catch (e) {
console.info('取消保存', e);
}
submitting.value = false;
};
const handleCancel = async () => {
try {
await proxy.$confirm('确定要放弃未保存的数据继续离开吗?', '数据未保存');
handleClose();
} catch (e) {
console.info('取消关闭', e);
}
};
const handleClose = () => {
router.push({ name: 'UserManagement' });
};
</script>
<style lang="less" scoped></style>

@ -23,7 +23,7 @@
<script setup lang="jsx">
const router = useRouter();
const store = useStore();
const loading = computed(() => store.state.user.loading);
const loading = ref(false);
const list = computed(() => store.state.user.list);
const total = computed(() => store.state.user.total);
const opts = computed(() => store.state.user.opts);
@ -32,8 +32,10 @@
username: null,
},
});
const handleSearch = (page) => {
store.dispatch('user/search', { ...page, ...state.condition });
const handleSearch = async (page) => {
loading.value = true;
await store.dispatch('user/search', { ...page, ...state.condition });
loading.value = false;
};
const handleCreate = () => {
router.push({ name: 'CreateUser' });
@ -41,11 +43,14 @@
const handleUpdate = (row) => {
router.push({ name: 'UpdateUser', params: { id: row.id } });
};
const handleRemove = (rows) => {
alert('delete ' + rows.map((item) => item.id).join(','));
const handleRemove = async (rows) => {
store.dispatch(
'user/remove',
rows.map((item) => item.id)
);
};
const handleDetail = (row) => {
alert('detail ' + row.id);
router.push({ name: 'UserDetail', params: { id: row.id } });
};
const handleEnabled = (row, enabled) => {
alert((enabled ? 'enabled ' : 'disabled ') + row.id);

Loading…
Cancel
Save