feat(ear-tag): 新增耳标登记功能
- 添加耳标登记页面,支持新增和编辑功能 - 实现养殖场、养殖舍、养殖栏的级联选择- 添加耳标信息的详细录入,包括生物芯片耳标号、电子耳标号等 -优化列表页面,增加搜索和筛选功能 - 重构表格组件,支持更多列类型和操作
This commit is contained in:
@@ -1,7 +1,21 @@
|
||||
<script>
|
||||
import {mapState} from "vuex"
|
||||
import AiSelect from "dui/packages/basic/AiSelect.vue";
|
||||
|
||||
const columns = [
|
||||
{label: "序号", type: "index"},
|
||||
{label: "生物芯片耳标号", prop: "biochipEarNumber"},
|
||||
{label: "电子耳标号", prop: "electronicEarNumber"},
|
||||
{label: "原厂耳标号", prop: "originalEarNumber"},
|
||||
{label: "戴耳标照片", prop: "picture", upload: 1},
|
||||
{label: "品种", prop: "variety", select: 1, dict: "variety"},
|
||||
{label: "类别", prop: "category", select: 1, dict: "category"},
|
||||
{label: "日龄/天", prop: "age", edit: 1},
|
||||
{label: "体重/公斤", prop: "weight", edit: 1},
|
||||
]
|
||||
export default {
|
||||
name: "etAdd",
|
||||
components: {AiSelect},
|
||||
props: {
|
||||
instance: Function,
|
||||
permissions: Function,
|
||||
@@ -10,10 +24,18 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
detail: {},
|
||||
columns,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isAuditing: v => v.detail.auditStatus == 1
|
||||
...mapState(["user"]),
|
||||
userinfo: v => v.user.info || {},
|
||||
isAdd: v => !v.$route.query.id,
|
||||
isEdit: v => v.$route.query.edit == 1,
|
||||
pageTitle: v => {
|
||||
const appName = v.$parent.menuName || v.$parent.$options.label
|
||||
return v.$route.query.id ? v.isEdit ? `编辑${appName}` : `${appName}详情` : `新增${appName}`
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
back(params = {}) {
|
||||
@@ -21,60 +43,121 @@ export default {
|
||||
},
|
||||
getDetail() {
|
||||
const {id} = this.$route.query
|
||||
this.instance.post("/api/user/auth/page", null, {params: {id}}).then(res => {
|
||||
return this.instance.post("/api/breed/earTag/page", {id}).then(res => {
|
||||
if (res?.data?.records) {
|
||||
const detail = res.data.records[0] || {}
|
||||
let {picture = "{}"} = detail
|
||||
picture = JSON.parse(picture)
|
||||
this.detail = {...detail, ...picture}
|
||||
return this.detail = {...detail}
|
||||
}
|
||||
})
|
||||
},
|
||||
getNeedCerts(type) {
|
||||
return this.$parent.certificates.filter(e => !e.permit || e.permit.includes(type))
|
||||
getList() {
|
||||
const {penId} = this.detail
|
||||
this.instance.post("/api/breed/earTag/getEarTagByPenId", null, {params: {penId}}).then(res => {
|
||||
if (res?.data) {
|
||||
this.$set(this.detail, 'detailList', res.data)
|
||||
}
|
||||
})
|
||||
},
|
||||
handleAudit(auditStatus) {
|
||||
const auditLabels = {
|
||||
2: "同意通过", 3: "驳回"
|
||||
}
|
||||
this.$confirm(`是否要${auditLabels[auditStatus]}认证?`).then(() => {
|
||||
this.instance.post("/api/user/audit", null, {params:{
|
||||
id: this.detail.id, auditStatus
|
||||
}}).then(res => {
|
||||
handleDelete(index) {
|
||||
this.$confirm("确定删除该条数据?").then(() => {
|
||||
this.detail.splice(index, 1)
|
||||
})
|
||||
},
|
||||
submit() {
|
||||
this.$refs.detail.validate().then(() => {
|
||||
this.instance.post("/api/breed/earTag/addOrEdit", this.detail).then(res => {
|
||||
if (res?.code == 0) {
|
||||
this.$confirm("是否要返回列表?","提交成功").then(() => this.back())
|
||||
this.$confirm("是否要返回列表?", "提交成功").then(() => this.back())
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.dict.load("auditStatus")
|
||||
this.dict.load("auditStatus", "category", "variety")
|
||||
this.getDetail()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ai-page title="认证材料" class="etAdd" showBack content-string="detail">
|
||||
<el-form size="small" label-position="top" :model="detail" ref="detail">
|
||||
<ai-card title="认证材料">
|
||||
<div class="grid">
|
||||
<el-form-item v-for="(op,i) in getNeedCerts(detail.type)" :key="i" v-bind="op" :rules="{required:true,message:`请上传${op.label}`,trigger:'change'}">
|
||||
<el-image :src="detail[op.prop]" :preview-src-list="[detail[op.prop]]"/>
|
||||
<ai-page :title="pageTitle" class="etAdd" showBack content-string="blank">
|
||||
<el-form size="small" label-width="120px" :model="detail" ref="detail">
|
||||
<ai-card title="基础信息">
|
||||
<div class="grid c-3">
|
||||
<template v-if="isAdd">
|
||||
<el-form-item label="养殖场" prop="farmId">
|
||||
<ai-select v-model="detail.farmId" :instance="instance" :action="`/api/siteUser/querySiteByUserId?userId=${userinfo.id}`" :prop="{label:'name'}"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="养殖舍" prop="houseId">
|
||||
<ai-select v-model="detail.houseId" :instance="instance" :action="`/api/siteUser/querySiteById?id=${detail.farmId||-1}`" :prop="{label:'name'}"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="养殖栏" prop="penId">
|
||||
<ai-select v-model="detail.penId" @change="getList" :instance="instance" :action="`/api/siteUser/querySiteById?id=${detail.houseId||-1}`" :prop="{label:'name'}"/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-form-item label="养殖场" prop="farmId">
|
||||
<b v-text="detail.farmName"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="养殖舍" prop="houseId">
|
||||
<b v-text="detail.houseName"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="养殖栏" prop="penId">
|
||||
<b v-text="detail.penName"/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</div>
|
||||
</ai-card>
|
||||
<ai-card title="耳标录入">
|
||||
<ai-table v-if="isAdd" :tableData="detail.detailList" :colConfigs="columns" :isShowPagination="!1">
|
||||
<el-table-column slot="options" label="操作" fixed="right" align="center">
|
||||
<template slot-scope="{row,$index}">
|
||||
<div class="table-options">
|
||||
<el-button type="text" class="deleteBtn" @click="handleDelete($index)">删除</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</ai-table>
|
||||
<div class="grid" v-else>
|
||||
<el-form-item label="生物芯片耳标号">
|
||||
<b v-text="detail.biochipEarNumber"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="电子耳标号" prop="electronicEarNumber">
|
||||
<el-input v-if="isEdit" v-model="detail.electronicEarNumber" placeholder="请输入" clearable/>
|
||||
<b v-else v-text="detail.electronicEarNumber"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="原厂耳标号" prop="originalEarNumber">
|
||||
<el-input v-if="isEdit" v-model="detail.originalEarNumber" placeholder="请输入" clearable/>
|
||||
<b v-else v-text="detail.originalEarNumber"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="戴耳标照片" class="row">
|
||||
<el-image :src="detail.picture" :preview-src-list="[detail.picture]"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="品种" prop="variety">
|
||||
<ai-select v-if="isEdit" v-model="detail.variety" dict="variety"/>
|
||||
<b v-else v-text="detail.variety"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="类别" prop="category">
|
||||
<ai-select v-if="isEdit" v-model="detail.category" dict="category"/>
|
||||
<b v-else v-text="detail.category"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="日龄/天">
|
||||
<el-input v-if="isEdit" v-model.number="detail.age" placeholder="请输入" clearable/>
|
||||
<b v-else v-text="detail.age"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="体重/公斤">
|
||||
<el-input v-if="isEdit" v-model.number="detail.weight" placeholder="请输入" clearable/>
|
||||
<b v-else v-text="detail.weight"/>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</ai-card>
|
||||
<ai-card title="备注说明">
|
||||
<div v-text="detail.remark"/>
|
||||
</ai-card>
|
||||
</el-form>
|
||||
<div slot="footer">
|
||||
<template v-if="isAuditing">
|
||||
<el-button type="primary" @click="handleAudit(2)">同意</el-button>
|
||||
<el-button type="danger" @click="handleAudit(3)">拒绝</el-button>
|
||||
<template v-if="isEdit||isAdd">
|
||||
<el-button type="primary" @click="submit">提交</el-button>
|
||||
</template>
|
||||
<el-button @click="back">关闭</el-button>
|
||||
<el-button @click="back">返回</el-button>
|
||||
</div>
|
||||
</ai-page>
|
||||
</template>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script>
|
||||
import AiSearchBar from "dui/packages/layout/AiSearchBar.vue";
|
||||
import {mapState} from "vuex"
|
||||
|
||||
const columns = [
|
||||
{label: "序号", type: "index"},
|
||||
@@ -12,7 +12,6 @@ const columns = [
|
||||
]
|
||||
export default {
|
||||
name: "etList",
|
||||
components: {AiSearchBar},
|
||||
props: {
|
||||
instance: Function,
|
||||
dict: Object,
|
||||
@@ -28,6 +27,19 @@ export default {
|
||||
form: {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(['user']),
|
||||
userinfo: v => v.user.info || {}
|
||||
},
|
||||
watch: {
|
||||
search: {
|
||||
deep: true,
|
||||
handler() {
|
||||
this.page.pageNum = 1
|
||||
this.getTableData()
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getTableData() {
|
||||
this.instance.post("/api/breed/earTag/page", {...this.page, ...this.search}).then(res => {
|
||||
@@ -49,7 +61,7 @@ export default {
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.dict.load("auditStatus")
|
||||
this.dict.load("auditStatus", "category", "variety")
|
||||
this.getTableData()
|
||||
}
|
||||
}
|
||||
@@ -59,14 +71,14 @@ export default {
|
||||
<ai-page class="etList" title="耳标登记">
|
||||
<ai-search-bar>
|
||||
<template #left>
|
||||
<ai-select placeholder="所属机构" v-model="search.userId" dict="authStatus"/>
|
||||
<ai-select placeholder="养殖场" v-model="search.farmId" dict="authStatus"/>
|
||||
<ai-select placeholder="养殖舍" v-model="search.houseId" dict="authStatus"/>
|
||||
<ai-select placeholder="养殖栏" v-model="search.penId" dict="authStatus"/>
|
||||
<ai-select placeholder="全部机构" v-model="search.userId" :instance="instance" :action="`/api/breed/earTag/getOrgList`" :prop="{label:'name'}"/>
|
||||
<ai-select placeholder="全部养殖场" v-model="search.farmId" :instance="instance" :action="`/api/siteUser/querySiteByUserId?userId=${search.userId||''}`" :prop="{label:'name'}"/>
|
||||
<ai-select placeholder="全部养殖舍" v-model="search.houseId" :instance="instance" :action="`/api/siteUser/querySiteById?id=${search.farmId||-1}`" :prop="{label:'name'}"/>
|
||||
<ai-select placeholder="全部养殖栏" v-model="search.penId" :instance="instance" :action="`/api/siteUser/querySiteById?id=${search.houseId||-1}`" :prop="{label:'name'}"/>
|
||||
<el-input placeholder="戴标员" v-model="search.userName" dict="authStatus" size="small" clearable/>
|
||||
<el-input placeholder="生物芯片耳标号" v-model="search.biochipEarNumber" dict="authStatus" size="small" clearable/>
|
||||
<ai-select placeholder="类别" v-model="search.category" dict="authStatus"/>
|
||||
<ai-select placeholder="品种" v-model="search.variety" dict="authStatus"/>
|
||||
<ai-select placeholder="全部类别" v-model="search.category" dict="category"/>
|
||||
<ai-select placeholder="全部品种" v-model="search.variety" dict="variety"/>
|
||||
<ai-search label="登记日期">
|
||||
<el-date-picker v-model="search.beginDate" type="datetime" placeholder="开始日期" size="small"/>
|
||||
<el-date-picker v-model="search.endDate" type="datetime" placeholder="结束日期" size="small"/>
|
||||
@@ -76,14 +88,10 @@ export default {
|
||||
<el-input placeholder="最大日龄" v-model="search.endAge" size="small" clearable/>
|
||||
</ai-search>
|
||||
</template>
|
||||
<template #right>
|
||||
<el-input size="small" placeholder="搜索账号" v-model="search.name" clearable
|
||||
@change="page.pageNum=1, getTableData()" @getList="getTableData"/>
|
||||
</template>
|
||||
</ai-search-bar>
|
||||
<ai-search-bar>
|
||||
<template #left>
|
||||
<el-button type="primary" icon="iconfont iconAdd" @clicl="$router.push({hash:'#add'})">新增</el-button>
|
||||
<el-button type="primary" icon="iconfont iconAdd" @click="$router.push({hash:'#add'})">新增</el-button>
|
||||
</template>
|
||||
</ai-search-bar>
|
||||
<ai-table :tableData="tableData" :colConfigs="columns" :dict="dict" @getList="getTableData"
|
||||
@@ -91,8 +99,8 @@ export default {
|
||||
<el-table-column slot="options" label="操作" fixed="right" align="center">
|
||||
<template slot-scope="{row}">
|
||||
<div class="table-options">
|
||||
<el-button type="text">查看</el-button>
|
||||
<el-button type="text">编辑</el-button>
|
||||
<el-button type="text" @click="$router.push({hash:'#add',query:{id:row.id}})">查看</el-button>
|
||||
<el-button type="text" @click="$router.push({hash:'#add',query:{id:row.id,edit:1}})">编辑</el-button>
|
||||
<el-button type="text" class="deleteBtn" @click="handleDelete(row.id)">删除</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -21,33 +21,17 @@
|
||||
:is="colConfig.component"
|
||||
:col-config="colConfig">
|
||||
</component>
|
||||
<el-table-column
|
||||
v-else-if="colConfig.dict"
|
||||
:key="colConfig.id"
|
||||
v-bind="colConfig">
|
||||
<span slot-scope="{row}" :style="{color:colConfig.color||dict.getColor(colConfig.dict, row[colConfig.prop])}">
|
||||
{{ dict.getLabel(colConfig.dict, row[colConfig.prop]) }}
|
||||
</span>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
v-else-if="colConfig.openType"
|
||||
:key="colConfig.id"
|
||||
v-bind="colConfig">
|
||||
<template v-slot="{row}">
|
||||
<ai-open-data :type="colConfig.openType" :openid="row[colConfig.prop]"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
v-else-if="colConfig.type"
|
||||
:key="colConfig.id"
|
||||
v-bind="colConfig"
|
||||
:width="colConfig.width || 100"/>
|
||||
<el-table-column v-else v-bind="colConfig" :key="colConfig.id"
|
||||
:show-overflow-tooltip="colConfig['show-overflow-tooltip'] != false">
|
||||
<template slot-scope="scope">
|
||||
<render-slot v-if="colConfig.render" :render="colConfig.render" :row="scope.row" :index="scope.$index"
|
||||
:column="colConfig"/>
|
||||
<span v-else>{{ getValue(colConfig, scope.row) }}</span>
|
||||
<el-table-column v-else-if="colConfig.type" v-bind="colConfig" :width="colConfig.width||80" align="center"/>
|
||||
<el-table-column v-else v-bind="colConfig">
|
||||
<template slot-scope="{row,$index}">
|
||||
<span v-if="colConfig.dict" :style="{color:colConfig.color||dict.getColor(colConfig.dict, row[colConfig.prop])}" v-text="dict.getLabel(colConfig.dict, row[colConfig.prop])"/>
|
||||
<render-slot v-else-if="colConfig.render" :render="colConfig.render" :row="row" :index="$index" :column="colConfig"/>
|
||||
<el-input v-else-if="colConfig.edit==1" v-model="row[colConfig.prop]" :index="$index"/>
|
||||
<el-input v-else-if="colConfig.num==1" v-model.number="row[colConfig.prop]" :index="$index"/>
|
||||
<ai-select v-else-if="colConfig.select==1" v-model="row[colConfig.prop]" v-bind="colConfig"/>
|
||||
<ai-uploader v-else-if="colConfig.upload==1" v-model="row[colConfig.prop]" v-bind="colConfig"/>
|
||||
<ai-open-data v-else-if="colConfig.openType" :type="colConfig.openType" :openid="row[colConfig.prop]"/>
|
||||
<span v-else>{{ getValue(colConfig, row) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
@@ -88,6 +72,7 @@
|
||||
<script>
|
||||
import moment from 'dayjs'
|
||||
import dict from "../../lib/js/dict"
|
||||
import AiUploader from "./AiUploader.vue";
|
||||
|
||||
export default {
|
||||
name: 'AiTable',
|
||||
@@ -121,6 +106,7 @@ export default {
|
||||
}
|
||||
},
|
||||
components: {
|
||||
AiUploader,
|
||||
renderSlot: {
|
||||
functional: true,
|
||||
props: {
|
||||
|
||||
@@ -70,6 +70,11 @@ export default {
|
||||
|
||||
}
|
||||
|
||||
&.blank {
|
||||
width: 100%;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
&.hasFooter {
|
||||
padding-bottom: 64px;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<div ref="AiSearchBarZone" class="searchLeftZone">
|
||||
<slot name="left"/>
|
||||
</div>
|
||||
<div class="searchRightZone" ref="searchRightZone">
|
||||
<div class="searchRightZone" ref="searchRightZone" v-if="$slots.right">
|
||||
<slot name="right"/>
|
||||
</div>
|
||||
<ai-pull-down v-if="!isSingleRow" v-model="expand"/>
|
||||
@@ -30,14 +30,6 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handlePullDown(style) {
|
||||
this.searchBarStyle = style
|
||||
if (style.height == 'auto') {
|
||||
this.searchBarStyle.marginBottom = '16px'
|
||||
} else {
|
||||
this.searchBarStyle.marginBottom = '0'
|
||||
}
|
||||
},
|
||||
initSize() {
|
||||
this.height = this.$refs?.AiSearchBarZone?.offsetHeight
|
||||
this.rightHeight = this.$refs?.searchRightZone?.offsetHeight + 12
|
||||
|
||||
Reference in New Issue
Block a user