index.vue 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. <template>
  2. <div class="web-home">
  3. <div class="title">
  4. <img src="@/assets/images/web/web-home_title.png"/>
  5. </div>
  6. <div class="area">
  7. <div class="selected">
  8. <div class="label">搜索范围:</div>
  9. <div class="value" v-if="!noAreaCpt">
  10. <template v-if="searchAreaCpt.text">
  11. {{searchAreaCpt.text}}
  12. </template>
  13. <template v-else>
  14. <template v-for="item in searchAreaCpt.arr">
  15. <div>{{item.treeName}}</div>
  16. </template>
  17. </template>
  18. </div>
  19. </div>
  20. <div class="search-input">
  21. <template v-if="!noAreaCpt">
  22. <div class="left-select __hover" @click="state.showArea = true">
  23. 搜索范围<SvgIcon name="arrow_1" rotate="90" size="14" color="var(--cus-text-color-3)"/>
  24. </div>
  25. </template>
  26. <template v-else>
  27. <div class="left-select __disabled">
  28. 暂无范围
  29. </div>
  30. </template>
  31. <el-input v-model="state.searchText" :placeholder="!noAreaCpt ? '请输入关键字进行查询' : '请先配置搜索范围'" @keyup.enter="toList(state.searchText)" :disabled="noAreaCpt"/>
  32. <div class="right-icon __hover" @click="toList(state.searchText)">
  33. <SvgIcon name="search_1" color="var(--cus-main-color)" size="40"/>
  34. </div>
  35. </div>
  36. </div>
  37. <div class="history" v-if="state.historyList?.length > 0">
  38. <div class="label">搜索记录</div>
  39. <div class="result">
  40. <template v-for="(item, index) in state.historyList">
  41. <span class="__hover" @click="toList(item, true)">{{index + 1}}.{{item}}</span>
  42. </template>
  43. </div>
  44. </div>
  45. <CusDialog
  46. :show="state.showArea"
  47. @onClose="$emit('update:show', false)"
  48. width="1000px"
  49. height="auto"
  50. submit-text="关闭"
  51. :show-close="false"
  52. @onSubmit="state.showArea = false"
  53. >
  54. <CusTab :tabs="state.areaList" type="type1" v-model:param="state.areaTab" label-key="treeName" value-key="treeId"/>
  55. <div class="index-list">
  56. <div class="all">
  57. <div class="__check" :class="{active: indexTabAllCpt}" @click="onIndexTabAll">全选</div>
  58. </div>
  59. <div class="list">
  60. <template v-for="(item, index) in indexListCpt">
  61. <div class="list-item">
  62. <div class="__check" :class="{active: item.__select}" @click="item.__select = !item.__select">{{ item.treeName }}</div>
  63. </div>
  64. </template>
  65. </div>
  66. </div>
  67. </CusDialog>
  68. </div>
  69. </template>
  70. <script setup lang="ts">
  71. import {computed, getCurrentInstance, onMounted, reactive} from "vue";
  72. import router from "@/router";
  73. import {ElMessage} from "element-plus";
  74. import {useWebStore} from "@/stores";
  75. const {proxy} = getCurrentInstance()
  76. const WebStore = useWebStore()
  77. const state: any = reactive({
  78. searchText: '',
  79. historyList: [],
  80. areaList: [],
  81. showArea: false,
  82. areaTab: ''
  83. })
  84. const indexListCpt = computed(() => {
  85. return state.areaList.filter(v => v.treeId === state.areaTab)?.[0]?.children || []
  86. })
  87. const indexTabAllCpt = computed(() => {
  88. return indexListCpt.value.every(v => v.__select)
  89. })
  90. const searchAreaCpt = computed(() => {
  91. const obj = {
  92. text: '',
  93. arr: []
  94. }
  95. let i = 0
  96. state.areaList.forEach(v => {
  97. v.children.forEach(c => {
  98. i++
  99. if (c.__select) {
  100. obj.arr.push(c)
  101. }
  102. })
  103. })
  104. if (i === obj.arr.length) {
  105. obj.arr = []
  106. }
  107. if (obj.arr.length === 0) {
  108. obj.text = '全部'
  109. }
  110. return obj
  111. })
  112. const noAreaCpt = computed(() => {
  113. return !(state.areaList.length > 0)
  114. })
  115. const initHistory = () => {
  116. proxy.$api.mockGetSearchHistory().then(res => {
  117. state.historyList = res.data
  118. })
  119. }
  120. const initArea = () => {
  121. WebStore.getSearchAreaTree().then(res => {
  122. state.areaList = JSON.parse(JSON.stringify(res))
  123. state.areaTab = state.areaList[0]?.treeId
  124. })
  125. }
  126. const onIndexTabAll = () => {
  127. const flag = JSON.parse(JSON.stringify(indexTabAllCpt.value))
  128. indexListCpt.value.forEach(v => {
  129. v.__select = !flag
  130. })
  131. }
  132. const toList = (text, isAll = false) => {
  133. console.log(searchAreaCpt.value.arr)
  134. if (text) {
  135. const routerUrl = router.resolve({
  136. name: '4f6dd2ea-7c0a-4923-9a57-932ef42235f6',
  137. query: {
  138. text,
  139. index: isAll ? '' : searchAreaCpt.value.arr.map(v => v.treeId).join(',')
  140. }
  141. });
  142. window.open(routerUrl.href, "_blank");
  143. } else {
  144. ElMessage({
  145. message: '请输入关键字进行查询!',
  146. grouping: true,
  147. type: 'warning',
  148. })
  149. }
  150. }
  151. onMounted(() => {
  152. // initHistory()
  153. initArea()
  154. })
  155. </script>
  156. <style lang="scss" scoped>
  157. .web-home {
  158. width: 100%;
  159. height: 100%;
  160. background-image: url("@/assets/images/web/web-home_bg.png");
  161. background-size: 100% 100%;
  162. background-repeat: no-repeat;
  163. display: flex;
  164. flex-direction: column;
  165. justify-content: center;
  166. align-items: center;
  167. gap: 40px;
  168. .area {
  169. width: 1000px;
  170. .selected {
  171. display: flex;
  172. line-height: 30px;
  173. .label {
  174. font-weight: 500;
  175. font-size: 16px;
  176. color: var(--cus-main-color);
  177. padding-left: 16px;
  178. }
  179. .value {
  180. flex: 1;
  181. color: var(--cus-text-color-2);
  182. display: flex;
  183. flex-wrap: wrap;
  184. column-gap: 20px;
  185. }
  186. }
  187. .search-input {
  188. margin-top: 10px;
  189. display: flex;
  190. align-items: center;
  191. width: 100%;
  192. height: 60px;
  193. background: rgba(255,255,255,0.9);
  194. box-shadow: 0px 0px 2px 0px rgba(167,220,255,0.5);
  195. border-radius: 60px;
  196. border: 1px solid var(--cus-main-color);
  197. .left-select {
  198. display: flex;
  199. align-items: center;
  200. justify-content: center;
  201. width: 184px;
  202. gap: 17px;
  203. color: var(--cus-text-color-4);
  204. font-size: 18px;
  205. position: relative;
  206. &:after {
  207. content: '';
  208. position: absolute;
  209. right: 0;
  210. height: 40px;
  211. width: 1px;
  212. background-color: var(--cus-main-color);
  213. }
  214. }
  215. :deep(.el-input) {
  216. font-size: 18px;
  217. color: var(--cus-text-color-2);
  218. .el-input__wrapper {
  219. box-shadow: none !important;
  220. background-color: transparent;
  221. .el-input__inner {
  222. &::placeholder {
  223. color: var(--cus-text-color-4);
  224. }
  225. }
  226. }
  227. }
  228. .right-icon {
  229. margin-right: 20px;
  230. }
  231. }
  232. }
  233. .history {
  234. width: 1000px;
  235. .label {
  236. font-weight: 500;
  237. font-size: 16px;
  238. color: var(--cus-main-color);
  239. padding-left: 16px;
  240. }
  241. .result {
  242. margin-top: 10px;
  243. width: 100%;
  244. padding: 16px;
  245. background: rgba(255,255,255,0.8);
  246. box-shadow: 0px 4px 4px 0px rgba(255,255,255,0.15);
  247. border-radius: 8px;
  248. font-weight: 400;
  249. font-size: 16px;
  250. color: var(--cus-text-color-2);
  251. display: flex;
  252. flex-wrap: wrap;
  253. gap: 10px 32px;
  254. }
  255. }
  256. }
  257. .cus-tab {
  258. padding: 30px 0 22px 28px;
  259. :deep(.cus-tab-item::after) {
  260. bottom: -23px !important;
  261. }
  262. }
  263. .index-list {
  264. padding: 20px 28px 0;
  265. .list {
  266. margin-top: 10px;
  267. display: flex;
  268. flex-wrap: wrap;
  269. gap: 30px;
  270. }
  271. }
  272. </style>