index.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570
  1. <template>
  2. <div class="app-header">
  3. <div class="top">
  4. <a> <span class="iconfont icon-youxiang"></span> market@aporesearch.com</a>
  5. <a><span class="iconfont icon-lianxidianhua"></span> 1-332-251-9412</a>
  6. <div><span class="iconfont icon-weidenglu"></span>Login/Register</div>
  7. </div>
  8. <div class="navBox">
  9. <a class="navBox_l" href="/">
  10. <img src="/assets/images/img2.png" alt="">
  11. </a>
  12. <div class="navBox_c">
  13. <n-dropdown :options="reportOptions" trigger="hover" size="huge" @select="chooseReportMenu">
  14. <a :class="{'router-link-active':(route.name=='reports')}" :href="jumpLink('/report-industries')">
  15. Reports
  16. </a>
  17. </n-dropdown>
  18. <a :class="{'router-link-active':route.path=='/market'}" :href="jumpLink('/market')">
  19. Custom Researc
  20. </a>
  21. <n-dropdown :options="newsOptions" trigger="hover" size="huge" @select="chooseNewsMenu">
  22. <a :class="{'router-link-active':(route.name=='newsCategories'||route.path=='/news-categories')}" :href="jumpLink('/news-categories')">
  23. Industry News
  24. </a>
  25. </n-dropdown>
  26. <n-dropdown :options="aboutOptions" trigger="hover" size="huge" @select="chooseAboutMenu">
  27. <a :class="{'router-link-active':route.path=='/about'||route.path=='/link'||route.path=='/order'||route.path=='/term'||route.path=='/qualify'}" :href="jumpLink('/about')">
  28. About Us
  29. </a>
  30. </n-dropdown>
  31. <a :class="{'router-link-active':route.path=='/contactUs'}" :href="jumpLink('/contactUs')">Contact</a>
  32. </div>
  33. <div class="navBox_r">
  34. <div class="search">
  35. <div class="search_l">
  36. <n-dropdown trigger="hover" :keyboard="false" :options="selectTypeList">
  37. <div class="search_l_type">
  38. Industry News
  39. <span class="iconfont icon-dkw_guanbi-"></span>
  40. </div>
  41. </n-dropdown>
  42. </div>
  43. <div class="search_c">
  44. <n-input v-model:value="searchVal" @keydown.enter="handleSearch()" type="text" clearable placeholder="Please Enter Keywords" />
  45. </div>
  46. <div class="search_r" @click="handleSearch()">
  47. Search
  48. </div>
  49. </div>
  50. </div>
  51. </div>
  52. <n-modal :show="signInVisible" preset="dialog" :title="signInTitle" :showIcon="false" :close-on-esc="false" :mask-closable="false" @close="signInVisible = false" :class="{ 'login-dialog': !pcShow }">
  53. <SignInLogin @closeSginDialog="closeSginDialog" v-if="sginType == 'login'"></SignInLogin>
  54. <SignInRegister @closeSginDialog="closeSginDialog" v-if="sginType == 'register'"></SignInRegister>
  55. <SignInForgot @closeSginDialog="closeSginDialog" v-if="sginType == 'forgot'"></SignInForgot>
  56. </n-modal>
  57. <n-modal v-model:show="logoutVisible" preset="dialog" title="提示" :showIcon="false" content="确认退出登录吗?" positive-text="确认" negative-text="取消" :close-on-esc="false" :mask-closable="false" @positive-click="submitLogoutCallback" @negative-click="cancelLogoutCallback" :class="{ 'login-dialog': !pcShow }" />
  58. </div>
  59. </template>
  60. <script lang="ts" setup>
  61. import { useI18n } from "#imports";
  62. import SignInLogin from "@/components/Login/index.vue";
  63. import SignInRegister from "@/components/Login/register.vue";
  64. import SignInForgot from "@/components/Login/forgot.vue";
  65. import { useLocaleStoreWithOut } from "@/store";
  66. import {
  67. // Component,
  68. // h,
  69. onMounted,
  70. ref,
  71. onUnmounted,
  72. onBeforeMount,
  73. watch,
  74. computed,
  75. inject,
  76. onServerPrefetch,
  77. } from "vue";
  78. import { createDiscreteApi } from "naive-ui";
  79. import { useRouter, useRoute } from "vue-router";
  80. import {
  81. MdApps,
  82. MdHome,
  83. IosPaper,
  84. IosSearch,
  85. MdToday,
  86. MdPeople,
  87. MdSearch,
  88. IosCall,
  89. IosGlobe,
  90. } from "@vicons/ionicons4";
  91. import { useUserStore } from "@/store/user";
  92. const message = createDiscreteApi(["message"]);
  93. const { t, locale, setLocale } = useI18n();
  94. const switchLocalePath = useSwitchLocalePath();
  95. const router = useRouter();
  96. const route = useRoute();
  97. const userStore = useUserStore();
  98. const pcShow = ref(true);
  99. const keyword = ref<string>(""); //关键字
  100. userStore.setLang(locale.value == "en" ? "en-US" : "zh-CN");
  101. const value = userStore.getLang;
  102. const language = ref("");
  103. const langSelected = ref("zh");
  104. language.value = value === "en-US" ? "en" : "";
  105. langSelected.value = value === "en-US" ? "en" : "zh";
  106. const renderIcon = (icon: string) => {
  107. return () => {
  108. return h("span", { class: icon });
  109. };
  110. };
  111. const renderIconC4 = (icon: Component) => {
  112. return () => {
  113. return h(NIcon, null, {
  114. default: () => h(icon),
  115. });
  116. };
  117. };
  118. // const renderIconLabel = (option: DropdownOption) => {
  119. // return h('a',{ onclick: () => chooseMenu, target: '_blank' },{ default: () => option.label});
  120. // }
  121. const reportOptions = [] as any; //报告列表
  122. const newsOptions = [] as any; //行业资讯
  123. const aboutOptions = [] as any; //关于我们
  124. const bulletinOptions = [] as any; // 简报智库
  125. const mobileMenu = [
  126. { label: t("common.navigate.home"), key: "home", name: "home" },
  127. {
  128. label: t("common.navigate.report"),
  129. key: "reports",
  130. children: reportOptions,
  131. name: "reports",
  132. },
  133. { label: t("common.navigate.market"), key: "market", name: "marketIndex" },
  134. {
  135. label: t("common.navigate.news"),
  136. key: "newsCategories",
  137. children: newsOptions,
  138. name: "newsCategories",
  139. },
  140. {
  141. label: t("common.navigate.aboutUs"),
  142. key: "about",
  143. children: aboutOptions,
  144. name: "about",
  145. },
  146. {
  147. label: t("common.navigate.contactUs"),
  148. key: "contactUs",
  149. name: "contactUsIndex",
  150. },
  151. // {
  152. // label: "简报智库",
  153. // key: "bulletin",
  154. // children: bulletinOptions,
  155. // name: "bulletin",
  156. // },
  157. ];
  158. const selectTypeValue = ref();
  159. const selectTypeList = ref([
  160. {
  161. label: t("common.navigate.report"),
  162. value: "reports",
  163. },
  164. {
  165. label: t("common.navigate.news"),
  166. value: "newsCategories",
  167. },
  168. {
  169. label: t("common.navigate.bulletin"),
  170. value: "bulletinThinkTank",
  171. },
  172. ]);
  173. const signInVisible = ref<boolean>(false);
  174. const signInTitle = ref<string>("");
  175. const sginType = ref<string>("login");
  176. const logoutVisible = ref(false);
  177. const userInfo = computed(() => userStore.getUserInfo);
  178. const isLogin = computed(() =>
  179. userStore.getToken && userStore.getUserInfo ? true : false
  180. );
  181. const jumpLink = (url: string) => {
  182. return (language.value == "en" ? "/en" : "") + url;
  183. };
  184. watch(
  185. () => userStore.getSearchType,
  186. (val) => {
  187. selectTypeValue.value = val || null;
  188. }
  189. );
  190. watch(langSelected, () => {
  191. if (langSelected.value == "en") {
  192. selectTypeList.value = [
  193. {
  194. label: t("common.navigate.report"),
  195. value: "reports",
  196. },
  197. {
  198. label: t("common.navigate.news"),
  199. value: "newsCategories",
  200. },
  201. ];
  202. // userStore.resetState();
  203. }
  204. });
  205. watch(
  206. () => userStore.getShowLoginDialog,
  207. (newval, oldval) => {
  208. signInVisible.value = newval;
  209. sginType.value = "login";
  210. signInTitle.value = t("common.login.title");
  211. }
  212. );
  213. watch(signInVisible, (val) => {
  214. if (val === false) {
  215. userStore.setShowLoginDialog(false);
  216. }
  217. });
  218. // 中英文切换
  219. const langChange = async (lng: string) => {
  220. userStore.setLang(lng == "zh" ? "zh-CN" : "en-US");
  221. const path = switchLocalePath(lng);
  222. setLocale(lng);
  223. // router.push(path);
  224. // location.reload();
  225. location.href = path;
  226. };
  227. // 研究报告菜单切换
  228. function chooseReportMenu(key: string | number, _option: DropdownOption) {
  229. router.push({
  230. name: "reports",
  231. params: { category: key, lang: language.value },
  232. });
  233. }
  234. // 行业资讯
  235. function chooseNewsMenu(key: string | number) {
  236. router.push({
  237. name: "newsCategories",
  238. params: { marketType: key, lang: language.value },
  239. });
  240. }
  241. onBeforeMount(async () => {
  242. pcShow.value = !isMobile();
  243. });
  244. // 关于我们跳转
  245. function chooseAboutMenu(key: string | number, option: DropdownOption) {
  246. router.push({ name: option.name, params: { lang: language.value } });
  247. }
  248. // 关于简报智库
  249. function chooseBulletinMenu(key: string | number, _option: DropdownOption) {
  250. router.push({
  251. name: "bulletinThinkTank",
  252. params: {
  253. marketType: _option.marketType,
  254. },
  255. });
  256. }
  257. // 手机端跳转
  258. function chooseMenu(key: string | number, option: DropdownOption) {
  259. if ("reports" === option.name) {
  260. router.push({
  261. name: option.name,
  262. params: { category: key, lang: language.value },
  263. });
  264. } else if ("newsCategories" === option.name) {
  265. router.push({
  266. name: option.name,
  267. params: { marketType: key, lang: language.value },
  268. });
  269. } else if ("home" === option.name) {
  270. // router.push({
  271. // name: language.value === "" ? "home" : "homeEn",
  272. // params: { marketType: key, lang: language.value },
  273. // });
  274. jumpLink("/");
  275. } else {
  276. router.push({ name: option.name, params: { lang: language.value } });
  277. }
  278. }
  279. function handleSearch() {
  280. switch (selectTypeValue.value) {
  281. case "reports":
  282. router.push({
  283. name: "reports",
  284. params: { lang: language.value, keyword: keyword.value },
  285. });
  286. break;
  287. case "newsCategories":
  288. router.push({
  289. name: "newsCategories",
  290. params: { lang: language.value, keyword: keyword.value },
  291. });
  292. break;
  293. case "bulletinThinkTank":
  294. router.push({
  295. name: "bulletinThinkTank",
  296. params: { marketType: "industry-brief", title: keyword.value },
  297. });
  298. break;
  299. default:
  300. router.push({
  301. name: "reports",
  302. params: { lang: language.value, keyword: keyword.value },
  303. });
  304. break;
  305. }
  306. }
  307. function keyDown() {
  308. handleSearch();
  309. }
  310. const handleSignIn = () => {
  311. signInVisible.value = true;
  312. sginType.value = "login";
  313. signInTitle.value = t("common.login.title");
  314. };
  315. const toMine = () => {
  316. router.push({
  317. name: "mine",
  318. });
  319. };
  320. const handleLogout = () => {
  321. logoutVisible.value = true;
  322. };
  323. const submitLogoutCallback = () => {
  324. logOut_Api().then((res) => {
  325. message.message.success(t("report.demand.success"));
  326. userStore.resetState();
  327. router.push("/");
  328. });
  329. };
  330. const cancelLogoutCallback = () => {
  331. logoutVisible.value = false;
  332. };
  333. const closeSginDialog = (type: string) => {
  334. switch (type) {
  335. case "success":
  336. signInVisible.value = false;
  337. break;
  338. case "login":
  339. signInTitle.value = t("common.login.title");
  340. break;
  341. case "register":
  342. sginType.value = type;
  343. signInTitle.value = t("common.login.register");
  344. break;
  345. case "forgot":
  346. sginType.value = type;
  347. signInTitle.value = t("common.login.forgetPasswordTitle");
  348. break;
  349. default:
  350. break;
  351. }
  352. };
  353. // onMounted(async () => {
  354. //window.addEventListener('scroll',onScroll);
  355. // 下拉菜单
  356. const getDictListData = async () => {
  357. const cacheDict = await getLocalSessionReport();
  358. cacheDict?.forEach(
  359. (vo: { dictLabel: any; dictValue: any; dictIcon: any }) => {
  360. reportOptions.push({
  361. label: vo.dictLabel,
  362. key: vo.dictValue,
  363. icon: renderIcon(vo.dictIcon),
  364. name: "reports",
  365. });
  366. }
  367. );
  368. const cacheDictNews = await getLocalSessionNews();
  369. cacheDictNews?.forEach((vo: any) => {
  370. newsOptions.push({
  371. label: vo.dictLabel,
  372. key: vo.dictValue,
  373. icon: renderIcon(vo.dictIcon),
  374. name: "newsCategories",
  375. });
  376. });
  377. aboutOptions.push({
  378. label: t("common.navAboutUs.comp"),
  379. name: "about",
  380. icon: renderIcon("iconfont iconfont icon-ziyuan"),
  381. });
  382. aboutOptions.push({
  383. label: t("common.navAboutUs.method"),
  384. name: "link",
  385. icon: renderIcon("iconfont icon-chaxun"),
  386. });
  387. aboutOptions.push({
  388. label: t("common.navAboutUs.order"),
  389. name: "order",
  390. icon: renderIcon("iconfont icon-a-dingdanguanli2x"),
  391. });
  392. aboutOptions.push({
  393. label: t("common.navAboutUs.term"),
  394. name: "term",
  395. icon: renderIcon("iconfont icon-shejiyukaifa-"),
  396. });
  397. aboutOptions.push({
  398. label: t("common.navAboutUs.qualify"),
  399. name: "qualify",
  400. icon: renderIcon("iconfont iconfont icon-ziyuan"),
  401. });
  402. bulletinOptions.push({
  403. label: "行业简报",
  404. name: "bulletinThinkTank",
  405. marketType: "industry-brief",
  406. icon: renderIcon("bqfl-iconfont bqfl-iconfont icon-zhinengjianbao"),
  407. });
  408. bulletinOptions.push({
  409. label: "企业洞察",
  410. name: "bulletinThinkTank",
  411. marketType: "enterprise-hole-analysis",
  412. icon: renderIcon("bqfl-iconfont bqfl-iconfont icon-yanjiubaogao"),
  413. });
  414. bulletinOptions.push({
  415. label: "行业简报",
  416. name: "bulletinThinkTank",
  417. marketType: "industry-brief",
  418. icon: renderIcon("bqfl-iconfont bqfl-iconfont icon-zhinengjianbao"),
  419. });
  420. };
  421. watch(
  422. () => route.path,
  423. (val) => {
  424. getDictListData();
  425. }
  426. );
  427. getDictListData();
  428. </script>
  429. <style lang='scss' >
  430. .app-header {
  431. z-index: 9;
  432. width: 100%;
  433. position: fixed;
  434. left: 0;
  435. top: 0;
  436. .top {
  437. display: flex;
  438. align-items: center;
  439. justify-content: end;
  440. background: rgba(6, 17, 29, 0.5);
  441. padding: 0 var(--size-60);
  442. border-bottom: 1px solid rgba(255, 255, 255, 0.2);
  443. > a,
  444. > div {
  445. display: inline-block;
  446. font-size: var(--size-14);
  447. color: #ffffff;
  448. margin-left: var(--size-35);
  449. height: var(--size-45);
  450. line-height: var(--size-45);
  451. cursor: pointer;
  452. display: flex;
  453. align-items: center;
  454. span {
  455. font-size: var(--size-19);
  456. display: inline-block;
  457. margin-right: var(--size-4);
  458. }
  459. &:last-child {
  460. padding-left: var(--size-35);
  461. border-left: var(--size-1) solid #fff;
  462. }
  463. }
  464. }
  465. .navBox {
  466. display: flex;
  467. align-items: center;
  468. justify-content: space-between;
  469. background: rgba(6, 17, 29, 0.5);
  470. padding: 0 var(--size-60);
  471. border-bottom: 1px solid rgba(255, 255, 255, 0.2);
  472. height: var(--size-85);
  473. .navBox_l {
  474. font-size: var(--size-34);
  475. color: #ffffff;
  476. img {
  477. width: var(--size-366);
  478. height: var(--size-57);
  479. display: block;
  480. }
  481. }
  482. .navBox_c {
  483. font-size: var(--size-18);
  484. color: #ffffff;
  485. display: flex;
  486. cursor: pointer;
  487. > a {
  488. padding: var(--size-7) var(--size-43);
  489. border-right: var(--size-1) solid rgba(255, 255, 255, 0.5);
  490. }
  491. }
  492. .navBox_r {
  493. .search {
  494. display: flex;
  495. align-items: center;
  496. width: var(--size-450);
  497. height: var(--size-44);
  498. background: #ffffff;
  499. border-radius: 8px;
  500. overflow: hidden;
  501. .search_l {
  502. width: var(--size-148);
  503. font-size: var(--size-14);
  504. text-align: center;
  505. cursor: pointer;
  506. .search_l_type {
  507. span {
  508. transform: rotateZ(90deg);
  509. display: inline-block;
  510. color: #1a1a1a;
  511. }
  512. }
  513. }
  514. .search_c {
  515. border-left: 1px solid #cccccc;
  516. .n-input {
  517. --n-height: var(--size-26) !important;
  518. line-height: var(--size-26) !important;
  519. }
  520. }
  521. .search_r {
  522. width: var(--size-105);
  523. font-size: var(--size-16);
  524. color: #ffffff;
  525. text-align: center;
  526. height: var(--size-44);
  527. background: linear-gradient(0deg, #7b9c4f 0%, #2da19d 100%), #1a1a1a;
  528. line-height: var(--size-44);
  529. cursor: pointer;
  530. }
  531. }
  532. }
  533. }
  534. }
  535. .n-input {
  536. --n-border: none !important;
  537. --n-border-hover: none !important;
  538. --n-border-focus: none !important;
  539. --n-box-shadow-focus: none !important;
  540. --n-caret-color: #ef001f !important;
  541. font-size: var(--size-16) !important;
  542. --n-text-color-hover: none !important;
  543. }
  544. </style>