|
|
@@ -1,43 +1,480 @@
|
|
|
<template>
|
|
|
<div class="select-category">
|
|
|
<div class="select-category__content">
|
|
|
- <!-- 选择种植品类 -->
|
|
|
- 种植品类
|
|
|
+ <div class="page-header">
|
|
|
+ <div class="page-title">请选择您的种植品类</div>
|
|
|
+ <div class="page-subtitle">完善档案,精准匹配农机服务与农情预警</div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="major-tabs">
|
|
|
+ <div
|
|
|
+ v-for="tab in majorTabs"
|
|
|
+ :key="tab.key"
|
|
|
+ class="major-tab"
|
|
|
+ :class="{ active: activeTabKey === tab.key }"
|
|
|
+ @click="activeTabKey = tab.key"
|
|
|
+ >
|
|
|
+ {{ tab.label }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="search-bar">
|
|
|
+ <el-icon class="search-icon"><Search /></el-icon>
|
|
|
+ <input
|
|
|
+ v-model="searchKeyword"
|
|
|
+ class="search-input"
|
|
|
+ type="text"
|
|
|
+ placeholder="请输入品种名称"
|
|
|
+ @keyup.enter="handleSearch"
|
|
|
+ />
|
|
|
+ <div class="search-btn" @click="handleSearch">搜索</div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="category-list">
|
|
|
+ <div
|
|
|
+ v-for="group in displayGroups"
|
|
|
+ :key="group.name"
|
|
|
+ class="category-card"
|
|
|
+ >
|
|
|
+ <div class="section-title">
|
|
|
+ <span class="title-icon"></span>
|
|
|
+ <span>{{ group.name }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="tag-group add-tag-group">
|
|
|
+ <div
|
|
|
+ v-for="item in group.items"
|
|
|
+ :key="item.id"
|
|
|
+ class="tag-item"
|
|
|
+ :class="{ selected: item.selected }"
|
|
|
+ @click="handleSelect(item)"
|
|
|
+ >
|
|
|
+ <span class="text">{{ item.name }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div v-if="!displayGroups.length" class="empty-tip">暂无匹配品类</div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
+
|
|
|
<div class="custom-bottom-fixed-btns">
|
|
|
<div class="bottom-btn secondary-btn" @click="emit('prev')">上一步</div>
|
|
|
- <div class="bottom-btn primary-btn" @click="emit('next')">下一步</div>
|
|
|
+ <div class="bottom-btn primary-btn" @click="handleNext">下一步 (2/3)</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
+import { computed, onMounted, ref } from "vue";
|
|
|
+import { ElMessage } from "element-plus";
|
|
|
+import { Search } from "@element-plus/icons-vue";
|
|
|
+
|
|
|
+const SESSION_KEY = "ENTRY_SELECTED_CATEGORY";
|
|
|
+
|
|
|
const emit = defineEmits(["prev", "next"]);
|
|
|
+
|
|
|
+const majorTabs = ref([
|
|
|
+ {
|
|
|
+ key: "fruit",
|
|
|
+ label: "果树类",
|
|
|
+ groups: [
|
|
|
+ {
|
|
|
+ name: "热带亚热带",
|
|
|
+ items: [
|
|
|
+ { id: "mango", name: "芒果", selected: false },
|
|
|
+ { id: "litchi", name: "荔枝", selected: false },
|
|
|
+ { id: "longan", name: "龙眼", selected: false },
|
|
|
+ { id: "banana", name: "香蕉", selected: false },
|
|
|
+ { id: "pineapple", name: "菠萝", selected: false },
|
|
|
+ { id: "coconut", name: "椰子", selected: false },
|
|
|
+ { id: "papaya", name: "木瓜", selected: false },
|
|
|
+ { id: "jackfruit", name: "菠萝蜜", selected: false },
|
|
|
+ { id: "passion", name: "百香果", selected: false },
|
|
|
+ { id: "durian", name: "榴莲", selected: false },
|
|
|
+ { id: "rambutan", name: "红毛丹", selected: false },
|
|
|
+ { id: "waxapple", name: "莲雾", selected: false },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "柑果类",
|
|
|
+ items: [
|
|
|
+ { id: "mandarin", name: "柑橘", selected: false },
|
|
|
+ { id: "orange", name: "橙子", selected: false },
|
|
|
+ { id: "pomelo", name: "柚子", selected: false },
|
|
|
+ { id: "lemon", name: "柠檬", selected: false },
|
|
|
+ { id: "kumquat", name: "金桔", selected: false },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "仁果类",
|
|
|
+ items: [
|
|
|
+ { id: "apple", name: "苹果", selected: false },
|
|
|
+ { id: "pear", name: "梨", selected: false },
|
|
|
+ { id: "hawthorn", name: "山楂", selected: false },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "核果类",
|
|
|
+ items: [
|
|
|
+ { id: "tao", name: "桃", selected: false },
|
|
|
+ { id: "yt", name: "樱桃", selected: false },
|
|
|
+ { id: "li", name: "李", selected: false },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ {
|
|
|
+ key: "field",
|
|
|
+ label: "大田类",
|
|
|
+ groups: [
|
|
|
+ {
|
|
|
+ name: "粮食作物",
|
|
|
+ items: [
|
|
|
+ { id: "rice", name: "水稻", selected: false },
|
|
|
+ { id: "wheat", name: "小麦", selected: false },
|
|
|
+ { id: "corn", name: "玉米", selected: false },
|
|
|
+ { id: "soybean", name: "大豆", selected: false },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "经济作物",
|
|
|
+ items: [
|
|
|
+ { id: "cotton", name: "棉花", selected: false },
|
|
|
+ { id: "peanut", name: "花生", selected: false },
|
|
|
+ { id: "rape", name: "油菜", selected: false },
|
|
|
+ { id: "sugarcane", name: "甘蔗", selected: false },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ {
|
|
|
+ key: "vegetable",
|
|
|
+ label: "蔬菜类",
|
|
|
+ groups: [
|
|
|
+ {
|
|
|
+ name: "叶菜类",
|
|
|
+ items: [
|
|
|
+ { id: "cabbage", name: "白菜", selected: false },
|
|
|
+ { id: "spinach", name: "菠菜", selected: false },
|
|
|
+ { id: "lettuce", name: "生菜", selected: false },
|
|
|
+ { id: "celery", name: "芹菜", selected: false },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "瓜果类",
|
|
|
+ items: [
|
|
|
+ { id: "tomato", name: "番茄", selected: false },
|
|
|
+ { id: "cucumber", name: "黄瓜", selected: false },
|
|
|
+ { id: "eggplant", name: "茄子", selected: false },
|
|
|
+ { id: "pepper", name: "辣椒", selected: false },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+]);
|
|
|
+
|
|
|
+const activeTabKey = ref("fruit");
|
|
|
+const searchKeyword = ref("");
|
|
|
+const appliedKeyword = ref("");
|
|
|
+
|
|
|
+const activeTab = computed(() =>
|
|
|
+ majorTabs.value.find((tab) => tab.key === activeTabKey.value) || majorTabs.value[0]
|
|
|
+);
|
|
|
+
|
|
|
+const displayGroups = computed(() => {
|
|
|
+ const groups = activeTab.value?.groups || [];
|
|
|
+ const keyword = (appliedKeyword.value || "").trim();
|
|
|
+ if (!keyword) return groups;
|
|
|
+ return groups
|
|
|
+ .map((group) => ({
|
|
|
+ ...group,
|
|
|
+ items: group.items.filter((item) => item.name.includes(keyword)),
|
|
|
+ }))
|
|
|
+ .filter((group) => group.items.length);
|
|
|
+});
|
|
|
+
|
|
|
+const selectedItems = computed(() => {
|
|
|
+ const list = [];
|
|
|
+ majorTabs.value.forEach((tab) => {
|
|
|
+ tab.groups.forEach((group) => {
|
|
|
+ group.items.forEach((item) => {
|
|
|
+ if (item.selected) {
|
|
|
+ list.push({
|
|
|
+ id: item.id,
|
|
|
+ name: item.name,
|
|
|
+ groupName: group.name,
|
|
|
+ majorKey: tab.key,
|
|
|
+ majorLabel: tab.label,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+ });
|
|
|
+ return list;
|
|
|
+});
|
|
|
+
|
|
|
+const handleSearch = () => {
|
|
|
+ appliedKeyword.value = searchKeyword.value.trim();
|
|
|
+};
|
|
|
+
|
|
|
+const handleSelect = (item) => {
|
|
|
+ item.selected = !item.selected;
|
|
|
+};
|
|
|
+
|
|
|
+const restoreSelection = () => {
|
|
|
+ try {
|
|
|
+ const raw = sessionStorage.getItem(SESSION_KEY);
|
|
|
+ if (!raw) return;
|
|
|
+ const selectedIds = new Set(JSON.parse(raw).map((item) => item.id));
|
|
|
+ majorTabs.value.forEach((tab) => {
|
|
|
+ tab.groups.forEach((group) => {
|
|
|
+ group.items.forEach((item) => {
|
|
|
+ item.selected = selectedIds.has(item.id);
|
|
|
+ });
|
|
|
+ });
|
|
|
+ });
|
|
|
+ } catch {
|
|
|
+ // ignore
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+const handleNext = () => {
|
|
|
+ if (!selectedItems.value.length) {
|
|
|
+ ElMessage.warning("请至少选择一个种植品类");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ sessionStorage.setItem(SESSION_KEY, JSON.stringify(selectedItems.value));
|
|
|
+ emit("next", selectedItems.value);
|
|
|
+};
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ restoreSelection();
|
|
|
+});
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
.select-category {
|
|
|
- flex: 1;
|
|
|
+ height: calc(100% - 80px);
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
- overflow: hidden;
|
|
|
- padding-bottom: 80px;
|
|
|
+ overflow: auto;
|
|
|
|
|
|
&__content {
|
|
|
flex: 1;
|
|
|
overflow-y: auto;
|
|
|
+ padding: 8px 16px 20px;
|
|
|
}
|
|
|
|
|
|
- .custom-bottom-fixed-btns {
|
|
|
- gap: 12px;
|
|
|
- background: transparent;
|
|
|
- box-shadow: none;
|
|
|
+ .page-header {
|
|
|
+ padding: 8px 4px 16px;
|
|
|
|
|
|
- .bottom-btn {
|
|
|
+ .page-title {
|
|
|
+ font-size: 26px;
|
|
|
+ color: #005599;
|
|
|
+ font-family: "PangMenZhengDao";
|
|
|
+ line-height: 36px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .page-subtitle {
|
|
|
+ margin-top: 4px;
|
|
|
+ font-size: 14px;
|
|
|
+ color: rgba(46, 46, 46, 0.4);
|
|
|
+ line-height: 20px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .major-tabs {
|
|
|
+ display: flex;
|
|
|
+ gap: 10px;
|
|
|
+ margin-bottom: 12px;
|
|
|
+
|
|
|
+ .major-tab {
|
|
|
+ flex: 1;
|
|
|
+ height: 36px;
|
|
|
+ line-height: 36px;
|
|
|
+ text-align: center;
|
|
|
+ border-radius: 8px;
|
|
|
+ font-size: 15px;
|
|
|
+ color: rgba(0, 0, 0, 0.55);
|
|
|
+ background: #fff;
|
|
|
+ cursor: pointer;
|
|
|
+
|
|
|
+ &.active {
|
|
|
+ color: #fff;
|
|
|
+ background: #2199f8;
|
|
|
+ font-weight: 500;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .search-bar {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ height: 36px;
|
|
|
+ padding: 0 12px;
|
|
|
+ margin-bottom: 10px;
|
|
|
+ background: rgba(255, 255, 255, 0.5);
|
|
|
+ border: 1px solid rgba(33, 153, 248, 0.5);
|
|
|
+ border-radius: 6px;
|
|
|
+
|
|
|
+ .search-icon {
|
|
|
+ color: rgba(0, 0, 0, 0.35);
|
|
|
+ font-size: 16px;
|
|
|
+ margin-right: 6px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .search-input {
|
|
|
flex: 1;
|
|
|
- padding: 12px 0;
|
|
|
+ border: none;
|
|
|
+ outline: none;
|
|
|
+ background: transparent;
|
|
|
+ font-size: 14px;
|
|
|
+ color: #333;
|
|
|
+
|
|
|
+ &::placeholder {
|
|
|
+ color: rgba(0, 0, 0, 0.3);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .search-btn {
|
|
|
+ flex-shrink: 0;
|
|
|
+ padding-left: 10px;
|
|
|
+ color: #2199f8;
|
|
|
+ font-size: 14px;
|
|
|
+ cursor: pointer;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .category-list {
|
|
|
+ .category-card {
|
|
|
+ background: #fff;
|
|
|
+ border-radius: 12px;
|
|
|
+ padding: 14px 12px 16px;
|
|
|
+ margin-bottom: 12px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .section-title {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 8px;
|
|
|
+ margin-bottom: 4px;
|
|
|
font-size: 16px;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #1a1a1a;
|
|
|
+
|
|
|
+ .title-icon {
|
|
|
+ position: relative;
|
|
|
+ width: 14px;
|
|
|
+ height: 14px;
|
|
|
+ flex-shrink: 0;
|
|
|
+
|
|
|
+ &::before,
|
|
|
+ &::after {
|
|
|
+ content: "";
|
|
|
+ position: absolute;
|
|
|
+ width: 10px;
|
|
|
+ height: 10px;
|
|
|
+ border-radius: 50%;
|
|
|
+ }
|
|
|
+
|
|
|
+ &::before {
|
|
|
+ left: 0;
|
|
|
+ top: 2px;
|
|
|
+ background: #2199f8;
|
|
|
+ opacity: 0.85;
|
|
|
+ }
|
|
|
+
|
|
|
+ &::after {
|
|
|
+ right: 0;
|
|
|
+ top: 0;
|
|
|
+ background: #7ec8ff;
|
|
|
+ opacity: 0.9;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .empty-tip {
|
|
|
+ padding: 40px 0;
|
|
|
+ text-align: center;
|
|
|
+ color: rgba(0, 0, 0, 0.35);
|
|
|
+ font-size: 14px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .tag-group {
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: repeat(4, 1fr);
|
|
|
+ gap: 0 8px;
|
|
|
+ font-size: 14px;
|
|
|
+
|
|
|
+ .tag-item {
|
|
|
+ margin-top: 10px;
|
|
|
+ position: relative;
|
|
|
+ border-radius: 6px;
|
|
|
+ box-sizing: border-box;
|
|
|
+ height: 36px;
|
|
|
+ text-align: center;
|
|
|
+ line-height: 36px;
|
|
|
+ cursor: pointer;
|
|
|
+ transition: all 0.3s;
|
|
|
+ color: #000000;
|
|
|
+ background: rgba(241, 241, 241, 0.12);
|
|
|
+ border: 1px solid #ebebeb;
|
|
|
+
|
|
|
+ .text {
|
|
|
+ display: inline-flex;
|
|
|
+ align-items: center;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.selected {
|
|
|
+ border: 1px solid #2199f8;
|
|
|
+ background: #e8f5ff;
|
|
|
+ color: #2199f8;
|
|
|
+
|
|
|
+ &::after {
|
|
|
+ content: "";
|
|
|
+ position: absolute;
|
|
|
+ z-index: 9;
|
|
|
+ top: -1px;
|
|
|
+ right: -1px;
|
|
|
+ width: 18px;
|
|
|
+ height: 14px;
|
|
|
+ background: url("@/assets/img/home/checked-bg-top.png") no-repeat bottom right / 18px 13px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ &.add-tag-group {
|
|
|
+ .tag-item {
|
|
|
+ color: #000000;
|
|
|
+ background: rgba(241, 241, 241, 0.12);
|
|
|
+ border: 1px solid #ebebeb;
|
|
|
+
|
|
|
+ &.selected {
|
|
|
+ border: 1px solid #2199f8;
|
|
|
+ background: #e8f5ff;
|
|
|
+ color: #2199f8;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .custom-bottom-fixed-btns {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: baseline;
|
|
|
+ padding: 10px 12px 0 12px;
|
|
|
+ height: 80px;
|
|
|
+ background: #fff;
|
|
|
+ box-sizing: border-box;
|
|
|
+ box-shadow: 2px 2px 5px 0 rgba(0, 0, 0, 0.4);
|
|
|
+
|
|
|
+ .bottom-btn {
|
|
|
+ padding: 0 30px;
|
|
|
+ height: 40px;
|
|
|
+ line-height: 40px;
|
|
|
+ font-size: 14px;
|
|
|
border-radius: 25px;
|
|
|
+ text-align: center;
|
|
|
}
|
|
|
|
|
|
.secondary-btn {
|