@@ -11,8 +11,6 @@ | |||||
* 5.请不得将本软件应用于危害国家安全、荣誉和利益的行为,不能以任何形式用于非法为目的的行为不要删除和修改作者声明。 | * 5.请不得将本软件应用于危害国家安全、荣誉和利益的行为,不能以任何形式用于非法为目的的行为不要删除和修改作者声明。 | ||||
* 6.任何基于本软件而产生的一切法律纠纷和责任,均于我司无关 | * 6.任何基于本软件而产生的一切法律纠纷和责任,均于我司无关 | ||||
*/ | */ | ||||
import { ReqPage } from "@/api"; | |||||
/** | /** | ||||
* @Description: 服装底库管理接口 | * @Description: 服装底库管理接口 | ||||
* @Author: syy | * @Author: syy | ||||
@@ -22,54 +20,20 @@ import { ReqPage } from "@/api"; | |||||
export namespace SysUserCloth { | export namespace SysUserCloth { | ||||
// 服装底库树 | // 服装底库树 | ||||
export interface Page { | export interface Page { | ||||
clothSetId: number | string; | |||||
clothSetName: number | string; | |||||
clothSetId?: number | string; | |||||
clothSetName?: number | string; | |||||
} | } | ||||
/** id请求参数 */ | |||||
export interface ReqName { | |||||
name: number | string; | |||||
} | |||||
/** 底库信息 */ | |||||
export interface ClassPage { | |||||
personSetId?: string | number | undefined; | |||||
personSetName?: string | undefined; | |||||
id?: string | undefined; | |||||
name?: string | undefined; | |||||
personId?: string | undefined | number; | |||||
} | |||||
/** 人脸信息 */ | |||||
export interface SysUserAvatar { | |||||
/** 人脸 */ | |||||
personId?: string | undefined | number; | |||||
faceId?: string | number; | |||||
faceUrl: string; | |||||
uid?: string | number; | |||||
export interface list { | |||||
clothUrl: string; | |||||
clothId: number | string; | |||||
clothSetId: string; | |||||
} | } | ||||
// 人脸删除 | |||||
export interface SysUserFace { | |||||
personId: string | undefined; | |||||
faceIds: Array<string | number>; | |||||
} | |||||
/** 用户信息 */ | /** 用户信息 */ | ||||
export interface SysUserClothInfo { | export interface SysUserClothInfo { | ||||
/** 人员id */ | |||||
personId?: string; | |||||
/** 姓名 */ | |||||
name?: string; | |||||
/** 年龄 */ | |||||
age?: number | string; | |||||
/** 性别 */ | |||||
gender?: string; | |||||
/** 手机 */ | |||||
phone?: string; | |||||
/** 扩展字段 */ | |||||
extData?: string; | |||||
/** 人脸 */ | |||||
faces: Array<SysUserAvatar>; | |||||
/** 分组 */ | |||||
personSets: Array<ClassPage>; | |||||
personSetId?: number | string; | |||||
clothSetId: number | string; | |||||
clothSetName: number | string; | |||||
/** 列表 */ | |||||
clothes?: Array<list>; | |||||
} | } | ||||
} | } |
@@ -34,24 +34,24 @@ const userManageClothApi = { | |||||
return http.delete("deleteClothDataBaseD", params); | return http.delete("deleteClothDataBaseD", params); | ||||
}, | }, | ||||
/** 新增服装底库 */ | /** 新增服装底库 */ | ||||
addClothDataBaseA(params: SysUserCloth.ReqName) { | |||||
addClothDataBaseA(params: SysUserCloth.Page) { | |||||
return http.post("addClothDataBaseA", params); | return http.post("addClothDataBaseA", params); | ||||
}, | }, | ||||
/** 更新服装底库 */ | /** 更新服装底库 */ | ||||
update(params: SysUserCloth.SysUserPerInfo) { | |||||
update(params: SysUserCloth.Page) { | |||||
return http.put("updateClothU", params); | return http.put("updateClothU", params); | ||||
}, | }, | ||||
/** 服装图片上传 */ | /** 服装图片上传 */ | ||||
uploadFile(params: SysUserCloth.SysUserAvatar) { | |||||
uploadFile(params: any) { | |||||
return http.post("uploadFile", params); | return http.post("uploadFile", params); | ||||
}, | }, | ||||
/** 新增服装 */ | /** 新增服装 */ | ||||
add(params: SysUserCloth.SysUserPerInfo) { | |||||
add(params: any) { | |||||
return http.post("addClothA", params); | return http.post("addClothA", params); | ||||
}, | }, | ||||
/** 删除服装 */ | /** 删除服装 */ | ||||
delete(params: SysUserCloth.SysUserFace) { | |||||
delete(params: SysUserCloth.list) { | |||||
return http.post("deleteClothD", params); | return http.post("deleteClothD", params); | ||||
} | } | ||||
}; | }; | ||||
@@ -27,6 +27,8 @@ declare namespace FormProps { | |||||
disabled?: boolean; | disabled?: boolean; | ||||
/** 行内表单模式 */ | /** 行内表单模式 */ | ||||
inline?: boolean; | inline?: boolean; | ||||
// 树数据 | |||||
treeAllData?: Array<any>; | |||||
/** 表单布局 */ | /** 表单布局 */ | ||||
successful?: () => void; | successful?: () => void; | ||||
} | } | ||||
@@ -0,0 +1,156 @@ | |||||
<!-- | |||||
* @Description: 表单 | |||||
* @Author: syy | |||||
* @Date: 2023-12-15 15:45:59 | |||||
--> | |||||
<template> | |||||
<div> | |||||
<form-container v-model="visible" :title="`${sysUserProps.opt}人员`" form-size="500px" @close="onClose"> | |||||
<el-form | |||||
ref="sysUserFormRef" | |||||
:rules="rules" | |||||
:disabled="sysUserProps.disabled" | |||||
:model="sysUserProps.record" | |||||
:hide-required-asterisk="sysUserProps.disabled" | |||||
label-width="auto" | |||||
label-suffix=" :" | |||||
> | |||||
<div> | |||||
<el-row :gutter="16"> | |||||
<el-col :span="24"> | |||||
<s-form-item label="所属服装库" prop="clothSetId"> | |||||
<s-select | |||||
v-model="sysUserProps.record.clothSetId" | |||||
:options="sysUserProps.treeAllData" | |||||
label="clothSetName" | |||||
value="clothSetId" | |||||
></s-select> | |||||
</s-form-item> | |||||
</el-col> | |||||
</el-row> | |||||
<el-row :gutter="16"> | |||||
<el-col :span="24"> | |||||
<s-form-item label="上传服装" prop="faces"> | |||||
<el-upload | |||||
class="avatar-uploader" | |||||
action="/api/business/clothApi/uploadFile" | |||||
:show-file-list="false" | |||||
:on-success="handleAvatarSuccess" | |||||
accept=".jpg, .jpeg, .png" | |||||
:headers="{ | |||||
Authorization: `${TokenEnum.TOKEN_PREFIX} ${accessToken}` | |||||
}" | |||||
> | |||||
<img v-if="sysUserProps.record.clothUrl" :src="sysUserProps.record.clothUrl" class="avatar" /> | |||||
<el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon> | |||||
</el-upload> | |||||
</s-form-item> | |||||
</el-col> | |||||
</el-row> | |||||
</div> | |||||
</el-form> | |||||
<template #footer> | |||||
<el-button @click="onClose"> 取消 </el-button> | |||||
<el-button v-show="!sysUserProps.disabled" type="primary" @click="handleSubmit"> 确定 </el-button> | |||||
</template> | |||||
</form-container> | |||||
</div> | |||||
</template> | |||||
<script setup lang="ts" name="SysUserClothForm"> | |||||
import { SysUserCloth, userManageClothApi } from "@/api"; | |||||
import { FormOptEnum } from "@/enums"; | |||||
import { required } from "@/utils/formRules"; | |||||
import { FormInstance } from "element-plus"; | |||||
import { useUserStore } from "@/stores/modules"; | |||||
import type { UploadProps } from "element-plus"; | |||||
import { TokenEnum } from "@/enums"; | |||||
const visible = ref(false); //是否显示表单 | |||||
const activeName = ref("basic"); | |||||
const userStore = useUserStore(); | |||||
const { accessToken } = userStore; | |||||
// 表单参数 | |||||
const sysUserProps = reactive<FormProps.Base<SysUserCloth.list>>({ | |||||
opt: FormOptEnum.ADD, | |||||
record: {}, | |||||
treeAllData: [], | |||||
disabled: false | |||||
}); | |||||
// 表单验证规则 | |||||
const rules = reactive({ | |||||
clothSetId: [required("请选择所属服装库")], | |||||
clothUrl: [required("请上传服装")] | |||||
}); | |||||
const handleAvatarSuccess: UploadProps["onSuccess"] = (response: any) => { | |||||
if (response.code === 200) { | |||||
sysUserProps.record.clothUrl = response.data; | |||||
} | |||||
}; | |||||
/** | |||||
* 打开表单 | |||||
* @param props 表单参数 | |||||
*/ | |||||
function onOpen(props: FormProps.Base<SysUserCloth.list>) { | |||||
Object.assign(sysUserProps, props); //合并参数 | |||||
visible.value = true; //显示表单 | |||||
sysUserProps.record = props.record; | |||||
} | |||||
// 提交数据(新增/编辑) | |||||
const sysUserFormRef = ref<FormInstance>(); | |||||
/** 提交表单 */ | |||||
async function handleSubmit() { | |||||
sysUserFormRef.value?.validate(async valid => { | |||||
if (!valid) return; //表单验证失败 | |||||
await userManageClothApi | |||||
.add(sysUserProps.record) | |||||
.then(() => { | |||||
sysUserProps.successful!(); //调用父组件的successful方法 | |||||
}) | |||||
.finally(() => { | |||||
onClose(); | |||||
}); | |||||
}); | |||||
} | |||||
/** 关闭表单*/ | |||||
function onClose() { | |||||
visible.value = false; | |||||
activeName.value = "basic"; | |||||
} | |||||
// 暴露给父组件的方法 | |||||
defineExpose({ | |||||
onOpen | |||||
}); | |||||
</script> | |||||
<style lang="scss" scoped> | |||||
.avatar-uploader .avatar { | |||||
display: block; | |||||
width: 178px; | |||||
height: 178px; | |||||
} | |||||
</style> | |||||
<style> | |||||
.avatar-uploader .el-upload { | |||||
position: relative; | |||||
overflow: hidden; | |||||
cursor: pointer; | |||||
border: 1px dashed var(--el-border-color); | |||||
border-radius: 6px; | |||||
transition: var(--el-transition-duration-fast); | |||||
} | |||||
.avatar-uploader .el-upload:hover { | |||||
border-color: var(--el-color-primary); | |||||
} | |||||
.el-icon.avatar-uploader-icon { | |||||
width: 178px; | |||||
height: 178px; | |||||
font-size: 28px; | |||||
color: #8c939d; | |||||
text-align: center; | |||||
} | |||||
</style> |
@@ -0,0 +1,105 @@ | |||||
<!-- | |||||
* @Description: 表单 | |||||
* @Author: syy | |||||
* @Date: 2023-12-18 15:45:59 | |||||
--> | |||||
<template> | |||||
<div> | |||||
<form-container v-model="visibleClass" :title="`${sysUserProps.opt}班级`" form-size="400px" @close="onClose"> | |||||
<el-form | |||||
ref="sysUserFormRef" | |||||
:rules="rules" | |||||
:disabled="sysUserProps.disabled" | |||||
:model="sysUserProps.record" | |||||
:hide-required-asterisk="sysUserProps.disabled" | |||||
label-width="auto" | |||||
label-suffix=" :" | |||||
> | |||||
<div> | |||||
<el-row :gutter="16"> | |||||
<el-col :span="22"> | |||||
<s-form-item label="服装库名称" prop="clothSetName"> | |||||
<s-input v-model="sysUserProps.record.clothSetName"></s-input> | |||||
</s-form-item> | |||||
</el-col> | |||||
</el-row> | |||||
</div> | |||||
</el-form> | |||||
<template #footer> | |||||
<el-button @click="onClose"> 取消 </el-button> | |||||
<el-button v-show="!sysUserProps.disabled" type="primary" @click="handleSubmit"> 确定 </el-button> | |||||
</template> | |||||
</form-container> | |||||
</div> | |||||
</template> | |||||
<script setup lang="ts" name="SysUserClothDk"> | |||||
import { ref } from "vue"; | |||||
import { userManageClothApi, SysUserCloth } from "@/api"; | |||||
import { FormOptEnum } from "@/enums"; | |||||
import { required } from "@/utils/formRules"; | |||||
import { FormInstance } from "element-plus"; | |||||
const visibleClass = ref(false); //是否显示表单 | |||||
// 表单参数 | |||||
const sysUserProps = reactive<FormProps.Base<SysUserCloth.Page>>({ | |||||
opt: FormOptEnum.ADD, | |||||
record: {}, | |||||
disabled: false | |||||
}); | |||||
// 表单验证规则 | |||||
const rules = reactive({ | |||||
clothSetName: [required("请输入服装库名称")] | |||||
}); | |||||
/** | |||||
* 打开表单 | |||||
* @param props 表单参数 | |||||
*/ | |||||
function onOpen(props: FormProps.Base<SysUserCloth.Page>) { | |||||
Object.assign(sysUserProps, props); //合并参数 | |||||
visibleClass.value = true; //显示表单 | |||||
sysUserProps.record = props.record; | |||||
} | |||||
// 提交数据(新增/编辑) | |||||
const sysUserFormRef = ref<FormInstance>(); | |||||
/** 提交表单 */ | |||||
async function handleSubmit() { | |||||
sysUserFormRef.value?.validate(async valid => { | |||||
if (!valid) return; //表单验证失败 | |||||
//提交表单 | |||||
if (sysUserProps.record.clothSetId) { | |||||
await userManageClothApi | |||||
.update(sysUserProps.record) | |||||
.then(() => { | |||||
sysUserProps.successful!(); //调用父组件的successful方法 | |||||
}) | |||||
.finally(() => { | |||||
onClose(); | |||||
}); | |||||
} else { | |||||
await userManageClothApi | |||||
.addClothDataBaseA(sysUserProps.record) | |||||
.then(() => { | |||||
sysUserProps.successful!(); //调用父组件的successful方法 | |||||
}) | |||||
.finally(() => { | |||||
onClose(); | |||||
}); | |||||
} | |||||
}); | |||||
} | |||||
/** 关闭表单*/ | |||||
function onClose() { | |||||
visibleClass.value = false; | |||||
} | |||||
// 暴露给父组件的方法 | |||||
defineExpose({ | |||||
onOpen | |||||
}); | |||||
</script> | |||||
<style lang="scss" scoped></style> |
@@ -0,0 +1,194 @@ | |||||
<!-- | |||||
* @Description: 服装库管理 | |||||
* @Author: syy | |||||
* @Date: 2024-7-18 | |||||
--> | |||||
<template> | |||||
<div class="main-box"> | |||||
<TreeFilter | |||||
ref="treeFilter" | |||||
label="clothSetName" | |||||
id="clothSetId" | |||||
width="300px" | |||||
:show-all="false" | |||||
:request-api="userManageClothApi.getList" | |||||
@change="changeTreeFilter" | |||||
> | |||||
<template v-slot:header> | |||||
<s-button suffix="服装库" @click="addClass(FormOptEnum.ADD)" style="margin-bottom: 15px" /> | |||||
</template> | |||||
<template v-slot:label="{ row }"> | |||||
<span class="custom-tree-node"> | |||||
<span>{{ row.node.label }}</span> | |||||
<span> | |||||
<a @click="addClass(FormOptEnum.EDIT, row.node.data)"> | |||||
<el-icon><Edit /></el-icon> | |||||
</a> | |||||
<a style="margin-left: 8px" @click="addDelete(row.node.data.clothSetId, '删除服装库')"> | |||||
<el-icon><Delete /></el-icon> | |||||
</a> | |||||
</span> | |||||
</span> | |||||
</template> | |||||
</TreeFilter> | |||||
<div class="table-box"> | |||||
<ProTable ref="proTable" title="服装库管理" :columns="columns" rowKey="clothId" :data="tableData.clothes"> | |||||
<!-- 表格 header 按钮 --> | |||||
<template #tableHeader="scope"> | |||||
<s-button suffix="服装" @click="onOpen(FormOptEnum.ADD, { clothSetId: clothSetId }, treeFilter.treeAllData)" /> | |||||
<s-button | |||||
type="danger" | |||||
:opt="FormOptEnum.DELETE" | |||||
plain | |||||
suffix="服装" | |||||
:disabled="!scope.isSelected" | |||||
@click="onDelete(scope.selectedListIds, '删除所选服装')" | |||||
/> | |||||
</template> | |||||
<!-- 表格操作栏 --> | |||||
<template #operation="scope"> | |||||
<el-space> | |||||
<s-button link :opt="FormOptEnum.DELETE" @click="onDelete([scope.row.clothId], `删除服装`)" /> | |||||
</el-space> | |||||
</template> | |||||
</ProTable> | |||||
</div> | |||||
<!-- 人员新增/编辑表单 --> | |||||
<Form ref="formRef"></Form> | |||||
<!-- 班级新增/编辑表单 --> | |||||
<Form1 ref="formRefC" /> | |||||
<!-- 预览头像 --> | |||||
<el-dialog v-model="visible" title="查看头像" width="830px" :before-close="handleClose"> | |||||
<div> | |||||
<img style="width: 100%" class="detailpic" :src="faceUrl" alt="" /> | |||||
</div> | |||||
<template #footer> | |||||
<div class="dialog-footer"> | |||||
<el-button @click="visible = false">关闭</el-button> | |||||
</div> | |||||
</template> | |||||
</el-dialog> | |||||
</div> | |||||
</template> | |||||
<script setup lang="tsx" name="SysUserClothing"> | |||||
import { userManageClothApi,userClothButtonCode,SysUserCloth } from "@/api"; | |||||
import { useHandleData } from "@/hooks/useHandleData"; | |||||
import { FormOptEnum } from "@/enums"; | |||||
import Form from "./components/form/index.vue"; | |||||
import Form1 from "./components/form1/index.vue"; | |||||
import { ColumnProps, ProTableInstance } from "@/components/ProTable/interface"; | |||||
import TreeFilter from "@/components/TreeFilter/index.vue"; | |||||
import { useUserStore } from "@/stores/modules"; | |||||
// 获取 ProTable 元素,调用其获取刷新数据方法(还能获取到当前查询参数,方便导出携带参数) | |||||
const faceUrl = ref(''); | |||||
const visible = ref(false); //是否显示人员表单 | |||||
const proTable = ref<ProTableInstance>(); | |||||
const treeFilter = ref<any>({}); | |||||
const userStore = useUserStore(); | |||||
const { accessToken } = userStore; | |||||
const tableData = ref<any>([]) | |||||
// 表格配置项 | |||||
const columns: ColumnProps<SysUserCloth.list>[] = [ | |||||
{ type: "selection", fixed: "left", width: 50 }, | |||||
{ | |||||
prop: "clothUrl", | |||||
label: "服装图", | |||||
render: scope => { | |||||
return ( | |||||
<img src={scope.row.clothUrl} onClick={() => viewHeadImage(scope)} style='width:50px;height:50px' alt=''/> | |||||
); | |||||
} | |||||
}, | |||||
{ prop: "operation", label: "操作", width: 250, fixed: "right" } | |||||
]; | |||||
const viewHeadImage = (scope: any) => { | |||||
faceUrl.value = scope.row.clothUrl; | |||||
visible.value = true | |||||
}; | |||||
const handleClose = () => { | |||||
visible.value = false; | |||||
}; | |||||
// 人员表单引用 | |||||
const formRef = ref<InstanceType<typeof Form> | null>(null); | |||||
// 班级表单引用 | |||||
const formRefC = ref<InstanceType<typeof Form1> | null>(null); | |||||
/** | |||||
* 打开服装表单 | |||||
* @param opt 操作类型 | |||||
* @param record 记录 | |||||
*/ | |||||
function onOpen(opt: FormOptEnum, record: {},treeAllData:any) { | |||||
formRef.value?.onOpen({ opt: opt, record: record,treeAllData:treeAllData, successful: RefreshTable }); | |||||
} | |||||
/** | |||||
* 打开服装库表单 | |||||
* @param opt 操作类型 | |||||
* @param record 记录 | |||||
*/ | |||||
function addClass(opt: FormOptEnum, record: {} | SysUserCloth.list = {}) { | |||||
formRefC.value?.onOpen({ opt: opt, record: record, successful: RefreshTree }); | |||||
} | |||||
/** | |||||
* 服装库删除 | |||||
* @param ids id数组 | |||||
*/ | |||||
async function addDelete(clothSetId: string[],msg: string) { | |||||
// 二次确认 => 请求api => 刷新表格 | |||||
await useHandleData(userManageClothApi.deleteClothDataBaseD, { clothSetId }, msg); | |||||
RefreshTree(); //刷新表格 | |||||
} | |||||
/** | |||||
* 服装删除 | |||||
* @param ids id数组 | |||||
*/ | |||||
async function onDelete(ids: string[], msg: string) { | |||||
// 二次确认 => 请求api => 刷新表格 | |||||
await useHandleData(userManageClothApi.delete, {clothId: ids.join(","), clothSetId:tableData.value.clothSetId}, msg); | |||||
RefreshTable(); //刷新表格 | |||||
} | |||||
// 刷新表格 | |||||
const RefreshTable = () => { | |||||
getList(clothSetId.value) | |||||
} | |||||
// 刷新表格+树 | |||||
const RefreshTree = () => { | |||||
getList(clothSetId.value) | |||||
treeFilter.value?.refresh(); //刷新树形筛选器 | |||||
} | |||||
/** 服装库切换切换 */ | |||||
const clothSetId = ref<number | string>() | |||||
function changeTreeFilter(val: number | string) { | |||||
clothSetId.value = val | |||||
proTable.value!.pageable.pageNum = 1; | |||||
getList(val) | |||||
} | |||||
// 获取列表 | |||||
const getList = (clothSetId:any)=>{ | |||||
userManageClothApi.page({clothSetId:clothSetId}).then((resp:any)=>{ | |||||
if(resp.code == 200){ | |||||
tableData.value = resp.data | |||||
} | |||||
}) | |||||
} | |||||
</script> | |||||
<style scoped lang="scss"> | |||||
.table-box { | |||||
width: 100%; | |||||
height: 100%; | |||||
} | |||||
.custom-tree-node { | |||||
display: flex; | |||||
flex: 1; | |||||
align-items: center; | |||||
justify-content: space-between; | |||||
padding-right: 8px; | |||||
font-size: 14px; | |||||
} | |||||
</style> |