农产品种植档案,生产经营主体档案模块页面开发

This commit is contained in:
郭永超 2025-06-30 17:16:25 +08:00
parent 8ec3db15c5
commit 78a7ef2937
12 changed files with 2436 additions and 20 deletions

View File

@ -2,7 +2,7 @@ import request from '@/utils/axios';
/* 种子种苗需求-列表 */
export function getSeedDemandRecords(params) {
return request('/inputGoods/supervise/provenance/page', {
return request('/inputGoods/demand/provenance/page', {
params,
});
}

View File

@ -7,7 +7,7 @@
<div class="search-bar-left">
<el-form ref="searchForm" :inline="true" :model="formInline" class="demo-form-inline" :label-width="'auto'">
<el-form-item label="关键词" prop="name">
<el-input v-model="formInline.name" placeholder="请输入关键词" clearable />
<el-input v-model="formInline.name" placeholder="请输入关键词" clearable @keyup.enter="onSubmit" />
</el-form-item>
<!-- <el-form-item label="分类" prop="seedTypeId">
<el-select v-model="formInline.seedTypeId" placeholder="请选择" clearable @change="seedTypeChange">

View File

@ -162,16 +162,16 @@ const columns = ref([
{ prop: 'regionName', label: '行政区域名称' },
{ prop: 'gridId', label: '网格编码' },
{ prop: 'gridName', label: '网格名称' },
{ prop: 'landId', label: '地块编码' },
{ prop: 'landNumber', label: '地块编码' },
{ prop: 'landName', label: '地块名称' },
{ prop: 'extent', label: '面积(亩)' },
{ prop: 'provenanceId', label: '种子种苗编号' },
{ prop: 'provenanceName', label: '种子种苗名称' },
{ prop: 'useUnit', label: '规格' },
{ prop: 'useNumber', label: '需求量(件)' },
{ prop: 'useTime', label: '需求时间' },
{ prop: 'businessEntityCode', label: '生产经营主体编码' },
{ prop: 'businessEntityName', label: '生产经营主体名称' },
{ prop: 'area', label: '面积(亩)' },
{ prop: 'seedNumber', label: '种子种苗编号' },
{ prop: 'seedName', label: '种子种苗名称' },
{ prop: 'productSpecification', label: '规格' },
{ prop: 'demandCount', label: '需求量(件)' },
{ prop: 'demandDate', label: '需求时间' },
{ prop: 'subjectName', label: '生产经营主体编码' },
{ prop: 'subjectNumber', label: '生产经营主体名称' },
// { prop: 'action', label: '', slotName: 'action', width: 230, fixed: 'right' },
]);
const handlePaginationChange = ({ page, pageSize }) => {
@ -182,14 +182,14 @@ const handlePaginationChange = ({ page, pageSize }) => {
let landNums = ref(0);
let totalArea = computed(() => {
const sum = selectedRows.value.reduce((sum, item) => {
return sum + Math.round(item.extent * 100);
return sum + Math.round(item.area * 100);
}, 0);
const result = sum / 100;
return parseFloat(result.toFixed(2));
});
let totalSeed = computed(() => {
const sum = selectedRows.value.reduce((sum, item) => {
return sum + Math.round(item.useNumber * 100);
return sum + Math.round(item.productSpecification * 100);
}, 0);
const result = sum / 100;
return parseFloat(result.toFixed(2));

View File

@ -0,0 +1,437 @@
<template>
<div class="app-container">
<div class="container-custom">
<h2 class="custom-h2">种子种苗基本信息档案</h2>
<div ref="searchBarRef" class="search-box">
<div class="search-bar">
<div class="search-bar-left">
<el-form ref="searchForm" :inline="true" :model="formInline" class="demo-form-inline" :label-width="'auto'">
<el-form-item label="关键字" prop="seedName">
<el-input v-model="formInline.seedName" placeholder="请输入姓名" clearable />
</el-form-item>
<el-form-item label="分类" prop="seedTypeId">
<el-select v-model="formInline.seedTypeId" placeholder="请选择" clearable @change="seedTypeChange">
<el-option v-for="item in seedTypeList" :key="item.id" :value="item.id" :label="item.dataName" />
</el-select>
</el-form-item>
<el-form-item label="">
<el-button type="primary" icon="Search" @click="onSubmit">查询</el-button>
<el-button icon="Refresh" @click="resetForm">重置</el-button>
</el-form-item>
</el-form>
</div>
</div>
</div>
<!-- <div class="table-toolbar">
<el-button type="primary" icon="plus" @click="addItem()">新增</el-button>
</div> -->
<div class="table-cont">
<tableComponent
:table-data="tableData"
:columns="columns"
:show-selection="false"
:loading="tableLoading"
:total="tableTotal"
:current-page="formInline.current"
:page-size="formInline.size"
:show-sort="true"
@page-change="handlePaginationChange"
>
<!-- 自定义-操作 -->
<template #action="slotProps">
<el-button type="primary" @click="seeDetails(slotProps.row)">查看</el-button>
<!-- <el-button type="primary" @click="handleEdit(slotProps.row)">编辑</el-button> -->
<!-- <el-button @click="handleDelete(slotProps.row)">删除</el-button> -->
</template>
</tableComponent>
</div>
</div>
<el-dialog v-model="dialogFormVisible" :title="dialogTitle" width="800" :close-on-click-modal="false" align-center>
<el-form
ref="dialogRef"
:model="dialogForm"
:inline="true"
:label-width="'120'"
:rules="dialogFormRules"
:disabled="formDisabled"
class="dialog-form-container"
>
<el-form-item label="种子种苗名称" prop="seedName" class="dialog-form-item">
<el-input v-model="dialogForm.seedName" clearable placeholder="请输入种子种苗名称" />
</el-form-item>
<el-form-item label="品种名称" prop="varietyName" class="dialog-form-item">
<el-input v-model="dialogForm.varietyName" clearable placeholder="请输入品种名称" />
</el-form-item>
<el-form-item label="品牌" prop="brand" class="dialog-form-item">
<el-input v-model="dialogForm.brand" clearable placeholder="请输入品牌" />
</el-form-item>
<el-form-item label="生产厂家" prop="manufacturer" class="dialog-form-item">
<el-input v-model="dialogForm.manufacturer" clearable placeholder="请输入生产厂家" />
</el-form-item>
<el-form-item label="蔬菜种苗" prop="classifyId" class="dialog-form-item">
<el-cascader
v-model="dialogForm.classifyId"
:options="seedTypeDialogList"
:props="cascaderProps"
placeholder="请选择"
@change="handleCascaderChange"
/>
</el-form-item>
<el-form-item label="产品规格" prop="productUnit" class="dialog-form-item">
<el-input v-model="dialogForm.productUnit" clearable placeholder="请输入产品规格" />
</el-form-item>
<div style="display: flex">
<div style="width: 50%; display: inline-block">
<el-form-item label="种子种苗主图" prop="photoUrl" class="dialog-form-item" style="width: 100%">
<FileUploader v-model="dialogForm.photoUrl" :limit="1" />
</el-form-item>
</div>
<div style="width: 50%; display: inline-block">
<el-form-item label="种子种苗详情图" prop="photoUrlDetail" class="dialog-form-item" style="width: 100%">
<FileUploader v-model="dialogForm.photoUrlDetail" :limit="1" />
</el-form-item>
</div>
</div>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button v-if="!formDisabled" type="primary" @click="onSaveCategory">保存</el-button>
<el-button v-if="!formDisabled" @click="cancelDialog">取消</el-button>
<el-button v-else @click="cancelDialog">关闭</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { ref, reactive, computed, onMounted, onBeforeUnmount, nextTick } from 'vue';
import tableComponent from '@/components/tableComponent.vue';
import { ElMessage } from 'element-plus';
import inputSuppliesApi from '@/apis/inputSuppliesApi';
const { getSeedList, seedSave, delSeed, getMaterailTypes } = inputSuppliesApi;
import { useApp } from '@/hooks';
const app = useApp();
import Mock from 'mockjs';
//
const formInline = reactive({
seedName: '',
seedTypeId: '',
current: 1,
size: 10,
});
const searchForm = ref(null);
const onSubmit = () => {
formInline.current = 1;
loadData();
};
const resetForm = () => {
searchForm.value.resetFields();
};
//
const tableData = ref([]);
const selectedIds = ref([]);
const tableLoading = ref(false);
const tableTotal = ref(0);
const columns = ref([
// { prop: 'regionCode', label: '' },
// { prop: 'regionCode', label: '' },
// { prop: 'gridId', label: '' },
// { prop: 'gridName', label: '' },
// { prop: 'landId', label: '' },
// { prop: 'landName', label: '' },
{ prop: 'provenanceId', label: '种子编号' },
{ prop: 'provenanceName', label: '种子种苗名称' },
{ prop: 'varietyName', label: '品种名称' },
{ prop: 'brand', label: '品牌' },
{ prop: 'manufacturer', label: '生产厂家' },
{ prop: 'seedTypeName', label: '分类' },
{ prop: 'productUnit', label: '产品规格' },
{ prop: 'action', label: '操作', slotName: 'action', width: 100, fixed: 'right' },
]);
const handlePaginationChange = ({ page, pageSize }) => {
formInline.current = page;
formInline.size = pageSize;
loadData();
};
const loadData = async () => {
tableLoading.value = true;
try {
let response = await getSeedList(formInline);
tableLoading.value = false;
if (response.code == 200) {
// tableData.value = response.data.records;
// tableTotal.value = response.data.total;
tableData.value = createMockData;
tableTotal.value = createMockData.length;
}
} catch (error) {
tableLoading.value = false;
console.error(error);
}
};
const createMockData = Mock.mock({
'list|5': [
{
'provenanceId|+1': 10000, //
provenanceName: '@ctitle(3, 5)种子', //
varietyName: '@ctitle(2, 4)品种', //
brand: '@ctitle(2, 3)牌', //
manufacturer: '@province@cword("公司", 1)', //
seedTypeName: '@pick(["蔬菜种子", "花卉种苗", "果树苗木"])', //
productUnit: '@pick(["50克/袋", "100粒/包", "20株/盒", "5公斤/箱"])', //
},
],
}).list;
const extractThirdLevelChildren = (dataArray) => {
let result = [];
//
for (const level1 of dataArray) {
// children
if (level1.children && Array.isArray(level1.children)) {
//
for (const level2 of level1.children) {
// children
if (level2.children && Array.isArray(level2.children)) {
//
result.push(...level2.children);
}
}
}
}
return result;
};
const seedTypeChange = () => {
console.log(formInline.seedTypeId);
//
};
const dialogFormVisible = ref(false);
const dialogRef = ref(null);
const dialogTitle = ref('新增');
const formDisabled = ref(false);
const dialogForm = reactive({
id: '',
seedName: '', //
varietyName: '', //
brand: '', //
manufacturer: '', //
classifyId: '', //id
classifyName: '', //
productSpecification: '', //number
productUnit: '', //
productAttributes: '', //
photoUrl: '', //
photoUrlDetail: '', //
});
const dialogFormRules = ref({
seedName: [{ required: true, message: '请输入种子种苗名称', trigger: 'blur' }],
varietyName: [{ required: true, message: '请输入品种名称', trigger: 'blur' }],
brand: [{ required: true, message: '请输入品牌', trigger: 'blur' }],
manufacturer: [{ required: true, message: '请输入品牌', trigger: 'blur' }],
classifyId: [
{
required: true,
message: '请选择蔬菜种苗',
trigger: ['change', 'blur'],
},
],
productUnit: [{ required: true, message: '请输入产品规格', trigger: 'blur' }],
});
//
const addItem = async () => {
restDialogForm();
dialogTitle.value = '新增';
formDisabled.value = false;
dialogFormVisible.value = true;
};
//
const seeDetails = async (row) => {
dialogTitle.value = '详情';
setDialogForm(row);
formDisabled.value = true;
dialogFormVisible.value = true;
};
//
const handleEdit = (row) => {
console.log('要编辑的行: ', row);
dialogTitle.value = '编辑';
setDialogForm(row);
formDisabled.value = false;
dialogFormVisible.value = true;
};
const setDialogForm = (row) => {
dialogForm.id = row.id;
dialogForm.seedName = row.seedName;
dialogForm.varietyName = row.varietyName;
dialogForm.brand = row.brand;
dialogForm.manufacturer = row.manufacturer;
dialogForm.classifyId = row.classifyId;
dialogForm.classifyName = row.classifyName;
dialogForm.productSpecification = row.productSpecification;
dialogForm.productUnit = row.productUnit;
dialogForm.productAttributes = row.productAttributes;
dialogForm.photoUrl = row.photoUrl;
dialogForm.photoUrlDetail = row.photoUrlDetail;
};
//
const handleDelete = (row) => {
app
.$confirm(`删除后信息将不可查看,确认要删除吗?`, '确定删除', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
deleteGoods(row.id)
.then((res) => {
if (res.code === 200) {
onSubmit();
app.$message.success('删除成功!');
}
})
.catch((err) => {
app.$message.error(err.msg);
});
})
.catch(() => {});
};
const deleteGoods = async (ids) => {
try {
let res = await delSeed(ids);
return res;
} catch (error) {
return false;
}
};
const onSaveCategory = () => {
console.log(dialogForm);
dialogRef.value.validate(async (valid, fields) => {
if (valid) {
try {
let param = { ...dialogForm };
param.classifyId = dialogForm.classifyId.join(',');
param.classifyName = dialogForm.classifyName.join(',');
console.log(param);
let response;
if (dialogTitle.value == '新增') {
response = await seedSave(param);
} else {
response = await seedSave(param);
}
if (response.code == 200) {
cancelDialog();
onSubmit();
if (dialogTitle.value == '新增') {
ElMessage.success('新增成功!');
} else {
ElMessage.success('编辑成功!');
}
} else {
ElMessage.error(response.msg);
}
} catch (error) {
console.error(error);
}
}
});
};
const cancelDialog = async () => {
restDialogForm();
dialogFormVisible.value = false;
};
const restDialogForm = () => {
Object.assign(dialogForm, {
id: '',
seedName: '', //
varietyName: '', //
brand: '', //
manufacturer: '', //
classifyId: '', //id
classifyName: '', //
productSpecification: '', //number
productUnit: '', //
productAttributes: '', //
photoUrl: '', //
photoUrlDetail: '', //
});
};
const seedTypeList = ref([]);
const seedTypeDialogList = ref([]);
const getSeedTypeList = async () => {
try {
let response = await getMaterailTypes({ moduleType: '4' });
console.log(response);
if (response.code == 200) {
if (response.data?.length > 0) {
seedTypeDialogList.value = response.data[0].children;
let result = extractThirdLevelChildren(response.data);
seedTypeList.value = result;
console.log(seedTypeDialogList.value);
}
}
} catch (error) {
console.error(error);
}
};
//
const cascaderProps = ref({
label: 'dataName', //
value: 'id', //
children: 'children', //
emitPath: true,
expandTrigger: 'hover',
});
const handleCascaderChange = () => {
const selectedNames = getSelectedNames(dialogForm.classifyId);
console.log('对应的名称:', selectedNames); // : ['', '']
//
dialogForm.classifyName = selectedNames;
};
const getSelectedNames = (ids) => {
if (!ids || !ids.length) return [];
let names = [];
let currentLevel = seedTypeDialogList.value;
for (const id of ids) {
const foundItem = currentLevel.find((item) => item.id === id);
if (!foundItem) break;
names.push(foundItem.dataName);
currentLevel = foundItem.children || [];
}
return names;
};
onMounted(() => {
onSubmit();
getSeedTypeList();
});
</script>
<style lang="scss" scoped>
.dialog-form-item {
:deep(.el-upload--picture-card) {
width: 100px;
height: 100px;
}
:deep(.file-uploader__upload) {
width: 100px;
height: 100px;
}
:deep(.el-upload-list__item) {
width: 100px;
height: 100px;
}
}
</style>

View File

@ -1,9 +1,479 @@
<template>
<div></div>
<div class="app-container">
<div class="container-custom">
<h2 class="custom-h2">种子种苗使用档案</h2>
<div ref="searchBarRef" class="search-box">
<div class="search-bar">
<div class="search-bar-left">
<el-form ref="searchForm" :inline="true" :model="formInline" class="demo-form-inline" :label-width="'auto'">
<el-form-item label="关键词" prop="name">
<el-input v-model="formInline.name" placeholder="请输入关键词" clearable />
</el-form-item>
<!-- <el-form-item label="分类" prop="seedTypeId">
<el-select v-model="formInline.seedTypeId" placeholder="请选择" clearable @change="seedTypeChange">
<el-option v-for="item in seedTypeList" :key="item.id" :value="item.id" :label="item.dataName" />
</el-select>
</el-form-item> -->
<el-form-item label="">
<el-button type="primary" icon="Search" @click="onSubmit">查询</el-button>
<el-button icon="Refresh" @click="resetForm">重置</el-button>
</el-form-item>
</el-form>
</div>
</div>
</div>
<div class="table-toolbar">
<el-button type="primary" icon="plus" @click="addItem()">新增</el-button>
</div>
<div class="table-cont">
<tableComponent
:table-data="tableData"
:columns="columns"
:show-selection="false"
:loading="tableLoading"
:total="tableTotal"
:current-page="formInline.current"
:page-size="formInline.size"
:show-sort="false"
@page-change="handlePaginationChange"
>
<!-- 自定义-操作 -->
<template #action="slotProps">
<el-button type="primary" @click="seeDetails(slotProps.row)">查看</el-button>
<!-- <el-button type="primary" @click="handleEdit(slotProps.row)">编辑</el-button> -->
<!-- <el-button @click="handleDelete(slotProps.row)">删除</el-button> -->
</template>
</tableComponent>
</div>
</div>
<el-dialog v-model="dialogFormVisible" :title="dialogTitle" width="800" :close-on-click-modal="false" align-center>
<el-form :inline="true" :label-width="'auto'">
<LandSelect ref="landSelectRef" v-model="dialogForm.landId" :options="landSelectList" :disabled="formDisabled" @change="handleLandChange" />
</el-form>
<el-descriptions title="地块信息" border class="mb-20 custom-descriptions" :column="2">
<el-descriptions-item label="行政区域编码">{{ dialogForm.regionCode }}</el-descriptions-item>
<el-descriptions-item label="行政区域名称">{{ dialogForm.regionName }}</el-descriptions-item>
<el-descriptions-item label="网格编码">{{ dialogForm.gridId }}</el-descriptions-item>
<el-descriptions-item label="网格名称">{{ dialogForm.gridName }}</el-descriptions-item>
<el-descriptions-item label="地块编码">{{ dialogForm.landId }}</el-descriptions-item>
<el-descriptions-item label="地块名称">{{ dialogForm.landName }}</el-descriptions-item>
</el-descriptions>
<el-descriptions title="经营主体信息" border class="mb-20 custom-descriptions" :column="2">
<el-descriptions-item label="经营主体编码">{{ dialogForm.businessEntityCode }}</el-descriptions-item>
<el-descriptions-item label="经营主体名称">{{ dialogForm.businessEntityName }}</el-descriptions-item>
</el-descriptions>
<el-form
ref="dialogRef"
:model="dialogForm"
:inline="true"
:label-width="'120'"
:rules="dialogFormRules"
:disabled="formDisabled"
class="dialog-form-container"
>
<div class="el-descriptions__title" style="margin-bottom: 16px">使用信息</div>
<el-form-item label="种子种苗编号" prop="provenanceId" class="dialog-form-item">
<el-input v-model="dialogForm.provenanceId" clearable placeholder="请输入种子种苗编号" />
</el-form-item>
<el-form-item label="种子种苗名称" prop="provenanceName" class="dialog-form-item">
<el-input v-model="dialogForm.provenanceName" clearable placeholder="请输入种子种苗名称" />
</el-form-item>
<el-form-item label="使用量" required prop="useNumber" class="dialog-form-item">
<el-input-number v-model="dialogForm.useNumber" :min="1" controls-position="right" placeholder="请输入使用量" style="width: 150px" />
<el-select v-model="dialogForm.useUnit" placeholder="请选择" style="width: 80px">
<el-option v-for="el in unitList" :key="el.dictValue" :value="el.dictValue" :label="el.dictValue" />
</el-select>
</el-form-item>
<el-form-item label="使用时间" prop="detectionTime" class="dialog-form-item">
<el-date-picker v-model="dialogForm.detectionTime" :clearable="false" type="date" value-format="YYYY-MM-DD" placeholder="请选择使用时间" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button v-if="!formDisabled" type="primary" @click="onSaveCategory">保存</el-button>
<el-button v-if="!formDisabled" @click="cancelDialog">取消</el-button>
<el-button v-else @click="cancelDialog">关闭</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { ref, watch, onMounted, computed } from 'vue';
</script>
import { ref, reactive, computed, onMounted, onBeforeUnmount, nextTick } from 'vue';
import tableComponent from '@/components/tableComponent.vue';
import LandSelect from '@/components/LandSelect.vue';
import { ElMessage } from 'element-plus';
import inputSuppliesApi from '@/apis/inputSuppliesApi';
const { getMaterailTypes } = inputSuppliesApi;
import {
getSeedUseRegulatoryRecords,
seedUseRegulatorySave,
editSeedUseRegulatory,
delSeedUseRegulatory,
getLandList,
} from '@/apis/inputSuppliesApi/supervisionOfInputs';
import request from '@/utils/axios';
import { GetDictTypeInfo } from '@/apis/system/dictType';
import { useApp } from '@/hooks';
const app = useApp();
<style scoped lang="scss"></style>
//
const formInline = reactive({
name: '',
seedTypeId: '',
current: 1,
size: 10,
});
const searchForm = ref(null);
const onSubmit = () => {
formInline.current = 1;
loadData();
};
const resetForm = () => {
searchForm.value.resetFields();
};
//
const tableData = ref([]);
const selectedIds = ref([]);
const tableLoading = ref(false);
const tableTotal = ref(0);
const columns = ref([
{ prop: 'landName', label: '地块名称' },
{ prop: 'regionCode', label: '所属行政区划' },
{ prop: 'gridName', label: '所属网格' },
{ prop: 'name', label: '姓名' },
{ prop: 'phone', label: '联系方式' },
{ prop: 'provenanceId', label: '种子编号' },
{ prop: 'provenanceName', label: '种子种苗名称' },
{ prop: 'useNumber', label: '使用量' },
{ prop: 'useTime', label: '使用时间' },
{ prop: 'action', label: '操作', slotName: 'action', width: 100, fixed: 'right' },
]);
const handlePaginationChange = ({ page, pageSize }) => {
formInline.current = page;
formInline.size = pageSize;
loadData();
};
const loadData = async () => {
tableLoading.value = true;
try {
let response = await getSeedUseRegulatoryRecords(formInline);
tableLoading.value = false;
if (response.code == 200) {
tableData.value = response.data.records;
tableTotal.value = response.data.total;
}
} catch (error) {
tableLoading.value = false;
console.error(error);
}
};
const extractThirdLevelChildren = (dataArray) => {
let result = [];
//
for (const level1 of dataArray) {
// children
if (level1.children && Array.isArray(level1.children)) {
//
for (const level2 of level1.children) {
// children
if (level2.children && Array.isArray(level2.children)) {
//
result.push(...level2.children);
}
}
}
}
return result;
};
const seedTypeChange = () => {
console.log(formInline.seedTypeId);
//
};
const dialogFormVisible = ref(false);
const dialogRef = ref(null);
const dialogTitle = ref('新增');
const formDisabled = ref(false);
const landSelectRef = ref(null);
const nowSelectRow = ref({});
const dialogForm = reactive({
regionCode: '', //
regionName: '', //
gridId: '', //
gridName: '', //
landId: '', //id
landName: '', //
name: '', //
phone: '', //
provenanceId: '', //id
provenanceName: '', //
useNumber: 1, //使
useUnit: 'g', //使
detectionTime: '', //使
businessEntityCode: '', //
businessEntityName: '', //
});
const dialogFormRules = ref({
provenanceId: [{ required: true, message: '请输入种子种苗编号', trigger: 'blur' }],
provenanceName: [{ required: true, message: '请输入种子种苗名称', trigger: 'blur' }],
useNumber: [{ required: true, message: '请输入使用量', trigger: ['change', 'blur'] }],
detectionTime: [{ required: true, message: '请选择使用时间', trigger: 'blur' }],
});
const addItem = async () => {
// ElMessage.success('!');
restDialogForm();
dialogTitle.value = '新增';
formDisabled.value = false;
dialogFormVisible.value = true;
};
const seeDetails = async (row) => {
// ElMessage.success('!');
dialogTitle.value = '详情';
console.log(row);
formDisabled.value = true;
dialogForm.landId = row.landId;
getDetails();
dialogForm.provenanceId = row.provenanceId;
dialogForm.provenanceName = row.provenanceName;
dialogForm.useNumber = row.useNumber;
dialogForm.useUnit = row.useUnit;
dialogForm.detectionTime = row.useTime;
dialogFormVisible.value = true;
};
const handleEdit = (row) => {
// ElMessage.success('!');
nowSelectRow.value = row;
dialogTitle.value = '编辑';
console.log(row);
formDisabled.value = false;
dialogForm.landId = row.landId;
getDetails();
dialogForm.provenanceId = row.provenanceId;
dialogForm.provenanceName = row.provenanceName;
dialogForm.useNumber = row.useNumber;
dialogForm.useUnit = row.useUnit;
dialogForm.detectionTime = row.useTime;
dialogFormVisible.value = true;
};
//
const getDetails = async () => {
let response = await request({
url: `/land-resource/landManage/getLandInfo?landId=${dialogForm.landId}`,
});
console.log(response);
if (response.code == 200) {
if (response.data) {
setDialogForm(response.data);
} else {
ElMessage.error('未查询到数据');
}
} else {
ElMessage.error(response.message);
}
};
const setDialogForm = (row) => {
dialogForm.regionCode = row.gridAreaCode;
dialogForm.regionName = row.fullRegionName;
dialogForm.gridId = row.gridId;
dialogForm.gridName = row.gridName;
dialogForm.landId = row.id;
dialogForm.landName = row.landName;
dialogForm.name = row.propertyName;
dialogForm.phone = row.propertyPhone;
dialogForm.businessEntityCode = row.businessEntityCode ?? '';
dialogForm.businessEntityName = row.businessEntityName ?? '';
};
const handleDelete = (row) => {
console.log('删除操作: ', row);
app
.$confirm(`删除后信息将不可查看,确认要删除吗?`, '确定删除', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
deleteGoods(row.id)
.then((res) => {
if (res.code === 200) {
onSubmit();
app.$message.success('删除成功!');
}
})
.catch((err) => {
app.$message.error(err.msg);
});
})
.catch(() => {});
};
const deleteGoods = async (ids) => {
try {
let res = await delSeedUseRegulatory(ids);
return res;
} catch (error) {
return false;
}
};
const onSaveCategory = () => {
console.log(dialogForm);
if (dialogForm.landId == '') {
landSelectRef.value.handleChange();
return;
}
dialogRef.value.validate(async (valid, fields) => {
if (valid) {
try {
let param = { ...dialogForm };
param.useTime = dialogForm.detectionTime;
console.log(param);
// valid.businessEntityCode = dialogForm.businessEntityCode; //
// valid.businessEntityName = dialogForm.businessEntityName; //
let response;
if (dialogTitle.value == '新增') {
response = await seedUseRegulatorySave(param);
} else {
param.id = nowSelectRow.value.id;
response = await editSeedUseRegulatory(param);
}
if (response.code == 200) {
cancelDialog();
onSubmit();
if (dialogTitle.value == '新增') {
ElMessage.success('新增成功!');
} else {
ElMessage.success('编辑成功!');
}
} else {
ElMessage.error(response.msg);
}
} catch (error) {
console.error(error);
}
}
});
};
const cancelDialog = async () => {
restDialogForm();
dialogFormVisible.value = false;
};
const restDialogForm = () => {
Object.assign(dialogForm, {
regionCode: '', //
regionName: '', //
gridId: '', //
gridName: '', //
landId: '', //id
landName: '', //
name: '', //
phone: '', //
provenanceId: '', //id
provenanceName: '', //
useNumber: 1, //使
useUnit: 'g', //使
useTime: '', //使
businessEntityCode: '', //
businessEntityName: '', //
});
nowSelectRow.value = ref({});
};
const seedTypeList = ref([]);
const seedTypeDialogList = ref([]);
const getSeedTypeList = async () => {
try {
let response = await getMaterailTypes({ moduleType: '4' });
console.log(response);
if (response.code == 200) {
if (response.data?.length > 0) {
seedTypeDialogList.value = response.data[0].children;
let result = extractThirdLevelChildren(response.data);
seedTypeList.value = result;
console.log(seedTypeDialogList.value);
}
}
} catch (error) {
console.error(error);
}
};
const unitList = ref([
{ dictCode: '52', dictValue: 'g' },
{ dictCode: '53', dictValue: 'kg' },
]);
const landSelectList = ref([]);
const getLandsList = async () => {
let res = await getLandList();
if (res.code == 200) {
landSelectList.value = res.data;
}
};
const handleLandChange = (val) => {
console.log(val);
if (val) {
getDetails();
} else {
restDialogForm();
}
};
const getEntityOptions = async () => {
let res = await GetDictTypeInfo('sys_use_supervise_number');
console.log(res);
if (res.code == 200) {
unitList.value = res.data;
} else {
unitList.value = [
{ dictCode: '52', dictValue: 'g' },
{ dictCode: '53', dictValue: 'kg' },
];
}
};
onMounted(() => {
onSubmit();
getLandsList();
getEntityOptions();
// getSeedTypeList();
});
</script>
<style lang="scss" scoped>
.dialog-form-item {
:deep(.el-upload--picture-card) {
width: 100px;
height: 100px;
}
:deep(.file-uploader__upload) {
width: 100px;
height: 100px;
}
:deep(.el-upload-list__item) {
width: 100px;
height: 100px;
}
}
/* 必须使用深度选择器 + 精确DOM层级 */
.custom-descriptions :deep(.el-descriptions__body) table.el-descriptions__table {
table-layout: fixed; /* 关键属性1强制等宽 */
width: 100%;
}
.custom-descriptions :deep(.el-descriptions__label) {
width: 130px !important; /* 关键属性2固定宽度 */
min-width: 130px !important;
max-width: 130px !important;
background: #f5f7fa;
font-weight: bold;
text-align: left;
padding-right: 20px;
}
.custom-descriptions :deep(.el-descriptions__content) {
width: calc(100% - 130px) !important; /* 自动填充剩余空间 */
word-break: break-word;
}
</style>

View File

@ -0,0 +1,137 @@
<template>
<section class="custom_attrs_upload_content_lx" :style="{ '--columns': props.fileNum }">
<el-upload
v-if="props.type != 'view'"
class="custom-form__uploader"
action=""
:show-file-list="false"
:accept="props.accept"
:limit="props.limit"
:http-request="rowUploadPicture"
:disabled="attrs_.length >= props.limit"
>
<el-icon class="custom-form__uploader__icon"><Plus /></el-icon>
</el-upload>
<div v-for="item in attrs_" :key="`attr_${item.uid}`" class="attrs_content__item">
<video v-if="isMP4(item.url)" :src="item.url" controls />
<img v-else :src="item.url" :alt="item.name" @click="handlePreview(i)" />
<el-icon v-if="props.type != 'view'" class="clear_btn" @click="handleClearAttr(item.uid)"><CircleCloseFilled /></el-icon>
</div>
<el-image-viewer v-if="previewShow" :url-list="srcList" :initial-index="index" @close="previewShow = false" />
</section>
</template>
<script setup>
import { nextTick, ref, watch } from 'vue';
import { CommonUpload } from '@/apis';
const emit = defineEmits(['update:attrs']);
const props = defineProps({
accept: {
type: String,
default: 'image/*',
},
type: {
type: String,
default: 'view',
},
attrs: {
type: Array,
default: () => [],
},
limit: {
type: Number,
default: 20,
},
fileNum: {
type: Number,
default: 4,
},
});
const attrs_ = ref([]);
const srcList = ref([]);
srcList.value = attrs_.value.map((item) => item.url);
watch(
() => props.attrs,
(val) => {
attrs_.value = val;
},
{ deep: true, immediate: true }
);
const index = ref(0);
const previewShow = ref(false);
function handleClearAttr(uid) {
attrs_.value = attrs_.value.filter((item) => item.uid !== uid);
emit('update:attrs', attrs_.value);
}
async function rowUploadPicture({ file }) {
const formData = new FormData();
formData.append('file', file);
const res = await CommonUpload(formData);
if (res.code === 200) {
attrs_.value.push({
...res.data,
uid: 'id_' + Date.now(),
});
emit('update:attrs', attrs_.value);
}
}
function isMP4(filePath) {
// 使 .mp4
const regex = /\.mp4$/i;
return regex.test(filePath);
}
function handlePreview(i) {
previewShow.value = false;
nextTick(() => {
index.value = i;
previewShow.value = true;
});
}
</script>
<style lang="scss">
.custom_attrs_upload_content_lx {
display: grid;
flex-wrap: wrap;
grid-template-columns: repeat(var(--columns), 1fr);
box-sizing: border-box;
gap: 20px;
> div {
width: 100%;
height: 100%;
aspect-ratio: 1 / 1;
box-sizing: border-box;
}
.attrs_content__item {
aspect-ratio: 1 / 1;
box-sizing: border-box;
position: relative;
padding: 6px;
border: 1px solid #ccc;
border-radius: 4px;
img,
video {
vertical-align: middle;
width: 100%;
height: 100%;
border-radius: 2px;
}
.clear_btn {
position: absolute;
right: 0px;
top: 0px;
font-size: 18px;
color: #f15c5c;
opacity: 0;
cursor: pointer;
background-color: #fff;
border-radius: 50%;
}
&:hover {
.clear_btn {
opacity: 1;
}
}
}
}
</style>

View File

@ -0,0 +1,71 @@
<template>
<el-form :model="localForm" label-width="120px" :disabled="readonly">
<h3>经营主体信息</h3>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="农企/合作社名称">
<el-input v-model="localForm.businessName" placeholder="请输入" />
</el-form-item>
<el-form-item label="面积">
<el-input v-model="localForm.area" placeholder="请输入" />
</el-form-item>
<el-form-item label="联系人">
<el-input v-model="localForm.contactPerson" placeholder="请输入" />
</el-form-item>
<el-form-item label="农企/合作社照片">
<FileUploader v-model="localForm.cooperativePhoto" :limit="1" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="地址">
<area-select v-model="localForm.addressArr" :disabled="readonly" :label="null" />
<!-- <el-cascader v-model="localForm.addressArr" :options="options" @change="handleChange" /> -->
</el-form-item>
<el-form-item label="经营产品">
<el-input v-model="localForm.primaryProduct" placeholder="请输入" />
</el-form-item>
<el-form-item label="联系电话">
<el-input v-model="localForm.phone" placeholder="请输入" />
</el-form-item>
</el-col>
</el-row>
<h3>证件资料</h3>
<el-row :gutter="20">
<el-col :span="24">
<el-form-item label="营业执照">
<FileUploader v-model="localForm.businessLicence" :limit="1" />
</el-form-item>
</el-col>
</el-row>
</el-form>
</template>
<script setup>
import { ref, toRefs, reactive, watch } from 'vue';
const props = defineProps({
modelValue: {
type: Object,
required: true,
default: () => ({}),
},
readonly: Boolean,
});
const emit = defineEmits(['update:modelValue']);
const { modelValue: localForm } = toRefs(props);
</script>
<style scoped lang="scss">
h3 {
margin-top: 20px;
margin-bottom: 20px;
font-size: 16px;
font-weight: 500;
color: #333333;
width: 110px;
text-align: right;
}
</style>

View File

@ -0,0 +1,165 @@
<template>
<div class="tab-business">
<el-form :model="localForm" label-width="0">
<el-row :gutter="24">
<!-- 负债表 -->
<el-col :span="8">
<h3>负债表</h3>
<!-- <el-upload
class="upload-btn"
action="#"
:auto-upload="false"
:file-list="localForm.debtFiles"
:before-upload="(file) => handleImport('debt', file)"
:disabled="readonly"
>
<el-icon><Plus /></el-icon>
<el-button size="small" :disabled="readonly">导入表格</el-button>
</el-upload> -->
<div class="view-file"></div>
<div class="upload-btn">
<el-button type="primary" :disabled="readonly">导入表格</el-button>
<el-button type="success" @click="downloadTemplate('debt')"> 下载模板 </el-button>
</div>
</el-col>
<!-- 利润表 -->
<el-col :span="8">
<h3>利润表</h3>
<!-- <el-upload
class="upload-btn"
action="#"
:auto-upload="false"
:file-list="localForm.profitFiles"
:before-upload="(file) => handleImport('profit', file)"
:disabled="readonly"
>
<el-button size="small" :disabled="readonly">导入表格</el-button>
</el-upload> -->
<div class="view-file"></div>
<div class="upload-btn">
<el-button type="primary" :disabled="readonly">导入表格</el-button>
<el-button type="success" @click="downloadTemplate('profit')"> 下载模板 </el-button>
</div>
</el-col>
<!-- 现金流量表 -->
<el-col :span="8">
<h3>现金流量表</h3>
<!-- <el-upload
class="upload-btn"
action="#"
:auto-upload="false"
:file-list="localForm.cashflowFiles"
:before-upload="(file) => handleImport('cashflow', file)"
:disabled="readonly"
>
<el-button size="small" :disabled="readonly">导入表格</el-button>
</el-upload> -->
<div class="view-file"></div>
<div class="upload-btn">
<el-button type="primary" :disabled="readonly">导入表格</el-button>
<el-button type="success" @click="downloadTemplate('cashflow')"> 下载模板 </el-button>
</div>
</el-col>
</el-row>
</el-form>
</div>
</template>
<script setup>
import { reactive, watch } from 'vue';
import { Plus } from '@element-plus/icons-vue';
import cloneDeep from 'lodash/cloneDeep';
import { useCoop } from '@/store/modules/coop';
// const localForm = useCoop().$state.data;
const props = defineProps({
modelValue: {
type: Object,
default: () => ({}),
},
readonly: {
type: Boolean,
default: false,
},
});
const emit = defineEmits(['update:modelValue']);
//
const localForm = reactive(cloneDeep(props.modelValue));
// watch
watch(
() => localForm,
(val) => {
emit('update:modelValue', { ...val });
},
{ deep: true }
);
// watch(
// () => props.modelValue,
// (newVal) => {
// Object.assign(localForm, cloneDeep(newVal));
// },
// { deep: true }
// );
//
function downloadTemplate(type) {
let url = '';
switch (type) {
case 'debt':
url = '/templates/debt-template.xlsx';
break;
case 'profit':
url = '/templates/profit-template.xlsx';
break;
case 'cashflow':
url = '/templates/cashflow-template.xlsx';
break;
}
//
window.open(url, '_blank');
}
//
function handleImport(type, file) {
const key = type + 'Files'; // debtFiles / profitFiles / cashflowFiles
//
localForm[key] = [file];
//
return false;
}
</script>
<style scoped>
h3 {
margin-top: 20px;
margin-bottom: 20px;
font-size: 16px;
font-weight: 500;
color: #606266;
width: 100%;
text-align: center;
}
.upload-btn {
margin: 20px 0;
display: flex;
justify-content: space-around;
}
.business-footer el-button + el-button {
margin-left: 8px;
}
.view-file {
height: 400px;
border: 1px solid #dcdfe6;
border-radius: 4px;
margin-bottom: 10px;
display: flex;
align-items: center;
justify-content: center;
color: #909399;
}
</style>

View File

@ -0,0 +1,78 @@
<template>
<el-form :model="localForm" label-width="160px" :disabled="readonly">
<div class="credit-evaluation">
<h3>信用评级</h3>
<el-form-item label="信用评价">
<el-rate v-model="localForm.creditEvaluation" show-score score-template="{value} 分" />
</el-form-item>
<el-form-item label="带动周边农户">
<el-rate v-model="localForm.supportedFarmers" show-score score-template="{value} 分" />
</el-form-item>
<el-form-item label="社会效益">
<el-rate v-model="localForm.socialImpact" show-score score-template="{value} 分" />
</el-form-item>
<el-form-item label="高新技术应用">
<el-rate v-model="localForm.techApplication" show-score score-template="{value} 分" />
</el-form-item>
<el-form-item label="产品质量及服务保障">
<el-rate v-model="localForm.productQuality" show-score score-template="{value} 分" />
</el-form-item>
</div>
</el-form>
</template>
<script setup>
import { toRefs, watch } from 'vue';
const props = defineProps({
modelValue: {
type: Object,
required: true,
default: () => ({}),
},
readonly: Boolean,
});
const emit = defineEmits(['update:modelValue']);
//
const { modelValue: localForm } = toRefs(props);
//
// watch(
// localForm,
// (newVal) => {
// emit('update:modelValue', { ...newVal });
// },
// { deep: true }
// );
</script>
<style scoped lang="scss">
.credit-evaluation {
width: 600px;
margin: 0 auto;
display: flex;
flex-direction: column;
gap: 20px;
.el-rate {
font-size: 16px;
color: #f90;
}
}
h3 {
margin-top: 20px;
margin-bottom: 20px;
font-size: 16px;
font-weight: 500;
color: #333333;
width: 110px;
text-align: right;
}
</style>

View File

@ -0,0 +1,336 @@
<template>
<div>
<avue-crud ref="crudRef" v-model:page="pageData" :data="crudData" :option="crudOptions" :table-loading="loading">
<template #menu-left>
<el-button type="primary" icon="Plus" @click="handleAdd">新增</el-button>
</template>
<template #menu="scope">
<custom-table-operate :actions="crudOptions.actions" :data="scope" />
</template>
</avue-crud>
<el-dialog :key="dialogTitle" v-model="dialogVisible" :title="dialogTitle" width="60%" append-to-body>
<el-form :model="formData" label-width="120px" class="custom-form" :disabled="isReadonly">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="姓名" prop="name">
<el-input v-model="formData.name" placeholder="请输入姓名" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="证件类型" prop="idType">
<el-select v-model="formData.idType" placeholder="请选择证件类型" disabled>
<el-option label="身份证" value="101" />
<el-option label="护照" value="2" />
<el-option label="港澳身份证" value="3" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="证件号码" prop="idCard">
<el-input v-model="formData.idCard" placeholder="请输入证件号码" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="性别" prop="sex">
<el-radio-group v-model="formData.sex">
<el-radio label="1"></el-radio>
<el-radio label="0"></el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="年龄" prop="age">
<el-input v-model="formData.age" placeholder="请输入年龄" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="联系方式" prop="phone">
<el-input v-model="formData.phone" placeholder="请输入联系方式" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="居住地行政区划" prop="addressArr">
<area-select v-model="formData.addressArr" :label="null" />
<!-- <el-input v-model="formData.detailAddress" placeholder="请选择居住地行政区划" /> -->
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="具体地址" prop="detailAddress">
<el-input v-model="formData.detailAddress" placeholder="请输入具体地址" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="种植面积" prop="area">
<el-input v-model="formData.area" placeholder="请输入种植面积" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="种植作物" prop="planCrop">
<!-- <el-select v-model="formData.planCrop" placeholder="种植作物" style="width: 380px" :clearable="true">
<el-option v-for="item in cropsOptions" :key="item.id" :label="item.cropsName" :value="item.id" />
</el-select> -->
<url-select
v-model="formData.planCrop"
url="/land-resource/crops/page"
:params="{ status: '0' }"
label-key="cropsName"
value-key="id"
placeholder="请选择种植作物"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button v-if="!isReadonly" type="primary" @click="handleSave">保存</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { ref, reactive, watch, onMounted, computed } from 'vue';
import { CRUD_OPTIONS } from '@/config';
import { ElMessageBox, ElMessage } from 'element-plus';
import { getMemberList, addMember, updateMember, deleteMembers } from '@/apis/businessEntity';
// import { useCoop } from '../../../../store/modules/coop';
// const defaultFormData = useCoop().$state.data;
const props = defineProps({
entId: {
type: String,
required: true,
},
});
const dialogTitle = ref('新增');
const dialogVisible = ref(false);
const isReadonly = ref(false);
const loading = ref(false);
const crudRef = ref();
//
const pageData = ref({
currentPage: 1,
pageSize: 10,
total: 0,
});
const searchForm = ref({
entId: props.entId,
userId: '',
});
const crudData = ref([]);
//
const defaultFormData = {
id: '',
entId: '',
name: '',
idType: '101',
idCard: '',
sex: '1',
age: '',
phone: '',
provinceCode: '', //
cityCode: '', //
countyCode: '', //
townCode: '', //
street: '', //
addressArr: [],
detailAddress: '',
area: '',
planCrop: '',
planCropName: '',
address: '',
createTime: '',
createUser: '',
updateTime: '',
updateUser: '',
};
// 使
const formData = ref({ ...defaultFormData });
const resetForm = () => {
formData.value = { ...defaultFormData };
};
const crudOptions = reactive({
...CRUD_OPTIONS,
addBtn: false,
searchBtn: false,
emptyBtn: false,
refreshBtn: false,
column: [
{ label: '姓名', prop: 'name' },
{
label: '证件类型',
prop: 'idType',
formatter: (row, column, cellValue) => {
return cellValue === '101' ? '身份证' : cellValue === '2' ? '护照' : cellValue === '3' ? '港澳身份证' : '';
},
},
{ label: '证件号码', prop: 'idCardEncrypt' },
{
label: '性别',
prop: 'sex',
formatter: (row, column, cellValue) => {
return cellValue === '1' ? '男' : cellValue === '0' ? '女' : '';
},
},
{ label: '年龄', prop: 'age' },
{ label: '联系方式', prop: 'phone' },
{ label: '居住地行政区划', prop: 'address' },
{ label: '种植作物', prop: 'planCropName' },
],
actions: [
{
name: '查看',
icon: 'view',
event: ({ row }) => handleView(row),
},
{
name: '编辑',
icon: 'edit',
event: ({ row }) => handleEdit(row),
},
{
type: 'danger',
name: '删除',
icon: 'delete',
event: ({ row }) => handleDelete(row),
},
],
});
const syncAddressToForm = () => {
const arr = formData.value.addressArr || [];
[formData.value.provinceCode, formData.value.cityCode, formData.value.countyCode, formData.value.townCode, formData.value.villageCode] = arr;
};
async function getData() {
loading.value = true;
try {
const params = {
// ...searchForm.value,
entId: props.entId,
current: pageData.value.currentPage,
size: pageData.value.pageSize,
};
if (!props.entId) {
return;
}
const response = await getMemberList(params);
if (response.code === 200 && response.data) {
crudData.value = response.data.records;
console.log('获取数据成功:', crudData.value);
pageData.value = {
currentPage: response.data.current,
pageSize: response.data.size,
total: response.data.total,
};
} else {
ElMessage.error(response.msg || '获取数据失败');
}
} catch (error) {
ElMessage.error('获取数据失败,请稍后重试');
} finally {
loading.value = false;
}
}
getData();
// onMounted(() => {
// getData();
// });
watch(
() => props.entId,
() => {
getData();
}
);
const handleSave = async () => {
try {
let response;
syncAddressToForm();
if (dialogTitle.value === '新增') {
// saveFarmerList
formData.value.entId = props.entId;
response = await addMember(formData.value);
if (response.code === 200) {
ElMessage.success('新增成功');
}
} else if (dialogTitle.value === '编辑') {
// editFarmer
response = await updateMember(formData.value);
if (response.code === 200) {
ElMessage.success('编辑成功');
}
}
if (response && response.code === 200) {
dialogVisible.value = false;
getData(); //
}
} catch (error) {
if (dialogTitle.value === '新增') {
ElMessage.error('新增失败,请稍后重试');
} else {
ElMessage.error('编辑失败,请稍后重试');
}
}
};
const handleAdd = () => {
isReadonly.value = false; //
resetForm();
dialogTitle.value = '新增';
dialogVisible.value = true;
};
function handleView(row) {
console.log('查看', row);
dialogTitle.value = '查看';
isReadonly.value = true; //
dialogVisible.value = true;
const addressArr = [row.provinceCode || '', row.cityCode || '', row.countyCode || '', row.townCode || '', row.villageCode || ''];
formData.value = {
...row,
addressArr,
};
//
}
async function handleEdit(row) {
dialogTitle.value = '编辑';
isReadonly.value = false;
dialogVisible.value = true;
const addressArr = [row.provinceCode || '', row.cityCode || '', row.countyCode || '', row.townCode || '', row.villageCode || ''];
formData.value = {
...row,
addressArr,
};
}
async function handleDelete(row) {
try {
await ElMessageBox.confirm('确定删除该条记录?', '删除提示');
console.log(`删除 ID=${row.id}`);
await deleteMembers(row.id); // ID
await getData();
ElMessage.success('已删除');
} catch (error) {
if (error !== 'cancel') {
ElMessage.error(`删除失败: ${error.message || '请稍后重试'}`);
}
}
}
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,100 @@
<template>
<el-form :model="localForm" label-width="150px" :disabled="readonly">
<h3>登记注册信息</h3>
<el-row :gutter="20">
<!-- 左列 -->
<el-col :span="12">
<el-form-item label="企业名称">
<el-input v-model="localForm.businessName" placeholder="请输入" />
</el-form-item>
<el-form-item label="法定代表人">
<el-input v-model="localForm.legalRep" placeholder="请输入" />
</el-form-item>
<el-form-item label="企业类型">
<el-select v-model="localForm.comType" placeholder="请选择">
<el-option label="农民专业合作社" value="农民专业合作社" />
<el-option label="农业公司" value="农业公司" />
<el-option label="个体工商户" value="个体工商户" />
</el-select>
</el-form-item>
<el-form-item label="登记机关">
<el-input v-model="localForm.regAuthority" placeholder="请输入" />
</el-form-item>
<el-form-item label="核准日期">
<el-date-picker
v-model="localForm.approveDate"
style="width: 100%"
type="date"
placeholder="请选择"
format="YYYY年MM月DD日"
value-format="YYYY-MM-DD"
/>
</el-form-item>
</el-col>
<!-- 右列 -->
<el-col :span="12">
<el-form-item label="统一社会信用代码">
<el-input v-model="localForm.uscc" placeholder="请输入" />
</el-form-item>
<el-form-item label="登记状态">
<el-select v-model="localForm.registrationStatus" placeholder="请选择">
<el-option label="存续" value="存续" />
<el-option label="注销" value="注销" />
<el-option label="吊销" value="吊销" />
</el-select>
</el-form-item>
<el-form-item label="成立日期">
<el-date-picker
v-model="localForm.estDate"
style="width: 100%"
type="date"
placeholder="请选择"
format="YYYY年MM月DD日"
value-format="YYYY-MM-DD"
/>
</el-form-item>
<el-form-item label="成员出资总额">
<el-input v-model="localForm.totalCapital" placeholder="请输入" />
</el-form-item>
<el-form-item label="住所">
<el-input v-model="localForm.address" placeholder="请输入" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="经营范围">
<el-input v-model="localForm.businessScope" type="businessScope" placeholder="请输入" :rows="4" />
</el-form-item>
</el-col>
</el-row>
</el-form>
</template>
<script setup>
import { toRefs, reactive, watch } from 'vue';
const props = defineProps({
modelValue: {
type: Object,
required: true,
default: () => ({}),
},
readonly: Boolean,
});
const emit = defineEmits(['update:modelValue']);
//
const { modelValue: localForm } = toRefs(props);
</script>
<style scoped lang="scss">
h3 {
margin-top: 20px;
margin-bottom: 20px;
font-size: 16px;
font-weight: 500;
color: #333333;
width: 110px;
text-align: right;
}
</style>

View File

@ -1,9 +1,631 @@
<template>
<div></div>
<div class="app-container">
<div class="container-custom">
<h2 class="custom-h2">企业档案</h2>
<div ref="searchBarRef" class="search-box">
<div class="search-bar">
<div class="search-bar-left">
<el-form ref="customForm" :inline="true" :model="searchForm" class="demo-form-inline" :label-width="'auto'">
<el-form-item label="关键字" prop="businessName">
<el-input v-model="searchForm.businessName" placeholder="请输入姓名" clearable />
</el-form-item>
<el-form-item label="">
<el-button type="primary" icon="Search" @click="onSubmit">查询</el-button>
<el-button icon="Refresh" @click="resetSearchForm">重置</el-button>
</el-form-item>
</el-form>
</div>
</div>
</div>
</div>
</div>
<section class="custom-page">
<!-- 四个固定 Tabs -->
<!-- <el-tabs v-model="activeCrudTab" @tab-click="handleTabChange">
<el-tab-pane label="待提交" name="0" />
<el-tab-pane label="待审核" name="1" />
<el-tab-pane label="已通过" name="2" />
<el-tab-pane label="已驳回" name="3" />
</el-tabs> -->
<!-- 表格 -->
<avue-crud
ref="crudRef"
v-model:page="pageData"
:data="crudData"
:option="crudOptions"
:table-loading="loading"
@current-change="handleCurrentChange"
@size-change="handleSizeChange"
>
<!-- <template v-if="activeCrudTab === '0'" #menu-left>
<el-button type="primary" icon="Plus" @click="handleAdd">新增</el-button>
</template> -->
<template #menu="scope">
<custom-table-operate :actions="getActions(scope.row)" :data="scope" />
</template>
</avue-crud>
<el-dialog :key="dialogTitle" v-model="visible" :title="dialogTitle" width="60%" align-center :draggable="true">
<el-tabs v-model="activeTab" class="tabs-wrapper">
<el-tab-pane label="基础信息" name="basic">
<TabBasicInfo v-model="formData" :readonly="isReadonly" />
</el-tab-pane>
<el-tab-pane label="登记注册信息" name="register">
<TabRegister v-model="formData" :readonly="isReadonly" />
</el-tab-pane>
<el-tab-pane label="经营信息" name="business">
<TabBusinessInfo v-model="formData" :readonly="isReadonly" />
</el-tab-pane>
<el-tab-pane label="信用评级" name="credit">
<TabCreditEvaluation v-model="formData" :readonly="isReadonly" />
</el-tab-pane>
<el-tab-pane v-if="dialogTitle !== '新增'" label="职工/社员管理" name="employee">
<TabMember :readonly="isReadonly" :ent-id="formData.id" />
</el-tab-pane>
</el-tabs>
<template v-if="dialogTitle !== '查看'" #footer>
<el-button v-if="!isFirstTab" type="primary" @click="handlePrev">上一步</el-button>
<el-button v-if="!isLastTab" type="primary" @click="handleNext">下一步</el-button>
<el-button v-if="!isFirstTab && !isLastTab" type="info" @click="handleSkip">跳过</el-button>
<el-button v-if="isLastTab" type="primary" @click="handleSubmit">保存</el-button>
<el-button v-if="isLastTab" type="info" @click="handleSkipSave">跳过并保存</el-button>
</template>
</el-dialog>
</section>
</template>
<script setup>
import { ref, watch, onMounted, computed } from 'vue';
import { ref, reactive, watch, onMounted, computed } from 'vue';
import { CRUD_OPTIONS } from '@/config';
import { ElMessage, ElMessageBox } from 'element-plus';
import TabBasicInfo from './components/TabBasicInfo.vue';
import TabRegister from './components/TabRegister.vue';
import TabBusinessInfo from './components/TabBusinessInfo.vue';
import TabCreditEvaluation from './components/TabCreditEvaluation.vue';
import TabMember from './components/TabMember.vue';
import { getEnterList, getEnterById, addEnter, updateEnter, approvalEnter, deleteEnter } from '@/apis/businessEntity';
const customForm = ref(null);
//
const visible = ref(false);
const activeCrudTab = ref('1');
const activeTab = ref('basic');
const dialogTitle = ref('新增');
const isReadonly = ref(false);
//
const searchForm = ref({
businessName: '',
uscc: '',
productType: '',
primaryProduct: '',
});
const onSubmit = () => {
pageData.value.currentPage = 1;
getData();
};
const resetSearchForm = () => {
Object.assign(searchForm.value, initialSearchForm);
};
const initialSearchForm = { ...searchForm.value };
//
const formData = ref({
id: '',
// basicInfo
businessName: '',
area: '',
contactPerson: '',
cooperativePhoto: '', //
addressArr: [],
primaryProduct: '',
phone: '',
businessLicence: '', //
provinceCode: '',
cityCode: '',
countyCode: '',
townCode: '',
villageCode: '',
// registerInfo
// businessName: '',
legalRep: '',
comType: '',
regAuthority: '',
approveDate: '',
uscc: '',
registrationStatus: '',
estDate: '',
totalCapital: '',
address: '',
businessScope: '',
//
debtFiles: [],
profitFiles: [],
cashflowFiles: [],
//
creditEvaluation: 5,
supportedFarmers: 4,
socialImpact: 3,
techApplication: 2,
productQuality: 1,
});
const initialFormData = { ...formData.value };
const resetForm = () => {
formData.value = { ...initialFormData };
};
const syncAddressToForm = () => {
const arr = Array.isArray(formData.value.addressArr) ? formData.value.addressArr : [];
formData.value.provinceCode = arr[0] || '';
formData.value.cityCode = arr[1] || '';
formData.value.countyCode = arr[2] || '';
formData.value.townCode = arr[3] || '';
formData.value.villageCode = arr[4] || '';
};
//
const handleSubmit = async () => {
try {
loading.value = true;
let response;
if (dialogTitle.value === '新增') {
formData.value.id = '';
syncAddressToForm();
response = await addEnter(formData.value);
if (response.code === 200) {
ElMessage.success('新增成功');
visible.value = false;
getData();
}
} else if (dialogTitle.value === '编辑') {
syncAddressToForm();
response = await updateEnter(formData.value);
if (response.code === 200) {
ElMessage.success('编辑成功');
visible.value = false;
getData();
}
}
} catch (e) {
ElMessage.error('保存失败');
} finally {
loading.value = false;
}
};
const pageData = ref({
currentPage: 1,
pageSize: 10,
total: 0,
});
const crudData = ref([]);
const loading = ref(false);
const crudOptions = reactive({
...CRUD_OPTIONS,
addBtn: false,
header: false,
searchBtn: false,
emptyBtn: false,
refreshBtn: false,
height: 'calc(100vh - 360px)',
column: [
{ label: '生产经营主体编码', prop: 'id' },
{ label: '企业名称', prop: 'businessName' },
// { label: '', prop: 'contactPerson' },
{ label: '所属行政区划', prop: 'address' },
{ label: '所属网格', prop: 'gridCode' },
{ label: '面积', prop: 'area', formatter: (row, column, cellValue) => `${Number(cellValue).toFixed(2)}` },
{ label: '经营品类', prop: 'businessCategory' },
{ label: '经营品种', prop: 'businessVariety' },
// { label: '', prop: 'phone' },
// { label: '', prop: 'address' },
// { label: '', prop: 'landCount' },
// { label: '', prop: 'landNumber' },
// { label: '', prop: 'landName' },
// { label: '', prop: 'planCrop' },
// { label: '', prop: 'phone' },
// { label: '', prop: 'createTime' },
// { label: '', prop: 'updateTime' },
],
});
const handleCurrentChange = (val) => {
pageData.value.currentPage = val;
};
const handleSizeChange = (val) => {
pageData.value.pageSize = val;
};
// watch(
// () => formData.value.addressArr,
// (newValue) => {
// if (newValue.length === 5) {
// formData.value.provinceCode = newValue[0] || '';
// formData.value.cityCode = newValue[1] || '';
// formData.value.countyCode = newValue[2] || '';
// formData.value.townCode = newValue[3] || '';
// formData.value.villageCode = newValue[4] || '';
// } else {
// ElMessageBox.alert('');
// }
// }
// );
onMounted(() => {
getData();
});
const getData = async () => {
loading.value = true;
try {
const response = await getEnterList({
...searchForm.value,
status: activeCrudTab.value,
page: pageData.value.currentPage,
size: pageData.value.pageSize,
});
crudData.value = response.data.records;
pageData.value.total = response.data.records.length;
pageData.value.currentPage = response.data.current;
pageData.value.pageSize = response.data.size;
//
crudData.value.forEach((item, index, arr) => {
item.businessCategory = '辣椒';
if (index == 1) {
arr[index].businessVariety = '圆椒';
} else {
arr[index].businessVariety = '尖椒';
}
});
} catch (error) {
ElMessage.error('加载数据失败');
} finally {
loading.value = false;
}
};
const getEnterDetail = async (id) => {
try {
resetForm();
const response = await getEnterById(id);
formData.value = {
...response.data,
// addressArr5
addressArr: [
response.data.provinceCode || '',
response.data.cityCode || '',
response.data.countyCode || '',
response.data.townCode || '',
response.data.villageCode || '',
],
};
} catch (error) {
ElMessage.error(`获取详情失败:${error.message || '请稍后重试'}`);
}
};
function handleSearch() {
getData();
}
function handleTabChange(tab) {
handleSearch();
}
const handleAdd = () => {
isReadonly.value = false;
resetForm();
dialogTitle.value = '新增';
visible.value = true;
};
//
const handleView = async (row) => {
loading.value = true;
dialogTitle.value = '查看';
try {
await getEnterDetail(row.id);
isReadonly.value = true;
activeTab.value = 'basic';
visible.value = true;
} finally {
loading.value = false;
}
};
//
const handleEdit = async (row) => {
loading.value = true;
dialogTitle.value = '编辑';
try {
await getEnterDetail(row.id);
isReadonly.value = false;
activeTab.value = 'basic';
visible.value = true;
} finally {
loading.value = false;
}
};
//
const handleSubmitApprove = async (row) => {
try {
const params = {
id: row.id,
status: '1', //
reason: '提交审核',
};
const res = await approvalEnter(params);
if (res.code === 200) {
ElMessage.success('提交审核成功');
row.status = '1';
getData(); //
} else {
ElMessage.error(res.msg || '提交审核失败');
}
} catch (error) {
ElMessage.error('提交审核失败');
}
};
//
function handleResubmit(row) {
ElMessageBox.confirm('确认重新提交吗?', '重新提交').then(() => {
const params = {
id: row.id,
status: '1', //
reason: '重新提交审核',
};
approvalEnter(params)
.then(() => {
console.log(`ID=${row.id} 重新提交审核`);
row.status = '1';
row.rejectReason = '';
getData();
ElMessage.success('已重新提交,状态已变为"待审核"');
})
.catch((error) => {
console.error('重新提交失败:', error);
ElMessage.error(error.response?.data?.msg || '重新提交失败');
});
});
}
//
function handleWithdraw(row) {
ElMessageBox.confirm('确认撤销本次审核吗?', '撤销').then(() => {
const params = {
id: row.id,
status: '0', //
reason: '用户主动撤销',
};
approvalEnter(params)
.then(() => {
console.log(`ID=${row.id} 撤销审核`);
row.status = '0';
getData();
ElMessage.success('已撤销,状态已变为"待提交"');
})
.catch((error) => {
console.error('撤销失败:', error);
ElMessage.error(error.response?.data?.msg || '撤销失败');
});
});
}
//
function handleApprove(row) {
ElMessageBox.confirm('确认通过审核?', '审核通过').then(() => {
const params = {
id: row.id,
status: '2', //
reason: '审核通过',
};
approvalEnter(params)
.then(() => {
console.log(`ID=${row.id} 审核通过`);
row.status = '2';
getData();
ElMessage.success('审核已通过');
})
.catch((error) => {
console.error('审核通过操作失败:', error);
ElMessage.error(error.response?.data?.msg || '审核操作失败');
});
});
}
//
function handleReject(row) {
ElMessageBox.prompt('请输入驳回原因', '审核驳回', {
confirmButtonText: '确定',
cancelButtonText: '取消',
inputPattern: /.+/, //
inputErrorMessage: '驳回原因不能为空',
})
.then(({ value }) => {
const params = {
id: row.id,
status: '3', //
reason: value.trim(),
};
return approvalEnter(params).then(() => {
console.log(`ID=${row.id} 驳回,原因:${value.trim()}`);
row.status = '3';
row.rejectReason = value.trim();
getData();
ElMessage.success('已驳回');
});
})
.catch((error) => {
if (error !== 'cancel') {
console.error('驳回操作失败:', error);
ElMessage.error(error.response?.data?.msg || '驳回操作失败');
}
});
}
// /
function showRejectReason(row) {
ElMessageBox.alert(row.reason || '无驳回原因', '驳回原因');
}
//
const handleDelete = async (id) => {
try {
await ElMessageBox.confirm('确认删除该合作社信息?', '提示', {
type: 'warning',
});
loading.value = true;
const res = await deleteEnter(id);
if (res.code === 200) {
ElMessage.success('删除成功');
getData(); //
} else {
ElMessage.error(res.msg || '删除失败');
}
} catch (e) {
if (e !== 'cancel') {
ElMessage.error('删除失败');
}
} finally {
loading.value = false;
}
};
// tabs
const tabOrder = ['basic', 'register', 'business', 'credit'];
const currentTabIndex = computed(() => tabOrder.indexOf(activeTab.value));
const isFirstTab = computed(() => currentTabIndex.value === 0);
const isLastTab = computed(() => currentTabIndex.value === tabOrder.length - 1);
/** 跳转到下一 Tab */
function handleNext() {
if (currentTabIndex.value < tabOrder.length - 1) {
activeTab.value = tabOrder[currentTabIndex.value + 1];
}
}
/** 跳转到上一 Tab */
function handlePrev() {
if (currentTabIndex.value > 0) {
activeTab.value = tabOrder[currentTabIndex.value - 1];
}
}
/** 跳过当前步骤 */
function handleSkip() {
handleNext();
}
/** 跳过并保存 */
function handleSkipSave() {
handleSkip();
handleSubmit();
}
import { useUserStore } from '@/store/modules/user';
const UserStore = useUserStore();
const user = UserStore.getUserInfo();
console.log('admin 属性:', user.admin);
const isAdmin = user.admin;
const getActions = (row) => {
const actions = [
{
name: '查看',
icon: 'view',
event: () => handleView(row),
},
{
name: '编辑',
icon: 'edit',
event: () => handleEdit(row),
},
{
type: 'danger',
name: '删除',
icon: 'delete',
event: () => handleDelete(row.id),
},
];
switch (row.status) {
case '0': //
actions.push(
{
name: '提交审核',
icon: 'check',
event: () => handleSubmitApprove(row),
},
{
name: '重新提交',
icon: 'resubmit',
event: () => handleResubmit(row),
}
);
break;
case '1': //
if (isAdmin) {
actions.push(
{
name: '通过',
icon: 'check-circle',
event: () => handleApprove(row),
},
{
name: '驳回',
icon: 'close-circle',
event: () => handleReject(row),
}
);
} else {
actions.push({
name: '撤销',
icon: 'undo',
event: () => handleWithdraw(row),
});
}
break;
case '2': //
//
break;
case '3': //
actions.push({
name: '驳回原因',
icon: 'warning',
event: () => showRejectReason(row),
});
break;
}
return actions;
};
</script>
<style scoped lang="scss"></style>
<style scoped lang="scss">
.tabs-wrapper {
width: 100%;
display: flex;
align-items: center;
// background-color: #7daaaa;
:deep(.el-tabs__item) {
font-size: 16px;
color: #555555;
font-weight: 500;
// border: 1 solid #f000;
}
:deep(.el-tabs__content) {
padding: 20px;
width: 100%;
// background-color: #f5f5f5;
border-radius: 4px;
height: calc(100vh - 300px);
overflow-y: auto;
}
:deep(.el-tab-pane) {
margin: 0 auto;
width: 80%;
}
:deep(.el-tab-pane:nth-child(5)) {
margin: 0 auto;
width: 100%;
}
}
</style>