完善生产异常维修与备件管理功能
This commit is contained in:
@@ -394,16 +394,21 @@ export interface ProduceRepairRecordRow {
|
||||
product_name?: string | null;
|
||||
category_id?: string | number | null;
|
||||
category_name?: string | null;
|
||||
category_ids?: Array<string | number> | string | null;
|
||||
category_names?: string[] | string | null;
|
||||
fault_description_id?: string | number | null;
|
||||
fault_description_ids?: Array<string | number>;
|
||||
fault_description?: string | null;
|
||||
fault_descriptions?: string[];
|
||||
repair_result?: string | null;
|
||||
parts?: Array<Record<string, any>> | string | null;
|
||||
images?: string[] | string | null;
|
||||
operation_fault_steps?: Array<Record<string, any>> | string | null;
|
||||
responsible_operators?: Array<Record<string, any>> | string | null;
|
||||
operator?: string | null;
|
||||
repaired_at?: number | null;
|
||||
repaired_date?: string | null;
|
||||
repair_result_name?: string;
|
||||
remark?: string | null;
|
||||
created_date?: string;
|
||||
}
|
||||
|
||||
@@ -30,6 +30,12 @@ const settingList = ref([
|
||||
name: '基础设置',
|
||||
loadKey: 0
|
||||
},
|
||||
{
|
||||
component: markRaw(defineAsyncComponent(() => import('./modules/repair-flow.vue'))),
|
||||
key: 'repair-flow',
|
||||
name: '维修流程',
|
||||
loadKey: 0
|
||||
},
|
||||
{
|
||||
component: markRaw(defineAsyncComponent(() => import('./modules/step-rule.vue'))),
|
||||
key: 'step-rule',
|
||||
|
||||
+54
-2
@@ -122,7 +122,7 @@ const [BasicForm, formApi] = useForm({
|
||||
class: 'w-full'
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
prop: 'recent_records_today_only',
|
||||
label: '最近记录只显示当日',
|
||||
component: 'RadioGroup',
|
||||
@@ -133,6 +133,54 @@ const [BasicForm, formApi] = useForm({
|
||||
{ label: '否', value: 0 }
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
prop: 'exception_process_id',
|
||||
label: '异常提报工序',
|
||||
component: 'ApiSelect',
|
||||
componentProps: {
|
||||
api: '/produce/process',
|
||||
requestMethod: 'get',
|
||||
params: { format: 'select' },
|
||||
clearable: true,
|
||||
placeholder: '请选择异常提报对应工序',
|
||||
},
|
||||
},
|
||||
{
|
||||
prop: 'exception_step_id',
|
||||
label: '异常提报步骤',
|
||||
component: 'ApiSelect',
|
||||
componentProps: {
|
||||
api: '/produce/process-step',
|
||||
requestMethod: 'get',
|
||||
params: { format: 'select' },
|
||||
clearable: true,
|
||||
placeholder: '请选择异常提报对应步骤',
|
||||
},
|
||||
},
|
||||
{
|
||||
prop: 'repair_process_id',
|
||||
label: '维修记录工序',
|
||||
component: 'ApiSelect',
|
||||
componentProps: {
|
||||
api: '/produce/process',
|
||||
requestMethod: 'get',
|
||||
params: { format: 'select' },
|
||||
clearable: true,
|
||||
placeholder: '请选择维修记录对应工序',
|
||||
},
|
||||
},
|
||||
{
|
||||
prop: 'repair_step_id',
|
||||
label: '维修记录步骤',
|
||||
component: 'ApiSelect',
|
||||
componentProps: {
|
||||
api: '/produce/process-step',
|
||||
requestMethod: 'get',
|
||||
params: { format: 'select' },
|
||||
clearable: true,
|
||||
placeholder: '请选择维修记录对应步骤',
|
||||
},
|
||||
}
|
||||
]
|
||||
})
|
||||
@@ -156,7 +204,11 @@ async function onSubmit() {
|
||||
{ code: 'product_code_max_length', name: '商品编码最大长度', content: values.product_code_max_length ?? 20 },
|
||||
{ code: 'global_allow_repeat', name: '全局允许重复', content: Number(values.global_allow_repeat ?? 0) },
|
||||
{ code: 'repeat_scan_interval', name: '重复扫码最小间隔', content: values.repeat_scan_interval ?? 0 },
|
||||
{ code: 'recent_records_today_only', name: '最近记录只显示当日', content: Number(values.recent_records_today_only ?? 1) }
|
||||
{ code: 'recent_records_today_only', name: '最近记录只显示当日', content: Number(values.recent_records_today_only ?? 1) },
|
||||
{ code: 'exception_process_id', name: '异常提报工序', content: values.exception_process_id ?? '' },
|
||||
{ code: 'exception_step_id', name: '异常提报步骤', content: values.exception_step_id ?? '' },
|
||||
{ code: 'repair_process_id', name: '维修记录工序', content: values.repair_process_id ?? '' },
|
||||
{ code: 'repair_step_id', name: '维修记录步骤', content: values.repair_step_id ?? '' }
|
||||
]
|
||||
})
|
||||
ElMessage.success('保存成功')
|
||||
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
<template>
|
||||
<div class="repair-flow-page">
|
||||
<BasicForm />
|
||||
<el-button class="site-submit" type="primary" :loading="saving" @click="onSubmit">保存配置</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="tsx">
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { useForm } from '@/components/form'
|
||||
import { ProduceConfigApi } from '@/apps/produce/api'
|
||||
|
||||
const saving = ref(false)
|
||||
const [BasicForm, formApi] = useForm({
|
||||
labelPosition: 'right',
|
||||
labelWidth: '160px',
|
||||
inline: false,
|
||||
schema: [
|
||||
{
|
||||
prop: 'repair_process_id',
|
||||
label: '维修流程工序',
|
||||
component: 'ApiSelect',
|
||||
componentProps: {
|
||||
api: '/produce/process',
|
||||
requestMethod: 'get',
|
||||
params: { format: 'select' },
|
||||
clearable: true,
|
||||
placeholder: '请选择维修流程对应工序',
|
||||
},
|
||||
},
|
||||
{
|
||||
prop: 'repair_step_id',
|
||||
label: '维修流程步骤',
|
||||
component: 'ApiSelect',
|
||||
componentProps: {
|
||||
api: '/produce/process-step',
|
||||
requestMethod: 'get',
|
||||
params: { format: 'select' },
|
||||
clearable: true,
|
||||
placeholder: '请选择维修流程对应步骤',
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const loadConfig = async () => {
|
||||
const current = await ProduceConfigApi.info({ group_code: 'repair_flow' }) as Record<string, any>
|
||||
if (current?.repair_process_id || current?.repair_step_id) {
|
||||
await formApi.setValues(current)
|
||||
return
|
||||
}
|
||||
const legacy = await ProduceConfigApi.info({ group_code: 'basic_setting' }) as Record<string, any>
|
||||
await formApi.setValues({
|
||||
repair_process_id: legacy?.repair_process_id || '',
|
||||
repair_step_id: legacy?.repair_step_id || '',
|
||||
})
|
||||
}
|
||||
|
||||
const onSubmit = async () => {
|
||||
if (saving.value) return
|
||||
saving.value = true
|
||||
try {
|
||||
const values = await formApi.getValues()
|
||||
await ProduceConfigApi.save({
|
||||
group_code: 'repair_flow',
|
||||
configs: [
|
||||
{ code: 'repair_process_id', name: '维修流程工序', content: values.repair_process_id ?? '' },
|
||||
{ code: 'repair_step_id', name: '维修流程步骤', content: values.repair_step_id ?? '' },
|
||||
],
|
||||
})
|
||||
ElMessage.success('保存成功')
|
||||
} finally {
|
||||
saving.value = false
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
void loadConfig()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.site-submit {
|
||||
margin-left: 160px;
|
||||
}
|
||||
</style>
|
||||
+228
@@ -0,0 +1,228 @@
|
||||
<template>
|
||||
<div class="exception-analysis-page">
|
||||
<div class="analysis-toolbar">
|
||||
<el-date-picker
|
||||
v-model="filters.reported_at_range"
|
||||
type="daterange"
|
||||
value-format="YYYY-MM-DD"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
/>
|
||||
<el-input v-model="filters.type_code" clearable placeholder="处理类型编码" @keyup.enter="loadData" />
|
||||
<el-select v-model="filters.status" clearable placeholder="处理状态">
|
||||
<el-option label="待处理" :value="0" />
|
||||
<el-option label="处理中" :value="1" />
|
||||
<el-option label="已处理" :value="2" />
|
||||
</el-select>
|
||||
<el-button type="primary" :loading="loading" @click="loadData">查询</el-button>
|
||||
<el-button @click="resetFilters">重置</el-button>
|
||||
</div>
|
||||
|
||||
<div class="metric-grid">
|
||||
<div class="metric-item"><span>异常总数</span><strong>{{ overview.total }}</strong></div>
|
||||
<div class="metric-item pending"><span>待处理</span><strong>{{ overview.pending }}</strong></div>
|
||||
<div class="metric-item processing"><span>处理中</span><strong>{{ overview.processing }}</strong></div>
|
||||
<div class="metric-item completed"><span>已处理</span><strong>{{ overview.completed }}</strong></div>
|
||||
</div>
|
||||
|
||||
<div class="analysis-grid" v-loading="loading">
|
||||
<section class="analysis-section">
|
||||
<h3>处理类型分布</h3>
|
||||
<el-table :data="overview.by_type" size="small" height="260" empty-text="暂无数据">
|
||||
<el-table-column prop="name" label="处理类型" min-width="150" />
|
||||
<el-table-column prop="total" label="数量" width="100" align="right" />
|
||||
</el-table>
|
||||
</section>
|
||||
<section class="analysis-section">
|
||||
<h3>异常原因排行</h3>
|
||||
<el-table :data="overview.by_reason" size="small" height="260" empty-text="暂无数据">
|
||||
<el-table-column type="index" label="排名" width="70" />
|
||||
<el-table-column prop="name" label="异常原因" min-width="150" />
|
||||
<el-table-column prop="total" label="数量" width="100" align="right" />
|
||||
</el-table>
|
||||
</section>
|
||||
<section class="analysis-section">
|
||||
<h3>具体问题排行</h3>
|
||||
<el-table :data="overview.by_issue" size="small" height="260" empty-text="暂无数据">
|
||||
<el-table-column type="index" label="排名" width="70" />
|
||||
<el-table-column prop="name" label="具体问题" min-width="150" />
|
||||
<el-table-column prop="total" label="数量" width="100" align="right" />
|
||||
</el-table>
|
||||
</section>
|
||||
<section class="analysis-section full-width">
|
||||
<h3>每日提报趋势</h3>
|
||||
<el-table :data="overview.by_date" size="small" height="260" empty-text="暂无数据">
|
||||
<el-table-column type="index" label="序号" width="70" />
|
||||
<el-table-column prop="date" label="日期" min-width="180" />
|
||||
<el-table-column prop="total" label="异常数量" width="130" align="right" />
|
||||
</el-table>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, reactive, ref } from 'vue'
|
||||
import request from '@/utils/http'
|
||||
|
||||
interface AnalysisItem {
|
||||
code: string
|
||||
name: string
|
||||
total: number
|
||||
}
|
||||
|
||||
interface DateItem {
|
||||
date: string
|
||||
total: number
|
||||
}
|
||||
|
||||
interface AnalysisOverview {
|
||||
total: number
|
||||
pending: number
|
||||
processing: number
|
||||
completed: number
|
||||
by_type: AnalysisItem[]
|
||||
by_reason: AnalysisItem[]
|
||||
by_issue: AnalysisItem[]
|
||||
by_date: DateItem[]
|
||||
}
|
||||
|
||||
defineOptions({ name: 'ProduceExceptionAnalysis' })
|
||||
|
||||
const defaultRange = (): [string, string] => {
|
||||
const today = new Date()
|
||||
const start = new Date(today)
|
||||
start.setDate(today.getDate() - 29)
|
||||
const format = (date: Date) => date.toISOString().slice(0, 10)
|
||||
return [format(start), format(today)]
|
||||
}
|
||||
|
||||
const filters = reactive({
|
||||
reported_at_range: defaultRange() as string[] | undefined,
|
||||
type_code: '',
|
||||
status: undefined as number | undefined,
|
||||
})
|
||||
const loading = ref(false)
|
||||
const overview = ref<AnalysisOverview>({
|
||||
total: 0,
|
||||
pending: 0,
|
||||
processing: 0,
|
||||
completed: 0,
|
||||
by_type: [],
|
||||
by_reason: [],
|
||||
by_issue: [],
|
||||
by_date: [],
|
||||
})
|
||||
|
||||
async function loadData() {
|
||||
loading.value = true
|
||||
try {
|
||||
overview.value = await request.get<AnalysisOverview>({
|
||||
url: '/produce/exception-analysis/overview',
|
||||
params: filters,
|
||||
})
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function resetFilters() {
|
||||
filters.reported_at_range = defaultRange()
|
||||
filters.type_code = ''
|
||||
filters.status = undefined
|
||||
loadData()
|
||||
}
|
||||
|
||||
onMounted(loadData)
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.exception-analysis-page {
|
||||
min-height: 100%;
|
||||
padding: 16px;
|
||||
background: var(--el-bg-color-page);
|
||||
}
|
||||
|
||||
.analysis-toolbar,
|
||||
.metric-grid,
|
||||
.analysis-grid {
|
||||
display: grid;
|
||||
gap: 14px;
|
||||
}
|
||||
|
||||
.analysis-toolbar {
|
||||
grid-template-columns: minmax(260px, 1fr) 180px 150px auto auto;
|
||||
align-items: center;
|
||||
padding: 14px;
|
||||
background: var(--el-bg-color);
|
||||
border: 1px solid var(--el-border-color-light);
|
||||
}
|
||||
|
||||
.metric-grid {
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
margin: 16px 0;
|
||||
}
|
||||
|
||||
.metric-item,
|
||||
.analysis-section {
|
||||
background: var(--el-bg-color);
|
||||
border: 1px solid var(--el-border-color-light);
|
||||
}
|
||||
|
||||
.metric-item {
|
||||
padding: 18px;
|
||||
}
|
||||
|
||||
.metric-item span,
|
||||
.metric-item strong {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.metric-item span {
|
||||
color: var(--el-text-color-secondary);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.metric-item strong {
|
||||
margin-top: 8px;
|
||||
color: var(--el-text-color-primary);
|
||||
font-size: 28px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.metric-item.pending strong { color: var(--el-color-danger); }
|
||||
.metric-item.processing strong { color: var(--el-color-warning); }
|
||||
.metric-item.completed strong { color: var(--el-color-success); }
|
||||
|
||||
.analysis-grid {
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.analysis-section {
|
||||
min-width: 0;
|
||||
padding: 14px;
|
||||
}
|
||||
|
||||
.analysis-section h3 {
|
||||
margin: 0 0 12px;
|
||||
color: var(--el-text-color-primary);
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.full-width {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
|
||||
@media (max-width: 1100px) {
|
||||
.analysis-toolbar,
|
||||
.analysis-grid { grid-template-columns: 1fr 1fr; }
|
||||
.metric-grid { grid-template-columns: 1fr 1fr; }
|
||||
}
|
||||
|
||||
@media (max-width: 700px) {
|
||||
.analysis-toolbar,
|
||||
.analysis-grid,
|
||||
.metric-grid { grid-template-columns: 1fr; }
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,22 @@
|
||||
<template>
|
||||
<div class="produce-exception-data-page art-full-height">
|
||||
<BasicCrud />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="tsx">
|
||||
import { useCrud } from '@/components/crud'
|
||||
import { crudSchema } from './schemas'
|
||||
|
||||
defineOptions({ name: 'ProduceExceptionDataList' })
|
||||
|
||||
const [BasicCrud] = useCrud({
|
||||
...crudSchema(),
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.produce-exception-data-page {
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
+187
@@ -0,0 +1,187 @@
|
||||
import { CrudSchema } from '@/components/crud'
|
||||
import { ProduceExceptionRecordService } from '@/apps/produce/api'
|
||||
|
||||
const statusOptions = [
|
||||
{ label: '待处理', value: 0 },
|
||||
{ label: '处理中', value: 1 },
|
||||
{ label: '已处理', value: 2 }
|
||||
]
|
||||
|
||||
export const crudSchema = (): CrudSchema => ({
|
||||
api: ProduceExceptionRecordService.list,
|
||||
dialogTitle: '异常数据',
|
||||
crudApi: {
|
||||
add: ProduceExceptionRecordService.create,
|
||||
edit: ProduceExceptionRecordService.update,
|
||||
remove: ProduceExceptionRecordService.remove,
|
||||
view: ProduceExceptionRecordService.get
|
||||
},
|
||||
useCrud: true,
|
||||
hasAdd: true,
|
||||
hasEdit: true,
|
||||
hasRemove: true,
|
||||
hasView: true,
|
||||
addAuth: 'produce:exception-data:create',
|
||||
editAuth: 'produce:exception-data:update',
|
||||
removeAuth: 'produce:exception-data:delete',
|
||||
viewAuth: 'produce:exception-data:read',
|
||||
rowKey: 'id',
|
||||
searchFormSchema: {
|
||||
labelWidth: '90px',
|
||||
schema: [
|
||||
{
|
||||
prop: 'keyword',
|
||||
label: '关键字',
|
||||
component: 'Input',
|
||||
componentProps: { clearable: true, placeholder: '单号、提报人、处理类型、原因或具体问题' },
|
||||
colSpan: 8
|
||||
},
|
||||
{
|
||||
prop: 'type_code',
|
||||
label: '处理类型',
|
||||
component: 'Input',
|
||||
componentProps: { clearable: true, placeholder: '请输入处理类型编码' },
|
||||
colSpan: 8
|
||||
},
|
||||
{
|
||||
prop: 'status',
|
||||
label: '处理状态',
|
||||
component: 'Select',
|
||||
componentProps: { clearable: true, placeholder: '请选择处理状态', options: statusOptions },
|
||||
colSpan: 8
|
||||
},
|
||||
{
|
||||
prop: 'reported_at_range',
|
||||
label: '提报时间',
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
type: 'daterange',
|
||||
clearable: true,
|
||||
valueFormat: 'YYYY-MM-DD',
|
||||
startPlaceholder: '开始日期',
|
||||
endPlaceholder: '结束日期'
|
||||
},
|
||||
colSpan: 12
|
||||
}
|
||||
]
|
||||
},
|
||||
columns: [
|
||||
{ type: 'selection' },
|
||||
{ type: 'index', label: '序号', width: 70 },
|
||||
{ prop: 'order_no', label: '单号/条码', minWidth: 160 },
|
||||
{ prop: 'type_name', label: '处理类型', minWidth: 120 },
|
||||
{ prop: 'reason_name', label: '异常原因', minWidth: 120 },
|
||||
{ prop: 'issue_name', label: '具体问题', minWidth: 140 },
|
||||
{ prop: 'reporter', label: '提报人', minWidth: 110 },
|
||||
{ prop: 'status_name', label: '处理状态', minWidth: 100 },
|
||||
{ prop: 'handler', label: '处理人', minWidth: 110 },
|
||||
{ prop: 'reported_date', label: '提报时间', minWidth: 170 },
|
||||
{ prop: 'handled_date', label: '处理时间', minWidth: 170 }
|
||||
],
|
||||
dialogProps: { width: '820px' },
|
||||
formSchema: {
|
||||
showDefaultActions: false,
|
||||
labelWidth: '105px',
|
||||
schema: [
|
||||
{ component: 'Input', prop: 'id', label: 'ID', show: false, ifDetail: true, colSpan: 24 },
|
||||
{
|
||||
component: 'Input',
|
||||
prop: 'order_no',
|
||||
label: '单号/条码',
|
||||
componentProps: { placeholder: '请输入单号或条码', maxlength: 100 },
|
||||
rules: [{ required: true, message: '请输入单号或条码' }],
|
||||
colSpan: 12
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
prop: 'user_code',
|
||||
label: '提报人工号',
|
||||
componentProps: { placeholder: '请输入提报人工号', maxlength: 50 },
|
||||
colSpan: 12
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
prop: 'reporter',
|
||||
label: '提报人',
|
||||
componentProps: { placeholder: '请输入提报人', maxlength: 100 },
|
||||
colSpan: 12
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
prop: 'type_code',
|
||||
label: '处理类型编码',
|
||||
componentProps: { placeholder: '例如 defective_repair', maxlength: 64 },
|
||||
rules: [{ required: true, message: '请输入处理类型编码' }],
|
||||
colSpan: 12
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
prop: 'type_name',
|
||||
label: '处理类型',
|
||||
componentProps: { placeholder: '例如 不良维修', maxlength: 100 },
|
||||
rules: [{ required: true, message: '请输入处理类型' }],
|
||||
colSpan: 12
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
prop: 'reason_code',
|
||||
label: '异常原因编码',
|
||||
componentProps: { placeholder: '例如 test_defect', maxlength: 64 },
|
||||
rules: [{ required: true, message: '请输入异常原因编码' }],
|
||||
colSpan: 12
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
prop: 'reason_name',
|
||||
label: '异常原因',
|
||||
componentProps: { placeholder: '例如 测试不良', maxlength: 100 },
|
||||
rules: [{ required: true, message: '请输入异常原因' }],
|
||||
colSpan: 12
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
prop: 'issue_code',
|
||||
label: '具体问题编码',
|
||||
componentProps: { placeholder: '可选', maxlength: 64 },
|
||||
colSpan: 12
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
prop: 'issue_name',
|
||||
label: '具体问题',
|
||||
componentProps: { placeholder: '可选', maxlength: 100 },
|
||||
colSpan: 12
|
||||
},
|
||||
{
|
||||
component: 'Select',
|
||||
prop: 'status',
|
||||
label: '处理状态',
|
||||
defaultValue: 0,
|
||||
componentProps: { options: statusOptions },
|
||||
colSpan: 12
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
prop: 'handler',
|
||||
label: '处理人',
|
||||
componentProps: { placeholder: '请输入处理人', maxlength: 100 },
|
||||
colSpan: 12
|
||||
},
|
||||
{
|
||||
component: 'Upload',
|
||||
prop: 'images',
|
||||
label: '现场图片',
|
||||
componentProps: { listType: 'picture-card' },
|
||||
ifDetail: true,
|
||||
colSpan: 24
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
prop: 'remark',
|
||||
label: '补充说明',
|
||||
componentProps: { type: 'textarea', rows: 3, placeholder: '请输入现场情况或处理说明' },
|
||||
colSpan: 24
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
<template>
|
||||
<div class="exception-setting-page art-full-height">
|
||||
<BasicCrud />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="tsx">
|
||||
import { useCrud } from '@/components/crud'
|
||||
import { crudSchema } from './schemas'
|
||||
|
||||
defineOptions({ name: 'ProduceExceptionSettingList' })
|
||||
|
||||
const [BasicCrud] = useCrud({
|
||||
...crudSchema(),
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.exception-setting-page {
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
import { CrudSchema } from '@/components/crud'
|
||||
import { ProduceExceptionSettingService } from '@/apps/produce/api'
|
||||
|
||||
const settingTypeOptions = [
|
||||
{ label: '处理类型', value: 'type' },
|
||||
{ label: '异常原因', value: 'reason' },
|
||||
{ label: '具体问题', value: 'issue' },
|
||||
]
|
||||
|
||||
export const crudSchema = (): CrudSchema => ({
|
||||
api: ProduceExceptionSettingService.list,
|
||||
dialogTitle: '异常设置',
|
||||
crudApi: {
|
||||
add: ProduceExceptionSettingService.create,
|
||||
edit: ProduceExceptionSettingService.update,
|
||||
remove: ProduceExceptionSettingService.remove,
|
||||
view: ProduceExceptionSettingService.get,
|
||||
},
|
||||
useCrud: true,
|
||||
hasAdd: true,
|
||||
hasEdit: true,
|
||||
hasRemove: true,
|
||||
hasView: true,
|
||||
addAuth: 'produce:exception-setting:create',
|
||||
editAuth: 'produce:exception-setting:update',
|
||||
removeAuth: 'produce:exception-setting:delete',
|
||||
viewAuth: 'produce:exception-setting:read',
|
||||
rowKey: 'id',
|
||||
searchFormSchema: {
|
||||
labelWidth: '90px',
|
||||
schema: [
|
||||
{
|
||||
prop: 'keyword', label: '关键字', component: 'Input',
|
||||
componentProps: { clearable: true, placeholder: '编码、名称或备注' }, colSpan: 8,
|
||||
},
|
||||
{
|
||||
prop: 'setting_type', label: '设置层级', component: 'Select',
|
||||
componentProps: { clearable: true, placeholder: '请选择设置层级', options: settingTypeOptions }, colSpan: 8,
|
||||
},
|
||||
{
|
||||
prop: 'is_enabled', label: '启用状态', component: 'Select',
|
||||
componentProps: {
|
||||
clearable: true, placeholder: '请选择启用状态',
|
||||
options: [{ label: '启用', value: 1 }, { label: '停用', value: 0 }],
|
||||
}, colSpan: 8,
|
||||
},
|
||||
],
|
||||
},
|
||||
columns: [
|
||||
{ type: 'selection' },
|
||||
{ type: 'index', label: '序号', width: 70 },
|
||||
{ prop: 'setting_type', label: '设置层级', minWidth: 100, formatter: (row: { setting_type?: string }) => settingTypeOptions.find((item) => item.value === row.setting_type)?.label || row.setting_type || '' },
|
||||
{ prop: 'code', label: '编码', minWidth: 150 },
|
||||
{ prop: 'name', label: '名称', minWidth: 160 },
|
||||
{ prop: 'parent_name', label: '所属上级', minWidth: 140 },
|
||||
{ prop: 'sort', label: '排序', width: 90 },
|
||||
{ prop: 'is_enabled', label: '状态', width: 90, formatter: (row: any) => row.is_enabled === 0 ? '停用' : '启用' },
|
||||
{ prop: 'remark', label: '备注', minWidth: 180, showOverflowTooltip: true },
|
||||
{ prop: 'created_name', label: '创建人', minWidth: 110 },
|
||||
],
|
||||
dialogProps: { width: '700px' },
|
||||
formSchema: {
|
||||
showDefaultActions: false,
|
||||
labelWidth: '105px',
|
||||
schema: [
|
||||
{ component: 'Input', prop: 'id', label: 'ID', show: false, ifDetail: true, colSpan: 24 },
|
||||
{
|
||||
component: 'Select', prop: 'setting_type', label: '设置层级',
|
||||
componentProps: { placeholder: '请选择设置层级', options: settingTypeOptions },
|
||||
rules: [{ required: true, message: '请选择设置层级' }], colSpan: 12,
|
||||
},
|
||||
{
|
||||
component: 'ApiSelect', prop: 'parent_id', label: '所属上级',
|
||||
componentProps: {
|
||||
api: '/produce/exception-setting', requestMethod: 'get',
|
||||
params: { format: 'select', NE_setting_type: 'issue' }, clearable: true, placeholder: '处理类型无需选择上级',
|
||||
}, colSpan: 12,
|
||||
},
|
||||
{
|
||||
component: 'Input', prop: 'code', label: '设置编码',
|
||||
componentProps: { placeholder: '请输入唯一编码', maxlength: 64 },
|
||||
rules: [{ required: true, message: '请输入设置编码' }], colSpan: 12,
|
||||
},
|
||||
{
|
||||
component: 'Input', prop: 'name', label: '设置名称',
|
||||
componentProps: { placeholder: '请输入显示名称', maxlength: 100 },
|
||||
rules: [{ required: true, message: '请输入设置名称' }], colSpan: 12,
|
||||
},
|
||||
{ component: 'InputNumber', prop: 'sort', label: '排序', defaultValue: 0, componentProps: { min: 0 }, colSpan: 12 },
|
||||
{
|
||||
component: 'RadioGroup', prop: 'is_enabled', label: '是否启用', defaultValue: 1,
|
||||
componentProps: { options: [{ label: '启用', value: 1 }, { label: '停用', value: 0 }] }, colSpan: 12,
|
||||
},
|
||||
{
|
||||
component: 'Input', prop: 'remark', label: '备注',
|
||||
componentProps: { type: 'textarea', rows: 3, placeholder: '请输入备注' }, colSpan: 24,
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
+93
-33
@@ -4,7 +4,7 @@ import { ProduceExceptionRecordService } from '@/apps/produce/api'
|
||||
const statusOptions = [
|
||||
{ label: '待处理', value: 0 },
|
||||
{ label: '处理中', value: 1 },
|
||||
{ label: '已处理', value: 2 },
|
||||
{ label: '已处理', value: 2 }
|
||||
]
|
||||
|
||||
export const crudSchema = (): CrudSchema => ({
|
||||
@@ -14,7 +14,7 @@ export const crudSchema = (): CrudSchema => ({
|
||||
add: ProduceExceptionRecordService.create,
|
||||
edit: ProduceExceptionRecordService.update,
|
||||
remove: ProduceExceptionRecordService.remove,
|
||||
view: ProduceExceptionRecordService.get,
|
||||
view: ProduceExceptionRecordService.get
|
||||
},
|
||||
useCrud: true,
|
||||
hasAdd: true,
|
||||
@@ -34,21 +34,21 @@ export const crudSchema = (): CrudSchema => ({
|
||||
label: '关键字',
|
||||
component: 'Input',
|
||||
componentProps: { clearable: true, placeholder: '单号、提报人、处理类型、原因或具体问题' },
|
||||
colSpan: 8,
|
||||
colSpan: 8
|
||||
},
|
||||
{
|
||||
prop: 'type_code',
|
||||
label: '处理类型',
|
||||
component: 'Input',
|
||||
componentProps: { clearable: true, placeholder: '请输入处理类型编码' },
|
||||
colSpan: 8,
|
||||
colSpan: 8
|
||||
},
|
||||
{
|
||||
prop: 'status',
|
||||
label: '处理状态',
|
||||
component: 'Select',
|
||||
componentProps: { clearable: true, placeholder: '请选择处理状态', options: statusOptions },
|
||||
colSpan: 8,
|
||||
colSpan: 8
|
||||
},
|
||||
{
|
||||
prop: 'reported_at_range',
|
||||
@@ -59,11 +59,11 @@ export const crudSchema = (): CrudSchema => ({
|
||||
clearable: true,
|
||||
valueFormat: 'YYYY-MM-DD',
|
||||
startPlaceholder: '开始日期',
|
||||
endPlaceholder: '结束日期',
|
||||
endPlaceholder: '结束日期'
|
||||
},
|
||||
colSpan: 12,
|
||||
},
|
||||
],
|
||||
colSpan: 12
|
||||
}
|
||||
]
|
||||
},
|
||||
columns: [
|
||||
{ type: 'selection' },
|
||||
@@ -76,7 +76,7 @@ export const crudSchema = (): CrudSchema => ({
|
||||
{ prop: 'status_name', label: '处理状态', minWidth: 100 },
|
||||
{ prop: 'handler', label: '处理人', minWidth: 110 },
|
||||
{ prop: 'reported_date', label: '提报时间', minWidth: 170 },
|
||||
{ prop: 'handled_date', label: '处理时间', minWidth: 170 },
|
||||
{ prop: 'handled_date', label: '处理时间', minWidth: 170 }
|
||||
],
|
||||
dialogProps: { width: '820px' },
|
||||
formSchema: {
|
||||
@@ -85,43 +85,103 @@ export const crudSchema = (): CrudSchema => ({
|
||||
schema: [
|
||||
{ component: 'Input', prop: 'id', label: 'ID', show: false, ifDetail: true, colSpan: 24 },
|
||||
{
|
||||
component: 'Input', prop: 'order_no', label: '单号/条码',
|
||||
component: 'Input',
|
||||
prop: 'order_no',
|
||||
label: '单号/条码',
|
||||
componentProps: { placeholder: '请输入单号或条码', maxlength: 100 },
|
||||
rules: [{ required: true, message: '请输入单号或条码' }], colSpan: 12,
|
||||
rules: [{ required: true, message: '请输入单号或条码' }],
|
||||
colSpan: 12
|
||||
},
|
||||
{ component: 'Input', prop: 'user_code', label: '提报人工号', componentProps: { placeholder: '请输入提报人工号', maxlength: 50 }, colSpan: 12 },
|
||||
{ component: 'Input', prop: 'reporter', label: '提报人', componentProps: { placeholder: '请输入提报人', maxlength: 100 }, colSpan: 12 },
|
||||
{
|
||||
component: 'Input', prop: 'type_code', label: '处理类型编码',
|
||||
component: 'Input',
|
||||
prop: 'user_code',
|
||||
label: '提报人工号',
|
||||
componentProps: { placeholder: '请输入提报人工号', maxlength: 50 },
|
||||
colSpan: 12
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
prop: 'reporter',
|
||||
label: '提报人',
|
||||
componentProps: { placeholder: '请输入提报人', maxlength: 100 },
|
||||
colSpan: 12
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
prop: 'type_code',
|
||||
label: '处理类型编码',
|
||||
componentProps: { placeholder: '例如 defective_repair', maxlength: 64 },
|
||||
rules: [{ required: true, message: '请输入处理类型编码' }], colSpan: 12,
|
||||
rules: [{ required: true, message: '请输入处理类型编码' }],
|
||||
colSpan: 12
|
||||
},
|
||||
{
|
||||
component: 'Input', prop: 'type_name', label: '处理类型',
|
||||
component: 'Input',
|
||||
prop: 'type_name',
|
||||
label: '处理类型',
|
||||
componentProps: { placeholder: '例如 不良维修', maxlength: 100 },
|
||||
rules: [{ required: true, message: '请输入处理类型' }], colSpan: 12,
|
||||
rules: [{ required: true, message: '请输入处理类型' }],
|
||||
colSpan: 12
|
||||
},
|
||||
{
|
||||
component: 'Input', prop: 'reason_code', label: '异常原因编码',
|
||||
component: 'Input',
|
||||
prop: 'reason_code',
|
||||
label: '异常原因编码',
|
||||
componentProps: { placeholder: '例如 test_defect', maxlength: 64 },
|
||||
rules: [{ required: true, message: '请输入异常原因编码' }], colSpan: 12,
|
||||
rules: [{ required: true, message: '请输入异常原因编码' }],
|
||||
colSpan: 12
|
||||
},
|
||||
{
|
||||
component: 'Input', prop: 'reason_name', label: '异常原因',
|
||||
component: 'Input',
|
||||
prop: 'reason_name',
|
||||
label: '异常原因',
|
||||
componentProps: { placeholder: '例如 测试不良', maxlength: 100 },
|
||||
rules: [{ required: true, message: '请输入异常原因' }], colSpan: 12,
|
||||
},
|
||||
{ component: 'Input', prop: 'issue_code', label: '具体问题编码', componentProps: { placeholder: '可选', maxlength: 64 }, colSpan: 12 },
|
||||
{ component: 'Input', prop: 'issue_name', label: '具体问题', componentProps: { placeholder: '可选', maxlength: 100 }, colSpan: 12 },
|
||||
{ component: 'Select', prop: 'status', label: '处理状态', defaultValue: 0, componentProps: { options: statusOptions }, colSpan: 12 },
|
||||
{ component: 'Input', prop: 'handler', label: '处理人', componentProps: { placeholder: '请输入处理人', maxlength: 100 }, colSpan: 12 },
|
||||
{
|
||||
component: 'Upload', prop: 'images', label: '现场图片', componentProps: { listType: 'picture-card' }, ifDetail: true, colSpan: 24,
|
||||
rules: [{ required: true, message: '请输入异常原因' }],
|
||||
colSpan: 12
|
||||
},
|
||||
{
|
||||
component: 'Input', prop: 'remark', label: '补充说明',
|
||||
componentProps: { type: 'textarea', rows: 3, placeholder: '请输入现场情况或处理说明' }, colSpan: 24,
|
||||
component: 'Input',
|
||||
prop: 'issue_code',
|
||||
label: '具体问题编码',
|
||||
componentProps: { placeholder: '可选', maxlength: 64 },
|
||||
colSpan: 12
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
prop: 'issue_name',
|
||||
label: '具体问题',
|
||||
componentProps: { placeholder: '可选', maxlength: 100 },
|
||||
colSpan: 12
|
||||
},
|
||||
{
|
||||
component: 'Select',
|
||||
prop: 'status',
|
||||
label: '处理状态',
|
||||
defaultValue: 0,
|
||||
componentProps: { options: statusOptions },
|
||||
colSpan: 12
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
prop: 'handler',
|
||||
label: '处理人',
|
||||
componentProps: { placeholder: '请输入处理人', maxlength: 100 },
|
||||
colSpan: 12
|
||||
},
|
||||
{
|
||||
component: 'Upload',
|
||||
prop: 'images',
|
||||
label: '现场图片',
|
||||
componentProps: { listType: 'picture-card' },
|
||||
ifDetail: true,
|
||||
colSpan: 24
|
||||
},
|
||||
{
|
||||
component: 'Input',
|
||||
prop: 'remark',
|
||||
label: '补充说明',
|
||||
componentProps: { type: 'textarea', rows: 3, placeholder: '请输入现场情况或处理说明' },
|
||||
colSpan: 24
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
|
||||
+2
-2
@@ -25,7 +25,7 @@ export const crudSchema = (): CrudSchema => ({
|
||||
labelWidth: '90px',
|
||||
schema: [
|
||||
{ prop: 'keyword', label: '关键字', component: 'Input', componentProps: { clearable: true, placeholder: '商品编码或商品名称' }, colSpan: 8 },
|
||||
{ prop: 'category_id', label: '物料分类', component: 'ApiSelect', componentProps: { api: ProduceMaterialService.categoryOptions, labelField: 'category_name', valueField: 'id', clearable: true, placeholder: '请选择分类' }, colSpan: 8 },
|
||||
{ prop: 'category_id', label: '物料分类', component: 'ApiSelect', componentProps: { api: ProduceMaterialService.categoryOptions, labelField: 'label', valueField: 'value', clearable: true, placeholder: '请选择分类' }, colSpan: 8 },
|
||||
],
|
||||
},
|
||||
columns: [
|
||||
@@ -42,7 +42,7 @@ export const crudSchema = (): CrudSchema => ({
|
||||
labelWidth: '90px',
|
||||
schema: [
|
||||
{ component: 'Input', show: false, ifDetail: true, colSpan: 24, prop: 'id', label: 'ID' },
|
||||
{ component: 'ApiSelect', prop: 'category_id', label: '物料分类', componentProps: { api: ProduceMaterialService.categoryOptions, labelField: 'category_name', valueField: 'id', clearable: true, placeholder: '请选择分类' }, rules: [{ required: true, message: '请选择物料分类' }], colSpan: 12 },
|
||||
{ component: 'ApiSelect', prop: 'category_id', label: '物料分类', componentProps: { api: ProduceMaterialService.categoryOptions, labelField: 'label', valueField: 'value', clearable: true, placeholder: '请选择分类' }, rules: [{ required: true, message: '请选择物料分类' }], colSpan: 12 },
|
||||
{ component: 'Input', prop: 'product_code', label: '商品编码', componentProps: { maxlength: 100, placeholder: '请输入或扫描商品编码' }, rules: [{ required: true, message: '请输入商品编码' }], colSpan: 12 },
|
||||
{ component: 'Input', prop: 'product_name', label: '商品名称', componentProps: { maxlength: 200, placeholder: '请输入商品名称' }, rules: [{ required: true, message: '请输入商品名称' }], colSpan: 24 },
|
||||
],
|
||||
|
||||
-1
@@ -297,7 +297,6 @@ export const crudSchema = (): CrudSchema => ({
|
||||
prop: "id",
|
||||
label: "ID",
|
||||
show: false,
|
||||
ifDetail: true,
|
||||
colSpan: 24,
|
||||
},
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user