feat:物资管理统一处理分类数据,页面调整,修改所有投入品管理接口网关

This commit is contained in:
李想 2025-03-24 17:21:44 +08:00
parent 62f7cbbac9
commit e06c50de65
13 changed files with 466 additions and 164 deletions

View File

@ -1,13 +1,13 @@
import request from '@/utils/axios';
export function getQuestionList(params) {
return request('/input/knowledge/page', {
return request('/inputGoods/knowledge/page', {
params,
});
}
export function getQuestionReply(data) {
return request('/input/knowledge/reply', {
return request('/inputGoods/knowledge/reply', {
data,
method: 'PUT',
});

View File

@ -2,14 +2,14 @@ import request from '@/utils/axios';
/* 租赁列表 */
export function getLeaseSuperviseList(params) {
return request('/input/machineLease/page', {
return request('/inputGoods/machineLease/page', {
params,
});
}
/* 新增租赁 */
export function addLeaseSupervise(data) {
return request('/input/machineLease/save', {
return request('/inputGoods/machineLease/save', {
method: 'POST',
data,
});

View File

@ -2,7 +2,13 @@ import request from '@/utils/axios';
/* 获取物资类型 */
export function getMaterailTypes(params) {
return request('/input/common/getList', {
return request('/inputGoods/common/getList', {
params,
});
}
/* 获取农药列表 */
export function getPesticideList(params) {
return request('/inputGoods/pesticide/page', {
params,
});
}

View File

@ -40,24 +40,24 @@ const inputSuppliesRoutes = [
component: () => import('@/views/inputSuppliesManage/material/fertilizer/index.vue'),
meta: { title: '肥料管理', icon: 'Document' },
},
{
path: '/sub-government-affairs-service/material/ratPoison',
name: 'input-supplies-ratPoison',
component: () => import('@/views/inputSuppliesManage/material/ratPoison/index.vue'),
meta: { title: '兽药管理', icon: 'Document' },
},
{
path: '/sub-government-affairs-service/material/farmMachinery',
name: 'input-supplies-farmMachinery',
component: () => import('@/views/inputSuppliesManage/material/farmMachinery/index.vue'),
meta: { title: '农机管理', icon: 'Document' },
},
{
path: '/sub-government-affairs-service/material/seed',
name: 'input-supplies-seed',
component: () => import('@/views/inputSuppliesManage/material/seed/index.vue'),
meta: { title: '种源管理', icon: 'Document' },
},
// {
// path: '/sub-government-affairs-service/material/ratPoison',
// name: 'input-supplies-ratPoison',
// component: () => import('@/views/inputSuppliesManage/material/ratPoison/index.vue'),
// meta: { title: '兽药管理', icon: 'Document' },
// },
// {
// path: '/sub-government-affairs-service/material/farmMachinery',
// name: 'input-supplies-farmMachinery',
// component: () => import('@/views/inputSuppliesManage/material/farmMachinery/index.vue'),
// meta: { title: '农机管理', icon: 'Document' },
// },
// {
// path: '/sub-government-affairs-service/material/seed',
// name: 'input-supplies-seed',
// component: () => import('@/views/inputSuppliesManage/material/seed/index.vue'),
// meta: { title: '种源管理', icon: 'Document' },
// },
],
},
// {

View File

@ -0,0 +1,85 @@
<template>
<section class="custom_number_select_" style="">
<el-input-number v-model="data.num" :precision="2" :step="1" :min="1" controls-position="right" @change="handleChange"></el-input-number>
<el-select v-model="data.type" @change="handleChange">
<el-option v-for="item in props.options" :key="'custom_' + Date.now() + item.value" :label="item.label" :value="item.value" />
</el-select>
</section>
</template>
<script lang="ts" setup>
import { ref, watchEffect } from 'vue';
const emit = defineEmits(['update:value']);
const props = defineProps({
value: {
type: Object,
default: () => {
return {
num: 1,
type: '1',
};
},
},
options: {
type: Array,
default: () => [
{
value: '1',
label: 'value1',
},
{
value: '2',
label: 'value2',
},
{
value: '3',
label: 'value3',
},
],
},
numberSet: {
type: Object,
default: () => {
return {};
},
},
});
const _numberSet = ref({
precision: 2,
setp: 1,
min: 1,
max: 100,
controlsPosition: 'right',
});
const data = ref({
num: 1,
type: '1',
});
watchEffect(() => {
data.value = Object.assign(data.value, props.value);
_numberSet.value = Object.assign(_numberSet.value, props.set);
});
function handleChange() {
emit('update:value', data.value);
}
</script>
<style lang="scss" scoped>
.custom_number_select_ {
display: grid;
grid-template-columns: 75% 25%;
::v-deep() {
.el-input-number {
width: 100%;
.el-input__wrapper {
border-radius: 4px 0 0 4px;
}
}
.el-select__wrapper {
border-radius: 0 4px 4px 0 !important;
border-left: none;
}
}
}
</style>

View File

@ -2,16 +2,15 @@
<el-sub-menu :index="types.value" :popper-offset="2">
<template #title>{{ types.label }}</template>
<template v-for="item in types.children" :key="`type_menu_${item.value}`">
<el-menu-item v-if="!item.children" :index="item.value">{{ item.label }}</el-menu-item>
<el-menu-item v-if="!item.children || !item.children.length" :index="item.value">{{ item.label }}</el-menu-item>
<SubMenu v-else :types="item" />
</template>
</el-sub-menu>
</template>
<script setup>
import { ref } from 'vue';
import SubMenu from './SubMenu.vue';
defineProps({
const props = defineProps({
types: {
type: Object,
default: () => {
@ -32,15 +31,6 @@ defineProps({
},
},
});
/* --------------- data --------------- */
// #region
// #endregion
/* --------------- methods --------------- */
// #region
// #endregion
</script>
<style lang="scss" scoped></style>

View File

@ -11,7 +11,7 @@
import SubMenu from './SubMenu.vue';
const emit = defineEmits(['update:type']);
defineProps({
const props = defineProps({
types: {
type: Array,
default: () => [

View File

@ -1,51 +1,103 @@
import { ref } from 'vue';
import { ref, onMounted, reactive } from 'vue';
import inputSuppliesApis from '@/apis/inputSuppliesApi';
const { getMaterailTypes } = inputSuppliesApis;
export function useBasicInfo(set = {}) {
const loadFinish = ref(false);
const searchCondition = Object.assign(
{
dataType: '',
moduleType: '',
},
set
);
/* ------ data ------ */
// #region
const materialTypes = reactive({
1: [{ value: '0', label: '全部' }],
2: [{ value: '0', label: '全部' }],
3: [{ value: '0', label: '全部' }],
4: [{ value: '0', label: '全部' }],
5: [{ value: '0', label: '全部' }],
});
const materialTwoLevel = ref({});
export function useBasicInfo() {
const pesticideData = ref([
{ label: '全部', value: '0' },
{
label: '防治对象',
value: '1',
children: [
{ label: '杀虫剂', value: '1-1' },
{ label: '除草剂', value: '1-2' },
{ label: '杀菌剂', value: '1-3' },
{ label: '杀螨剂', value: '1-4' },
{ label: '生物农药', value: '1-5' },
{ label: '植物生长调节剂', value: '1-6' },
],
},
{
label: '化学成分',
value: '2',
children: [
{ label: '无机农药', pid: '2', value: '2-1' },
{ label: '生物农药', pid: '2', value: '2-2' },
{
label: '有机农药',
pid: '2',
value: '2-3',
children: [
{ label: '天然有机农药', pid: '2-3', value: '2-3-1' },
{ label: '人工合成农药', pid: '2-3', value: '2-3-2' },
],
},
],
},
{
label: '加工剂型',
value: '3',
children: [
{ label: '可湿性粉剂', value: '3-1' },
{ label: '可溶性粉剂', value: '3-2' },
{ label: '乳剂', value: '3-3' },
{ label: '颗粒剂', value: '4-4' },
{ label: '缓释剂', value: '5-5' },
{ label: '烟剂', value: '6-6' },
],
},
/* ------ 农药 ------ */
// #region
const pesticideTypes = reactive({});
const goodsUnitOptions = reactive([
{ value: '1', label: 'ml/瓶' },
{ value: '2', label: 'mg/盒' },
{ value: '3', label: 'kg/袋' },
]);
const useDosageUnit = reactive([
{ value: '1', label: '/亩' },
{ value: '2', label: '/平方米' },
{ value: '3', label: '/株' },
]);
// #endregion
// #endregion
async function getmaterialType(_set = {}) {
let params = Object.assign(searchCondition, _set);
let res = await getMaterailTypes(params);
console.log('two --- ', res);
if (res && res?.code == 200) {
res.data.forEach((item) => {
const { moduleType, children } = item;
materialTypes[moduleType].push(...handleTypes(children));
handleTwoLevel();
});
}
loadFinish.value = true;
}
function handleTypes(arr) {
arr.forEach((item) => {
item.value = item.id;
item.label = item.dataName;
if (item.children.length > 0) {
item.children = handleTypes(item.children);
}
});
return arr;
}
function handleTwoLevel() {
for (let key in materialTypes) {
materialTwoLevel.value[key] = {};
materialTypes[key].forEach((v) => {
if (v.value != 0) {
materialTwoLevel.value[key][v.dataType] = v.children;
}
});
}
}
function filterTypes(_set = {}) {
let filterType = Object.assign(
{
dataType: '1',
moduleType: '1',
},
_set
);
let all = materialTypes[filterType.moduleType];
let _arr = [];
all.forEach((item) => {
console.log('item', item);
if (filterType.dataType == item.dataType) {
_arr = item.children;
}
});
return _arr;
}
onMounted(getmaterialType);
return {
pesticideData,
loadFinish,
materialTypes,
materialTwoLevel,
goodsUnitOptions,
useDosageUnit,
getmaterialType,
filterTypes,
};
}

View File

@ -1,7 +1,7 @@
<template>
<CustomCard>
<h2>农药基本信息</h2>
<TypeMenu v-model:type="_type" :types="pesticideData" />
<TypeMenu v-if="materialTypes.length > 1" v-model:type="_type" :types="materialTypes['1']" />
<br />
<avue-crud
ref="crud"
@ -10,6 +10,7 @@
:data="data"
:option="option"
:before-close="handleCloseDialog"
@refresh-change="getData"
@row-save="handleRowSave"
@row-update="handleRowUpdate"
>
@ -17,18 +18,23 @@
<el-button type="primary" @click="handleEdit(row)">上传报告</el-button>
<el-button @click="handleInfo(row)">详情</el-button>
</template>
<template #img-form="{ type }">
<Attrs v-model:attrs="img" :type="type == 'add' ? 'add' : 'view'" />
<template #photoUrl-form="{ type }">
<Attrs v-model:attrs="attrs" :type="type == 'add' ? 'add' : 'view'" />
</template>
<template #checkInfo-form="{ row }">
<section style="text-align: center; line-height: 58px">
{{ row }}
<el-button @click="handleCheckInfo('open')">查看报告</el-button>
</section>
</template>
<template #checkReport-form="{ type }">
<Attrs v-model:attrs="reportAttrs" :type="type" :up-btn="reportAttrs.length < 1" :file-num="reportAttrs.length > 0 ? 1 : 3" />
</template>
<template #productSpecification-form>
<NumberSelect v-model:value="productSpecification" :options="goodsUnitOptions" />
</template>
<template #dosage-form>
<NumberSelect v-model:value="useDosage" :options="useDosageUnit" />
</template>
<template #checkBtn-form>
<section style="text-align: center; line-height: 58px">
<el-button @click="handleCheckInfo('close')">关闭</el-button>
@ -39,14 +45,20 @@
</template>
<script setup>
import { reactive, ref, watch, h } from 'vue';
import { reactive, ref, watch, onMounted, h, computed } from 'vue';
import CustomCard from '@/components/CustomCard.vue';
import TypeMenu from '../../common/TypeMenu.vue';
import { CRUD_OPTIONS } from '@/config';
import { useBasicInfo } from '@/views/inputSuppliesManage/hooks/useBasicInfo';
import Attrs from '@/views/inputSuppliesManage/common/Attrs.vue';
import NumberSelect from '@/views/inputSuppliesManage/common/NumberSelect.vue';
import inputSuppliesApi from '@/apis/inputSuppliesApi';
const { pesticideData } = useBasicInfo();
const { loadFinish, materialTypes, materialTwoLevel, goodsUnitOptions, useDosageUnit, filterTypes } = useBasicInfo({
moduleType: '1',
});
const { getPesticideList } = inputSuppliesApi;
onMounted(getData);
/* --------------- data --------------- */
// #region
@ -60,51 +72,33 @@ watch(
deep: true,
}
);
const searchCondition = ref({
pesticideName: '',
});
const crud = ref();
const _loading = ref(false);
const data = ref([
{
name: '农药1',
id: '1111',
produicer: '生产商1',
dealer: '经销商1',
img: [
'https://gips0.baidu.com/it/u=3602773692,1512483864&fm=3028',
'https://gips3.baidu.com/it/u=100751361,1567855012&fm=3028',
'https://gips2.baidu.com/it/u=195724436,3554684702&fm=3028',
],
checkReport: [],
},
{
name: '农药2',
id: '2222',
produicer: '生产商2',
dealer: '经销商2',
img: ['https://gips3.baidu.com/it/u=100751361,1567855012&fm=3028'],
checkReport: ['https://gips3.baidu.com/it/u=100751361,1567855012&fm=3028'],
},
{
name: '农药3',
id: '3333',
produicer: '生产商3',
dealer: '经销商3',
img: [],
checkReport: [],
},
]);
const data = ref([]);
const pageData = ref({
total: 0,
currentPage: 1,
pageSize: 10,
size: 10,
});
const option = ref({
CRUD_OPTIONS,
...CRUD_OPTIONS,
selection: false,
labelWidth: 124,
editBtn: false,
delBtn: false,
menuWidth: 220,
dialogWidth: '60%',
column: [
{
hide: true,
label: '关键字',
search: true,
addDisplay: false,
editDisplay: false,
},
{
prop: 'id',
label: '农药编号',
@ -112,50 +106,55 @@ const option = ref({
editDisplay: false,
},
{
prop: 'name',
prop: 'pesticideName',
label: '名称',
editDisplay: false,
},
{
hide: true,
prop: 'code',
prop: 'productStandCode',
label: '产品标准证号',
viewDisplay: false,
editDisplay: false,
},
{
hide: true,
prop: 'img',
prop: 'photoUrl',
label: '农药图片',
editDisplay: false,
},
{
hide: true,
prop: 'code1',
prop: 'pesticideRegistCode',
label: '农药登记证号',
viewDisplay: false,
editDisplay: false,
},
{
prop: 'producer',
prop: 'manufacturer',
label: '生产厂家',
editDisplay: false,
},
{
prop: 'dealer',
prop: 'distributor',
label: '经销商',
editDisplay: false,
},
{
prop: 'format',
prop: 'productSpecification',
label: '产品规格',
editDisplay: false,
},
{
prop: 'toxicity',
prop: 'toxicityLevel',
label: '毒性',
editDisplay: false,
},
{
prop: 'dosage',
label: '建议用量',
editDisplay: false,
},
{
prop: 'validity',
label: '保质期',
@ -167,17 +166,17 @@ const option = ref({
type: 'cascader',
checkStrictly: true,
multiple: true,
dicData: pesticideData.value[1].children,
dicData: [],
span: 24,
editDisplay: false,
},
{
prop: 'chemicalComposition',
prop: 'mainComponents',
label: '化学成分',
type: 'cascader',
checkStrictly: true,
multiple: true,
dicData: pesticideData.value[2].children,
dicData: materialTwoLevel.value?.['1']?.['2'] ?? [],
span: 24,
editDisplay: false,
},
@ -187,7 +186,7 @@ const option = ref({
type: 'cascader',
checkStrictly: true,
multiple: true,
dicData: pesticideData.value[3].children,
dicData: materialTwoLevel.value?.['1']?.['3'] ?? [],
span: 24,
editDisplay: false,
},
@ -231,17 +230,17 @@ const option = ref({
editDisabled: true,
},
{
prop: 'producer',
prop: 'manufacturer',
label: '生产商',
editDisabled: true,
},
{
prop: 'img',
prop: 'photoUrl',
label: '农药图片',
editDisabled: true,
},
{
prop: 'dealer',
prop: 'distributor',
label: '经销商',
editDisabled: true,
},
@ -284,12 +283,56 @@ const option = ref({
},
],
});
const img = ref([]);
watch(
() => loadFinish.value,
() => {
if (loadFinish.value) {
let newDicName = [
{ key: '', one: '1', two: '1' },
{ key: '', one: '1', two: '2' },
{ key: '', one: '1', two: '3' },
];
newDicName.forEach((v) => {
option.value.column.forEach((item) => {
if (item.prop === v.key) {
item.dicData = materialTwoLevel?.[v.one]?.[v.two] ?? [];
}
});
});
}
}
);
const attrs = ref([]);
const reportAttrs = ref([]);
const productSpecification = ref({
num: 1,
type: '1',
});
const useDosage = ref({
num: 1,
type: '1',
});
// #endregion
/* --------------- methods --------------- */
// #region
async function getData(reset) {
_loading.value = true;
reset == 1 && (pageData.value.currentPage = 1);
let params = {
current: pageData.value.currentPage,
size: pageData.value.size,
...searchCondition.value,
};
let res = await getPesticideList(params);
console.log('res --- ', res);
_loading.value = false;
if (res && res.code === 200) {
data.value = res.data.records;
pageData.value.total = res.data.total;
}
}
function handleCloseDialog(done) {
handleCheckInfoChange();
done();
@ -302,7 +345,7 @@ function handleRowSave(form, done, loading) {
function handleEdit(row) {
console.log('handleEdit', row);
handleCheckInfoChange('open');
img.value = row.img.map((v) => {
attrs.value = row.map((v) => {
return {
url: v,
uid: Date.now(),
@ -336,7 +379,7 @@ function handleCheckInfoChange(bol = false) {
});
} else {
option.value.column.forEach((v) => {
if (!v.hide || v.prop == 'img') {
if (!v.hide || v.prop == 'photoUrl') {
v.viewDisplay = true;
}
});

View File

@ -1,5 +1,11 @@
<template>
<el-radio-group v-model="val" class="radio_group" style="margin-bottom: 30px" @change="emit('update:value', val)">
<el-radio-group
v-model="val"
class="radio_group"
style="margin-bottom: 30px"
:style="{ '--title-theme': val == '1' ? 'red' : 'black' }"
@change="emit('update:value', val)"
>
<el-radio-button v-for="item in options" :key="'radio_' + item.value" :value="item.value" color="red">
{{ item.label }}
</el-radio-button>
@ -65,20 +71,19 @@ const options = reactive([
}
.is-active {
.el-radio-button__inner {
background-color: unset !important;
background-color: var(--title-theme) !important;
color: #fff !important;
border-color: var(--title-theme) !important;
}
}
&:nth-child(1) {
.el-radio-button__inner {
background-color: red !important;
color: #fff;
border-color: red !important;
}
}
&:nth-child(2) {
.el-radio-button__inner {
color: rgba(28, 111, 255, 0.77) !important;
border-color: #c5c5c5 !important;
border-color: #c5c5c5;
}
}
}

View File

@ -1,13 +1,15 @@
<template>
<section class="rank_content" :style="{ '--theme': radio == '1' ? 'red' : 'black' }">
<h2>{{ type == '1' ? '企业' : '品牌' }}红黑榜</h2>
<br />
<RankType v-model:value="radio" />
<div class="rank_item rank_header">
<div class="index_">排名</div>
<div>企业名称</div>
<div>上榜理由</div>
<div>企业类型</div>
<div>{{ type == '1' ? '企业类型' : '所属品牌' }}</div>
</div>
<div v-for="(item, i) in radio == '1' ? props.data.red : props.data.black" :key="`rank_${props.type}_${i}`" class="rank_item">
<div v-for="(item, i) in radio == '1' ? data.red : data.black" :key="`rank_${type}_${i}`" class="rank_item">
<div class="index_">{{ i + 1 }}</div>
<div>{{ item.name }}</div>
<div>{{ item.reason }}</div>
@ -19,33 +21,36 @@
<script setup>
import { reactive, ref } from 'vue';
import RankType from './RankType.vue';
const props = defineProps({
defineProps({
type: {
type: String,
default: '1',
},
data: {
type: Object,
default: () => {
return {
red: [
{
name: '企业1',
reason: '企业1',
name: '惠民肥料公司',
reason: '物美价廉,对农民补贴力度大',
type: '生产商',
},
{
name: '企业2',
reason: '好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好',
name: '新气象农机生产有限公司',
reason: '产品质量有保证,售后服务周到',
type: '生产商',
},
{
name: '企业3',
reason: '2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222',
name: '万好芽种公司',
reason: '种源质量可靠,相关培训指导完善',
type: '生产商',
},
],
black: [
{
name: '企业222',
reason: '不好不好不好不好不好不好不好不好不好不好不好不好不好不好不好不好不好不好不好不好不好不好不好不好不好不好不好不好不好不好不好',
name: '欣欣肥料生产有限公司',
reason: '存在制假售假行为,目前正处于整改阶段',
type: '经销商',
},
],
@ -78,7 +83,7 @@ section {
font-size: 28px;
font-family: '黑体';
text-align: center;
color: var(--theme);
// color: var(--theme);
}
.rank_header {

View File

@ -1,8 +1,8 @@
<template>
<CustomCard>
<section class="rank_container">
<RankCard />
<RankCard />
<RankCard :data="data1" />
<RankCard :data="data2" type="2" />
</section>
</CustomCard>
</template>
@ -58,7 +58,123 @@ const redData = ref([
},
]);
const blackData = ref(JSON.parse(JSON.stringify(redData.value)));
const data1 = ref({
red: [
{
name: '惠民肥料公司',
reason: '物美价廉,对农民补贴力度大',
type: '生产商',
},
{
name: '新气象农机生产有限公司',
reason: '产品质量有保证,售后服务周到',
type: '生产商',
},
{
name: '中化化肥集团',
reason: '诚信经营',
type: '生产商',
},
{
name: '万好芽种公司',
reason: '货真价实',
type: '生产商',
},
{
name: '金正大复合肥',
reason: '诚信经营',
type: '经销商',
},
],
black: [
{
name: '欣欣肥料生产有限公司',
reason: '存在制假售假行为,目前正处于整改阶段',
type: '生产商',
},
{
name: '丰收之源化肥厂',
reason: '质量欠佳',
type: '生产商',
},
{
name: '肥效先锋农资店',
reason: '资质欠缺',
type: '经销商',
},
{
name: '四季农机专营店',
reason: '质量欠佳',
type: '经销商',
},
],
});
const data2 = ref({
red: [
{
name: '中化',
reason: '物美价廉,对农民补贴力度大',
type: '宋博农业',
},
{
name: '宜化',
reason: '产品质量有保证,售后服务周到',
type: '青岛迈高',
},
{
name: '金正大',
reason: '诚信经营',
type: '金正大',
},
{
name: '新洋丰',
reason: '货真价实',
type: '新洋丰',
},
{
name: '嘉施利',
reason: '诚信经营',
type: '麦得利',
},
{
name: '芭田生态',
reason: '产品质量有保证,售后服务周到',
type: '芭田生态',
},
{
name: '安牧歌',
reason: '诚信经营',
type: '蒙原牧场',
},
{
name: '今麦高',
reason: '货真价实',
type: '麦得利',
},
],
black: [
{
name: '得民农机',
reason: '质量欠佳',
type: '得名',
},
{
name: '麦洋洋',
reason: '存在制假售假行为,目前正处于整改阶段',
type: '阳光麦业',
},
{
name: '希沃',
reason: '资质欠缺',
type: '沣西',
},
{
name: '南丰',
reason: '质量欠佳',
type: '阿斯达',
},
],
});
// #endregion
/* --------------- methods --------------- */

View File

@ -38,9 +38,9 @@
</template>
</el-popconfirm>
</template>
<template #area-form="{ row, type }">
<section class="area_form_" style="">
<el-input-number v-model="landArea" :min="1" controls-position="right"></el-input-number>
<template #area-form>
<section class="area_form_">
<el-input-number v-model="landArea" :precision="2" :step="1" :min="1" controls-position="right"></el-input-number>
<el-select v-model="unitValue">
<el-option v-for="item in unitOptions" :key="'unitOptions_' + item.value" :label="item.label" :value="item.value" />
</el-select>