产线管理

This commit is contained in:
zc
2026-06-18 14:18:28 +08:00
parent ae41b388cb
commit 5c3721a88c
16 changed files with 484 additions and 177 deletions

View File

@@ -14,16 +14,6 @@ export function listBranchTree(query: { description: string | unknown }) {
return http.get<TreeNodeData[]>(`${BASE_URL}/tree/branch`, query)
}
/** @desc 查询空间树 */
export function listSpaceTree(query: { description: string | unknown }) {
return http.get<TreeNodeData[]>(`${BASE_URL}/tree/space`, query)
}
/** @desc 查询空间树 */
export function listPointTree(query: { description: string | unknown }) {
return http.get<TreeNodeData[]>(`${BASE_URL}/tree/point`, query)
}
/** @desc 查询菜单树 */
export function listMenuTree(query: { description: string }) {
return http.get<TreeNodeData[]>(`${BASE_URL}/tree/menu`, query)

View File

@@ -0,0 +1,62 @@
import http from '@/utils/http'
const BASE_URL = '/production/productionLine'
export interface ProductionLineResp {
id: string
lineCode: string
lineName: string
lineType: string
workshop: string
supervisor: string
capacityPerShift: string
status: string
sortOrder: string
remark: string
createUser: string
createTime: string
updateUser: string
updateTime: string
createUserString: string
updateUserString: string
disabled: boolean
}
export interface ProductionLineQuery {
lineCode: string | undefined
lineName: string | undefined
lineType: string | undefined
status: string | undefined
createTime: string | undefined
sort: Array<string>
}
export interface ProductionLinePageQuery extends ProductionLineQuery, PageQuery {}
/** @desc 查询产线基础列表 */
export function listProductionLine(query: ProductionLinePageQuery) {
return http.get<PageRes<ProductionLineResp[]>>(`${BASE_URL}`, query)
}
/** @desc 查询产线基础详情 */
export function getProductionLine(id: string) {
return http.get<ProductionLineDetailResp>(`${BASE_URL}/${id}`)
}
/** @desc 新增产线基础 */
export function addProductionLine(data: any) {
return http.post(`${BASE_URL}`, data)
}
/** @desc 修改产线基础 */
export function updateProductionLine(data: any, id: string) {
return http.put(`${BASE_URL}/${id}`, data)
}
/** @desc 删除产线基础 */
export function deleteProductionLine(id: string) {
return http.del(`${BASE_URL}/${id}`)
}
/** @desc 导出产线基础 */
export function exportProductionLine(query: ProductionLineQuery) {
return http.download(`${BASE_URL}/export`, query)
}

View File

@@ -1,5 +1,4 @@
import http from '@/utils/http'
import type {LabelValueState} from "@/types/global";
const BASE_URL = '/sysPeople/people'

View File

@@ -16,8 +16,8 @@ export function deleteMessage(ids: string | Array<string>) {
}
/** @desc 标记已读 */
export function readMessage(ids?: string | Array<string>) {
return http.patch(`${BASE_URL}/read`, ids)
export function readMessage() {
return http.patch(`${BASE_URL}/read`)
}
/** @desc 查询未读消息数量 */

View File

@@ -1,23 +0,0 @@
import { ref } from 'vue'
import type { EquipmentQuery } from '@/apis/equipment/equipment'
import { getEquipmentNameList } from '@/apis/equipment/equipment'
import type { LabelValueState } from '@/types/global'
/** 设备名称列表 */
export function equipmentName(query: EquipmentQuery, options?: { onSuccess?: () => void }) {
const loading = ref(false)
const equipmentNameList = ref<LabelValueState[]>([])
const getEquipmentName = async () => {
try {
loading.value = true
const res = await getEquipmentNameList(query)
equipmentNameList.value = res.data
// eslint-disable-next-line ts/no-unused-expressions
options?.onSuccess && options.onSuccess()
} finally {
loading.value = false
}
}
return { equipmentNameList, getEquipmentName, loading }
}

View File

@@ -3,7 +3,3 @@ export * from './useDept'
export * from './useBranch'
export * from './useRole'
export * from './useDict'
export * from './space'
export * from './point'
export * from './equipmentName'
export * from './productName'

View File

@@ -1,21 +0,0 @@
import type { LabelValueState } from '@/types/global'
import { type ParkQuery, getParkNameList } from '@/apis/car/park'
/** 车场名称列表 */
export function parkName(query: ParkQuery, options?: { onSuccess?: () => void }) {
const loading = ref(false)
const parkNameList = ref<LabelValueState[]>([])
const getParkName = async () => {
try {
loading.value = true
const res = await getParkNameList(query)
parkNameList.value = res.data
// eslint-disable-next-line ts/no-unused-expressions
options?.onSuccess && options.onSuccess()
} finally {
loading.value = false
}
}
return { parkNameList, getParkName, loading }
}

View File

@@ -1,22 +0,0 @@
import { ref } from 'vue'
import type { TreeNodeData } from '@arco-design/web-vue'
import { listPointTree } from '@/apis'
/** 部门模块 */
export function point(options?: { onSuccess?: () => void }) {
const loading = ref(false)
const pointList = ref<TreeNodeData[]>([])
const getPointList = async (name?: string) => {
try {
loading.value = true
const res = await listPointTree({ description: name })
pointList.value = res.data
// eslint-disable-next-line ts/no-unused-expressions
options?.onSuccess && options.onSuccess()
} finally {
loading.value = false
}
}
return { pointList, getPointList, loading }
}

View File

@@ -1,22 +0,0 @@
import { ref } from 'vue'
import { getProductNameList } from '@/apis/equipment/product'
import type { LabelValueState } from '@/types/global'
/** 设备名称列表 */
export function productName(options?: { onSuccess?: () => void }) {
const loading = ref(false)
const productNameList = ref<LabelValueState[]>([])
const getProductName = async () => {
try {
loading.value = true
const res = await getProductNameList()
productNameList.value = res.data
// eslint-disable-next-line ts/no-unused-expressions
options?.onSuccess && options.onSuccess()
} finally {
loading.value = false
}
}
return { productNameList, getProductName, loading }
}

View File

@@ -1,22 +0,0 @@
import { ref } from 'vue'
import type { LabelValueState } from '@/types/global'
import { getRuleNameList } from '@/apis/rule/rule'
/** 设备名称列表 */
export function ruleName(options?: { onSuccess?: () => void }) {
const loading = ref(false)
const ruleNameList = ref<LabelValueState[]>([])
const getRuleName = async () => {
try {
loading.value = true
const res = await getRuleNameList()
ruleNameList.value = res.data
// eslint-disable-next-line ts/no-unused-expressions
options?.onSuccess && options.onSuccess()
} finally {
loading.value = false
}
}
return { ruleNameList, getRuleName, loading }
}

View File

@@ -1,22 +0,0 @@
import { ref } from 'vue'
import type { TreeNodeData } from '@arco-design/web-vue'
import { listSpaceTree } from '@/apis'
/** 部门模块 */
export function space(options?: { onSuccess?: () => void }) {
const loading = ref(false)
const spaceList = ref<TreeNodeData[]>([])
const getSpaceList = async (name?: string) => {
try {
loading.value = true
const res = await listSpaceTree({ description: name })
spaceList.value = res.data
// eslint-disable-next-line ts/no-unused-expressions
options?.onSuccess && options.onSuccess()
} finally {
loading.value = false
}
}
return { spaceList, getSpaceList, loading }
}

View File

@@ -115,8 +115,8 @@ const initWebSocket = (token: string) => {
// 查询未读消息数量
const getMessageCount = async () => {
const { data } = await getUnreadMessageCount()
unreadMessageCount.value = data.total
// const { data } = await getUnreadMessageCount()
// unreadMessageCount.value = data.total
const token = getToken()
if (token) {
initWebSocket(token)

View File

@@ -0,0 +1,178 @@
<template>
<a-modal
v-model:visible="visible"
:title="title"
:mask-closable="false"
:esc-to-close="false"
:width="width >= 600 ? 600 : '100%'"
draggable
@before-ok="save"
@close="reset"
>
<GiForm ref="formRef" v-model="form" :columns="columns" />
</a-modal>
</template>
<script setup lang="ts">
import { Message } from '@arco-design/web-vue'
import { useWindowSize } from '@vueuse/core'
import { getProductionLine, addProductionLine, updateProductionLine } from '@/apis/production/productionLine'
import { type ColumnItem, GiForm } from '@/components/GiForm'
import { useResetReactive } from '@/hooks'
import { useDict } from '@/hooks/app'
import {peopleName} from "@/hooks/app/peopleName";
import type {PeopleQuery} from "@/apis/sysPeople/people";
const emit = defineEmits<{
(e: 'save-success'): void
}>()
const { width } = useWindowSize()
const dataId = ref('')
const visible = ref(false)
const isUpdate = computed(() => !!dataId.value)
const title = computed(() => (isUpdate.value ? '修改产线基础' : '新增产线基础'))
const formRef = ref<InstanceType<typeof GiForm>>()
const { production_line_type, sys_normal_disable } = useDict('production_line_type', 'sys_normal_disable')
const [form, resetForm] = useResetReactive({
status: 1,
})
const queryPeople = ref<PeopleQuery>({
name: undefined,
branchId: "1",
branchParentId: undefined,
ids: undefined,
sort: [],
})
const { peopleNameList, getPeopleName } = peopleName(queryPeople.value)
const columns: ColumnItem[] = reactive([
{
label: '产线编码',
field: 'lineCode',
type: 'input',
span: 24,
required: true,
},
{
label: '产线名称',
field: 'lineName',
type: 'input',
span: 24,
required: true,
},
{
label: '产线类型',
field: 'lineType',
type: 'select',
span: 24,
required: true,
props: {
options: production_line_type,
},
},
{
label: '所属车间',
field: 'workshop',
type: 'input',
span: 24,
},
{
label: '产线主管',
field: 'supervisor',
type: 'select',
props: {
placeholder: '请搜索人员姓名',
allowClear: true,
allowSearch: true,
options: peopleNameList,
},
required: true,
span: 12,
},
{
label: '每班产能',
field: 'capacityPerShift',
type: 'input-number',
props: {
placeholder: '请输入每班产能(件/班)'
},
span: 24,
},
{
label: '状态',
field: 'status',
type: 'select',
span: 24,
required: true,
props: {
options: sys_normal_disable,
},
},
{
label: '排序号',
field: 'sortOrder',
type: 'input-number',
span: 24,
},
{
label: '备注',
field: 'remark',
type: 'textarea',
span: 24,
},
])
// 重置
const reset = () => {
formRef.value?.formRef?.resetFields()
resetForm()
}
// 保存
const save = async () => {
try {
const isInvalid = await formRef.value?.formRef?.validate()
if (isInvalid) return false
if (isUpdate.value) {
await updateProductionLine(form, dataId.value)
Message.success('修改成功')
} else {
await addProductionLine(form)
Message.success('新增成功')
}
emit('save-success')
return true
} catch (error) {
return false
}
}
// 新增
const onAdd = async () => {
reset()
await getPeopleName()
dataId.value = ''
visible.value = true
}
// 修改
const onUpdate = async (id: string) => {
reset()
dataId.value = id
const { data } = await getProductionLine(id)
Object.assign(form, data)
visible.value = true
}
defineExpose({ onAdd, onUpdate })
</script>
<style scoped lang="scss"></style>

View File

@@ -0,0 +1,56 @@
<template>
<a-drawer v-model:visible="visible" title="产线基础详情" :width="width >= 600 ? 600 : '100%'" :footer="false">
<a-descriptions :column="2" size="large" class="general-description">
<a-descriptions-item label="主键ID">{{ dataDetail?.id }}</a-descriptions-item>
<a-descriptions-item label="产线编码">{{ dataDetail?.lineCode }}</a-descriptions-item>
<a-descriptions-item label="产线名称">{{ dataDetail?.lineName }}</a-descriptions-item>
<a-descriptions-item label="产线类型">
<GiCellTag :value="dataDetail?.lineType" :dict="production_line_type" />
</a-descriptions-item>
<a-descriptions-item label="所属车间">{{ dataDetail?.workshop }}</a-descriptions-item>
<a-descriptions-item label="产线主管">{{ dataDetail?.supervisor }}</a-descriptions-item>
<a-descriptions-item label="每班产能">{{ dataDetail?.capacityPerShift }}</a-descriptions-item>
<a-descriptions-item label="状态">
<GiCellTag :value="dataDetail?.status" :dict="sys_normal_disable" />
</a-descriptions-item>
<a-descriptions-item label="排序号">{{ dataDetail?.sortOrder }}</a-descriptions-item>
<a-descriptions-item label="备注">{{ dataDetail?.remark }}</a-descriptions-item>
<a-descriptions-item label="创建人">{{ dataDetail?.createUserString }}</a-descriptions-item>
<a-descriptions-item label="创建时间">{{ dataDetail?.createTime }}</a-descriptions-item>
<a-descriptions-item label="修改人">{{ dataDetail?.updateUserString }}</a-descriptions-item>
<a-descriptions-item label="修改时间">{{ dataDetail?.updateTime }}</a-descriptions-item>
</a-descriptions>
</a-drawer>
</template>
<script setup lang="ts">
import { useWindowSize } from '@vueuse/core'
import { type ProductionLineResp, getProductionLine as getDetail } from '@/apis/production/productionLine'
import GiCellTag from '@/components/GiCell/GiCellTag.vue'
import { useDict } from '@/hooks/app'
const { width } = useWindowSize()
const { production_line_type, sys_normal_disable } = useDict('production_line_type', 'sys_normal_disable')
const dataId = ref('')
const dataDetail = ref<ProductionLineResp>()
const visible = ref(false)
// 查询详情
const getDataDetail = async () => {
const { data } = await getDetail(dataId.value)
dataDetail.value = data
}
// 打开
const onOpen = async (id: string) => {
dataId.value = id
await getDataDetail()
visible.value = true
}
defineExpose({ onOpen })
</script>
<style scoped lang="scss"></style>

View File

@@ -0,0 +1,176 @@
<template>
<div class="gi_table_page">
<GiTable
title="产线基础管理"
row-key="id"
:data="dataList"
:columns="columns"
:loading="loading"
:scroll="{ x: '100%', y: '100%', minWidth: 1000 }"
:pagination="pagination"
:disabled-tools="['size']"
:disabled-column-keys="['name']"
@refresh="search"
>
<template #toolbar-left>
<a-input-search v-model="queryForm.lineCode" placeholder="请输入产线编码" allow-clear @search="search" />
<a-input-search v-model="queryForm.lineName" placeholder="请输入产线名称" allow-clear @search="search" />
<a-select
v-model="queryForm.lineType"
placeholder="请选择产线类型"
:options="production_line_type"
allow-clear
style="width: 160px"
@change="search"
/>
<a-select
v-model="queryForm.status"
placeholder="请选择状态"
:options="sys_normal_disable"
allow-clear
style="width: 150px"
@change="search"
/>
<a-input-search v-model="queryForm.createTime" placeholder="请输入创建时间" allow-clear @search="search" />
<a-button @click="reset">
<template #icon><icon-refresh /></template>
<template #default>重置</template>
</a-button>
</template>
<template #toolbar-right>
<a-button v-permission="['production:productionLine:add']" type="primary" @click="onAdd">
<template #icon><icon-plus /></template>
<template #default>新增</template>
</a-button>
<a-button v-permission="['production:productionLine:export']" @click="onExport">
<template #icon><icon-download /></template>
<template #default>导出</template>
</a-button>
</template>
<template #lineType="{ record }">
<GiCellTag :value="record.lineType" :dict="production_line_type" />
</template>
<template #status="{ record }">
<GiCellTag :value="record.status" :dict="sys_normal_disable" />
</template>
<template #action="{ record }">
<a-space>
<a-link v-permission="['production:productionLine:detail']" title="详情" @click="onDetail(record)">详情</a-link>
<a-link v-permission="['production:productionLine:update']" title="修改" @click="onUpdate(record)">修改</a-link>
<a-link
v-permission="['production:productionLine:delete']"
status="danger"
:disabled="record.disabled"
:title="record.disabled ? '不可删除' : '删除'"
@click="onDelete(record)"
>
删除
</a-link>
</a-space>
</template>
</GiTable>
<ProductionLineAddModal ref="ProductionLineAddModalRef" @save-success="search" />
<ProductionLineDetailDrawer ref="ProductionLineDetailDrawerRef" />
</div>
</template>
<script setup lang="ts">
import ProductionLineAddModal from './ProductionLineAddModal.vue'
import ProductionLineDetailDrawer from './ProductionLineDetailDrawer.vue'
import { type ProductionLineResp, type ProductionLineQuery, deleteProductionLine, exportProductionLine, listProductionLine } from '@/apis/production/productionLine'
import type { TableInstanceColumns } from '@/components/GiTable/type'
import GiCellTag from '@/components/GiCell/GiCellTag.vue'
import { useDownload, useTable } from '@/hooks'
import { useDict } from '@/hooks/app'
import { isMobile } from '@/utils'
import has from '@/utils/has'
defineOptions({ name: 'ProductionLine' })
const { production_line_type, sys_normal_disable } = useDict('production_line_type', 'sys_normal_disable')
const queryForm = reactive<ProductionLineQuery>({
lineCode: undefined,
lineName: undefined,
lineType: undefined,
status: undefined,
createTime: undefined,
sort: ['pl.id,desc']
})
const {
tableData: dataList,
loading,
pagination,
search,
handleDelete
} = useTable((page) => listProductionLine({ ...queryForm, ...page }), { immediate: true })
const columns = ref<TableInstanceColumns[]>([
{ title: '主键ID', dataIndex: 'id', slotName: 'id' },
{ title: '产线编码', dataIndex: 'lineCode', slotName: 'lineCode' },
{ title: '产线名称', dataIndex: 'lineName', slotName: 'lineName' },
{ title: '产线类型', dataIndex: 'lineType', slotName: 'lineType', align: 'center' },
{ title: '所属车间', dataIndex: 'workshop', slotName: 'workshop' },
{ title: '产线主管', dataIndex: 'supervisorName', slotName: 'supervisorName' },
{ title: '每班产能', dataIndex: 'capacityPerShift', slotName: 'capacityPerShift' },
{ title: '状态', dataIndex: 'status', slotName: 'status', align: 'center' },
{ title: '排序号', dataIndex: 'sortOrder', slotName: 'sortOrder' },
{ title: '备注', dataIndex: 'remark', slotName: 'remark' },
{ title: '创建人', dataIndex: 'createUserString', slotName: 'createUser' },
{ title: '创建时间', dataIndex: 'createTime', slotName: 'createTime' , width: 180, show: false},
{ title: '修改人', dataIndex: 'updateUserString', slotName: 'updateUser', ellipsis: true, tooltip: true, show: false },
{ title: '修改时间', dataIndex: 'updateTime', slotName: 'updateTime', show: false },
{
title: '操作',
dataIndex: 'action',
slotName: 'action',
width: 160,
align: 'center',
fixed: !isMobile() ? 'right' : undefined,
show: has.hasPermOr(['production:productionLine:detail', 'production:productionLine:update', 'production:productionLine:delete'])
}
]);
// 重置
const reset = () => {
queryForm.lineCode = undefined
queryForm.lineName = undefined
queryForm.lineType = undefined
queryForm.status = undefined
queryForm.createTime = undefined
search()
}
// 删除
const onDelete = (record: ProductionLineResp) => {
return handleDelete(() => deleteProductionLine(record.id), {
content: `是否确定删除该条数据?`,
showModal: true
})
}
// 导出
const onExport = () => {
useDownload(() => exportProductionLine(queryForm))
}
const ProductionLineAddModalRef = ref<InstanceType<typeof ProductionLineAddModal>>()
// 新增
const onAdd = () => {
ProductionLineAddModalRef.value?.onAdd()
}
// 修改
const onUpdate = (record: ProductionLineResp) => {
ProductionLineAddModalRef.value?.onUpdate(record.id)
}
const ProductionLineDetailDrawerRef = ref<InstanceType<typeof ProductionLineDetailDrawer>>()
// 详情
const onDetail = (record: ProductionLineResp) => {
ProductionLineDetailDrawerRef.value?.onOpen(record.id)
}
</script>
<style scoped lang="scss"></style>

View File

@@ -19,9 +19,8 @@ import { useWindowSize } from '@vueuse/core'
import { mapTree } from 'xe-utils'
import { type ColumnItem, GiForm } from '@/components/GiForm'
import { useResetReactive } from '@/hooks'
import { useDept} from "@/hooks/app";
import {addBranch, type BranchQuery, type BranchResp, getBranch, updateBranch} from "@/apis/sysPeople/branch";
import {ruleName} from "@/hooks/app/ruleName";
import { useDept } from '@/hooks/app'
import { type BranchQuery, type BranchResp, addBranch, getBranch, updateBranch } from '@/apis/sysPeople/branch'
interface Props {
branchs: BranchQuery[]
@@ -42,7 +41,6 @@ const isUpdate = computed(() => !!dataId.value)
const title = computed(() => (isUpdate.value ? '修改部门' : '新增部门'))
const formRef = ref<InstanceType<typeof GiForm>>()
const { deptList, getDeptList } = useDept()
const { ruleNameList, getRuleName } = ruleName()
// 转换为部门树
const branchSelectTree = computed(() => {
@@ -70,7 +68,7 @@ const columns: ColumnItem[] = reactive([
allowClear: true,
allowSearch: true,
fallbackOption: false,
filterTreeNode(searchKey, nodeData) {
filterTreeNode(searchKey: string, nodeData: TreeNodeData) {
if (nodeData.title) {
return nodeData.title.toLowerCase().includes(searchKey.toLowerCase())
}
@@ -78,7 +76,7 @@ const columns: ColumnItem[] = reactive([
},
},
rules: [{ required: true, message: '请选择上级部门' }],
hide: (form) => {
hide: (form: any) => {
return form.parentId === '0'
},
},
@@ -111,18 +109,6 @@ const columns: ColumnItem[] = reactive([
},
// rules: [{ match: Regexp.Phone, message: '请输入正确的手机号' }],
},
{
label: '所属规则',
field: 'ruleIdList',
type: 'select',
span: 24,
props: {
options: ruleNameList,
multiple: true,
allowClear: true,
allowSearch: true,
},
},
{
label: '归属部门',
field: 'deptId',
@@ -143,7 +129,6 @@ const columns: ColumnItem[] = reactive([
},
])
// 重置
const reset = () => {
formRef.value?.formRef?.resetFields()
@@ -164,17 +149,15 @@ const save = async () => {
}
emit('save-success')
return true
} catch (error) {
} catch {
return false
}
}
// 新增
const onAdd = async (id?: string) => {
const onAdd = async (_id?: string) => {
reset()
form.parentId = id
await getRuleName();
await getDeptList();
await getDeptList()
dataId.value = ''
visible.value = true
}
@@ -182,7 +165,6 @@ const onAdd = async (id?: string) => {
// 修改
const onUpdate = async (id: string) => {
reset()
await getRuleName();
await getDeptList()
dataId.value = id
const { data } = await getBranch(id)