|
|
@@ -1,120 +1,280 @@
|
|
|
<template>
|
|
|
- <el-dialog :model-value="modelValue" :title="isEdit ? '编辑' : '新增'" width="780px" align-center destroy-on-close
|
|
|
- class="device-form-dialog" @update:model-value="emit('update:modelValue', $event)" @closed="handleClosed">
|
|
|
+ <el-dialog
|
|
|
+ :model-value="modelValue"
|
|
|
+ :title="isEdit ? '编辑' : '新增'"
|
|
|
+ width="780px"
|
|
|
+ align-center
|
|
|
+ destroy-on-close
|
|
|
+ class="device-form-dialog"
|
|
|
+ @update:model-value="emit('update:modelValue', $event)"
|
|
|
+ @closed="handleClosed"
|
|
|
+ >
|
|
|
<el-form ref="formRef" :model="form" :rules="rules" label-position="left" class="device-form">
|
|
|
- <el-form-item label="姓名/手机号:" prop="ownerName" class="form-item--inline">
|
|
|
+ <el-form-item label="个人信息:" prop="ownerName" class="form-item--inline">
|
|
|
<div class="name-phone-row">
|
|
|
- <el-input v-model="form.ownerName" placeholder="请输入姓名" maxlength="20" class="name-phone-row__name" />
|
|
|
+ <el-input
|
|
|
+ v-model="form.ownerName"
|
|
|
+ placeholder="请输入姓名"
|
|
|
+ maxlength="20"
|
|
|
+ class="name-phone-row__name"
|
|
|
+ />
|
|
|
<el-form-item prop="ownerPhone" class="name-phone-row__phone-item">
|
|
|
<el-input v-model="form.ownerPhone" placeholder="请输入手机号" maxlength="11" />
|
|
|
</el-form-item>
|
|
|
</div>
|
|
|
</el-form-item>
|
|
|
|
|
|
- <div class="form-section">
|
|
|
-
|
|
|
- <div class="form-section__head">
|
|
|
- <div class="form-section__label">
|
|
|
- 种植品种:
|
|
|
- </div>
|
|
|
- <el-button type="warning" @click="addCategory">
|
|
|
- + 添加品类
|
|
|
- </el-button>
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class="category-list">
|
|
|
- <div v-for="(group, gIdx) in form.categories" :key="group._key" class="category-block">
|
|
|
- <div class="category-block__head">
|
|
|
- <el-select v-model="group.category" placeholder="请选择品类" class="category-select">
|
|
|
- <el-option v-for="item in categoryOptions" :key="item" :label="item" :value="item" />
|
|
|
+ <!-- 农服人员表单 -->
|
|
|
+ <template v-if="isServiceForm">
|
|
|
+ <el-form-item label="团队名称:" prop="teamName">
|
|
|
+ <el-input v-model="form.teamName" placeholder="请输入团队名称" maxlength="50" />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="团队类型:" prop="teamType">
|
|
|
+ <el-select v-model="form.teamType" placeholder="请选择团队类型" style="width: 100%">
|
|
|
+ <el-option v-for="item in teamTypeOptions" :key="item" :label="item" :value="item" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="服务类别:" class="form-item--service-cat">
|
|
|
+ <div class="service-cat-form">
|
|
|
+ <div class="service-cat-form__row">
|
|
|
+ <span class="service-cat-form__label">果树类:</span>
|
|
|
+ <el-select
|
|
|
+ v-model="form.serviceCategories.fruit"
|
|
|
+ multiple
|
|
|
+ collapse-tags
|
|
|
+ collapse-tags-tooltip
|
|
|
+ :max-collapse-tags="3"
|
|
|
+ placeholder="请选择"
|
|
|
+ class="service-cat-form__select"
|
|
|
+ >
|
|
|
+ <el-option v-for="item in serviceCatOptions" :key="item" :label="item" :value="item" />
|
|
|
</el-select>
|
|
|
-
|
|
|
-
|
|
|
- <div class="link-btn secondary-link" @click="addPlanting(gIdx)">
|
|
|
- + 添加品种
|
|
|
</div>
|
|
|
-
|
|
|
- <el-button v-if="form.categories.length > 1" link type="danger" class="link-btn"
|
|
|
- @click="removeCategory(gIdx)">
|
|
|
- 删除品类
|
|
|
- </el-button>
|
|
|
+ <div class="service-cat-form__row">
|
|
|
+ <span class="service-cat-form__label">大田类:</span>
|
|
|
+ <el-select
|
|
|
+ v-model="form.serviceCategories.field"
|
|
|
+ multiple
|
|
|
+ collapse-tags
|
|
|
+ collapse-tags-tooltip
|
|
|
+ :max-collapse-tags="3"
|
|
|
+ placeholder="请选择"
|
|
|
+ class="service-cat-form__select"
|
|
|
+ >
|
|
|
+ <el-option v-for="item in serviceCatOptions" :key="item" :label="item" :value="item" />
|
|
|
+ </el-select>
|
|
|
</div>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="农机设备:" prop="equipments">
|
|
|
+ <el-select
|
|
|
+ v-model="form.equipments"
|
|
|
+ multiple
|
|
|
+ collapse-tags
|
|
|
+ collapse-tags-tooltip
|
|
|
+ :max-collapse-tags="3"
|
|
|
+ placeholder="请选择农机设备"
|
|
|
+ style="width: 100%"
|
|
|
+ >
|
|
|
+ <el-option v-for="item in equipmentOptions" :key="item" :label="item" :value="item" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="人工服务:" prop="manualServices">
|
|
|
+ <el-select
|
|
|
+ v-model="form.manualServices"
|
|
|
+ multiple
|
|
|
+ collapse-tags
|
|
|
+ collapse-tags-tooltip
|
|
|
+ :max-collapse-tags="3"
|
|
|
+ placeholder="请选择人工服务"
|
|
|
+ style="width: 100%"
|
|
|
+ >
|
|
|
+ <el-option v-for="item in farmWorkOptions" :key="item" :label="item" :value="item" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="常驻点位:" prop="residentLocation" class="form-item--resident">
|
|
|
+ <div class="location-box location-box--full">
|
|
|
+ <span class="location-box__text" :title="form.residentLocation">
|
|
|
+ {{ form.residentLocation || "请选择点位" }}
|
|
|
+ </span>
|
|
|
+ <el-button link type="warning" class="link-btn" @click="openResidentLocation">
|
|
|
+ 修改点位
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="邀请人:">
|
|
|
+ <div v-if="form.inviterName" class="inviter-cell">
|
|
|
+ <el-avatar :size="28" class="inviter-cell__avatar">
|
|
|
+ {{ form.inviterName.slice(0, 1) }}
|
|
|
+ </el-avatar>
|
|
|
+ <span class="inviter-cell__name">{{ form.inviterName }}</span>
|
|
|
+ </div>
|
|
|
+ <span v-else class="inviter-empty">-</span>
|
|
|
+ </el-form-item>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <!-- 权属人员表单 -->
|
|
|
+ <template v-else>
|
|
|
+ <el-form-item label="农机设备:" prop="equipments">
|
|
|
+ <el-select
|
|
|
+ v-model="form.equipments"
|
|
|
+ multiple
|
|
|
+ collapse-tags
|
|
|
+ collapse-tags-tooltip
|
|
|
+ :max-collapse-tags="3"
|
|
|
+ placeholder="请选择农机设备"
|
|
|
+ style="width: 100%"
|
|
|
+ >
|
|
|
+ <el-option v-for="item in equipmentOptions" :key="item" :label="item" :value="item" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="外包农事:" prop="outsourceFarmWorks">
|
|
|
+ <el-select
|
|
|
+ v-model="form.outsourceFarmWorks"
|
|
|
+ multiple
|
|
|
+ collapse-tags
|
|
|
+ collapse-tags-tooltip
|
|
|
+ :max-collapse-tags="3"
|
|
|
+ placeholder="请选择外包农事"
|
|
|
+ style="width: 100%"
|
|
|
+ >
|
|
|
+ <el-option v-for="item in farmWorkOptions" :key="item" :label="item" :value="item" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="常驻点位:" prop="residentLocation" class="form-item--resident">
|
|
|
+ <div class="location-box location-box--full">
|
|
|
+ <span class="location-box__text" :title="form.residentLocation">
|
|
|
+ {{ form.residentLocation || "请选择点位" }}
|
|
|
+ </span>
|
|
|
+ <el-button link type="warning" class="link-btn" @click="openResidentLocation">
|
|
|
+ 修改点位
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="邀请人:">
|
|
|
+ <div v-if="form.inviterName" class="inviter-cell">
|
|
|
+ <el-avatar :size="28" class="inviter-cell__avatar">
|
|
|
+ {{ form.inviterName.slice(0, 1) }}
|
|
|
+ </el-avatar>
|
|
|
+ <span class="inviter-cell__name">{{ form.inviterName }}</span>
|
|
|
+ </div>
|
|
|
+ <span v-else class="inviter-empty">-</span>
|
|
|
+ </el-form-item>
|
|
|
|
|
|
- <div class="planting-grid">
|
|
|
- <div v-for="(item, pIdx) in group.plantings" :key="item._key" class="planting-card">
|
|
|
- <div class="planting-card__top">
|
|
|
- <el-select v-model="item.variety" placeholder="请选择品种" class="variety-select">
|
|
|
- <el-option v-for="v in varietyOptions" :key="v" :label="v" :value="v" />
|
|
|
- </el-select>
|
|
|
- <el-button link type="danger" class="link-btn"
|
|
|
- :disabled="group.plantings.length <= 1 && form.categories.length <= 1"
|
|
|
- @click="removePlanting(gIdx, pIdx)">
|
|
|
- 删除
|
|
|
- </el-button>
|
|
|
- </div>
|
|
|
+ <div class="form-section">
|
|
|
+ <div class="form-section__head">
|
|
|
+ <div class="form-section__label">种植品种:</div>
|
|
|
+ <el-button type="warning" @click="addCategory">+ 添加品类</el-button>
|
|
|
+ </div>
|
|
|
|
|
|
- <div class="planting-card__row">
|
|
|
- <span class="planting-card__label">物候期:</span>
|
|
|
- <el-select v-model="item.phenology" placeholder="请选择物候期" class="planting-card__input">
|
|
|
- <el-option v-for="ph in phenologyOptions" :key="ph" :label="ph" :value="ph" />
|
|
|
- </el-select>
|
|
|
- </div>
|
|
|
+ <div class="category-list">
|
|
|
+ <div v-for="(group, gIdx) in form.categories" :key="group._key" class="category-block">
|
|
|
+ <div class="category-block__head">
|
|
|
+ <el-select v-model="group.category" placeholder="请选择品类" class="category-select">
|
|
|
+ <el-option v-for="item in categoryOptions" :key="item" :label="item" :value="item" />
|
|
|
+ </el-select>
|
|
|
+
|
|
|
+ <div class="link-btn secondary-link" @click="addPlanting(gIdx)">+ 添加品种</div>
|
|
|
+
|
|
|
+ <el-button
|
|
|
+ v-if="form.categories.length > 1"
|
|
|
+ link
|
|
|
+ type="danger"
|
|
|
+ class="link-btn"
|
|
|
+ @click="removeCategory(gIdx)"
|
|
|
+ >
|
|
|
+ 删除品类
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
|
|
|
- <div class="planting-card__row">
|
|
|
- <span class="planting-card__label">种植面积:</span>
|
|
|
- <el-input v-model="item.area" placeholder="请输入种植面积" class="planting-card__input" />
|
|
|
- </div>
|
|
|
+ <div class="planting-grid">
|
|
|
+ <div v-for="(item, pIdx) in group.plantings" :key="item._key" class="planting-card">
|
|
|
+ <div class="planting-card__top">
|
|
|
+ <el-select v-model="item.variety" placeholder="请选择品种" class="variety-select">
|
|
|
+ <el-option v-for="v in varietyOptions" :key="v" :label="v" :value="v" />
|
|
|
+ </el-select>
|
|
|
+ <el-button
|
|
|
+ link
|
|
|
+ type="danger"
|
|
|
+ class="link-btn"
|
|
|
+ :disabled="group.plantings.length <= 1 && form.categories.length <= 1"
|
|
|
+ @click="removePlanting(gIdx, pIdx)"
|
|
|
+ >
|
|
|
+ 删除
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
|
|
|
- <div class="planting-card__row">
|
|
|
- <span class="planting-card__label">起种点:</span>
|
|
|
- <el-select v-model="item.startPoint" placeholder="请选择" class="start-point-select">
|
|
|
- <el-option v-for="sp in startPointOptions" :key="sp" :label="sp" :value="sp" />
|
|
|
- </el-select>
|
|
|
- <el-date-picker v-model="item.startDate" type="date" placeholder="选择日期" value-format="YYYY.MM.DD"
|
|
|
- format="YYYY.MM.DD" class="start-date-picker" />
|
|
|
- </div>
|
|
|
+ <div class="planting-card__row">
|
|
|
+ <span class="planting-card__label">物候期:</span>
|
|
|
+ <el-select v-model="item.phenology" placeholder="请选择物候期" class="planting-card__input">
|
|
|
+ <el-option v-for="ph in phenologyOptions" :key="ph" :label="ph" :value="ph" />
|
|
|
+ </el-select>
|
|
|
+ </div>
|
|
|
|
|
|
- <div class="planting-card__row">
|
|
|
- <span class="planting-card__label">种植点位:</span>
|
|
|
- <div class="location-box">
|
|
|
- <span class="location-box__text" :title="item.plantLocation">
|
|
|
- {{ item.plantLocation || "请选择点位" }}
|
|
|
- </span>
|
|
|
- <el-button link type="warning" class="link-btn" @click="openPlantLocation(gIdx, pIdx)">
|
|
|
- 修改点位
|
|
|
- </el-button>
|
|
|
+ <div class="planting-card__row">
|
|
|
+ <span class="planting-card__label">种植面积:</span>
|
|
|
+ <el-input v-model="item.area" placeholder="请输入种植面积" class="planting-card__input" />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="planting-card__row">
|
|
|
+ <span class="planting-card__label">起种点:</span>
|
|
|
+ <el-select v-model="item.startPoint" placeholder="请选择" class="start-point-select">
|
|
|
+ <el-option v-for="sp in startPointOptions" :key="sp" :label="sp" :value="sp" />
|
|
|
+ </el-select>
|
|
|
+ <el-date-picker
|
|
|
+ v-model="item.startDate"
|
|
|
+ type="date"
|
|
|
+ placeholder="选择日期"
|
|
|
+ value-format="YYYY.MM.DD"
|
|
|
+ format="YYYY.MM.DD"
|
|
|
+ class="start-date-picker"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="planting-card__row">
|
|
|
+ <span class="planting-card__label">种植点位:</span>
|
|
|
+ <div class="location-box">
|
|
|
+ <span class="location-box__text" :title="item.plantLocation">
|
|
|
+ {{ item.plantLocation || "请选择点位" }}
|
|
|
+ </span>
|
|
|
+ <el-button link type="warning" class="link-btn" @click="openPlantLocation(gIdx, pIdx)">
|
|
|
+ 修改点位
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <el-form-item label="常驻点位:" prop="residentLocation" class="form-item--resident">
|
|
|
- <div class="location-box location-box--full">
|
|
|
- <span class="location-box__text" :title="form.residentLocation">
|
|
|
- {{ form.residentLocation || "请选择点位" }}
|
|
|
- </span>
|
|
|
- <el-button link type="warning" class="link-btn" @click="openResidentLocation">
|
|
|
- 修改点位
|
|
|
- </el-button>
|
|
|
- </div>
|
|
|
- </el-form-item>
|
|
|
+ </template>
|
|
|
</el-form>
|
|
|
|
|
|
<template #footer>
|
|
|
<div class="dialog-footer">
|
|
|
- <el-button @click="close">取消</el-button>
|
|
|
+ <el-button @click="close">{{ isServiceForm ? "取消编辑" : "取消" }}</el-button>
|
|
|
<el-button type="primary" :loading="submitting" @click="handleSubmit">
|
|
|
- 提交
|
|
|
+ {{ isServiceForm ? "确认信息" : "提交" }}
|
|
|
</el-button>
|
|
|
</div>
|
|
|
</template>
|
|
|
</el-dialog>
|
|
|
|
|
|
- <SelectLocationDialog v-model="locationDialogVisible" :farm-id="101532" :location-wkt="activeLocationWkt"
|
|
|
- @confirm="handleLocationConfirm" />
|
|
|
+ <SelectLocationDialog
|
|
|
+ v-model="locationDialogVisible"
|
|
|
+ :farm-id="101532"
|
|
|
+ :location-wkt="activeLocationWkt"
|
|
|
+ @confirm="handleLocationConfirm"
|
|
|
+ />
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
@@ -129,27 +289,40 @@ const props = defineProps({
|
|
|
},
|
|
|
mode: {
|
|
|
type: String,
|
|
|
- default: "add", // add | edit
|
|
|
+ default: "add",
|
|
|
},
|
|
|
data: {
|
|
|
type: Object,
|
|
|
default: null,
|
|
|
},
|
|
|
+ /** owner | service,新增时用当前 tab;编辑时优先 data.tabKey */
|
|
|
+ personType: {
|
|
|
+ type: String,
|
|
|
+ default: "owner",
|
|
|
+ },
|
|
|
});
|
|
|
|
|
|
const emit = defineEmits(["update:modelValue", "submit"]);
|
|
|
|
|
|
const isEdit = computed(() => props.mode === "edit");
|
|
|
+const isServiceForm = computed(() => {
|
|
|
+ if (isEdit.value && props.data?.tabKey) return props.data.tabKey === "service";
|
|
|
+ return props.personType === "service";
|
|
|
+});
|
|
|
+
|
|
|
const formRef = ref();
|
|
|
const submitting = ref(false);
|
|
|
const locationDialogVisible = ref(false);
|
|
|
-/** @type {import('vue').Ref<null | { type: 'resident' } | { type: 'plant', categoryIndex: number, plantingIndex: number }>} */
|
|
|
const locationTarget = ref(null);
|
|
|
|
|
|
const categoryOptions = ["品类一", "品类二", "荔枝", "龙眼"];
|
|
|
const varietyOptions = ["品种一", "妃子笑", "桂味", "糯米糍", "白糖罂", "仙进奉"];
|
|
|
const phenologyOptions = ["生育期一", "生育期二", "生育期三", "生育期四"];
|
|
|
const startPointOptions = ["来白点", "来白点2"];
|
|
|
+const equipmentOptions = ["设备一", "农机设备", "农机设备一", "农机设备二"];
|
|
|
+const farmWorkOptions = ["农事类别一", "农事类别二", "农事类别三"];
|
|
|
+const teamTypeOptions = ["家庭农场", "团队类型一", "合作社", "企业"];
|
|
|
+const serviceCatOptions = ["品类一", "品类二", "品类三"];
|
|
|
|
|
|
let keySeed = 0;
|
|
|
const nextKey = () => `k-${++keySeed}`;
|
|
|
@@ -176,35 +349,62 @@ const createCategory = (data = {}) => ({
|
|
|
|
|
|
const createEmptyForm = () => ({
|
|
|
id: null,
|
|
|
+ tabKey: "owner",
|
|
|
ownerName: "",
|
|
|
ownerPhone: "",
|
|
|
+ teamName: "",
|
|
|
+ teamType: "",
|
|
|
+ serviceCategories: { fruit: [], field: [] },
|
|
|
+ equipments: [],
|
|
|
+ outsourceFarmWorks: [],
|
|
|
+ manualServices: [],
|
|
|
residentLocation: "",
|
|
|
locationWkt: "",
|
|
|
+ inviterName: "张扬",
|
|
|
categories: [createCategory({ category: "品类一" })],
|
|
|
});
|
|
|
|
|
|
const form = reactive(createEmptyForm());
|
|
|
|
|
|
-const rules = {
|
|
|
- ownerName: [{ required: true, message: "请输入姓名", trigger: "blur" }],
|
|
|
- ownerPhone: [
|
|
|
- { required: true, message: "请输入手机号", trigger: "blur" },
|
|
|
- {
|
|
|
- pattern: /^1\d{10}$/,
|
|
|
- message: "请输入正确的手机号",
|
|
|
- trigger: "blur",
|
|
|
- },
|
|
|
- ],
|
|
|
- residentLocation: [
|
|
|
- {
|
|
|
- validator: (_rule, _value, callback) => {
|
|
|
- if (!form.residentLocation) callback(new Error("请选择常驻点位"));
|
|
|
- else callback();
|
|
|
+const rules = computed(() => {
|
|
|
+ const base = {
|
|
|
+ ownerName: [{ required: true, message: "请输入姓名", trigger: "blur" }],
|
|
|
+ ownerPhone: [
|
|
|
+ { required: true, message: "请输入手机号", trigger: "blur" },
|
|
|
+ { pattern: /^1\d{10}$/, message: "请输入正确的手机号", trigger: "blur" },
|
|
|
+ ],
|
|
|
+ equipments: [
|
|
|
+ { type: "array", required: true, min: 1, message: "请选择农机设备", trigger: "change" },
|
|
|
+ ],
|
|
|
+ residentLocation: [
|
|
|
+ {
|
|
|
+ validator: (_rule, _value, callback) => {
|
|
|
+ if (!form.residentLocation) callback(new Error("请选择常驻点位"));
|
|
|
+ else callback();
|
|
|
+ },
|
|
|
+ trigger: "change",
|
|
|
},
|
|
|
- trigger: "change",
|
|
|
- },
|
|
|
- ],
|
|
|
-};
|
|
|
+ ],
|
|
|
+ };
|
|
|
+
|
|
|
+ if (isServiceForm.value) {
|
|
|
+ return {
|
|
|
+ ...base,
|
|
|
+ teamName: [{ required: true, message: "请输入团队名称", trigger: "blur" }],
|
|
|
+ teamType: [{ required: true, message: "请选择团队类型", trigger: "change" }],
|
|
|
+ manualServices: [
|
|
|
+ { type: "array", required: true, min: 1, message: "请选择人工服务", trigger: "change" },
|
|
|
+ ],
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ return {
|
|
|
+ ...base,
|
|
|
+ outsourceFarmWorks: [
|
|
|
+ { type: "array", required: true, min: 1, message: "请选择外包农事", trigger: "change" },
|
|
|
+ ],
|
|
|
+ };
|
|
|
+});
|
|
|
|
|
|
const activeLocationWkt = computed(() => {
|
|
|
const target = locationTarget.value;
|
|
|
@@ -218,10 +418,7 @@ const normalizeCategoriesFromData = (data) => {
|
|
|
if (Array.isArray(data?.categories) && data.categories.length) {
|
|
|
return data.categories.map((c) => {
|
|
|
if (typeof c === "string") {
|
|
|
- return createCategory({
|
|
|
- category: c,
|
|
|
- plantings: data.plantings || [],
|
|
|
- });
|
|
|
+ return createCategory({ category: c, plantings: data.plantings || [] });
|
|
|
}
|
|
|
return createCategory({
|
|
|
category: c.category || c.name || c.cropCategory || "",
|
|
|
@@ -229,7 +426,6 @@ const normalizeCategoriesFromData = (data) => {
|
|
|
});
|
|
|
});
|
|
|
}
|
|
|
-
|
|
|
return [
|
|
|
createCategory({
|
|
|
category: data?.cropCategory || data?.type || "荔枝",
|
|
|
@@ -241,10 +437,21 @@ const normalizeCategoriesFromData = (data) => {
|
|
|
const fillForm = (data) => {
|
|
|
Object.assign(form, createEmptyForm(), {
|
|
|
id: data?.id ?? null,
|
|
|
+ tabKey: data?.tabKey || props.personType || "owner",
|
|
|
ownerName: data?.ownerName || data?.name || "",
|
|
|
ownerPhone: data?.ownerPhone || data?.phone || "",
|
|
|
+ teamName: data?.teamName || "",
|
|
|
+ teamType: data?.teamType || "",
|
|
|
+ serviceCategories: {
|
|
|
+ fruit: [...(data?.serviceCategories?.fruit || [])],
|
|
|
+ field: [...(data?.serviceCategories?.field || [])],
|
|
|
+ },
|
|
|
+ equipments: [...(data?.equipments || [])],
|
|
|
+ outsourceFarmWorks: [...(data?.outsourceFarmWorks || [])],
|
|
|
+ manualServices: [...(data?.manualServices || [])],
|
|
|
residentLocation: data?.residentLocation || data?.location || "",
|
|
|
locationWkt: data?.locationWkt || "",
|
|
|
+ inviterName: data?.inviterName || "张扬",
|
|
|
categories: normalizeCategoriesFromData(data),
|
|
|
});
|
|
|
};
|
|
|
@@ -256,7 +463,9 @@ watch(
|
|
|
if (isEdit.value && props.data) {
|
|
|
fillForm(props.data);
|
|
|
} else {
|
|
|
- Object.assign(form, createEmptyForm());
|
|
|
+ Object.assign(form, createEmptyForm(), {
|
|
|
+ tabKey: props.personType || "owner",
|
|
|
+ });
|
|
|
}
|
|
|
}
|
|
|
);
|
|
|
@@ -348,42 +557,80 @@ const validatePlantings = () => {
|
|
|
const handleSubmit = async () => {
|
|
|
await formRef.value?.validate?.(async (valid) => {
|
|
|
if (!valid) return;
|
|
|
- if (!validatePlantings()) return;
|
|
|
+
|
|
|
+ if (!isServiceForm.value && !validatePlantings()) return;
|
|
|
+
|
|
|
+ if (isServiceForm.value) {
|
|
|
+ const fruit = form.serviceCategories.fruit || [];
|
|
|
+ const field = form.serviceCategories.field || [];
|
|
|
+ if (!fruit.length && !field.length) {
|
|
|
+ ElMessage.warning("请至少选择一类服务类别");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
submitting.value = true;
|
|
|
try {
|
|
|
- const categories = form.categories.map(({ category, plantings }) => ({
|
|
|
- category,
|
|
|
- plantings: plantings.map(
|
|
|
- ({ variety, area, startPoint, startDate, plantLocation, plantLocationWkt, phenology }) => ({
|
|
|
- variety,
|
|
|
- area,
|
|
|
- startPoint,
|
|
|
- startDate,
|
|
|
- plantLocation,
|
|
|
- plantLocationWkt,
|
|
|
- phenology: phenology || "生育期一",
|
|
|
- })
|
|
|
- ),
|
|
|
- }));
|
|
|
-
|
|
|
- const plantings = categories.flatMap((g) =>
|
|
|
- g.plantings.map((p) => ({ ...p, cropCategory: g.category }))
|
|
|
- );
|
|
|
-
|
|
|
- const payload = {
|
|
|
- id: form.id,
|
|
|
- ownerName: form.ownerName,
|
|
|
- ownerPhone: form.ownerPhone,
|
|
|
- name: form.ownerName,
|
|
|
- phone: form.ownerPhone,
|
|
|
- residentLocation: form.residentLocation,
|
|
|
- location: form.residentLocation,
|
|
|
- locationWkt: form.locationWkt,
|
|
|
- cropCategory: categories[0]?.category || "",
|
|
|
- categories,
|
|
|
- plantings,
|
|
|
- };
|
|
|
+ const tabKey = isServiceForm.value ? "service" : "owner";
|
|
|
+ let payload;
|
|
|
+
|
|
|
+ if (isServiceForm.value) {
|
|
|
+ payload = {
|
|
|
+ id: form.id,
|
|
|
+ tabKey,
|
|
|
+ ownerName: form.ownerName,
|
|
|
+ ownerPhone: form.ownerPhone,
|
|
|
+ name: form.ownerName,
|
|
|
+ phone: form.ownerPhone,
|
|
|
+ teamName: form.teamName,
|
|
|
+ teamType: form.teamType,
|
|
|
+ serviceCategories: {
|
|
|
+ fruit: [...form.serviceCategories.fruit],
|
|
|
+ field: [...form.serviceCategories.field],
|
|
|
+ },
|
|
|
+ equipments: [...form.equipments],
|
|
|
+ manualServices: [...form.manualServices],
|
|
|
+ residentLocation: form.residentLocation,
|
|
|
+ location: form.residentLocation,
|
|
|
+ locationWkt: form.locationWkt,
|
|
|
+ inviterName: form.inviterName,
|
|
|
+ };
|
|
|
+ } else {
|
|
|
+ const categories = form.categories.map(({ category, plantings }) => ({
|
|
|
+ category,
|
|
|
+ plantings: plantings.map(
|
|
|
+ ({ variety, area, startPoint, startDate, plantLocation, plantLocationWkt, phenology }) => ({
|
|
|
+ variety,
|
|
|
+ area,
|
|
|
+ startPoint,
|
|
|
+ startDate,
|
|
|
+ plantLocation,
|
|
|
+ plantLocationWkt,
|
|
|
+ phenology: phenology || "生育期一",
|
|
|
+ })
|
|
|
+ ),
|
|
|
+ }));
|
|
|
+ const plantings = categories.flatMap((g) =>
|
|
|
+ g.plantings.map((p) => ({ ...p, cropCategory: g.category }))
|
|
|
+ );
|
|
|
+ payload = {
|
|
|
+ id: form.id,
|
|
|
+ tabKey,
|
|
|
+ ownerName: form.ownerName,
|
|
|
+ ownerPhone: form.ownerPhone,
|
|
|
+ name: form.ownerName,
|
|
|
+ phone: form.ownerPhone,
|
|
|
+ equipments: [...form.equipments],
|
|
|
+ outsourceFarmWorks: [...form.outsourceFarmWorks],
|
|
|
+ residentLocation: form.residentLocation,
|
|
|
+ location: form.residentLocation,
|
|
|
+ locationWkt: form.locationWkt,
|
|
|
+ inviterName: form.inviterName,
|
|
|
+ cropCategory: categories[0]?.category || "",
|
|
|
+ categories,
|
|
|
+ plantings,
|
|
|
+ };
|
|
|
+ }
|
|
|
|
|
|
emit("submit", { mode: props.mode, data: payload });
|
|
|
ElMessage.success(isEdit.value ? "编辑成功" : "新增成功");
|
|
|
@@ -406,6 +653,11 @@ const handleSubmit = async () => {
|
|
|
margin-bottom: 18px;
|
|
|
}
|
|
|
|
|
|
+ :deep(.el-tag.el-tag--info) {
|
|
|
+ --el-tag-text-color: rgba(0, 0, 0, 0.9);
|
|
|
+ --el-tag-bg-color: #E7E7E7;
|
|
|
+ }
|
|
|
+
|
|
|
:deep(.el-form-item__label) {
|
|
|
color: #1d2129;
|
|
|
font-size: 14px;
|
|
|
@@ -425,12 +677,12 @@ const handleSubmit = async () => {
|
|
|
width: 100%;
|
|
|
|
|
|
&__name {
|
|
|
- width: 190px;
|
|
|
+ width: 160px;
|
|
|
flex-shrink: 0;
|
|
|
}
|
|
|
|
|
|
&__phone-item {
|
|
|
- width: 190px;
|
|
|
+ flex: 1;
|
|
|
margin-bottom: 0 !important;
|
|
|
|
|
|
:deep(.el-form-item__content) {
|
|
|
@@ -439,20 +691,48 @@ const handleSubmit = async () => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-.form-section {
|
|
|
- margin-bottom: 18px;
|
|
|
+.form-item--service-cat {
|
|
|
+ :deep(.el-form-item__content) {
|
|
|
+ flex: 1;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.service-cat-form {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 10px;
|
|
|
+ width: 100%;
|
|
|
+}
|
|
|
+
|
|
|
+.service-cat-form__row {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 8px;
|
|
|
+ width: 100%;
|
|
|
+}
|
|
|
+
|
|
|
+.service-cat-form__label {
|
|
|
+ flex-shrink: 0;
|
|
|
+ width: 56px;
|
|
|
+ color: rgba(0, 0, 0, 0.2);
|
|
|
+ font-size: 13px;
|
|
|
+}
|
|
|
+
|
|
|
+.service-cat-form__select {
|
|
|
+ flex: 1;
|
|
|
}
|
|
|
|
|
|
.form-section__head {
|
|
|
display: flex;
|
|
|
- gap: 12px;
|
|
|
align-items: center;
|
|
|
- padding-bottom: 10px;
|
|
|
+ justify-content: space-between;
|
|
|
+ margin-bottom: 12px;
|
|
|
}
|
|
|
|
|
|
.form-section__label {
|
|
|
- color: #1D2129;
|
|
|
- font-size: 16px;
|
|
|
+ color: #1d2129;
|
|
|
+ font-size: 14px;
|
|
|
+ line-height: 22px;
|
|
|
}
|
|
|
|
|
|
.category-list {
|
|
|
@@ -461,11 +741,6 @@ const handleSubmit = async () => {
|
|
|
gap: 16px;
|
|
|
}
|
|
|
|
|
|
-.category-block + .category-block {
|
|
|
- border-top: 1px solid #E5E6EB;
|
|
|
- padding-top: 16px;
|
|
|
-}
|
|
|
-
|
|
|
.category-block__head {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
@@ -477,9 +752,8 @@ const handleSubmit = async () => {
|
|
|
width: 120px;
|
|
|
|
|
|
:deep(.el-select__wrapper) {
|
|
|
- // background: rgba($warning-color, 0.12);
|
|
|
- box-shadow: 0 0 0 1px $warning-color inset;
|
|
|
- border-radius: 2px;
|
|
|
+ background: rgba($warning-color, 0.12);
|
|
|
+ box-shadow: 0 0 0 1px rgba($warning-color, 0.25) inset;
|
|
|
|
|
|
.el-select__selected-item,
|
|
|
.el-select__placeholder,
|
|
|
@@ -528,10 +802,8 @@ const handleSubmit = async () => {
|
|
|
|
|
|
.planting-card__label {
|
|
|
flex-shrink: 0;
|
|
|
- display: inline-block;
|
|
|
- width: 70px;
|
|
|
color: #1d2129;
|
|
|
- font-size: 14px;
|
|
|
+ font-size: 13px;
|
|
|
line-height: 22px;
|
|
|
}
|
|
|
|
|
|
@@ -580,24 +852,15 @@ const handleSubmit = async () => {
|
|
|
|
|
|
.link-btn {
|
|
|
padding: 0;
|
|
|
- font-size: 14px;
|
|
|
+ height: auto;
|
|
|
+ font-size: 13px;
|
|
|
flex-shrink: 0;
|
|
|
- cursor: pointer;
|
|
|
-}
|
|
|
-.secondary-link {
|
|
|
- padding: 0 6px;
|
|
|
- color: #FB8E33;
|
|
|
- background: rgba(251, 142, 51, 0.1);
|
|
|
- height: 25px;
|
|
|
- line-height: 25px;
|
|
|
- border-radius: 2px;
|
|
|
- &:hover {
|
|
|
- opacity: 0.8;
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
-.add-link {
|
|
|
- margin-top: 8px;
|
|
|
+.secondary-link {
|
|
|
+ color: $warning-color;
|
|
|
+ cursor: pointer;
|
|
|
+ user-select: none;
|
|
|
}
|
|
|
|
|
|
.form-item--resident {
|
|
|
@@ -606,6 +869,29 @@ const handleSubmit = async () => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+.inviter-cell {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 8px;
|
|
|
+}
|
|
|
+
|
|
|
+.inviter-cell__avatar {
|
|
|
+ flex-shrink: 0;
|
|
|
+ background: #ffe4c4;
|
|
|
+ color: #c07020;
|
|
|
+ font-size: 12px;
|
|
|
+}
|
|
|
+
|
|
|
+.inviter-cell__name {
|
|
|
+ color: #1d2129;
|
|
|
+ font-size: 14px;
|
|
|
+}
|
|
|
+
|
|
|
+.inviter-empty {
|
|
|
+ color: #86909c;
|
|
|
+ font-size: 14px;
|
|
|
+}
|
|
|
+
|
|
|
.dialog-footer {
|
|
|
display: flex;
|
|
|
justify-content: center;
|