This commit is contained in:
李想 2025-04-27 17:27:22 +08:00
parent 72f6122d4f
commit 626e3e0076
10 changed files with 678 additions and 1 deletions

View File

@ -0,0 +1,144 @@
<template>
<section class="custom_number_select_" style="">
<el-input-number
v-model="data.num"
:precision="_numberSet.precision"
:step="_numberSet.step"
:min="_numberSet.min"
:controls-position="_numberSet.controlsPosition"
@change="handleChange"
>
</el-input-number>
<el-select v-model="data.value1" class="_center" @change="handleChange">
<el-option
v-for="item in props.options1"
:key="'custom_' + Date.now() + item[props.prop.value]"
:label="item[props.prop.label]"
:value="item[props.prop.value]"
/>
</el-select>
<el-select v-model="data.value2" @change="handleChange">
<el-option
v-for="item in props.options2"
:key="'custom_' + Date.now() + item[props.prop.value]"
:label="item[props.prop.label]"
:value="item[props.prop.value]"
/>
</el-select>
</section>
</template>
<script setup>
import { ref, watchEffect } from 'vue';
const emit = defineEmits(['update:value']);
const props = defineProps({
value: {
type: Object,
default: () => {
return {
num: 1,
value1: '1',
value2: '1',
};
},
},
options1: {
type: Array,
default: () => [
{
value: '1',
label: 'value1',
},
{
value: '2',
label: 'value2',
},
{
value: '3',
label: 'value3',
},
],
},
options2: {
type: Array,
default: () => [
{
value: '1',
label: '_value1',
},
{
value: '2',
label: '_value2',
},
{
value: '3',
label: '_value3',
},
],
},
set: {
type: Object,
default: () => {
return {};
},
},
numberSet: {
type: Object,
default: () => {
return {};
},
},
prop: {
type: Object,
default: () => {
return { label: 'label', value: 'value' };
},
},
});
const _numberSet = ref({
precision: 2,
step: 1,
min: 1,
controlsPosition: 'right',
});
const data = ref({
num: 1,
value1: '1',
value2: '1',
});
watchEffect(() => {
data.value = Object.assign(data.value, props.value);
_numberSet.value = Object.assign(_numberSet.value, props.numberSet);
if (data.value.num === null) {
data.value.num = _numberSet.value.min;
}
});
function handleChange() {
emit('update:value', data.value);
}
</script>
<style lang="scss" scoped>
.custom_number_select_ {
display: grid;
grid-template-columns: 56% 22% 22%;
::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;
}
._center {
.el-select__wrapper {
border-radius: 0 !important;
}
}
}
}
</style>

View File

@ -0,0 +1,112 @@
<template>
<section class="custom_number_select_" style="">
<el-input-number
v-model="data.num"
:precision="_numberSet.precision"
:step="_numberSet.step"
:min="_numberSet.min"
:controls-position="_numberSet.controlsPosition"
@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[props.prop.value]"
:label="item[props.prop.label]"
:value="item[props.prop.value]"
/>
</el-select>
</section>
</template>
<script 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',
},
],
},
set: {
type: Object,
default: () => {
return {};
},
},
numberSet: {
type: Object,
default: () => {
return {};
},
},
prop: {
type: Object,
default: () => {
return { label: 'label', value: 'value' };
},
},
});
const _numberSet = ref({
precision: 2,
step: 1,
min: 1,
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.numberSet);
if (data.value.num === null) {
data.value.num = _numberSet.value.min;
}
});
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

@ -19,6 +19,8 @@ import CustomEchartPieGauge from './custom-echart-pie-gauge';
import CustomEchartWordCloud from './custom-echart-word-cloud';
import customEchartScatterBlister from './custom-echart-scatter-blister';
import customEchartMaps from './custom-echart-maps';
import customNumberSelect from './custom-number-select';
import customNumberSelectDouble from './custom-number-select-double';
export {
SvgIcon,
@ -42,4 +44,6 @@ export {
CustomEchartWordCloud,
customEchartScatterBlister,
customEchartMaps,
customNumberSelect,
customNumberSelectDouble,
};

View File

@ -0,0 +1,5 @@
import * as produceList from './productList';
export default {
...produceList,
};

View File

@ -0,0 +1,43 @@
import request from '@/utils/axios';
/* 产出品列表 */
export function getProduceList(data) {
return request('/goods/business/goods/list', {
method: 'POST',
data,
});
}
/* 新增产出品 */
export function addProduceGoods(data) {
return request('/goods/business/goods/add', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
data: JSON.stringify(data),
});
}
/* 编辑产出品 */
export function editProduceGoods(data) {
return request('/goods/business/goods/edit', {
method: 'POST',
data,
});
}
/* 编辑产出品 */
export function delProduceGoods(data) {
return request('/goods/business/goods/remove', {
method: 'POST',
data,
});
}
/* 导出产出品列表 */
export function exportProduceGoods() {
return request(`/goods/business/goods/export`, {
method: 'POST',
responseType: 'blob',
});
}

View File

