用户管理编写

This commit is contained in:
wangyilin 2025-05-09 11:41:24 +08:00
parent e2a27af64c
commit 9a6771dc84
10 changed files with 567 additions and 13 deletions

View File

@ -64,7 +64,7 @@
class="l-footer"
:style="{ background: settingsStore.isDark ? '#1e1e1e' : '#fff' }"
>
<div>Copyright © {{ dayjs().year() }} 湖南长沪信息科技有限公司</div>
<div>Copyright © {{ dayjs().year() }} </div>
</n-layout-footer>
</n-layout>
</n-layout>

View File

@ -46,7 +46,7 @@
</div>
</main>
<footer class="p_24px">
Copyright © {{ dayjs().year() }} 湖南长沪信息科技有限公司
Copyright © {{ dayjs().year() }}
</footer>
</div>
</div>

View File

@ -289,6 +289,7 @@
const resetModelValue = () => {
userValue.value = { ...userDefaultValue };
title.value = '新增库存'
};
const addUserOrUpdate = ()=>{
@ -396,7 +397,7 @@
});
const loading = ref<boolean>(false);
const modalRef = ref();
const title = ref("新增");
const title = ref("新增库存");
const addDepartmentStructure = () => {
modalRef.value = modal.create({
title: title.value,

View File

@ -44,7 +44,7 @@ const datalist:DishesValue[] = [
essentials:"1.鸡蛋打散,炒熟备用。\n2.热锅烧油,放入西红柿翻炒。\n3.加入盐,白糖,鸡精炒熟。\n4.放入鸡蛋,翻拌均匀。\n5.生粉加水调匀,淋入锅中,收汁出锅。",
fat: 2.72,
fruitsVegetables:70,
image:"https://file.wy2020.com/admin/weiyi/img/vip/nutri/dish/cbf28b18d47a4c378ad7c702dc9da6f8_1280w_956h.jpg?x-image-process=image/resize,m_lfit,h_25,w_25",
image:"https://file.wy2020.com/admin/weiyi/img/vip/nutri/dish/cbf28b18d47a4c378ad7c702dc9da6f8_1280w_956h.jpg",
meatEgg:30,
name :"西红柿炒鸡蛋",
percentage:"西红柿70% 鸡蛋30%",
@ -72,7 +72,7 @@ const datalist:DishesValue[] = [
essentials:"1.鸡蛋打散,炒熟备用。\n2.热锅烧油,放入西红柿翻炒。\n3.加入盐,白糖,鸡精炒熟。\n4.放入鸡蛋,翻拌均匀。\n5.生粉加水调匀,淋入锅中,收汁出锅。",
fat: 2.72,
fruitsVegetables:70,
image:"https://file.wy2020.com/admin/weiyi/img/vip/nutri/dish/cbf28b18d47a4c378ad7c702dc9da6f8_1280w_956h.jpg?x-image-process=image/resize,m_lfit,h_25,w_25",
image:"https://file.wy2020.com/admin/weiyi/img/vip/nutri/dish/8b654afe895e11e6b87c0242ac110003_650w_650h.jpg",
meatEgg:30,
name :"西红柿炒鸡蛋",
percentage:"西红柿70% 鸡蛋30%",
@ -100,7 +100,7 @@ const datalist:DishesValue[] = [
essentials:"1.鸡蛋打散,炒熟备用。\n2.热锅烧油,放入西红柿翻炒。\n3.加入盐,白糖,鸡精炒熟。\n4.放入鸡蛋,翻拌均匀。\n5.生粉加水调匀,淋入锅中,收汁出锅。",
fat: 2.72,
fruitsVegetables:70,
image:"https://file.wy2020.com/admin/weiyi/img/vip/nutri/dish/cbf28b18d47a4c378ad7c702dc9da6f8_1280w_956h.jpg?x-image-process=image/resize,m_lfit,h_25,w_25",
image:"https://file.wy2020.com/admin/weiyi/img/vip/nutri/dish/cbf28b18d47a4c378ad7c702dc9da6f8_1280w_956h.jpg",
meatEgg:30,
name :"西红柿炒鸡蛋",
percentage:"西红柿70% 鸡蛋30%",
@ -128,7 +128,7 @@ const datalist:DishesValue[] = [
essentials:"1.鸡蛋打散,炒熟备用。\n2.热锅烧油,放入西红柿翻炒。\n3.加入盐,白糖,鸡精炒熟。\n4.放入鸡蛋,翻拌均匀。\n5.生粉加水调匀,淋入锅中,收汁出锅。",
fat: 2.72,
fruitsVegetables:70,
image:"https://file.wy2020.com/admin/weiyi/img/vip/nutri/dish/cbf28b18d47a4c378ad7c702dc9da6f8_1280w_956h.jpg?x-image-process=image/resize,m_lfit,h_25,w_25",
image:"https://file.wy2020.com/admin/weiyi/img/vip/nutri/dish/cbf28b18d47a4c378ad7c702dc9da6f8_1280w_956h.jpg",
meatEgg:30,
name :"西红柿炒鸡蛋",
percentage:"西红柿70% 鸡蛋30%",

View File

@ -184,8 +184,8 @@
width: 100,
render: (value: any) => {
return (
<n-avatar
round
<n-image
width="30"
src={value.image}
/>
);
@ -418,6 +418,7 @@
const resetModelValue = () => {
userValue.value = { ...userDefaultValue };
title.value = '添加食材原料'
};
const addUserOrUpdate = () => {

View File

@ -376,6 +376,7 @@
const resetModelValue = () => {
userValue.value = { ...userDefaultValue };
title.value = '添加食材原料'
};
const addUserOrUpdate = () => {

View File

@ -203,6 +203,8 @@
default: () => "确认要除么?"
}}
</NPopconfirm>
<n-button type="success" style={{ marginLeft: "10px" }}>菜单授权</n-button>
</div>
);
}
@ -249,6 +251,7 @@
const resetModelValue = () => {
userValue.value = { ...userRoleValue };
title.value = '新增角色'
};
const addUserOrUpdate = () => {

View File

@ -0,0 +1,102 @@
export interface userInterface {
/**
* @snowFlakeId
*/
snowFlakeId?: string
/**
* @name
*/
avatar?: string
/**
* @name _必传
*/
name: string
/**
* @sex _必传
*/
sex: string
/**
* @phoneNumber _必传
*/
phoneNumber: string
/**
* @phoneNumber _必传
*/
status: string
/**
* @authClient _必传
*/
authClient?: any[]
/**
* @deptIds id_必传
*/
deptIds?: any[]
/**
* @roleIds id_必传
*/
roleIds?: any[]
lastLoginTime?:string
}
export interface passwordInterface {
oldPassword: string
newPassword: string
confirmPassword: string
}
const userInfo:userInterface[] = [
{
avatar:'https://file.wy2020.com/admin/weiyi/img/mqtts/morning/record/1920283993400512513_headImg.jpg',
name:'刘德华',
sex:'man',
phoneNumber:'13575426241',
status:'enable',
lastLoginTime:'2025-05-09 09:45:37'
},
{
avatar:'',
name:'张学友',
sex:'man',
phoneNumber:'13575426241',
status:'enable',
lastLoginTime:'2025-05-09 09:45:37'
},
{
avatar:'https://file.wy2020.com/admin/weiyi/img/mqtts/morning/record/1920283993400512513_headImg.jpg',
name:'黎明',
sex:'man',
phoneNumber:'13575426241',
status:'enable',
lastLoginTime:'2025-05-09 09:45:37'
},{
avatar:'',
name:'郭富城',
sex:'man',
phoneNumber:'13575426241',
status:'enable',
lastLoginTime:'2025-05-09 09:45:37'
},
{
avatar:'https://file.wy2020.com/admin/weiyi/img/mqtts/morning/record/1920283993400512513_headImg.jpg',
name:'你',
sex:'woman',
phoneNumber:'13575426241',
status:'enable',
lastLoginTime:'2025-05-09 09:45:37'
},
{
avatar:'',
name:'他',
sex:'woman',
phoneNumber:'13575426241',
status:'enable',
}
]
export default userInfo

View File

@ -1,11 +1,456 @@
<template>
<div> 用户管理</div>
<div class="user" >
<div>
<div class="user3Item" :style="{ display: !collapsed ? '' : 'none' }">
<n-tree
:data="nodes"
:default-expanded-keys="['level1', 'level2-3']"
block-line
/>
</div>
<div class="user3ItemIndex" :style="{left:!collapsed?'244px':0}" @click="()=>(collapsed = !collapsed)"></div>
</div>
<div>
<div class="userItem">
<TablePro ref="tableRef" :request-api="reqApi" :search-form-options="searchFormOptions" :columns="columns" :isPageTable="true" :max-height="520">
<template #headerExtra>
<n-button strong secondary type="primary" @click="addOrUpdateUser"> 添加用户 </n-button>
</template>
</TablePro>
</div>
</div>
</div>
</template>
<script setup lang="tsx">
import { NButton, useModal, useMessage, NPopconfirm, type FormInst, type FormItemRule } from 'naive-ui'
import { TablePro, type TableProProps, FormPro, type FormItemOptions, type TableProInst } from '@/components'
import api from '@/axios'
import { reactive, ref, useTemplateRef } from 'vue'
import userInfo, { type userInterface } from './index'
import { enumSelectNodes } from '@/utils/emnus.ts'
import { adminUserId } from '@/config/constant.ts'
type TableType = TableProProps<any, any>
const tableRef = useTemplateRef<TableProInst>('tableRef')
const modal = useModal()
const message = useMessage()
<script setup lang="ts">
const collapsed = ref(false);
const nodes = ref([
{
label: '顶级(一级)',
key: 'level1',
children: [
{
label: '事业部1二级',
key: 'level2-1'
},
{
label: '事业部2二级',
key: 'level2-2'
},
{
label: '事业部3二级',
key: 'level2-3',
children: [
{
label: '医院(三级)',
key: 'level3-1'
},
{
label: '学校(三级)',
key: 'level3-2'
},
{
label: '小学(三级)',
key: 'level3-3'
}
]
}
]
}
])
const reqApi: TableType['requestApi'] = (params) => {
return new Promise((resolve) => {
resolve({
code: 200,
data: {
current: "1",
// @ts-ignore
pages: "2",
records: userInfo,
size: "5",
total: "12"
},
message: "操作成功!"
});
});
// return api.post('/management/user/pager', params)
}
const form = ref<FormInst | null>(null)
const searchFormOptions = reactive<TableType['searchFormOptions']>({
name: {
type: 'input',
label: '用户名',
},
})
const userDefaultValue: userInterface = {
// snowFlakeId: "",
avatar: '',
name: '',
sex: '',
phoneNumber: '',
status: 'enable',
authClient: [],
deptIds: [],
roleIds: [],
}
const userValue = ref<userInterface>({
...userDefaultValue,
})
const resetModelValue = () => {
userValue.value = { ...userDefaultValue }
title.value = '添加用户'
}
const formOptionsUser = reactive<FormItemOptions<userInterface>>({
//
avatar: {
type: 'custom',
label: '头像',
customRender: (val) => {
return (
<div>
<n-avatar
round
size="large"
src={val.avatar}
/>
</div>
);
}
},
name: {
type: 'input',
label: '用户名',
required: true,
},
sex: {
type: 'radioGroup',
label: '性别',
required: true,
options: [
{
label :"男",
value:"man"
},
{
value:'woman',
label:'女'
}
], //man woman
},
phoneNumber: {
type: 'input',
label: '手机号',
required: true,
},
status: {
type: 'radioGroup',
label: '账号状态',
required: true,
options: [
{
value:'disable',
label:'禁用'
},
{
value:'enable',
label:'启用'
}
], //enable disable
},
deptIds: {
type: 'treeSelect',
label: '所属部门',
options: [
{
value:'技术部',
label:'技术部'
},
{
value:'食堂部',
label:'食堂部'
}
],
componentsProps: {
multiple: true,
},
},
roleIds: {
type: 'select',
label: '角色',
options: [
{
value:'普通员工',
label:'普通员工'
},
{
value:'超级管理员',
label:'超级管理员'
}
],
componentsProps: {
multiple: true,
},
},
})
const modalRef = ref()
const title = ref('添加用户')
const addOrUpdateUser = () => {
modalRef.value = modal.create({
title: title.value,
preset: 'card',
style: {
width: '400px',
},
content: () => (
<>
<FormPro labelWidth='100' ref={form} v-model:value={userValue.value} form-item-options={formOptionsUser} />
</>
),
footer: () => (
<div
style={{
display: 'flex',
justifyContent: 'flex-end',
}}
>
<n-button
loading={loading.value}
style={{ marginRight: '10px' }}
type='primary'
onClick={() => {
addUserOrUpdate()
}}
>
确认
</n-button>
<n-button
onClick={() => {
modalRef.value.destroy()
resetModelValue()
}}
>
取消
</n-button>
</div>
),
onAfterLeave: () => {
resetModelValue()
},
})
}
function extractValues(data: any[]) {
return data.map((item: { value: any }) => item.value)
}
//
const addUserOrUpdate = async (params?: any) => {
form.value?.validate().then(async () => {
return 12132
})
}
const loading = ref<boolean>(false)
const columns = ref<TableType['columns']>([
{
key: 'name',
title: '用户名',
width: 150,
},
{
key: 'phoneNumber',
title: '手机号',
width: 150,
render: ({ phoneNumber }) => {
return <span>{phoneNumber}</span>
},
},
{
key: 'lastLoginTime',
title: '上次登录',
width: 150,
},
{
key: 'sex',
title: '性别',
width: 150,
render: ({ sex }) => {
return <n-tag type="success">
{sex === 'man'?'男':'女'}
</n-tag>
},
},
{
key: '',
title: '操作',
width: 150,
render: (value) => {
return <div style={{ display: 'flex' }}>
<n-button
strong
secondary
style={{ marginLeft: '10px' }}
type='warning'
onClick={() => {
title.value = `${value.name} 修改`
userValue.value.snowFlakeId = value.snowFlakeId
userValue.value.avatar = value.avatar
userValue.value.name = value.name
userValue.value.sex = value.sex
userValue.value.status = value.status
userValue.value.phoneNumber = value.phoneNumber
// userValue.value.deptIds = extractValues(value.deptList)
// userValue.value.roleIds = extractValues(value.roleList)
// userValue.value.authClient = extractValues(value.authClient)
modalRef.value = modal.create({
title: title.value,
preset: 'card',
style: {
width: '400px',
},
content: () => (
<>
<FormPro labelWidth='100' ref={form} v-model:value={userValue.value} form-item-options={formOptionsUser} />
</>
),
footer: () => (
<div
style={{
display: 'flex',
justifyContent: 'flex-end',
}}
>
<n-button
loading={loading.value}
style={{ marginRight: '10px' }}
type='primary'
onClick={() => {
addUserOrUpdate(value.snowFlakeId)
}}
>
确认
</n-button>
<n-button
onClick={() => {
modalRef.value.destroy()
resetModelValue()
}}
>
取消
</n-button>
</div>
),
onAfterLeave: () => {
resetModelValue()
},
})
}}
>
编辑
</n-button>
<NPopconfirm
onPositiveClick={async () => {
}}
onNegativeClick={() => {
}}
showIcon={false}
>
{{
trigger: () => (
<n-button
strong
secondary
style={{ marginLeft: "10px" }}
type="error"
>
删除
</n-button>
),
default: () => "确认要除么?"
}}
</NPopconfirm>
</div>
},
},
])
</script>
<style scoped lang="scss">
.user{
display: flex;
justify-content: space-between;
font-size: 14px;
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", Arial, sans-serif;
.userItem {
width: 100%;
height: 83vh;
background: var(--bg-color);
margin-bottom: 10px;
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, .05);
padding: 10px 15px;
color:var(--text-color);
.homeItemIndex{
margin-bottom: 10px;
line-height: 1.6;
border-left: 5px solid #5FB878;
border-radius: 0 2px 2px 0;
padding-left: 10px;
.homeSpan{
display: inline-block;
padding: 0 6px;
font-size: 12px;
text-align: center;
background-color: #FF5722;
color: #fff;
border-radius: 2px
}
}
}
.user3Item{
height: 84vh;
width: 200px;
position: relative;
margin-bottom: 15px;
border-radius: 2px;
background: var(--bg-color);
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, .05);
padding: 10px 15px;
color:var(--text-color);
}
.user3ItemIndex{
position: absolute;
top: 50%;
left: 0;
text-align: center;
height: 34px;
line-height: 34px;
width: 8px;
z-index: 1;
visibility: visible;
overflow: hidden;
cursor: pointer;
background: red
}
}
</style>
</style>

View File

@ -276,6 +276,7 @@
const resetModelValue = () => {
userValue.value = { ...workAccountsValueList };
title.value = '添加晨检记录'
};
const addUserOrUpdate = () => {