hookehuyr

物资选择组件列表变成单行列表

1 +<!--
2 + * @Date: 2024-07-23 16:24:08
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2024-07-24 18:14:14
5 + * @FilePath: /temple_material_request/src/components/chooseMaterial/index.vue
6 + * @Description: 选择物资组件
7 +-->
8 +<template>
9 + <div class="choose-material-page">
10 + <van-popup
11 + v-model:show="showBottom"
12 + position="bottom"
13 + closeable
14 + @close="onClose"
15 + :style="{ height: '100%' }"
16 + >
17 + <van-sticky :offset-top="-33">
18 + <div style="margin-top: 2rem; background-color: white;">
19 + <div style="padding: 1rem;">
20 + <van-row gutter="10" justify="center" align="center">
21 + <van-col span="16">
22 + <div style="background-color: #FBF9F1; display: flex; border-radius: 5rem; padding: 0 1rem; align-items: center; justify-content: center;">
23 + <van-icon name="search" /><van-field v-model="search_value" @blur="onBlur" label="" placeholder="搜索物资" style="background-color: #FBF9F1;" />
24 + </div>
25 + </van-col>
26 + <van-col span="8">
27 + <div @click="showType" style="border-radius: 8px; border: 1px solid #DBDBDB; padding: 0.5rem 0 0.5rem 1rem; font-size: 0.9rem; color: #B4B4B4;">
28 + 物资分类&nbsp;&nbsp;
29 + <van-icon name="arrow-down" color="#A67939" />
30 + </div>
31 + </van-col>
32 + </van-row>
33 + </div>
34 + </div>
35 + </van-sticky>
36 + <!-- TODO:物资列表显示值需要过滤掉购物车已经选中的物资,新增的物资需要显示在购物车最上面 -->
37 + <van-list
38 + v-model:loading="loading"
39 + :finished="finished"
40 + finished-text="没有更多了"
41 + @load="onLoad"
42 + >
43 + <div v-for="item in list" :key="item" >
44 + <van-row justify="space-around" align="center" style="padding: 1rem; background-color: #F2F2F2;">
45 + <van-col span="8" @click="onCheckAll(item)">
46 + <van-icon v-if="item.checked" name="checked" size="1.25rem" :color="styleColor.baseColor" />
47 + <van-icon v-else name="passed" size="1.25rem" />
48 + <span :style="{ color: styleColor.baseColor }">&nbsp;&nbsp;全选</span>
49 + </van-col>
50 + <van-col span="8" style="text-align: center; font-size: 0.95rem; color: #666666; font-weight: bold;">{{ item.name }}</van-col>
51 + <van-col span="8"></van-col>
52 + </van-row>
53 + <van-row align="center" justify="space-between" style="">
54 + <van-col v-for="m in item.m_list" :key="m.id" span="24" style="display: flex; padding: 1rem; border-bottom: 1px solid #F5F5F5;">
55 + <van-icon v-if="m.checked" @click="onCheck(item, m)" name="checked" size="1.25rem" :color="styleColor.baseColor" />
56 + <van-icon v-else name="passed" @click="onCheck(item, m)" size="1.25rem" />&nbsp;&nbsp;
57 + <div class="van-ellipsis" :style="{ color: styleColor.baseColor, textDecoration: 'underline' }" @click="onClickTitle(m)">
58 + {{ m.name }}
59 + </div>
60 + </van-col>
61 + </van-row>
62 + </div>
63 + </van-list>
64 + <div style="height: 6rem;"></div>
65 + <div class="control-bar">
66 + <van-button plain block type="primary" :color="styleColor.baseColor" @click="addShoppingCart">加入购物车</van-button>
67 + <div style="display: flex; align-items: center; margin-left: 1rem;">
68 + <van-badge :content="cart_count">
69 + <van-icon name="shopping-cart-o" size="2.5rem" :color="styleColor.baseColor" @click="goShoppingCart" />
70 + </van-badge>
71 + </div>
72 + </div>
73 + <van-back-top class="custom" bottom="12vh" z-index="9999">返回顶部</van-back-top>
74 + <van-dialog v-model:show="show_type" title="请选择筛选分类" @confirm="onConfirm" show-cancel-button :confirm-button-color="styleColor.baseColor">
75 + <div style="padding: 1rem;">
76 + <van-checkbox-group v-model="type_checked" shape="square" direction="horizontal" :checked-color="styleColor.baseColor">
77 + <van-checkbox name="a" style="margin-bottom: 0.5rem;">复选框 a</van-checkbox>
78 + <van-checkbox name="b" style="margin-bottom: 0.5rem;">复选框 b</van-checkbox>
79 + <van-checkbox name="c" style="margin-bottom: 0.5rem;">复选框 c</van-checkbox>
80 + <van-checkbox name="d" style="margin-bottom: 0.5rem;">复选框 d</van-checkbox>
81 + </van-checkbox-group>
82 + </div>
83 + </van-dialog>
84 + </van-popup>
85 + </div>
86 +
87 + <material-detail :show="show_material_detail" @close="onCloseDetail"></material-detail>
88 +
89 +</template>
90 +
91 +<script setup>
92 +import { ref } from 'vue'
93 +import { useRoute, useRouter } from 'vue-router'
94 +import { showToast } from 'vant';
95 +import { Cookies, $, _, axios, storeToRefs, mainStore, Toast, useTitle } from '@/utils/generatePackage.js'
96 +//import { } from '@/utils/generateModules.js'
97 +//import { } from '@/utils/generateIcons.js'
98 +//import { } from '@/composables'
99 +import { styleColor } from "@/constant.js";
100 +import materialDetail from '@/components/materialDetail/index.vue';
101 +
102 +const $route = useRoute();
103 +const $router = useRouter();
104 +useTitle($route.meta.title);
105 +
106 +const props = defineProps({
107 + show: Boolean,
108 +});
109 +const emit = defineEmits(['close']);
110 +
111 +const showBottom = ref(false);
112 +
113 +onMounted(() => {
114 +});
115 +
116 +// 监听字段变化
117 +watch(
118 + () => props.show,
119 + (v) => {
120 + showBottom.value = v;
121 + }
122 +);
123 +
124 +const onClose = () => {
125 + emit('close');
126 +}
127 +
128 +const list = ref([]);
129 +const loading = ref(false);
130 +const finished = ref(false);
131 +
132 +const onLoad = () => {
133 + // 异步更新数据
134 + // setTimeout 仅做示例,真实场景中一般为 ajax 请求
135 + setTimeout(() => {
136 + for (let i = 0; i < 5; i++) {
137 + list.value.push({ id: i, name: '物资分类' + i, checked: false, m_list: [] });
138 + }
139 +
140 + list.value.forEach((item) => {
141 + for (let j = 0; j < 5; j++) {
142 + item.m_list.push({ id: j, name: '标题' + j, checked: false });
143 + }
144 + })
145 +
146 + // 加载状态结束
147 + loading.value = false;
148 +
149 + // 数据全部加载完成
150 + if (list.value.length >= 40) {
151 + finished.value = true;
152 + }
153 + }, 1000);
154 +};
155 +
156 +const onClickTitle = (item) => { // 点击物资标题回调
157 + console.warn(item);
158 + show_material_detail.value = true;
159 +}
160 +
161 +const show_type = ref(false);
162 +const showType = () => {
163 + show_type.value = true;
164 +}
165 +const type_checked = ref([]);
166 +const onConfirm = () => {
167 + console.warn(type_checked.value);
168 +}
169 +
170 +const search_value = ref('');
171 +const onBlur = () => {
172 + // TODO: 输入框失去焦点,接口需要一个搜索接口,返回相应的值
173 + console.warn(search_value.value);
174 +}
175 +
176 +const show_material_detail = ref(false);
177 +const onCloseDetail = () => { // 关闭物资详情窗口
178 + show_material_detail.value = false;
179 +}
180 +
181 +const onCheckAll = (item) => { // 全选分类
182 + item.checked = !item.checked;
183 + item.m_list.forEach((m) => {
184 + m.checked = item.checked;
185 + });
186 +}
187 +const onCheck = (item, m) => { // 选中单个物资
188 + m.checked = !m.checked;
189 + item.checked = item.m_list.every(m => m.checked);
190 +}
191 +
192 +const addShoppingCart = () => { // 新增购物车
193 + shop_cart_list.value = [];
194 + list.value.forEach(item => {
195 + item.m_list.forEach(m => {
196 + if (m.checked) {
197 + shop_cart_list.value.push(m);
198 + }
199 + })
200 + });
201 + // 购物车为空提示
202 + if (!shop_cart_list.value.length) {
203 + showToast('请选择物资');
204 + return;
205 + }
206 + // TODO: 请求购物车接口,更新购物车数量
207 + console.warn(shop_cart_list.value);
208 +}
209 +
210 +const goShoppingCart = () => { // 点击购物车图标
211 + if ($route.path === '/material_pre_request') { // 待申领物资页面
212 + onClose()
213 + } else {
214 + $router.push({ path: '/material_pre_request' });
215 + }
216 +}
217 +
218 +const cart_count = ref(0); // 购物车数量
219 +
220 +const shop_cart_list = ref([]); // 购物车列表
221 +</script>
222 +
223 +<style lang="less">
224 +.choose-material-page {
225 + .control-bar {
226 + display: flex; position: fixed; padding: 1rem 1.5rem; left: 0; right: 0; bottom: 0; background-color: white; width: calc(100% - 3rem); justify-content: space-between; align-items: center; box-shadow: 0rem -0.33rem 0.33rem 0.08rem rgba(0,0,0,0.06);
227 + }
228 +}
229 +
230 +.custom {
231 + width: 80px;
232 + font-size: 14px;
233 + text-align: center;
234 + background-color: #A67939;
235 +}
236 +</style>
1 <!-- 1 <!--
2 * @Date: 2024-07-23 16:24:08 2 * @Date: 2024-07-23 16:24:08
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2024-07-24 18:14:14 4 + * @LastEditTime: 2024-07-25 13:32:12
5 * @FilePath: /temple_material_request/src/components/chooseMaterial/index.vue 5 * @FilePath: /temple_material_request/src/components/chooseMaterial/index.vue
6 * @Description: 选择物资组件 6 * @Description: 选择物资组件
7 --> 7 -->
...@@ -18,22 +18,25 @@ ...@@ -18,22 +18,25 @@
18 <div style="margin-top: 2rem; background-color: white;"> 18 <div style="margin-top: 2rem; background-color: white;">
19 <div style="padding: 1rem;"> 19 <div style="padding: 1rem;">
20 <van-row gutter="10" justify="center" align="center"> 20 <van-row gutter="10" justify="center" align="center">
21 - <van-col span="16"> 21 + <van-col span="24">
22 <div style="background-color: #FBF9F1; display: flex; border-radius: 5rem; padding: 0 1rem; align-items: center; justify-content: center;"> 22 <div style="background-color: #FBF9F1; display: flex; border-radius: 5rem; padding: 0 1rem; align-items: center; justify-content: center;">
23 <van-icon name="search" /><van-field v-model="search_value" @blur="onBlur" label="" placeholder="搜索物资" style="background-color: #FBF9F1;" /> 23 <van-icon name="search" /><van-field v-model="search_value" @blur="onBlur" label="" placeholder="搜索物资" style="background-color: #FBF9F1;" />
24 </div> 24 </div>
25 </van-col> 25 </van-col>
26 - <van-col span="8">
27 - <div @click="showType" style="border-radius: 8px; border: 1px solid #DBDBDB; padding: 0.5rem 0 0.5rem 1rem; font-size: 0.9rem; color: #B4B4B4;">
28 - 物资分类&nbsp;&nbsp;
29 - <van-icon name="arrow-down" color="#A67939" />
30 - </div>
31 - </van-col>
32 </van-row> 26 </van-row>
33 </div> 27 </div>
34 </div> 28 </div>
35 </van-sticky> 29 </van-sticky>
36 <!-- TODO:物资列表显示值需要过滤掉购物车已经选中的物资,新增的物资需要显示在购物车最上面 --> 30 <!-- TODO:物资列表显示值需要过滤掉购物车已经选中的物资,新增的物资需要显示在购物车最上面 -->
31 + <van-row justify="space-around" align="center" style="padding: 1rem; background-color: #F2F2F2;">
32 + <van-col span="8" @click="onCheckAll()">
33 + <van-icon v-if="is_all_checked" name="checked" size="1.25rem" :color="styleColor.baseColor" />
34 + <van-icon v-else name="passed" size="1.25rem" />
35 + <span :style="{ color: styleColor.baseColor }">&nbsp;&nbsp;全选</span>
36 + </van-col>
37 + <van-col span="8" style="text-align: center; font-size: 0.95rem; color: #666666; font-weight: bold;">选择物资</van-col>
38 + <van-col span="8"></van-col>
39 + </van-row>
37 <van-list 40 <van-list
38 v-model:loading="loading" 41 v-model:loading="loading"
39 :finished="finished" 42 :finished="finished"
...@@ -41,21 +44,12 @@ ...@@ -41,21 +44,12 @@
41 @load="onLoad" 44 @load="onLoad"
42 > 45 >
43 <div v-for="item in list" :key="item" > 46 <div v-for="item in list" :key="item" >
44 - <van-row justify="space-around" align="center" style="padding: 1rem; background-color: #F2F2F2;">
45 - <van-col span="8" @click="onCheckAll(item)">
46 - <van-icon v-if="item.checked" name="checked" size="1.25rem" :color="styleColor.baseColor" />
47 - <van-icon v-else name="passed" size="1.25rem" />
48 - <span :style="{ color: styleColor.baseColor }">&nbsp;&nbsp;全选</span>
49 - </van-col>
50 - <van-col span="8" style="text-align: center; font-size: 0.95rem; color: #666666; font-weight: bold;">{{ item.name }}</van-col>
51 - <van-col span="8"></van-col>
52 - </van-row>
53 <van-row align="center" justify="space-between" style=""> 47 <van-row align="center" justify="space-between" style="">
54 - <van-col v-for="m in item.m_list" :key="m.id" span="24" style="display: flex; padding: 1rem; border-bottom: 1px solid #F5F5F5;"> 48 + <van-col span="24" style="display: flex; padding: 1rem; border-bottom: 1px solid #F5F5F5;">
55 - <van-icon v-if="m.checked" @click="onCheck(item, m)" name="checked" size="1.25rem" :color="styleColor.baseColor" /> 49 + <van-icon v-if="item.checked" @click="onCheck(item)" name="checked" size="1.25rem" :color="styleColor.baseColor" />
56 - <van-icon v-else name="passed" @click="onCheck(item, m)" size="1.25rem" />&nbsp;&nbsp; 50 + <van-icon v-else name="passed" @click="onCheck(item)" size="1.25rem" />&nbsp;&nbsp;
57 - <div class="van-ellipsis" :style="{ color: styleColor.baseColor, textDecoration: 'underline' }" @click="onClickTitle(m)"> 51 + <div class="van-ellipsis" :style="{ color: styleColor.baseColor, textDecoration: 'underline' }" @click="onClickTitle(item)">
58 - {{ m.name }} 52 + {{ item.name }}
59 </div> 53 </div>
60 </van-col> 54 </van-col>
61 </van-row> 55 </van-row>
...@@ -71,16 +65,6 @@ ...@@ -71,16 +65,6 @@
71 </div> 65 </div>
72 </div> 66 </div>
73 <van-back-top class="custom" bottom="12vh" z-index="9999">返回顶部</van-back-top> 67 <van-back-top class="custom" bottom="12vh" z-index="9999">返回顶部</van-back-top>
74 - <van-dialog v-model:show="show_type" title="请选择筛选分类" @confirm="onConfirm" show-cancel-button :confirm-button-color="styleColor.baseColor">
75 - <div style="padding: 1rem;">
76 - <van-checkbox-group v-model="type_checked" shape="square" direction="horizontal" :checked-color="styleColor.baseColor">
77 - <van-checkbox name="a" style="margin-bottom: 0.5rem;">复选框 a</van-checkbox>
78 - <van-checkbox name="b" style="margin-bottom: 0.5rem;">复选框 b</van-checkbox>
79 - <van-checkbox name="c" style="margin-bottom: 0.5rem;">复选框 c</van-checkbox>
80 - <van-checkbox name="d" style="margin-bottom: 0.5rem;">复选框 d</van-checkbox>
81 - </van-checkbox-group>
82 - </div>
83 - </van-dialog>
84 </van-popup> 68 </van-popup>
85 </div> 69 </div>
86 70
...@@ -134,20 +118,14 @@ const onLoad = () => { ...@@ -134,20 +118,14 @@ const onLoad = () => {
134 // setTimeout 仅做示例,真实场景中一般为 ajax 请求 118 // setTimeout 仅做示例,真实场景中一般为 ajax 请求
135 setTimeout(() => { 119 setTimeout(() => {
136 for (let i = 0; i < 5; i++) { 120 for (let i = 0; i < 5; i++) {
137 - list.value.push({ id: i, name: '物资分类' + i, checked: false, m_list: [] }); 121 + list.value.push({ id: i, name: '物资' + i, checked: false });
138 } 122 }
139 123
140 - list.value.forEach((item) => {
141 - for (let j = 0; j < 5; j++) {
142 - item.m_list.push({ id: j, name: '标题' + j, checked: false });
143 - }
144 - })
145 -
146 // 加载状态结束 124 // 加载状态结束
147 loading.value = false; 125 loading.value = false;
148 126
149 // 数据全部加载完成 127 // 数据全部加载完成
150 - if (list.value.length >= 40) { 128 + if (list.value.length >= 10) {
151 finished.value = true; 129 finished.value = true;
152 } 130 }
153 }, 1000); 131 }, 1000);
...@@ -178,15 +156,29 @@ const onCloseDetail = () => { // 关闭物资详情窗口 ...@@ -178,15 +156,29 @@ const onCloseDetail = () => { // 关闭物资详情窗口
178 show_material_detail.value = false; 156 show_material_detail.value = false;
179 } 157 }
180 158
181 -const onCheckAll = (item) => { // 全选分类 159 +const is_all_checked = ref(false);
182 - item.checked = !item.checked; 160 +const onCheckAll = () => {
183 - item.m_list.forEach((m) => { 161 + is_all_checked.value = !is_all_checked.value;
184 - m.checked = item.checked; 162 + if (is_all_checked.value) {
185 - }); 163 + list.value.forEach(item => {
164 + item.checked = true;
165 + })
166 + } else {
167 + list.value.forEach(item => {
168 + item.checked = false;
169 + item.error = false;
170 + })
171 + }
186 } 172 }
187 -const onCheck = (item, m) => { // 选中单个物资 173 +const onCheck = (item) => {
188 - m.checked = !m.checked; 174 + item.checked = !item.checked;
189 - item.checked = item.m_list.every(m => m.checked); 175 + // 全部为选中
176 + let all_checked = list.value.every((item) => item.checked === true);
177 + if (all_checked) {
178 + is_all_checked.value = true;
179 + } else {
180 + is_all_checked.value = false;
181 + }
190 } 182 }
191 183
192 const addShoppingCart = () => { // 新增购物车 184 const addShoppingCart = () => { // 新增购物车
......