@ -14,6 +14,7 @@ import productOperateMainRoutes from './modules/productOperateMain';
import inputSuppliesRoutes from './modules/inputSupplies';
import plantingAndBreedingRouter from './modules/plantingAndBreeding';
import systemRouter from './modules/system';
import produceGoods from './modules/produceGoods';
export const constantRoutes = [
{
@ -46,6 +47,7 @@ export const constantRoutes = [
...resourceRouter,
...productOperateMainRoutes,
...inputSuppliesRoutes,
produceGoods,
...plantingAndBreedingRouter,
...traceRouter,
...systemRouter,

View File

@ -0,0 +1,24 @@
import Layout from '@/layouts/index.vue';
export default {
path: '/sub-government-affairs-service/produceGoodsMain',
name: 'produceGoodsMain',
component: Layout,
redirect: '/sub-government-affairs-service/produceGoods',
meta: { title: '产出品', icon: 'Document' },
children: [
{
path: '/sub-government-affairs-service/produceGoods',
name: 'produceGoods',
component: () => import('@/views/produceGoods/list/index.vue'),
meta: { title: '产出品列表', icon: 'Document' },
},
{
path: '/sub-government-affairs-service/produceGoods1',
name: 'produceGoods1',
component: () => import('@/views/produceGoods/test/index.vue'),
meta: { title: '投入品监管平台', icon: 'Document' },
},
],
};
// export default produceGoodsRoutes;

View File

@ -13,7 +13,7 @@
<el-icon class="custom-form__uploader__icon"><Plus /></el-icon>
</el-upload>
<div v-for="(item, i) in attrs_" :key="`attr_${item.uid}`" class="attrs_content__item">
<img :src="item.url" :alt="item.name" @click="handlePreview(i)" />
<img :src="item.url" @click="handlePreview(i)" />
<el-icon v-if="props.type != 'view'" class="clear_btn" @click.stop="handleClearAttr(item.uid)"><CircleCloseFilled /></el-icon>
</div>
<el-image-viewer v-if="previewShow" :url-list="srcList" :initial-index="index" @close="previewShow = false" />

View File

@ -0,0 +1,324 @@
<template>
<section class="custom-page">
<avue-crud
ref="crudRef"
v-model:search="searchCondition"
v-model:page="pageData"
:data
:option
:loading="_loading"
:before-close="handleCloseDialog"
@search-change="
(form, done) => {
getData(1);
done();
}
"
@search-reset="() => getData(1)"
@refresh-change="getData"
@current-change="getData"
@size-change="getData"
@row-save="handleRowSave"
@row-update="handleRowUpdate"
>
<!-- <template #menu-left>
<el-button type="success" @click="handleExport">
<el-icon><Download /></el-icon>导出
</el-button>
</template> -->
<template #_quantity-form="{ type, row }">
<template v-if="type === 'view'">{{ row.quantity }}{{ row.unit }}</template>
<template v-else>
<custom-number-select v-model:value="produceNum" :options="numUnitOptions" />
</template>
</template>
<template #marketPrice-form="{ type, row }">
<template v-if="type === 'view'">{{ row.priceOptions }}</template>
<template v-else>
<custom-number-select-double v-model:value="priceData" :options1="priceOptions" :options2="numUnitOptions" />
</template>
</template>
<template #menu="scope">
<custom-table-operate :actions="actions" :data="scope" />
</template>
</avue-crud>
</section>
</template>
<script setup>
import { ref, onMounted, reactive } from 'vue';
import { CRUD_OPTIONS, pageData, customRules } from '@/config';
import produceGoodsApi from '@/apis/produceGoodsApi';
import dayjs from 'dayjs';
import { GetEntityList } from '@/apis/system/dict';
import { getLandsList } from '@/apis/land';
import { ElMessage } from 'element-plus';
// import { Download } from '@element-plus/icons-vue';
const { getProduceList, addProduceGoods, editProduceGoods, exportProduceGoods } = produceGoodsApi;
onMounted(async () => {
await getBusiness();
await getLands();
await getPriceUnit();
await getData();
});
/* --------------- data --------------- */
// #region
const crudRef = ref();
const _loading = ref(false);
const searchCondition = ref({
landName: '',
quantity: null,
qualityGrade: '',
});
const produceNum = ref({
num: 1,
type: '公斤',
});
const numUnitOptions = reactive([
{ label: '公斤', value: '公斤' },
{ label: '吨', value: '吨' },
]);
const priceData = ref({
num: 1,
value1: '1',
value2: '公斤',
});
const priceOptions = ref([]);
const data = ref([]);
const option = ref({
...CRUD_OPTIONS,
showOverflowTooltip: true,
column: [
{
search: true,
label: '地块名称',
prop: 'landName',
type: 'select',
dicData: [],
props: {
label: 'landName',
value: 'id',
},
rules: customRules({ msg: '请选择地块' }),
},
{
hide: true,
search: true,
addDisplay: false,
editDisplay: false,
viewDisplay: false,
label: '亩产',
prop: 'quantity',
type: 'select',
dicData: [
{ label: '<30公斤', value: 30 },
{ label: '<300公斤', value: 300 },
{ label: '<3000公斤', value: 3000 },
],
},
{
label: '种植作物',
prop: 'goodsName',
// rules: customRules({ msg: '' }),
},
{
label: '种植面积',
prop: 'area',
addDisplay: false,
editDisplay: false,
},
{
label: '经营主体',
prop: 'producerName',
dicData: [],
props: {
label: 'dictLabel',
value: 'dictValue',
},
type: 'select',
rules: customRules({ msg: '请选择经营主体' }),
},
{
label: '生长周期',
type: 'number',
precision: 1,
min: 1,
prop: 'growthCycle',
suffix: '天',
rules: customRules({ msg: '请输入生长周期' }),
},
{
label: '产地',
prop: 'originPlace',
addDisplay: false,
editDisplay: false,
},
{
label: '亩产',
prop: '_quantity',
render: ({ row }) => `${row.quantity}${row.unit}`,
},
{
search: true,
label: '质量登记',
type: 'select',
dicData: [
{ label: '一级', value: '1' },
{ label: '二级', value: '2' },
{ label: '三级', value: '3' },
],
prop: 'qualityGrade',
rules: customRules({ msg: '请选择经营主体' }),
},
{
label: '单价',
prop: 'marketPrice',
},
{
label: '创建时间',
prop: 'createTime',
render: ({ row }) => dayjs(row.createTime).format('YYYY-MM-DD'),
addDisplay: false,
editDisplay: false,
},
],
});
const actions = reactive([
{
name: '详情',
icon: 'view',
event: ({ row }) => {
// handleCheckRegister(0);
crudRef.value.rowView(row);
},
},
{
name: '编辑',
icon: 'edit',
event: ({ row }) => {
crudRef.value.rowEdit(row);
},
},
{
type: 'danger',
name: '删除',
icon: 'delete',
event: ({ row }) => row,
},
]);
// #endregion
/* --------------- methods --------------- */
// #region
async function getBusiness() {
let res = await GetEntityList({
dictType: 'sys_business_type',
current: 1,
size: 999,
});
if (res.code == 200) {
option.value.column[4].dicData = res.data.records;
}
}
async function getLands() {
let res = await getLandsList({
current: 1,
size: 999,
});
if (res.code == 200) {
option.value.column[0].dicData = res.data.records;
}
console.log('res', res);
}
async function getPriceUnit() {
let res = await GetEntityList({ dictType: 'sys_price_unit', current: 1, size: 999 });
if (res.code == 200) {
priceOptions.value = res.data.records
.map((v) => {
return {
label: v.dictLabel,
value: v.dictValue,
};
})
.sort((a, b) => a - b);
priceData.value.value1 = priceOptions.value[0].value;
console.log('priceData', priceData.value);
}
}
async function getData(resetPage) {
resetPage === 1 && (pageData.value.currentPage = 1);
_loading.value = true;
let _data = {
current: pageData.value.currentPage,
size: pageData.value.pageSize,
...searchCondition.value,
};
let res = await getProduceList(_data);
if (res.code == 200) {
data.value = res.data.records;
console.log('data', data.value);
pageData.value.total = res.data.total;
}
_loading.value = false;
}
function handleCloseDialog(done) {
done();
}
function handleData(val) {
let _data = Object.assign({}, val);
return {
// id: _data.id,
landName: _data.landName,
producerName: _data.producerName,
growthCycle: _data.growthCycle,
qualityGrade: _data.qualityGrade,
goodsName: _data.goodsName,
plantingId: '0',
quantity: produceNum.value.num,
unit: produceNum.value.type,
marketPrice: priceData.value.num,
priceUnit: priceData.value.value1,
weightUnit: priceData.value.value2,
};
}
async function handleRowSave(row, done, loading) {
let _data = handleData(row);
console.log(_data);
let res = await addProduceGoods(_data);
loading();
if (res.code == 200) {
ElMessage.success('保存成功');
getData();
}
done();
}
async function handleRowUpdate(row, index, done, loading) {
// let data = handleData(row);
// let res;
// loading();
// if (res.code == 200) {
// ElMessage.success(`${basicInfo.value ? '' : ''}`);
// getData();
// }
done();
}
// async function handleExport() {
// let res = await exportProduceGoods();
// console.log('res', res);
// if (res.status == 200) {
// let a = document.createElement('a');
// let blob = new Blob([res.data]);
// let link = window.URL.createObjectURL(blob);
// a.href = link;
// a.download = '.xlsx';
// document.body.appendChild(a);
// a.click();
// document.body.removeChild(a);
// window.URL.revokeObjectURL(link);
// }
// }
// #endregion
</script>
<style lang="scss" scoped></style>

View File

@ -0,0 +1,19 @@
<template>
<section>1111111111111</section>
</template>
<script setup>
import { ref } from 'vue';
/* --------------- data --------------- */
// #region
// #endregion
/* --------------- methods --------------- */
// #region
// #endregion
</script>
<style lang="scss" scoped></style>