Merge remote-tracking branch 'origin/dev' into dev

This commit is contained in:
姚俊旭 2025-05-29 18:02:51 +08:00
commit aa6362ca5b
45 changed files with 1630 additions and 284 deletions

View File

@ -11,7 +11,10 @@ VITE_APP_SUB_GSS = '//localhost:9529/sub-government-screen-service/'
VITE_APP_SUB_GSR = '//localhost:9530/new-digital-agriculture-screen/'
# 接口
VITE_APP_BASE_API = '/apis'
# VITE_APP_BASE_URL = 'http://192.168.18.99:8080'
VITE_APP_BASE_URL = 'http://192.168.18.9:8080'
VITE_APP_UPLOAD_API = '/uploadApis'
VITE_APP_UPLOAD_URL = 'http://192.168.18.99:8080'
# 阿里云接口地址
# VITE_APP_BASE_URL = 'http://47.109.205.240:8080'
# VITE_APP_UPLOAD_URL = 'http://47.109.205.240:9300'
# 内网接口地址
VITE_APP_BASE_URL = 'http://192.168.18.9:8080'
VITE_APP_UPLOAD_URL = 'http://192.168.18.9:9300'

2
main/.gitignore vendored
View File

@ -23,3 +23,5 @@ dist-ssr
*.njsproj
*.sln
*.sw?
*.zip
*.rar

View File

