index.vue 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. <template>
  2. <div id="page" class="page">
  3. <div class="top-title wow fadeInUp" data-wow-duration="2s" data-wow-delay="0s" data-wow-offset="0">
  4. <div class="top-container">
  5. <n-icon :component="MdNavigate" size="40" style="vertical-align: middle" />
  6. <span>{{ t('common.navigate.contactUs') }}</span>
  7. </div>
  8. </div>
  9. <div class="page-nav-container wow fadeInLeft" data-wow-duration="2s" data-wow-delay="0s" data-wow-offset="0">
  10. <div class="nav-txt">
  11. <n-breadcrumb separator=">">
  12. <n-breadcrumb-item>
  13. <n-icon :component="MdHome" /><router-link to="/home">{{ t('common.navigate.home') }}</router-link>
  14. </n-breadcrumb-item>
  15. <n-breadcrumb-item> <n-icon :component="MdNavigate" />{{ t('common.navigate.contactUs') }} </n-breadcrumb-item>
  16. </n-breadcrumb>
  17. </div>
  18. </div>
  19. <div class="contact">
  20. <div class="container">
  21. <div class="title wow fadeInLeft" data-wow-duration="2s" data-wow-delay="0s" data-wow-offset="0">
  22. <h2>{{ t('contact.contact.title') }}</h2>
  23. </div>
  24. <div class="contact-desc wow fadeInLeft" data-wow-duration="2s" data-wow-delay="0s" data-wow-offset="0">
  25. <div class="contact-desc-info">
  26. <div class="corp">{{ t('contact.contact.corpName') }}</div>
  27. <div class="box">
  28. <n-icon :component="IosCall" size="20" />
  29. <!-- <a href="tel:86-027-85307885">86-027-85307885</a> -->
  30. <a href="tel:1-8884226999">+1-888 422 6999 (US)</a>
  31. <span style="display: inline-block; margin: 0 5px">or</span>
  32. <a href="tel:86-17320528525">+86-173 2052 8525 (Int'l)</a>
  33. </div>
  34. <div class="box" v-if="formData.lang === 'zh-CN'">
  35. <n-icon :component="MdPhonePortrait" size="20" />
  36. <a href="tel:86-17320528525">86-17320528525(24h)</a>
  37. </div>
  38. <div class="box">
  39. <n-icon :component="MdMail" size="20" />
  40. <a href="mailto:sales@dirmarketresearch.com">sales@dirmarketresearch.com</a>
  41. </div>
  42. <div class="box">
  43. <n-icon :component="IosPin" size="20" />
  44. <span>{{ t('common.footer.area') }}</span>
  45. <span>{{ t('common.footer.street') }}</span>
  46. </div>
  47. </div>
  48. <div class="contact-desc-we">
  49. <img src="@/assets/images/we.png" />
  50. </div>
  51. </div>
  52. </div>
  53. </div>
  54. <div class="contact-form">
  55. <div class="container">
  56. <div class="title wow fadeInLeft" data-wow-duration="2s" data-wow-delay="0s" data-wow-offset="0">
  57. {{ t('contact.form.title') }}
  58. </div>
  59. <div class="content wow fadeInLeft" data-wow-duration="2s" data-wow-delay="0s" data-wow-offset="0">
  60. <n-form require-mark-placement="left" ref="formRef" :model="formData" :rules="rules" label-width="auto">
  61. <n-form-item :label="t('report.demand.companyName')" label-placement="left" path="companyName">
  62. <n-input :placeholder="t('report.demand.companyNameTip')" v-model:value="formData.companyName" />
  63. </n-form-item>
  64. <n-form-item :label="t('report.demand.address')" label-placement="left" path="addr">
  65. <n-input :placeholder="t('report.demand.addressTip')" v-model:value="formData.addr" />
  66. </n-form-item>
  67. <n-form-item :label="t('report.demand.email')" label-placement="left" path="email">
  68. <n-input :placeholder="t('report.demand.emailTip')" v-model:value="formData.email" />
  69. </n-form-item>
  70. <n-form-item :label="t('report.demand.phone')" label-placement="left" path="contact">
  71. <n-input :placeholder="t('report.demand.phoneTip')" v-model:value="formData.contact" />
  72. </n-form-item>
  73. <n-form-item :label="t('report.demand.person')" label-placement="left" path="name">
  74. <n-input :placeholder="t('report.demand.personTip')" v-model:value="formData.name" />
  75. </n-form-item>
  76. <n-form-item label="" class="empty-form-item" />
  77. <n-form-item :label="t('report.demand.desc')" label-placement="left" path="demand" :style="{ width: '100%' }">
  78. <n-input type="textarea" :placeholder="t('report.demand.descTip')" v-model:value="formData.demand" />
  79. </n-form-item>
  80. <div class="form-item-btn">
  81. <n-button type="primary" size="large" @click="handleSubmit">{{ t('report.demand.submit') }}</n-button>
  82. </div>
  83. </n-form>
  84. </div>
  85. </div>
  86. </div>
  87. </div>
  88. </template>
  89. <script lang="ts" setup>
  90. import {
  91. MdPhonePortrait,
  92. MdNavigate,
  93. MdHome,
  94. IosPin,
  95. MdMail,
  96. IosCall,
  97. } from "@vicons/ionicons4";
  98. import {
  99. // NIcon,
  100. // NBreadcrumb,
  101. // NBreadcrumbItem,
  102. // FormItemRule,
  103. // NForm,
  104. // NButton,
  105. // NFormItem,
  106. // NInput,
  107. // FormRules,
  108. createDiscreteApi,
  109. // NSpin,
  110. } from "naive-ui";
  111. import { onMounted, ref, reactive } from "vue";
  112. import { useI18n } from "#imports";
  113. import { useUserStore } from "@/store/user";
  114. const userStore = useUserStore();
  115. const lang = userStore.getLang;
  116. const { t } = useI18n();
  117. onMounted(() => {
  118. if (typeof window !== "undefined") {
  119. window.scrollTo(0, 1);
  120. }
  121. });
  122. const formRef = ref();
  123. const formData = reactive({
  124. name: "", // 姓名
  125. contact: "", // 联系方式
  126. email: "", // 邮箱
  127. companyName: "", // 名称
  128. demand: "", // 需求
  129. reportId: "", // 报告id
  130. reportPrice: "", // 报告单价
  131. addr: "", // 联系地址
  132. lang: userStore.getLang, // 语言
  133. type: "", //类型,1.样本,2.定制
  134. });
  135. const rules: FormRules = {
  136. companyName: [
  137. {
  138. required: true,
  139. trigger: ["input", "blur"],
  140. validator(rule: FormItemRule, value: string) {
  141. if (!value) {
  142. return new Error(t("report.demand.companyNameTip"));
  143. }
  144. return true;
  145. },
  146. },
  147. ],
  148. // addr: [{
  149. // required: true,
  150. // trigger: ['input','blur'],
  151. // validator(rule: FormItemRule, value: string){
  152. // if(!value){
  153. // return new Error(t('report.demand.addressTip'));
  154. // }
  155. // return true;
  156. // }
  157. // }],
  158. email: [
  159. {
  160. required: true,
  161. trigger: ["blur"],
  162. validator(rule: FormItemRule, value: string) {
  163. if (!value) {
  164. return new Error(t("report.demand.emailTip"));
  165. } else if (!isEmail(value)) {
  166. return new Error(t("report.demand.emailFormat"));
  167. }
  168. return true;
  169. },
  170. },
  171. ],
  172. contact: [
  173. {
  174. required: true,
  175. trigger: ["blur"],
  176. validator(rule: FormItemRule, value: string) {
  177. if (!value) {
  178. return new Error(t("report.demand.phoneTip"));
  179. } else if (!isPhoneNumber(value)) {
  180. return new Error(t("report.demand.phoneFormat"));
  181. }
  182. return true;
  183. },
  184. },
  185. ],
  186. name: [
  187. {
  188. required: true,
  189. trigger: ["blur", "input"],
  190. validator(rule: FormItemRule, value: string) {
  191. if (!value) {
  192. return new Error(t("report.demand.personTip"));
  193. }
  194. return true;
  195. },
  196. },
  197. ],
  198. demand: [
  199. {
  200. required: true,
  201. trigger: ["input", "blur"],
  202. validator(rule: FormItemRule, value: string) {
  203. if (!value) {
  204. return new Error(t("report.demand.descTip"));
  205. }
  206. return true;
  207. },
  208. },
  209. ],
  210. };
  211. // 提交
  212. const message = createDiscreteApi(["message"]);
  213. function handleSubmit() {
  214. formRef.value?.validate(async (errors: any) => {
  215. if (!errors) {
  216. //formData.reportId = prop.rowId;
  217. //formData.reportPrice = prop.rowPrice;
  218. formData.lang = langOnBrowser();
  219. //formData.type = prop.rowType;
  220. await customerInfoSave(formData);
  221. message.message.success(t("report.demand.success"));
  222. formData.companyName = "";
  223. formData.addr = "";
  224. formData.email = "";
  225. formData.contact = "";
  226. formData.name = "";
  227. formData.demand = "";
  228. }
  229. });
  230. }
  231. </script>
  232. <style lang="scss" scoped>
  233. .contact {
  234. background-color: #fff;
  235. padding-bottom: 50px;
  236. .container {
  237. .title {
  238. border-bottom: 1px solid #eee;
  239. }
  240. }
  241. .contact-desc {
  242. display: flex;
  243. justify-content: space-between;
  244. align-items: center;
  245. .contact-desc-info {
  246. width: 55%;
  247. .corp {
  248. font-size: 2em;
  249. color: #18a058;
  250. padding: 1.5em 0 2.5em;
  251. }
  252. .box {
  253. padding: 1em 0;
  254. font-size: 1.2em;
  255. color: #666;
  256. border-bottom: 1px solid #eee;
  257. .n-icon {
  258. vertical-align: text-bottom;
  259. margin-right: 5px;
  260. }
  261. }
  262. }
  263. .contact-desc-we {
  264. width: 40%;
  265. padding-top: 30px;
  266. img {
  267. width: 100%;
  268. }
  269. }
  270. }
  271. }
  272. .contact-form {
  273. background-color: #fff;
  274. border-bottom: 1px solid #eee;
  275. padding-bottom: 50px;
  276. .container {
  277. background-color: #f2f2f2;
  278. .content {
  279. padding: 2em;
  280. .n-form {
  281. display: flex;
  282. flex-wrap: wrap;
  283. justify-content: space-between;
  284. align-items: center;
  285. .n-form-item {
  286. width: 30%;
  287. }
  288. .form-item-btn {
  289. width: 100%;
  290. text-align: center;
  291. }
  292. }
  293. }
  294. }
  295. }
  296. </style>