filter-bar.uvue 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441
  1. <template>
  2. <cl-page>
  3. <view class="p-3">
  4. <demo-item :label="t('基础用法')">
  5. <cl-filter-bar>
  6. <!-- 下拉框 -->
  7. <cl-filter-item
  8. label="综合排序"
  9. type="select"
  10. :value="1"
  11. :options="coreOptions"
  12. :pt="{
  13. className: 'w-[110px] !flex-none'
  14. }"
  15. @change="onOptionsChange"
  16. ></cl-filter-item>
  17. <!-- 排序 -->
  18. <cl-filter-item
  19. label="销量"
  20. type="sort"
  21. value="desc"
  22. @change="onSortChange"
  23. ></cl-filter-item>
  24. <!-- 开关 -->
  25. <cl-filter-item
  26. label="国补"
  27. type="switch"
  28. :value="false"
  29. @change="onSwitchChange"
  30. ></cl-filter-item>
  31. <!-- 自定义 -->
  32. <view
  33. class="flex flex-row items-center justify-center flex-1"
  34. @tap="openFilter"
  35. >
  36. <cl-text>筛选</cl-text>
  37. <cl-icon name="filter-line"></cl-icon>
  38. </view>
  39. </cl-filter-bar>
  40. </demo-item>
  41. <demo-item>
  42. <cl-text pre-wrap :pt="{ className: 'p-2' }">{{
  43. JSON.stringify(filterForm, null, 4)
  44. }}</cl-text>
  45. </demo-item>
  46. <demo-item>
  47. <cl-text pre-wrap :pt="{ className: 'p-2' }">{{
  48. JSON.stringify(searchForm, null, 4)
  49. }}</cl-text>
  50. </demo-item>
  51. </view>
  52. <!-- 自定义筛选 -->
  53. <cl-popup
  54. v-model="filterVisible"
  55. :title="t('筛选')"
  56. direction="right"
  57. size="80%"
  58. :show-header="false"
  59. >
  60. <view class="flex flex-col h-full">
  61. <scroll-view class="flex-1">
  62. <cl-form :pt="{ className: 'p-3' }">
  63. <cl-form-item label="服务/折扣">
  64. <cl-row :gutter="20">
  65. <cl-col :span="8" v-for="(item, index) in disOptions" :key="index">
  66. <cl-checkbox
  67. v-model="searchForm.dis"
  68. :label="item.label"
  69. :value="item.value"
  70. :show-icon="false"
  71. :pt="{
  72. className: parseClass([
  73. 'mb-3 p-2 rounded-lg justify-center border border-solid border-transparent',
  74. [isDark, 'bg-surface-800', 'bg-surface-100'],
  75. [
  76. searchForm.dis.includes(item.value),
  77. `${isDark ? '!bg-surface-700' : '!bg-white'} !border-primary-500`
  78. ]
  79. ])
  80. }"
  81. ></cl-checkbox>
  82. </cl-col>
  83. </cl-row>
  84. </cl-form-item>
  85. <cl-form-item label="价格区间">
  86. <view class="flex flex-row items-center">
  87. <cl-input
  88. v-model="searchForm.minPrice"
  89. type="digit"
  90. placeholder="最低价"
  91. :pt="{
  92. className: 'flex-1',
  93. inner: {
  94. className: 'text-center'
  95. }
  96. }"
  97. ></cl-input>
  98. <cl-text
  99. :pt="{
  100. className: 'px-2'
  101. }"
  102. >~</cl-text
  103. >
  104. <cl-input
  105. v-model="searchForm.maxPrice"
  106. type="digit"
  107. placeholder="最高价"
  108. :pt="{
  109. className: 'flex-1',
  110. inner: {
  111. className: 'text-center'
  112. }
  113. }"
  114. ></cl-input>
  115. </view>
  116. </cl-form-item>
  117. <cl-form-item label="品牌">
  118. <cl-row :gutter="20">
  119. <cl-col
  120. :span="8"
  121. v-for="(item, index) in brandOptions"
  122. :key="index"
  123. >
  124. <cl-checkbox
  125. v-model="searchForm.brand"
  126. :label="item.label"
  127. :value="item.value"
  128. :show-icon="false"
  129. :pt="{
  130. className: parseClass([
  131. 'mb-3 p-2 rounded-lg justify-center border border-solid border-transparent',
  132. [isDark, 'bg-surface-800', 'bg-surface-100'],
  133. [
  134. searchForm.brand.includes(item.value),
  135. `${isDark ? '!bg-surface-700' : '!bg-white'} !border-primary-500`
  136. ]
  137. ])
  138. }"
  139. ></cl-checkbox>
  140. </cl-col>
  141. </cl-row>
  142. </cl-form-item>
  143. <cl-form-item label="内存">
  144. <cl-row :gutter="20">
  145. <cl-col
  146. :span="8"
  147. v-for="(item, index) in memoryOptions"
  148. :key="index"
  149. >
  150. <cl-radio
  151. v-model="searchForm.memory"
  152. :label="item.label"
  153. :value="item.value"
  154. :show-icon="false"
  155. :pt="{
  156. className: parseClass([
  157. 'mb-3 p-2 rounded-lg justify-center border border-solid border-transparent',
  158. [isDark, 'bg-surface-800', 'bg-surface-100'],
  159. [
  160. searchForm.memory == item.value,
  161. `${isDark ? '!bg-surface-700' : '!bg-white'} !border-primary-500`
  162. ]
  163. ])
  164. }"
  165. ></cl-radio>
  166. </cl-col>
  167. </cl-row>
  168. </cl-form-item>
  169. <cl-form-item label="颜色">
  170. <cl-row :gutter="20">
  171. <cl-col
  172. :span="8"
  173. v-for="(item, index) in colorOptions"
  174. :key="index"
  175. >
  176. <cl-radio
  177. v-model="searchForm.color"
  178. :label="item.label"
  179. :value="item.value"
  180. :show-icon="false"
  181. :pt="{
  182. className: parseClass([
  183. 'mb-3 p-2 rounded-lg justify-center border border-solid border-transparent',
  184. [isDark, 'bg-surface-800', 'bg-surface-100'],
  185. [
  186. searchForm.color == item.value,
  187. `${isDark ? '!bg-surface-700' : '!bg-white'} !border-primary-500`
  188. ]
  189. ])
  190. }"
  191. ></cl-radio>
  192. </cl-col>
  193. </cl-row>
  194. </cl-form-item>
  195. </cl-form>
  196. </scroll-view>
  197. <view class="flex flex-row p-3">
  198. <cl-button size="large" type="info" text border fluid @tap="closeFilter">{{
  199. t("取消")
  200. }}</cl-button>
  201. <cl-button size="large" fluid @tap="submit">{{ t("确定") }}</cl-button>
  202. </view>
  203. <cl-safe-area type="bottom"></cl-safe-area>
  204. </view>
  205. </cl-popup>
  206. </cl-page>
  207. </template>
  208. <script lang="ts" setup>
  209. import DemoItem from "../components/item.uvue";
  210. import { reactive, ref } from "vue";
  211. import { useUi, type ClSelectOption } from "@/uni_modules/cool-ui";
  212. import { isDark, parseClass, t } from "@/.cool";
  213. const ui = useUi();
  214. const filterVisible = ref(false);
  215. function openFilter() {
  216. filterVisible.value = true;
  217. }
  218. function closeFilter() {
  219. filterVisible.value = false;
  220. }
  221. function submit() {
  222. closeFilter();
  223. ui.showLoading();
  224. setTimeout(() => {
  225. ui.hideLoading();
  226. }, 1000);
  227. }
  228. const coreOptions = ref<ClSelectOption[]>([
  229. {
  230. label: "综合排序",
  231. value: 1
  232. },
  233. {
  234. label: "价格从高到底",
  235. value: 2
  236. },
  237. {
  238. label: "价格从低到高",
  239. value: 3
  240. }
  241. ]);
  242. type Option = {
  243. label: string;
  244. value: string;
  245. };
  246. const disOptions = ref<Option[]>([
  247. {
  248. label: "百亿补贴",
  249. value: "billion_subsidy"
  250. },
  251. {
  252. label: "以旧换新",
  253. value: "trade_in"
  254. },
  255. {
  256. label: "分期免息",
  257. value: "installment"
  258. },
  259. {
  260. label: "包邮",
  261. value: "free_shipping"
  262. },
  263. {
  264. label: "促销",
  265. value: "promotion"
  266. },
  267. {
  268. label: "价保",
  269. value: "price_protection"
  270. },
  271. {
  272. label: "仅看有货",
  273. value: "in_stock"
  274. },
  275. {
  276. label: "货到付款",
  277. value: "cod"
  278. }
  279. ]);
  280. const brandOptions = ref<Option[]>([
  281. {
  282. label: "华为",
  283. value: "huawei"
  284. },
  285. {
  286. label: "苹果",
  287. value: "apple"
  288. },
  289. {
  290. label: "小米",
  291. value: "xiaomi"
  292. },
  293. {
  294. label: "三星",
  295. value: "samsung"
  296. },
  297. {
  298. label: "OPPO",
  299. value: "oppo"
  300. },
  301. {
  302. label: "vivo",
  303. value: "vivo"
  304. },
  305. {
  306. label: "荣耀",
  307. value: "honor"
  308. }
  309. ]);
  310. const colorOptions = ref<Option[]>([
  311. {
  312. label: "红色",
  313. value: "red"
  314. },
  315. {
  316. label: "蓝色",
  317. value: "blue"
  318. },
  319. {
  320. label: "黑色",
  321. value: "black"
  322. },
  323. {
  324. label: "白色",
  325. value: "white"
  326. },
  327. {
  328. label: "金色",
  329. value: "gold"
  330. },
  331. {
  332. label: "银色",
  333. value: "silver"
  334. },
  335. {
  336. label: "绿色",
  337. value: "green"
  338. },
  339. {
  340. label: "紫色",
  341. value: "purple"
  342. },
  343. {
  344. label: "灰色",
  345. value: "gray"
  346. },
  347. {
  348. label: "粉色",
  349. value: "pink"
  350. }
  351. ]);
  352. const memoryOptions = ref<Option[]>([
  353. {
  354. label: "128GB",
  355. value: "128"
  356. },
  357. {
  358. label: "256GB",
  359. value: "256"
  360. },
  361. {
  362. label: "512GB",
  363. value: "512"
  364. },
  365. {
  366. label: "1TB",
  367. value: "1024"
  368. }
  369. ]);
  370. type SearchForm = {
  371. dis: string[];
  372. minPrice: string;
  373. maxPrice: string;
  374. brand: string[];
  375. memory: string;
  376. color: string;
  377. };
  378. const searchForm = ref<SearchForm>({
  379. dis: [],
  380. minPrice: "50",
  381. maxPrice: "300",
  382. brand: [],
  383. memory: "",
  384. color: ""
  385. });
  386. type FilterForm = {
  387. core: number;
  388. sort: string;
  389. switch: boolean;
  390. };
  391. const filterForm = reactive<FilterForm>({
  392. core: 0,
  393. sort: "none",
  394. switch: false
  395. });
  396. function onOptionsChange(val: number) {
  397. console.log(val);
  398. filterForm.core = val;
  399. }
  400. function onSortChange(val: string) {
  401. console.log(val);
  402. filterForm.sort = val;
  403. }
  404. function onSwitchChange(val: boolean) {
  405. console.log(val);
  406. filterForm.switch = val;
  407. }
  408. </script>