@ -13,7 +13,7 @@ export const leftApps = [
{
name: 'sub-operation-admin',
entry: VITE_APP_SUB_OA,
activeRule: '/sub-operation-admin',
activeRule: 'http://192.168.18.99:82/login?loginType=2',
title: '管理后台',
icon: 'images/platform/icon-admin.png',
},
@ -44,7 +44,7 @@ export const rightApps = [
{
name: 'sub-government-admin',
entry: VITE_APP_SUB_GAS,
activeRule: '/sub-government-affairs-service',
activeRule: 'http://192.168.18.99:81/login?loginType=1',
title: '管理后台',
icon: 'images/platform/icon-admin.png',
},

View File

@ -4,9 +4,14 @@ VITE_MODE = 'DEV'
VITE_APP_MIAN = 'daimp-front-main'
VITE_APP_MIAN_URL = 'http://localhost:9000'
VITE_APP_NAME = 'sub-government-affairs-service'
VITE_APP_BASE_API = '/apis'
# VITE_APP_BASE_URL = 'http://192.168.18.99:8080'
VITE_APP_BASE_URL = 'http://192.168.18.9:8080'
VITE_APP_UPLOAD_API = '/uploadApis'
# 阿里云接口地址
# VITE_APP_BASE_URL = 'http://47.109.205.240:8080'
# VITE_APP_UPLOAD_URL = 'http://47.109.205.240:9300'
# 内网接口地址
VITE_APP_BASE_URL = 'http://192.168.18.99:8080'
VITE_APP_UPLOAD_URL = 'http://192.168.18.99:9300'
# VITE_APP_UPLOAD_URL = 'http://192.168.18.14:8080'

View File

@ -0,0 +1,140 @@
<template>
<div class="area-cascader-container">
<div v-if="label" class="area-cascader-label">{{ label }}</div>
<div style="display: flex; gap: 8px" :style="{ width: width + 'px' }">
<el-cascader
v-model="selectedAreaCode"
:options="areaOptions"
:props="cascaderProps"
:placeholder="areaPlaceholder"
style="flex: 1"
clearable
/>
<el-select v-model="selectedGridName" :placeholder="gridPlaceholder" style="flex: 1" clearable :disabled="!selectedAreaCode">
<el-option v-for="item in gridOptions" :key="item.gridName" :label="item.gridName" :value="item.gridName" />
</el-select>
</div>
</div>
</template>
<script setup>
import { ref, watch, onMounted, computed } from 'vue';
import { ElCascader, ElSelect, ElOption } from 'element-plus';
import axios from 'axios';
import { useUserStore } from '@/store/modules/user';
const props = defineProps({
value: {
type: Object,
default: () => ({}),
},
label: {
type: String,
default: '所属行政区域-网格:',
},
placeholder: {
type: String,
default: '请选择区域',
},
width: {
type: [Number, String],
default: 300,
},
});
const emit = defineEmits(['update:value']);
const userStore = useUserStore();
const areaOptions = ref([]);
const gridOptions = ref([]);
const selectedAreaCode = ref('');
const selectedGridName = ref('');
//
const fetchAreaData = async () => {
try {
const res = await axios.get(`${import.meta.env.VITE_APP_BASE_API}/system/area/region?areaCode=530000`, {
headers: {
authorization: userStore.token,
},
});
areaOptions.value = res.data?.data ?? [];
} catch (err) {
console.error('区域数据加载失败', err);
}
};
//
const fetchGridList = async (regionCode) => {
if (!regionCode) return;
try {
const res = await axios.get(`${import.meta.env.VITE_APP_BASE_API}/land-resource/gridManage/page?regionCode=${regionCode}`, {
headers: {
authorization: userStore.token,
},
});
gridOptions.value = res.data?.data?.records ?? [];
} catch (err) {
console.error('网格数据加载失败', err);
}
};
//
watch(selectedAreaCode, (val) => {
selectedGridName.value = '';
fetchGridList(val);
updateValue();
});
//
watch(selectedGridName, () => {
updateValue();
});
//
watch(
() => props.value,
(val) => {
selectedAreaCode.value = val.regionCode ?? '';
selectedGridName.value = val.gridName ?? '';
},
{ immediate: true }
);
// v-model:value
const updateValue = () => {
emit('update:value', {
regionCode: selectedAreaCode.value,
gridName: selectedGridName.value,
});
};
onMounted(() => {
fetchAreaData();
});
//
const cascaderProps = computed(() => ({
label: 'areaName',
value: 'areaCode',
children: 'areaChildVOS',
emitPath: false,
expandTrigger: 'hover',
}));
</script>
<style scoped>
.area-cascader-container {
display: flex;
/* flex-direction: column; */
gap: 8px;
}
.area-cascader-label {
font-size: 14px;
color: #606266;
align-self: center;
}
</style>

View File

@ -9,12 +9,12 @@ const dictRoutes = [
redirect: '/sub-government-affairs-service/region',
meta: { title: '基础信息维护', icon: 'DocumentRemove' },
children: [
// {
// path: '/sub-government-affairs-service/region',
// name: 'region',
// component: () => import('@/views/dict/component/region/index.vue'),
// meta: { title: '行政信息', icon: '' },
// },
{
path: '/sub-government-affairs-service/region',
name: 'region',
component: () => import('@/views/dict/component/region/index.vue'),
meta: { title: '行政信息', icon: '' },
},
{
path: '/sub-government-affairs-service/landCassification',
name: 'landCassification',

View File

@ -9,24 +9,24 @@ const landsRoutes = [
redirect: '/sub-government-affairs-service/plantPlan',
meta: { title: '土地管理', icon: 'Grape' },
children: [
// {
// path: '/sub-government-affairs-service/landsManage',
// name: 'landsManage',
// component: () => import('@/views/landManage/component/landsManage/index.vue'),
// meta: { title: '土地信息登记', icon: '' },
// },
// {
// path: '/sub-government-affairs-service/plantPlan',
// name: 'plantPlan',
// component: () => import('@/views/landManage/component/plantPlan/index.vue'),
// meta: { title: '种植计划', icon: '' },
// },
// {
// path: '/sub-government-affairs-service/operationRecord',
// name: 'operationRecord',
// component: () => import('@/views/landManage/component/operationRecord/index.vue'),
// meta: { title: '作业记录', icon: '' },
// },
{
path: '/sub-government-affairs-service/landsManage',
name: 'landsManage',
component: () => import('@/views/landManage/component/landsManage/index.vue'),
meta: { title: '土地信息登记', icon: '' },
},
{
path: '/sub-government-affairs-service/plantPlan',
name: 'plantPlan',
component: () => import('@/views/landManage/component/plantPlan/index.vue'),
meta: { title: '种植计划', icon: '' },
},
{
path: '/sub-government-affairs-service/operationRecord',
name: 'operationRecord',
component: () => import('@/views/landManage/component/operationRecord/index.vue'),
meta: { title: '作业记录', icon: '' },
},
{
path: '/sub-government-affairs-service/landPartol',
name: 'landPartol',

View File

@ -31,12 +31,12 @@ export default [
name: 'member',
meta: { title: '新增网格员', icon: '' },
},
// {
// path: '/sub-government-affairs-service/grid--management',
// component: () => import('@/views/resource/grid/GridManagement.vue'),
// name: 'management',
// meta: { title: '网格化管理', icon: '' },
// },
{
path: '/sub-government-affairs-service/grid--management',
component: () => import('@/views/resource/grid/GridManagement.vue'),
name: 'management',
meta: { title: '网格化管理', icon: '' },
},
],
},
...annualplanRouters,

View File

@ -116,7 +116,7 @@ const state = reactive({
addBtnText: '',
addBtn: false,
column: [
{ label: '计划编号', prop: 'id', width: '200px', showOverflowTooltip: true, addDisplay: false, editDisplay: false },
{ label: '计划编号', prop: 'id', width: '200px', search: true, showOverflowTooltip: true, addDisplay: false, editDisplay: false },
{
label: '计划名称',
prop: 'planName',
@ -129,14 +129,18 @@ const state = reactive({
trigger: 'blur',
},
},
{ label: '种植作物', prop: 'cropsName', width: '120px', search: true, editDisplay: false },
{
label: '种植面积(亩)',
label: '种植面积',
prop: 'plantingArea',
append: '亩',
rules: {
required: true,
message: '请输入',
trigger: 'blur',
},
// formatter: (value) => `${value} `,
formatter: (row, column, cellValue) => `${cellValue}`,
},
{
label: '种植月份',
@ -154,9 +158,10 @@ const state = reactive({
}
},
},
formatter: (row, column, cellValue) => `${cellValue}`,
},
{
label: '生长周期(周)',
label: '生长周期',
prop: 'growthCycle',
width: '120px',
viewDisabled: true,
@ -172,20 +177,33 @@ const state = reactive({
}
},
},
},
{
label: '备注',
prop: 'note',
width: '180px',
showOverflowTooltip: true,
rules: {
required: true,
message: '请输入',
trigger: 'blur',
formatter: (row, column, cellValue) => {
const unitMap = {
1: '天',
2: '周',
3: '月',
4: '年',
};
const unit = unitMap[row.growthCycleUnit] || '';
return `${cellValue} ${unit}`;
},
},
{ label: '计划进度', prop: 'planProgress', addDisplay: false, editDisplay: false },
{ label: '状态', prop: 'planStatus', addDisplay: false, editDisplay: false },
{ label: '所属行政区域', prop: 'regionName', width: '120px', search: true, searchLabelWidth: 100, addDisplay: false, editDisplay: false },
{ label: '所属网格', prop: 'gridName', width: '120px', search: true, addDisplay: false, editDisplay: false },
{ label: '当前进度', prop: 'currentProgress', width: '120px', addDisplay: false, editDisplay: false },
// {
// label: '',
// prop: 'note',
// width: '180px',
// showOverflowTooltip: true,
// rules: {
// required: true,
// message: '',
// trigger: 'blur',
// },
// },
// { label: '', prop: 'planProgress', addDisplay: false, editDisplay: false },
// { label: '', prop: 'planStatus', addDisplay: false, editDisplay: false },
],
actions: [
{

View File

@ -0,0 +1,37 @@
<template>
<div class="grid-records"></div>
</template>
<script setup>
import { ref } from 'vue';
import { ElMessage } from 'element-plus';
const records = ref([
{
createTime: '2025-05-26 09:58:29',
createUser: '1',
updateTime: '2025-05-26T10:02:02.000+08:00',
updateUser: '1',
tenantId: 0,
id: '1926820200675004417', //
year: null,
regionCode: null, //
cropsId: null, // id
gridId: null, // id
planName: '大兴乡2025水稻种植计划', //
plantingArea: 120, //
plantingAreaActual: 335, //
plantingMonths: '1', //
growthCycle: '20', //
growthCycleUnit: '1', // 1 2 3 4
note: '暂无备注', //
deleteFlag: '0', // 0 1
cropsName: '', //
gridName: null, //
regionName: null, //
currentProgress: 279.17, //
actualFlag: '1', // 0: 1
},
]);
</script>
<style scoped></style>

View File

@ -120,44 +120,27 @@ const option = reactive({
menuWidth: 120,
selection: false,
column: [
// {
// hide: true,
// label: '',
// prop: 'landType',
// search: true,
// type: 'cascader',
// dicData: landTreeDic,
// clearable: false,
// value: [],
// addDisplay: false,
// display: false,
// editDisplay: false,
// },
{
hide: true,
label: '用地分类',
prop: 'landType',
search: true,
type: 'cascader',
dicData: landTreeDic,
clearable: false,
value: [],
addDisplay: false,
display: false,
editDisplay: false,
},
{
label: '地块名',
label: '地块名称',
prop: 'landName',
search: true,
addDisplay: false,
display: false,
editDisplay: false,
width: 200,
},
{
label: '地址',
prop: 'address',
addDisplay: false,
display: false,
editDisplay: false,
width: 300,
},
{
label: '产权人',
prop: 'owner',
search: true,
addDisplay: false,
display: false,
editDisplay: false,
},
{
label: '所属网格',
prop: 'gridName',
@ -167,16 +150,6 @@ const option = reactive({
display: false,
editDisplay: false,
},
{
label: '农用地分类',
prop: 'landClassificationType',
select: 'select',
dicData: landTreeDic,
addDisplay: false,
display: false,
editDisplay: false,
width: 300,
},
{
label: '面积',
prop: 'area',
@ -192,20 +165,39 @@ const option = reactive({
},
},
{
label: '坐标',
prop: 'coordinate',
label: '土地类型',
prop: 'landTypeName',
search: true,
addDisplay: false,
},
{
label: '所属行政区域',
prop: 'regionName',
search: true,
addDisplay: false,
},
{
label: '具体位置',
prop: 'address',
addDisplay: false,
display: false,
editDisplay: false,
width: 300,
},
{
label: '是否流转土地',
prop: 'landTransfer',
label: '产权人姓名',
prop: 'owner',
addDisplay: false,
display: false,
editDisplay: false,
width: 140,
},
{
label: '产权人联系方式',
prop: 'ownerPhone',
addDisplay: false,
display: false,
editDisplay: false,
width: 300,
},
{
label: '产权编号',
@ -215,18 +207,10 @@ const option = reactive({
editDisplay: false,
},
{
label: '土壤类型',
prop: 'soilTypeName',
addDisplay: false,
editDisplay: false,
},
{
label: '是否上传附件',
prop: 'isUpload',
label: '信息录入时间',
prop: 'createTime',
addDisplay: false,
display: false,
editDisplay: false,
width: 140,
},
],
group: [

View File

@ -0,0 +1,7 @@
<script setup></script>
<template>
<div>123</div>
</template>
<style scoped></style>

View File

@ -18,6 +18,10 @@
@row-update="rowUpdate"
@row-del="rowDel"
>
<template #search="{ size }">
<AreaCascader v-model:value="state.query" placeholder="选择行政区域与网格" :width="400" />
</template>
<template #menu-left>
<el-button type="success" icon="download" @click="onExport">导出</el-button>
</template>
@ -25,6 +29,23 @@
<template #menu="scope">
<custom-table-operate :actions="state.options.actions" :data="scope" />
</template>
<template #detail="scope">
<el-tabs type="border-card">
<el-tab-pane label="基本信息">
<avue-detail :option="baseDetailOption" :data="scope.row"></avue-detail>
</el-tab-pane>
<el-tab-pane label="网格地图">
<div v-if="scope.row.mapUrl" style="height: 400px">
<img :src="scope.row.mapUrl" style="max-width: 100%; max-height: 100%" />
</div>
<el-empty v-else description="暂无地图数据"></el-empty>
</el-tab-pane>
<el-tab-pane label="其他信息">
<avue-detail :option="otherDetailOption" :data="scope.row"></avue-detail>
</el-tab-pane>
</el-tabs>
</template>
</avue-crud>
</div>
</template>
@ -46,31 +67,20 @@ const state = reactive({
query: {
current: 1,
size: 10,
gridName: '',
regionCode: '',
},
form: {},
selection: [],
options: {
...CRUD_OPTIONS,
// addBtnText: '',
addBtnText: '添加网格',
// detail: true,
// detailTitle: '',
column: [
// {
// label: '',
// prop: 'gridArea',
// search: true,
// width: 200,
// addDisplay: false,
// editDisplay: false,
// viewDisplay: true,
// rules: {
// required: true,
// message: '',
// trigger: 'blur',
// },
// },
{
label: '网格名称',
prop: 'gridName',
search: true,
rules: {
required: true,
message: '请输入',
@ -78,10 +88,10 @@ const state = reactive({
},
},
{
label: '网格区域',
label: '所属行政区域',
prop: 'gridAreaName',
// width: 300,
display: false,
addDisplay: false,
viewDisplay: true,
rules: {
required: true,
message: '请输入',
@ -89,18 +99,16 @@ const state = reactive({
},
},
{
label: '网格区域',
label: '所属行政区域',
prop: 'cities',
type: 'cascader',
hide: true,
span: 24,
width: 300,
addDisplay: true,
editDisplay: true,
viewDisplay: false,
// multiple: true,
// checkStrictly: true,
// collapseTags: true,
// emitPath: false,
// checkDescendants: false,
emitPath: false,
props: {
label: 'areaName',
value: 'areaCode',
@ -117,54 +125,31 @@ const state = reactive({
trigger: 'blur',
},
},
{
label: '网格地图',
prop: 'mapUrl',
type: 'upload',
hide: true,
// action: `${VITE_APP_BASE_API}/system/file/upload`,
},
// {
// label: '',
// prop: 'gridManager',
// rules: {
// required: true,
// message: '',
// trigger: 'blur',
// label: '',
// prop: 'gridName',
// type: 'select',
// addDisplay: false,
// hide: true,
// // search: true,
// searchLabelWidth: 100,
// dicUrl: `${VITE_APP_BASE_API}/land-resource/gridManage/page?regionCode={{key}}`,
// props: {
// label: 'gridName',
// value: 'gridName',
// },
// },
// {
// label: '',
// prop: 'contactInfo',
// rules: {
// required: true,
// message: '',
// trigger: 'blur',
// dicHeaders: {
// authorization: UserStore.token,
// },
// dicFormatter: (res) => res.data?.records,
// },
{
label: '省',
prop: 'provinceCode',
hide: true,
display: false,
},
{
label: '市',
prop: 'cityCode',
hide: true,
display: false,
},
{
label: '县/区',
prop: 'gridAreaCode',
hide: true,
display: false,
},
{
label: '乡镇',
prop: 'townCode',
hide: true,
display: false,
},
{
label: '乡镇',
prop: 'village',
hide: true,
display: false,
},
{
label: '备注',
prop: 'note',
@ -209,6 +194,32 @@ const state = reactive({
data: [],
currentRow: {},
});
const baseDetailOption = {
column: [
{
label: '网格名称',
prop: 'gridName',
},
{
label: '所属行政区域',
prop: 'gridAreaName',
},
{
label: '备注',
prop: 'note',
},
],
};
const otherDetailOption = {
column: [
{
label: '创建时间',
prop: 'createTime',
},
// ...
],
};
//
const loadData = () => {

View File

@ -82,7 +82,7 @@ const state = reactive({
type: 'select',
width: 200,
search: true,
dicData: [], // mounted
dicData: [], // loadGridOptions
props: {
label: 'gridName',
value: 'id',
@ -93,17 +93,17 @@ const state = reactive({
trigger: 'change',
},
},
{
label: '管理员标识',
prop: 'adminFlag',
type: 'radio',
dicData: [
{ label: '是', value: '1' },
{ label: '否', value: '0' },
],
valueDefault: '0',
hide: true, // false
},
// {
// label: '',
// prop: 'adminFlag',
// type: 'radio',
// dicData: [
// { label: '', value: '1' },
// { label: '', value: '0' },
// ],
// valueDefault: '0',
// hide: true, // false
// },
{
label: '电话号码',
prop: 'phone',

View File

@ -0,0 +1,3 @@
<template>计划</template>
<script></script>
<style></style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 600 B

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 669 B

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 804 B

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 964 B

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 772 B

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

View File

@ -85,6 +85,12 @@ export const constantRoutes = [
name: 'myFinance',
meta: { title: '我的金融' },
},
{
path: '/sub-operation-service/myBrand',
component: () => import('@/views/userCenter/myBrand.vue'),
name: 'myBrand',
meta: { title: '我的品牌' },
},
],
},

View File

@ -66,7 +66,7 @@ const leftMenu = reactive([
name: 'control',
title: '包装',
icon: 'menu3.png',
path: '/sub-operation-service/packaging/sorting',
path: '/sub-operation-service/packaging/index',
isOpen: false,
children: [],
},

View File

@ -1,19 +1,474 @@
<template>
<div></div>
<el-dialog v-model="dialogVisible" :close-on-click-modal="false" custom-class="custom-inquiry-dialog" width="450px">
<div class="info-section">
<div class="info-item">
<span class="label">首选商家</span>
<span class="value">{{ diodescription }}</span>
</div>
<div class="info-item">
<span class="label">选择服务</span>
<span class="value">{{ diotext }}</span>
</div>
</div>
<el-form ref="formRef" :model="form" label-position="top">
<el-form-item label="需求量:" prop="quantity" :rules="[{ required: true, message: '请输入重量' }]">
<el-input v-model="form.quantity" placeholder="请输入重量kg">
<template #suffix>kg</template>
</el-input>
</el-form-item>
<el-form-item label="您的称呼:" prop="name" :rules="[{ required: true, message: '请输入您的称呼' }]">
<el-input v-model="form.name" placeholder="请输入您的称呼" />
</el-form-item>
<el-form-item
label="您的电话:"
prop="phone"
:rules="[
{ required: true, message: '请输入电话' },
{ pattern: /^1[3-9]\d{9}$/, message: '手机号格式错误' },
]"
>
<el-input v-model="form.phone" placeholder="请输入电话号码" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button class="cancel-btn" @click="dialogVisible = false">取消</el-button>
<el-button class="submit-btn" type="primary" @click="handleSubmit">发送询价</el-button>
</div>
</template>
</el-dialog>
<!-- <page-layout :menus="state.menus"> </page-layout>-->
<section>
<common>
<template #main>
<el-card shadow="none" style="border-radius: 14px; height: 200px">
<div class="tabs">
<div class="tab cursor">
<div class="tab_list">塑料类包装</div>
<div
v-for="(item, index) in tab1"
:key="index"
class="tab_list_li"
:class="{ active: currentTab1 === index }"
@click.stop="currentTab1 = index"
>
{{ item }}
</div>
</div>
<div class="tab cursor">
<div class="tab_list">纸类包装</div>
<div
v-for="(item, index) in tab2"
:key="index"
class="tab_list_li"
:class="{ active: currentTab2 === index }"
@click.stop="currentTab2 = index"
>
{{ item }}
</div>
</div>
<div class="tab cursor">
<div class="tab_list">金属类包装</div>
<div
v-for="(item, index) in tab3"
:key="index"
class="tab_list_li"
:class="{ active: currentTab3 === index }"
@click.stop="currentTab3 = index"
>
{{ item }}
</div>
</div>
</div>
</el-card>
<el-row :gutter="20" style="margin-top: 10px">
<el-col v-for="(item, index) in state.data" :key="index" :span="12">
<el-card class="storage-card" shadow="hover">
<div class="storage-content">
<div class="storage-content-top" @click="toLink(item)">
<img :src="getAssetsFile(`${item.imageUrl}`)" fit="cover" class="storage-image" />
<div class="storage-info">
<h3 class="storage-title">{{ item.title }}</h3>
<div class="storage-desc">
<span>{{ item.description }}</span>
<img :src="getAssetsFile('images/warehouseLogistics/认证.png')" alt="" style="width: 20px" />
<img :src="getAssetsFile('images/warehouseLogistics/优先级.png')" alt="" style="width: 20px" />
</div>
<div class="storage-tags">
<el-tag effect="plain" round style="background-color: rgba(37, 191, 130, 0.2); color: #25bf82">高品质</el-tag>
<el-tag effect="plain" round style="background-color: rgba(37, 191, 130, 0.2); color: #25bf82">食品级</el-tag>
<el-tag effect="plain" round style="background-color: rgba(37, 191, 130, 0.2); color: #25bf82">塑料</el-tag>
</div>
<div class="storage-location">
<el-icon><Location /></el-icon>
{{ item.location }}
</div>
</div>
</div>
<div class="storage-price">
<div class="storage-price-left">
<span class="price-label">报价</span>
<span class="price-amount">¥{{ item.price }}/m</span>
</div>
<el-button type="success" class="contact-btn" @click="goDei(item)">
<img :src="getAssetsFile('images/warehouseLogistics/messageBox.png')" alt="" style="height: 30px; margin-right: 5px" />
<span>联系卖家</span>
</el-button>
</div>
<div v-if="item.rank" class="rank-badge">
<!-- {{ item.rank }}-->
<img :src="getAssetsFile('images/warehouseLogistics/top' + item.rank + '.png')" alt="" style="width: 80px" />
</div>
</div>
</el-card>
</el-col>
</el-row>
<page-pagination :total="6" @current-change="currentChange" />
</template>
</common>
</section>
</template>
<script setup name="page-menu">
import { ref, reactive, watch } from 'vue';
import { getAssetsFile } from '@/utils';
import { useRoute, useRouter } from 'vue-router';
import warehouseLogisticsRoutes from '@/router/modules/warehouseLogistics';
import Common from './components/common.vue';
<script setup>
import { ref } from 'vue';
const route = useRoute();
const router = useRouter();
/* --------------- data --------------- */
// #region
const tab1 = reactive(['塑料类薄膜袋', '塑料瓶/壶', '塑料桶', '塑料盒', '塑料箱', '其他塑料包装制品']);
const tab2 = reactive(['纸盒', '纸箱', '纸袋', '其他纸类包装容器']);
const tab3 = reactive(['金属罐', '金属桶', '金属盒', '其他金属类包装容器']);
const state = reactive({
menus: warehouseLogisticsRoutes[0].children,
query: {
current: 1,
},
data: [
{
imageUrl: 'images/film.png',
title: '薄膜包装服务',
description: '薄膜包装有限公司 ',
location: '临沧市-耿马县',
price: '3',
rank: '1',
},
{
imageUrl: 'images/plastics.png',
title: '塑料袋包装服务',
description: '塑料包装有限公司',
location: '临沧市-耿马县',
price: '150',
rank: '2',
},
{
imageUrl: 'images/carton.png',
title: '纸盒包装服务',
description: '保和纸盒包装厂',
location: '临沧市-耿马县',
price: '5',
rank: '3',
},
{
imageUrl: 'images/metal.png',
title: '金属罐包装服务',
description: '金属罐头厂',
location: '临沧市-耿马县',
price: '8',
rank: '',
},
],
});
// #endregion
const currentTab1 = ref(0);
const currentTab2 = ref(0);
const currentTab3 = ref(0);
const dialogVisible = ref(false);
const formRef = ref(null);
/* --------------- methods --------------- */
// #region
const form = reactive({
quantity: '',
title: '',
phone: '',
name: '',
});
// #endregion
const diotext = ref('');
const diodescription = ref('');
const goDei = (data) => {
diodescription.value = data.description;
diotext.value = data.title;
dialogVisible.value = true;
};
const handleSubmit = () => {
formRef.value.validate((valid) => {
if (valid) {
console.log('提交数据:', form);
dialogVisible.value = false;
}
});
};
const currentChange = (current) => {
state.query.current = current;
};
const toLink = (row) => {
// router.push({
// path: '/sub-operation-service/warehouse-detail',
// query: { id: row?.id ?? '100' },
// });
};
</script>
<style lang="scss" scoped>
//
$primary-color: #25bf82; //
$text-dark: #25bf82; //
$text-regular: #606266; //
$border-color: #dcdfe6; //
<style lang="scss" scoped></style>
//
:deep(.custom-inquiry-dialog) {
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
.el-dialog__header {
padding: 20px;
border-bottom: 1px solid #f2f6fc;
.el-dialog__title {
font-size: 18px;
color: $text-dark;
font-weight: 600;
}
}
.el-dialog__body {
padding: 20px 28px;
}
.el-form-item__label {
color: $text-regular;
font-size: 14px;
padding-bottom: 6px;
}
}
.info-section {
padding: 0px 50px;
margin-bottom: 24px;
.info-item {
margin-bottom: 12px;
.label {
color: $text-regular;
margin-right: 8px;
font-size: 20px;
}
.value {
color: $text-dark;
font-weight: 500;
font-size: 20px;
}
}
}
//
:deep(.el-input) {
.el-input__inner {
height: 40px;
line-height: 40px;
border-radius: 4px;
&:focus {
border-color: $primary-color;
}
}
.el-input__suffix {
color: $text-regular;
right: 12px;
}
}
//
:deep(.custom-select-dropdown) {
.el-select-dropdown__item {
color: $text-regular;
&.selected {
color: $primary-color;
}
}
}
//
.dialog-footer {
text-align: right;
.el-button {
padding: 10px 24px;
border-radius: 4px;
font-size: 14px;
}
.cancel-btn {
color: $text-regular;
&:hover {
color: $primary-color;
border-color: $primary-color;
}
}
.submit-btn {
color: #fff;
background: $primary-color;
&:hover {
background: mix($primary-color, #fff, 85%);
}
}
}
.tabs {
height: 160px;
line-height: 50px;
display: flex;
flex-direction: column;
font-size: 18px;
align-items: flex-start;
justify-content: space-between;
padding: 0 20px;
}
.tab {
height: 100px;
width: 850px;
display: flex;
align-items: center;
justify-content: flex-start;
overflow-x: auto;
overflow: auto; /* 启用滚动 */
white-space: nowrap; /* 强制单行显示 */
-ms-overflow-style: none; /* IE/Edge 兼容 */
scrollbar-width: none; /* 隐藏滚动条 */
.tab_list {
color: #999999;
font-size: 20px;
font-weight: 400;
}
.tab_list_li {
margin-left: 40px;
color: #000000;
font-size: 20px;
font-weight: 400;
}
.tab_list_li.active {
color: rgba(37, 191, 130, 1);
}
}
.cursor {
cursor: pointer;
}
.active {
color: rgba(37, 191, 130, 1);
}
.storage-card {
position: relative;
overflow: hidden;
margin-bottom: 20px;
border: 0;
border-radius: 24px;
}
.storage-content {
@include flex-column;
gap: 16px;
&-top {
@include flex-row;
align-items: center;
}
}
.storage-image {
margin-right: 16px;
width: 120px;
height: 120px;
border-radius: 8px;
object-fit: cover;
}
.storage-info {
padding-right: 50px;
flex: 1;
cursor: pointer;
}
.storage-title,
.storage-desc,
.storage-tags,
.storage-location {
overflow: hidden;
margin: 10px 0;
width: 100%;
text-align: left;
}
.storage-title {
font-size: 20px;
font-weight: 700;
color: #000000;
@include ellipsis;
}
.storage-desc {
font-size: 16px;
color: #999999;
@include ellipsis;
i {
display: inline-block;
width: 20px;
height: 20px;
}
}
.storage-tags {
span {
margin-right: 10px;
}
}
.storage-location {
display: flex;
align-items: center;
font-size: 16px;
font-weight: 400;
color: #000000;
}
.storage-price {
display: flex;
justify-content: space-between;
align-items: center;
&-left {
color: #25bf82;
}
}
.price-label {
margin-right: 10px;
font-size: 16px;
color: #999999;
}
.price-amount {
font-size: 20px;
font-weight: 700;
color: #25bf82;
}
.contact-btn {
width: 152px;
height: 48px;
font-size: 20px;
border-radius: 8px;
background: #25bf82 !important;
:deep(.el-icon) {
margin-right: 10px;
}
}
.rank-badge {
position: absolute;
top: 0;
right: 20px;
width: 80px;
height: 80px;
}
</style>

View File

@ -1,16 +1,88 @@
<template>
<el-dialog v-model="dialogVisible" :close-on-click-modal="false" custom-class="custom-inquiry-dialog" width="450px">
<div class="info-section">
<div class="info-item">
<span class="label">首选商家</span>
<span class="value">{{ diodescription }}</span>
</div>
<div class="info-item">
<span class="label">选择服务</span>
<span class="value">{{ diotext }}</span>
</div>
</div>
<el-form ref="formRef" :model="form" label-position="top">
<el-form-item label="需求量:" prop="quantity" :rules="[{ required: true, message: '请输入重量' }]">
<el-input v-model="form.quantity" placeholder="请输入重量kg">
<template #suffix>kg</template>
</el-input>
</el-form-item>
<el-form-item label="您的称呼:" prop="name" :rules="[{ required: true, message: '请输入您的称呼' }]">
<el-input v-model="form.name" placeholder="请输入您的称呼" />
</el-form-item>
<el-form-item
label="您的电话:"
prop="phone"
:rules="[
{ required: true, message: '请输入电话' },
{ pattern: /^1[3-9]\d{9}$/, message: '手机号格式错误' },
]"
>
<el-input v-model="form.phone" placeholder="请输入电话号码" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button class="cancel-btn" @click="dialogVisible = false">取消</el-button>
<el-button class="submit-btn" type="primary" @click="handleSubmit">发送询价</el-button>
</div>
</template>
</el-dialog>
<!-- <page-layout :menus="state.menus"> </page-layout>-->
<section>
<common>
<template #main>
<el-card shadow="none" style="border-radius: 14px">
<el-card shadow="none" style="border-radius: 14px; height: 200px">
<div class="tabs">
<div class="tab" style="color: rgba(153, 153, 153, 1)">仓储分类</div>
<div class="tab cursor" :class="{ active: currentTab === 0 }" @click.stop="currentTab = 0">普通仓库</div>
<div class="tab cursor" :class="{ active: currentTab === 1 }" @click.stop="currentTab = 1">恒温仓库</div>
<div class="tab cursor" :class="{ active: currentTab === 2 }" @click.stop="currentTab = 2">冷库</div>
<div class="tab cursor" :class="{ active: currentTab === 3 }" @click.stop="currentTab = 3">气调仓库</div>
<div class="tab">&nbsp;</div>
<div class="tab cursor">
<div class="tab_list">蔬菜分拣</div>
<div
v-for="(item, index) in tab1"
:key="index"
class="tab_list_li"
:class="{ active: currentTab1 === index }"
@click.stop="currentTab1 = index"
>
{{ item }}
</div>
</div>
<div class="tab cursor">
<div class="tab_list">水果分拣</div>
<div
v-for="(item, index) in tab2"
:key="index"
class="tab_list_li"
:class="{ active: currentTab2 === index }"
@click.stop="currentTab2 = index"
>
{{ item }}
</div>
</div>
<!-- <div class="tab cursor">
<div class="tab_list">水果分拣</div>
<div
v-for="(item, index) in tab3"
:key="index"
class="tab_list_li"
:class="{ active: currentTab3 === index }"
@click.stop="currentTab3 = index"
>
{{ item }}
</div>
</div> -->
</div>
</el-card>
<el-row :gutter="20" style="margin-top: 10px">
@ -18,7 +90,7 @@
<el-card class="storage-card" shadow="hover">
<div class="storage-content">
<div class="storage-content-top" @click="toLink(item)">
<el-image :src="item.imageUrl" fit="cover" class="storage-image" />
<img :src="getAssetsFile(`${item.imageUrl}`)" fit="cover" class="storage-image" />
<div class="storage-info">
<h3 class="storage-title">{{ item.title }}</h3>
<div class="storage-desc">
@ -27,8 +99,9 @@
<img :src="getAssetsFile('images/warehouseLogistics/优先级.png')" alt="" style="width: 20px" />
</div>
<div class="storage-tags">
<el-tag effect="plain" round style="background-color: rgba(37, 191, 130, 0.2); color: #25bf82">延长仓储</el-tag>
<el-tag effect="plain" round style="background-color: rgba(37, 191, 130, 0.2); color: #25bf82">保鲜储存</el-tag>
<el-tag effect="plain" round style="background-color: rgba(37, 191, 130, 0.2); color: #25bf82">高品质</el-tag>
<el-tag effect="plain" round style="background-color: rgba(37, 191, 130, 0.2); color: #25bf82">杀菌灭毒</el-tag>
<el-tag effect="plain" round style="background-color: rgba(37, 191, 130, 0.2); color: #25bf82">绿色</el-tag>
</div>
<div class="storage-location">
<el-icon><Location /></el-icon>
@ -39,9 +112,9 @@
<div class="storage-price">
<div class="storage-price-left">
<span class="price-label">报价</span>
<span class="price-amount">¥{{ item.price }}//</span>
<span class="price-amount">¥{{ item.price }}/kg</span>
</div>
<el-button type="success" class="contact-btn">
<el-button type="success" class="contact-btn" @click="goDei(item)">
<img :src="getAssetsFile('images/warehouseLogistics/messageBox.png')" alt="" style="height: 30px; margin-right: 5px" />
<span>联系卖家</span>
</el-button>
@ -54,7 +127,7 @@
</el-card>
</el-col>
</el-row>
<page-pagination :total="20" @current-change="currentChange" />
<page-pagination :total="5" @current-change="currentChange" />
</template>
</common>
</section>
@ -69,6 +142,9 @@ import Common from './components/common.vue';
const route = useRoute();
const router = useRouter();
const tab1 = reactive(['叶菜类', '豆菜类', '根茎类', '茄果菜类', '食用菌类', '其他类蔬菜']);
const tab2 = reactive(['甘蔗', '热带水果', '其他类水果']);
const tab3 = reactive(['水产', '其他类']);
const state = reactive({
menus: warehouseLogisticsRoutes[0].children,
query: {
@ -76,78 +152,226 @@ const state = reactive({
},
data: [
{
imageUrl: '/storage1.jpg',
title: '果蔬保鲜仓储',
description: '绿鲜蔬选果蔬仓储中心 ',
title: '蔬菜分拣服务',
description: '绿鲜甄选蔬菜分拣中心 ',
location: '临沧市-耿马县',
price: '600.0',
price: '150',
rank: '1',
imageUrl: 'images/vegetable.png',
},
{
imageUrl: '/storage2.jpg',
title: '果蔬保鲜仓储',
description: '绿鲜蔬选果蔬仓储中心',
title: '水果分拣服务',
description: '果韵鲜享分拣站',
location: '临沧市-耿马县',
price: '600.0',
price: '150',
rank: '2',
imageUrl: 'images/fruit.png',
},
{
imageUrl: '/storage3.jpg',
title: '果蔬保鲜仓储',
description: '绿鲜蔬选果蔬仓储中心 ',
title: '水果分拣服务',
description: '好果分拣站 ',
location: '临沧市-耿马县',
price: '600.0',
price: '150',
rank: '3',
imageUrl: 'images/fruit.png',
},
{
imageUrl: '/storage3.jpg',
title: '果蔬保鲜仓储',
description: '绿鲜蔬选果蔬仓储中心 ',
title: '水果分拣服务',
description: '果美分拣站 ',
location: '临沧市-耿马县',
price: '600.0',
price: '150',
rank: '',
imageUrl: 'images/fruit.png',
},
{
imageUrl: '/storage3.jpg',
title: '果蔬保鲜仓储',
description: '绿鲜蔬选果蔬仓储中心 ',
title: '水果分拣服务',
description: '好果存分拣站 ',
location: '临沧市-耿马县',
price: '600.0',
rank: '',
},
{
imageUrl: '/storage3.jpg',
title: '果蔬保鲜仓储',
description: '绿鲜蔬选果蔬仓储中心 ',
location: '临沧市-耿马县',
price: '600.0',
price: '150',
rank: '',
imageUrl: 'images/fruit.png',
},
],
});
const currentTab = ref(0);
const currentTab1 = ref(0);
const currentTab2 = ref(0);
const currentTab3 = ref(0);
const dialogVisible = ref(false);
const formRef = ref(null);
const form = reactive({
quantity: '',
title: '',
phone: '',
name: '',
});
const diotext = ref('');
const diodescription = ref('');
const goDei = (data) => {
diodescription.value = data.description;
diotext.value = data.title;
dialogVisible.value = true;
};
const handleSubmit = () => {
formRef.value.validate((valid) => {
if (valid) {
console.log('提交数据:', form);
dialogVisible.value = false;
}
});
};
const currentChange = (current) => {
state.query.current = current;
};
const toLink = (row) => {
router.push({
path: '/sub-operation-service/warehouse-detail',
query: { id: row?.id ?? '100' },
});
// router.push({
// path: '/sub-operation-service/warehouse-detail',
// query: { id: row?.id ?? '100' },
// });
};
</script>
<style lang="scss" scoped>
//
$primary-color: #25bf82; //
$text-dark: #25bf82; //
$text-regular: #606266; //
$border-color: #dcdfe6; //
//
:deep(.custom-inquiry-dialog) {
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
.el-dialog__header {
padding: 20px;
border-bottom: 1px solid #f2f6fc;
.el-dialog__title {
font-size: 18px;
color: $text-dark;
font-weight: 600;
}
}
.el-dialog__body {
padding: 20px 28px;
}
.el-form-item__label {
color: $text-regular;
font-size: 14px;
padding-bottom: 6px;
}
}
.info-section {
padding: 0px 50px;
margin-bottom: 24px;
.info-item {
margin-bottom: 12px;
.label {
color: $text-regular;
margin-right: 8px;
font-size: 20px;
}
.value {
color: $text-dark;
font-weight: 500;
font-size: 20px;
}
}
}
//
:deep(.el-input) {
.el-input__inner {
height: 40px;
line-height: 40px;
border-radius: 4px;
&:focus {
border-color: $primary-color;
}
}
.el-input__suffix {
color: $text-regular;
right: 12px;
}
}
//
:deep(.custom-select-dropdown) {
.el-select-dropdown__item {
color: $text-regular;
&.selected {
color: $primary-color;
}
}
}
//
.dialog-footer {
text-align: right;
.el-button {
padding: 10px 24px;
border-radius: 4px;
font-size: 14px;
}
.cancel-btn {
color: $text-regular;
&:hover {
color: $primary-color;
border-color: $primary-color;
}
}
.submit-btn {
color: #fff;
background: $primary-color;
&:hover {
background: mix($primary-color, #fff, 85%);
}
}
}
.tabs {
height: 50px;
height: 160px;
line-height: 50px;
display: flex;
flex-direction: column;
font-size: 18px;
align-items: flex-start;
justify-content: space-between;
padding: 0 20px;
}
.tab {
height: 100px;
width: 850px;
display: flex;
align-items: center;
justify-content: flex-start;
overflow-x: auto;
overflow: auto; /* 启用滚动 */
white-space: nowrap; /* 强制单行显示 */
-ms-overflow-style: none; /* IE/Edge 兼容 */
scrollbar-width: none; /* 隐藏滚动条 */
.tab_list {
color: #999999;
font-size: 20px;
font-weight: 400;
}
.tab_list_li {
margin-left: 40px;
color: #000000;
font-size: 20px;
font-weight: 400;
}
.tab_list_li.active {
color: rgba(37, 191, 130, 1);
}
}
.cursor {
cursor: pointer;
}
@ -190,6 +414,7 @@ const toLink = (row) => {
overflow: hidden;
margin: 10px 0;
width: 100%;
text-align: left;
}
.storage-title {
font-size: 20px;
@ -221,9 +446,10 @@ const toLink = (row) => {
}
.storage-price {
display: flex;
justify-content: space-between;
align-items: center;
&-left {
flex: 1;
color: #25bf82;
}
}
.price-label {
@ -234,7 +460,7 @@ const toLink = (row) => {
.price-amount {
font-size: 20px;
font-weight: 700;
color: $color-primary;
color: #25bf82;
}
.contact-btn {
width: 152px;

View File

@ -80,14 +80,14 @@ const devices = ref([
const leftTableData = ref([
{
name: '温度',
value: '>25',
value: '>25°C',
device: '制冷机',
behavior: '开启',
time: 10,
},
{
name: '湿度',
value: '<24',
value: '<24%',
device: '喷洒机',
behavior: '关闭',
time: 15,

View File

@ -80,14 +80,14 @@ const devices = ref([
const leftTableData = ref([
{
name: '虫群数量',
value: '>20',
value: '>20',
device: '诱虫灯',
behavior: '开启',
time: 10,
},
{
name: '诱捕数量',
value: '>30',
value: '>30',
device: '灭虫灯',
behavior: '开启',
time: 15,
@ -101,14 +101,14 @@ const leftTableData = ref([
},
{
name: '虫群数量',
value: '>20',
value: '>20',
device: '通风窗',
behavior: '关闭',
time: '/',
},
{
name: '诱捕数量',
value: '>30',
value: '>30',
device: '幕布',
behavior: '开启',
time: '/',

View File

@ -34,8 +34,9 @@ const leftMenu = reactive([
{ name: 'agricultural', title: '我的购物车', icon: 'menu1.png', path: '/sub-operation-service/userCenter' },
{ name: 'supplier', title: '我的订单', icon: 'menu2-1.png', path: '/sub-operation-service/userOrders' },
// { name: 'purchaser', title: '', icon: 'menu3-1.png', path: '/sub-operation-service/userLands' },
{ name: 'mySource', title: '我的溯源', icon: 'menu3-1.png', path: '/sub-operation-service/mySource' },
{ name: 'myFinance', title: '我的金融', icon: 'menu3-1.png', path: '/sub-operation-service/myFinance' },
{ name: 'mySource', title: '我的溯源', icon: 'menu4-1.png', path: '/sub-operation-service/mySource' },
{ name: 'myFinance', title: '我的金融', icon: 'menu5-1.png', path: '/sub-operation-service/myFinance' },
{ name: 'myBrand', title: '我的品牌', icon: 'menu6-1.png', path: '/sub-operation-service/myBrand' },
]);
let currentIndex = ref(0);
@ -114,15 +115,20 @@ const toLink = (n, index) => {
}
.item-img {
display: inline-block;
width: 32px;
height: 32px;
width: 40px;
height: 40px;
img {
width: 100%;
height: auto;
display: block;
}
}
.item-title {
display: -webkit-inline-box;
font-size: 20px;
font-weight: 400;
line-height: 40px;
padding-left: 20px;
padding-left: 10px;
}
}
}

View File

@ -29,7 +29,7 @@
:prop="column.prop"
:label="column.label"
:width="column.width"
:align="column.align || 'center'"
:align="column.align || 'left'"
:sortable="column.sortable"
:header-class-name="column.headerClassName"
>

View File

@ -0,0 +1,407 @@
<template>
<div>
<common current-name="myBrand">
<template #main>
<div class="container">
<userHeader ref="titleRef" :title="'我的金融'"></userHeader>
<!-- 搜索栏 -->
<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="brandName">
<el-input v-model="formInline.brandName" placeholder="请输入品牌名称" clearable />
</el-form-item>
<el-form-item label="申请人" prop="applicant">
<el-input v-model="formInline.applicant" placeholder="请输入申请人" clearable />
</el-form-item>
<el-form-item label="申请状态" prop="applyStatus">
<el-select v-model="formInline.applyStatus" placeholder="请选择">
<el-option label="全部" value="99" />
<el-option label="未申请" value="0" />
<el-option label="已申请" value="1" />
<el-option label="已通过" value="2" />
<el-option label="未通过" value="3" />
</el-select>
</el-form-item>
<el-form-item label="使用状态" prop="useStatus">
<el-select v-model="formInline.useStatus" placeholder="请选择">
<el-option label="全部" value="99" />
<el-option label="无法使用" value="0" />
<el-option label="正常使用" value="1" />
<el-option label="暂未使用" value="2" />
</el-select>
</el-form-item>
<el-form-item label="申请日期" prop="startDate" style="margin-right: 0">
<el-date-picker v-model="formInline.startDate" type="date" placeholder="请选择起始日期" clearable style="width: 160px" />
</el-form-item>
<el-form-item style="margin-right: 0">
<span style="width: 30px; text-align: center; display: inline-block"> - </span>
</el-form-item>
<el-form-item prop="endDate">
<el-date-picker v-model="formInline.endDate" type="date" placeholder="请选择截止日期" clearable style="width: 160px" />
</el-form-item>
</el-form>
</div>
<div class="search-bar-right">
<el-button type="primary" icon="Search" @click="onSubmit">查询</el-button>
<el-button icon="Refresh" style="margin: 24px 0 0 0" @click="resetForm">重置</el-button>
</div>
</div>
</div>
<!-- 表格 -->
<div class="table-cont" :style="{ height: tableViewportHeight + 'px' }">
<tableComponent
:table-data="tableData"
:columns="columns"
:show-border="false"
:show-selection="true"
:header-cell-class-name="getHeaderClass"
@page-change="handlePaginationChange"
@selection-change="handleSelectionChange"
>
<!-- 自定义-状态 -->
<template #applyStatus="slotProps">
<span v-if="slotProps.row.applyStatus == 0" class="color-gray">未申请</span>
<span v-else-if="slotProps.row.applyStatus == 1" class="color-orange">已申请</span>
<span v-else-if="slotProps.row.applyStatus == 2" class="color-green">已通过</span>
<span v-else-if="slotProps.row.applyStatus == 3" class="color-red">未通过</span>
</template>
<!-- 自定义-状态 -->
<template #useStatus="slotProps">
<span v-if="slotProps.row.useStatus == 0" class="color-red">无法使用</span>
<span v-else-if="slotProps.row.useStatus == 1" class="color-green">正常通过</span>
<span v-else-if="slotProps.row.useStatus == 2" class="color-orange">暂未使用</span>
</template>
<!-- 自定义-操作 -->
<template #action="slotProps">
<el-dropdown>
<span class="el-dropdown-link">
<el-icon><More /></el-icon>
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="handleEdit(slotProps.row, 1)">Action 1</el-dropdown-item>
<el-dropdown-item @click="handleEdit(slotProps.row, 2)">Action 2</el-dropdown-item>
<el-dropdown-item @click="handleEdit(slotProps.row, 3)">Action 3</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</template>
</tableComponent>
</div>
</div>
</template>
</common>
</div>
</template>
<script setup>
import common from './components/common.vue';
import { ref, reactive, computed, onMounted, onBeforeUnmount } from 'vue';
import userHeader from './components/userHeader.vue';
import tableComponent from './components/tableComponent.vue';
import Mock from 'mockjs';
const formInline = reactive({
brandName: '',
applicant: '',
guarantor: '',
applyStatus: '99',
useStatus: '99',
startDate: '',
endDate: '',
});
const searchForm = ref(null);
const onSubmit = () => {
console.log('submit!');
};
const resetForm = () => {
searchForm.value.resetFields();
};
//
const tableData = ref([]);
//
const columns = ref([
{ prop: 'brandName', label: '品牌名称' },
{ prop: 'applicant', label: '申请人' },
{ prop: 'applyStatus', label: '申请状态', slotName: 'applyStatus' },
{ prop: 'useStatus', label: '使用状态', slotName: 'useStatus' },
{ prop: 'applyTime', label: '申请日期', width: '180px' },
{ prop: 'action', label: '操作', slotName: 'action', width: '180' },
]);
//
const generateMockData = () => {
return Mock.mock({
'list|30': [
{
'id|+1': 1,
brandName: '耿马生态果蔬', //
applyTime: '@datetime',
'applyStatus|1': [0, 1, 2, 3], //0 1 2 3
'useStatus|1': [0, 1, 2], //0使 1使 2使
guarantor: '@cname',
applicant: '@cname',
},
],
}).list;
};
//
const loadData = () => {
// API
setTimeout(() => {
tableData.value = generateMockData();
}, 500);
};
// ,columnsheaderClassName: 'custom-header'
const getHeaderClass = ({ column }) => {
return 'custom-header';
};
//
const handlePaginationChange = ({ page, pageSize }) => {
console.log('分页变化:', page, pageSize);
// API
// fetchData(page, limit,pageSize)
};
//
const handleSelectionChange = (selection) => {
console.log('选中项:', selection);
};
let nowClickRow = ref(null);
//
const handleEdit = (row, num) => {
nowClickRow.value = row;
console.log('编辑的行:', row);
console.log('第几个按钮:', num);
};
const titleRef = ref(null);
const searchBarRef = ref(null);
const tableViewportHeight = ref(0);
//
const calculateTableHeight = () => {
//
const windowHeight = window.innerHeight;
//
const headerHeight = titleRef.value?.$el?.offsetHeight || 0;
const searchBarHeight = searchBarRef.value?.offsetHeight || 0;
//
const paddingCompensation = 60;
//
tableViewportHeight.value = windowHeight - headerHeight - searchBarHeight - paddingCompensation;
// console.log(tableViewportHeight.value);
};
//
onMounted(() => {
loadData();
calculateTableHeight();
//
window.addEventListener('resize', calculateTableHeight);
// DOMheader/searchbar
const observer = new ResizeObserver(calculateTableHeight);
if (titleRef.value?.$el) observer.observe(titleRef.value.$el);
if (searchBarRef.value) observer.observe(searchBarRef.value);
});
onBeforeUnmount(() => {
window.removeEventListener('resize', calculateTableHeight);
});
</script>
<style lang="scss" scoped>
.container {
width: 100%;
overflow: hidden; /* 防止全局滚动条 */
.search-box {
overflow: hidden;
margin: 16px 0;
padding: 16px 8px 0 16px;
border-radius: 16px;
background: #fff;
.order-tab {
width: 100%;
::v-deep() {
.el-tabs__nav-wrap::after {
background: transparent !important;
}
.el-tabs__active-bar {
height: 3px !important;
border-radius: 4px;
}
.el-descriptions__label,
.el-descriptions__content {
font-size: 16px !important;
}
.cell-item {
display: inline-flex;
}
.el-descriptions__label {
color: $color-999;
}
.el-descriptions__content {
color: $color-333;
}
}
}
}
.search-bar {
display: flex;
flex-shrink: 0; /* 禁止收缩 */
min-height: 100px;
.search-bar-left {
flex: 1;
}
.search-bar-right {
width: 100px;
}
.demo-form-inline {
text-align: left;
}
.el-form--inline .el-form-item {
margin-right: 30px;
}
.demo-form-inline .el-input {
--el-input-width: 160px;
}
.demo-form-inline .el-select {
--el-select-width: 160px;
}
.demo-form-inline .el-date-picker {
--el-select-width: 160px;
}
}
.table-cont {
min-height: 300px;
border-radius: 16px;
overflow: hidden;
background-color: #fff;
position: relative;
.el-icon-custom {
vertical-align: middle;
cursor: pointer;
}
}
/* 自定义弹窗样式 */
.traceability-dialog {
background: transparent;
box-shadow: none;
border-radius: 16px !important;
}
/* 主要内容区域 */
.dialog-content {
display: flex;
flex-direction: column;
align-items: center;
background: white;
border-radius: 8px;
padding: 0 0 20px 0;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
/* 产品信息 */
.product-info {
width: 100%;
display: flex;
justify-content: space-between;
margin-bottom: 20px;
font-size: 14px;
color: #666;
}
.product-name {
font-weight: bold;
color: #333;
}
/* 二维码图片 */
.qrcode-image {
width: 200px;
height: 200px;
margin: 0 auto;
}
/* 下载区域 */
.download-section {
display: flex;
align-items: center;
margin: 0 0 10px 0;
color: #25bf82;
cursor: pointer;
font-size: 12px;
line-height: 18px;
}
.download-icon {
margin-left: 8px;
font-size: 16px;
}
/* 遗传编码区域 */
.code-section {
display: flex;
align-items: center;
margin: 10px 0;
background: rgba(37, 191, 130, 0.1);
border-radius: 4px;
}
.genetic-code {
font-family: monospace;
font-size: 14px;
color: #25bf82;
display: inline-block;
max-width: 250px;
padding: 0 10px;
}
.copy-icon {
margin-left: 10px;
color: #409eff;
cursor: pointer;
font-size: 16px;
}
/* 关闭按钮 */
.close-button {
position: absolute;
left: 50%;
transform: translateX(-50%);
bottom: -60px;
color: white;
font-size: 30px;
cursor: pointer;
transition: all 0.3s;
}
//
.color-gray {
color: $color-5a;
}
.color-orange {
color: $color-warning;
}
.color-green {
color: $color-success;
}
.color-red {
color: $color-danger;
}
}
</style>

View File

@ -1,6 +1,6 @@
<template>
<div>
<common current-name="agricultural">
<common current-name="myFinance">
<template #main>
<div class="container">
<userHeader ref="titleRef" :title="'我的金融'"></userHeader>
@ -23,11 +23,13 @@
<el-form-item label="申请人" prop="applicant">
<el-input v-model="formInline.applicant" placeholder="请输入申请人" clearable />
</el-form-item>
<el-form-item label="申请状态" prop="status">
<el-select v-model="formInline.status" placeholder="请选择">
<el-form-item label="申请状态" prop="applyStatus">
<el-select v-model="formInline.applyStatus" placeholder="请选择">
<el-option label="全部" value="99" />
<el-option label="待检测" value="0" />
<el-option label="已检测" value="1" />
<el-option label="未申请" value="0" />
<el-option label="已申请" value="1" />
<el-option label="已通过" value="2" />
<el-option label="未通过" value="3" />
</el-select>
</el-form-item>
<el-form-item label="申请日期" prop="startDate" style="margin-right: 0">
@ -59,10 +61,11 @@
@selection-change="handleSelectionChange"
>
<!-- 自定义-状态 -->
<template #status="slotProps">
<span :style="{ color: slotProps.row.status == 1 ? 'green' : '#FFB345' }">
{{ slotProps.row.status === 1 ? '已通过' : '已申请' }}
</span>
<template #applyStatus="slotProps">
<span v-if="slotProps.row.applyStatus == 0" class="color-gray">未申请</span>
<span v-else-if="slotProps.row.applyStatus == 1" class="color-orange">已申请</span>
<span v-else-if="slotProps.row.applyStatus == 2" class="color-green">已通过</span>
<span v-else-if="slotProps.row.applyStatus == 3" class="color-red">未通过</span>
</template>
<!-- 自定义-操作 -->
@ -98,7 +101,7 @@ const formInline = reactive({
productName: '',
applicant: '',
guarantor: '',
status: '99',
applyStatus: '99',
startDate: '',
endDate: '',
});
@ -111,6 +114,11 @@ let bottomList = reactive([
]);
const tabChange = () => {
console.log(activeCurrent.value);
if (activeCurrent.value == '3') {
columns.value = columns2.value;
} else {
columns.value = columns1.value;
}
};
const searchForm = ref(null);
@ -124,12 +132,19 @@ const resetForm = () => {
//
const tableData = ref([]);
//
const columns = ref([
{ prop: 'id', label: 'ID', width: '80' },
const columns = ref([]);
const columns1 = ref([
{ prop: 'productName', label: '产品名称' },
{ prop: 'applicant', label: '申请人' },
{ prop: 'applyStatus', label: '申请状态', slotName: 'applyStatus' },
{ prop: 'applyTime', label: '申请日期', width: '180px' },
{ prop: 'action', label: '操作', slotName: 'action', width: '180' },
]);
const columns2 = ref([
{ prop: 'productName', label: '产品名称' },
{ prop: 'guarantor', label: '担保人' },
{ prop: 'applicant', label: '申请人' },
{ prop: 'status', label: '申请状态', slotName: 'status' },
{ prop: 'applyStatus', label: '申请状态', slotName: 'applyStatus' },
{ prop: 'applyTime', label: '申请日期', width: '180px' },
{ prop: 'action', label: '操作', slotName: 'action', width: '180' },
]);
@ -141,8 +156,8 @@ const generateMockData = () => {
'id|+1': 1,
productName: '惠农e贷', //
applyTime: '@datetime',
'status|1': [1, 1, 1, 0], //0 1
guarantor: '@cname',
'applyStatus|1': [0, 1, 2, 3], //0 1 2 3
guarantor: '惠农有限公司',
applicant: '@cname',
},
],
@ -199,6 +214,7 @@ const calculateTableHeight = () => {
};
//
onMounted(() => {
columns.value = columns1.value;
loadData();
calculateTableHeight();
@ -389,5 +405,18 @@ onBeforeUnmount(() => {
cursor: pointer;
transition: all 0.3s;
}
//
.color-gray {
color: $color-5a;
}
.color-orange {
color: $color-warning;
}
.color-green {
color: $color-success;
}
.color-red {
color: $color-danger;
}
}
</style>

View File

@ -1,6 +1,6 @@
<template>
<div>
<common current-name="agricultural">
<common current-name="mySource">
<template #main>
<div class="container">
<userHeader ref="titleRef" :title="'我的溯源'"></userHeader>
@ -50,9 +50,8 @@
>
<!-- 自定义-状态 -->
<template #status="slotProps">
<span :style="{ color: slotProps.row.status == 1 ? 'green' : 'red' }">
{{ slotProps.row.status === 1 ? '已检测' : '待检测' }}
</span>
<span v-if="slotProps.row.status == 0" class="color-red">待检测</span>
<span v-else-if="slotProps.row.status == 1" class="color-green">已检测</span>
</template>
<!-- 自定义-检测报告 -->
@ -154,7 +153,6 @@ const resetForm = () => {
const tableData = ref([]);
//
const columns = ref([
{ prop: 'id', label: 'ID', width: '80' },
{ prop: 'productName', label: '产品名称', width: '180px' },
{ prop: 'applyTime', label: '申请时间', width: '180px' },
{ prop: 'status', label: '申请状态', slotName: 'status' },
@ -205,7 +203,6 @@ const handleSelectionChange = (selection) => {
let nowClickRow = ref(null);
const dialogVisible = ref(false);
let codeUrl = ref('');
codeUrl.value = getAssetsFile('images/userCenter/检测报告.png').href ?? '';
//
const handleEdit = (row, num) => {
nowClickRow.value = row;
@ -223,7 +220,7 @@ const seeReportImg = (row) => {
if (row.reportUrl) {
//
// const imgUrl = row.reportUrl.startsWith('http') ? row.reportUrl : `${import.meta.env.VITE_API_BASE}${row.reportUrl}`;
const imgUrl = codeUrl.value;
const imgUrl = getAssetsFile('images/userCenter/检测报告.png').href ?? '';
previewImageUrl.value = imgUrl;
showPreview.value = true;
@ -484,5 +481,15 @@ onBeforeUnmount(() => {
cursor: pointer;
transition: all 0.3s;
}
//
.color-gray {
color: $color-5a;
}
.color-green {
color: $color-success;
}
.color-red {
color: $color-danger;
}
}
</style>