index.vue 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906
  1. <template>
  2. <div class="register-pages">
  3. <div class="register-bos">
  4. <img class="head-img" src="@/assets/images/head.png" alt="" />
  5. <div class="register-login flex-row-between">
  6. <div></div>
  7. <div>
  8. <!-- <span>已有账号?直接</span> -->
  9. <a href="http://119.97.180.88:8050/" @click.stop target="_blank"> 已有账号?直接 </a>
  10. <a href="http://119.97.180.88:8050/" class="zhu" @click.stop target="_blank"> 登录&gt;&gt; </a>
  11. </div>
  12. </div>
  13. <div class="progress-bos">
  14. <div class="progress-bar" :class="nextNum == 1 ? 'hig1' : 'hig2'">
  15. <div>01、基本资料</div>
  16. </div>
  17. <div class="progress-bar progress-bar2" :class="nextNum == 2 ? 'hig1' : 'hig2'">
  18. <div>02、完善信息</div>
  19. </div>
  20. <div class="progress-bar progress-bar2" :class="nextNum == 3 ? 'hig1' : ''">
  21. <div>03、完成</div>
  22. </div>
  23. </div>
  24. <template v-if="nextNum == 1">
  25. <div class="form-bos">
  26. <div class="form-title flex-row-start">
  27. <div class="star">*</div>
  28. <div>姓名</div>
  29. </div>
  30. <el-input style="width: 448px" v-model="form.purchaseName" placeholder="请输入姓名" />
  31. <div class="form-tip">请输入采购人全名,方便与您联系!</div>
  32. </div>
  33. <div class="form-bos" style="margin-top: 8px">
  34. <div class="form-title flex-row-start">
  35. <div class="star">*</div>
  36. <div>手机号码</div>
  37. </div>
  38. <el-input :maxlength="11" style="width: 448px" v-model="form.purchasePhone" placeholder="请输入手机号码">
  39. <template #suffix>
  40. <span @click="sendSmsCode" :class="['code', countdown > 0 ? 'disabled' : '']">
  41. {{ codeText }}
  42. </span>
  43. </template>
  44. </el-input>
  45. </div>
  46. <div class="form-bos form-bos1">
  47. <div class="form-title flex-row-start">
  48. <div class="star">*</div>
  49. <div>验证码</div>
  50. </div>
  51. <el-input style="width: 448px" v-model="form.code" placeholder="请输入验证码" />
  52. </div>
  53. <div class="form-bos form-bos1">
  54. <div class="form-title flex-row-start">
  55. <div class="star">*</div>
  56. <div>密码</div>
  57. </div>
  58. <el-input type="password" show-password style="width: 448px" v-model="form.password" placeholder="请输入密码" />
  59. </div>
  60. <div class="form-bos form-bos1">
  61. <div class="form-title flex-row-start">
  62. <div class="star">*</div>
  63. <div>请再次输入密码</div>
  64. </div>
  65. <el-input type="password" show-password style="width: 448px" v-model="form.confirmPassword" placeholder="请输入密码" />
  66. </div>
  67. </template>
  68. <template v-if="nextNum == 2">
  69. <div class="form-head">基本信息</div>
  70. <div class="form-bos">
  71. <div class="form-title flex-row-start">
  72. <div class="star">*</div>
  73. <div>供应商名称</div>
  74. </div>
  75. <el-input style="width: 100%" v-model="form.enterpriseName" placeholder="请输入供应商名称" />
  76. </div>
  77. <div class="flex-row-start">
  78. <div class="form-bos form-bos1" style="flex: 1">
  79. <div class="form-title flex-row-start">
  80. <div class="star">*</div>
  81. <div>规模</div>
  82. </div>
  83. <el-select v-model="form.membershipSize" placeholder="请选择规模" style="width: 100%">
  84. <el-option v-for="(item, index) in enterpriseList" :key="index" :label="item.enterpriseScaleName" :value="item.id" />
  85. </el-select>
  86. </div>
  87. <div class="form-bos form-bos1" style="flex: 1">
  88. <div class="form-title flex-row-start">
  89. <div class="star">*</div>
  90. <div>固定电话</div>
  91. </div>
  92. <el-input style="width: 100%" v-model="form.fixedPhone" placeholder="请输入固定电话" />
  93. </div>
  94. </div>
  95. <div class="flex-row-start">
  96. <div class="form-bos form-bos1" style="flex: 1">
  97. <div class="form-title flex-row-start">
  98. <div class="star"></div>
  99. <div>传真</div>
  100. </div>
  101. <el-input style="width: 100%" v-model="form.fax" placeholder="请输入固定电话" />
  102. </div>
  103. <div class="form-bos form-bos1" style="flex: 1">
  104. <div class="form-title flex-row-start">
  105. <div class="star"></div>
  106. <div>网址</div>
  107. </div>
  108. <el-input style="width: 100%" v-model="form.url" placeholder="请输入网址" />
  109. </div>
  110. </div>
  111. <div class="flex-row-start">
  112. <div class="form-bos form-bos1" style="flex: 1">
  113. <div class="form-title flex-row-start">
  114. <div class="star">*</div>
  115. <div>企业邮箱</div>
  116. </div>
  117. <el-input style="width: 100%" v-model="form.mailbox" placeholder="请输入企业邮箱" />
  118. </div>
  119. <div class="form-bos form-bos1" style="flex: 1"></div>
  120. </div>
  121. <div class="form-bos form-bos1">
  122. <div class="form-title flex-row-start">
  123. <div class="star">*</div>
  124. <div>办公地址</div>
  125. </div>
  126. <el-cascader
  127. v-model="regionCodes"
  128. :options="regionData as any"
  129. placeholder="请选择省/市/区"
  130. style="width: 100%"
  131. @change="handleRegionChange"
  132. />
  133. <el-input
  134. :maxlength="50"
  135. type="textarea"
  136. :rows="2"
  137. style="width: 100%; margin-top: 10px"
  138. v-model="form.officeAddress"
  139. placeholder="请输入详细地址"
  140. show-word-limit
  141. />
  142. </div>
  143. <div class="form-head" style="margin-top: 15px">其它信息</div>
  144. <div class="form-bos">
  145. <div class="form-title flex-row-start">
  146. <div class="star">*</div>
  147. <div>年销量</div>
  148. </div>
  149. <el-input style="width: 100%" v-model="form.yearSales" placeholder="请输入年销量" />
  150. </div>
  151. <div class="form-bos form-bos1">
  152. <div class="form-title flex-row-start">
  153. <div class="star">*</div>
  154. <div>主要经营品类</div>
  155. </div>
  156. <el-checkbox-group v-model="categoryList">
  157. <el-checkbox v-for="(item, index) in productCategoryList" :key="index" :label="item.categoryName" :value="item.id" />
  158. </el-checkbox-group>
  159. </div>
  160. <div class="form-bos form-bos1">
  161. <div class="form-title flex-row-start">
  162. <div class="star">*</div>
  163. <div>供应区域</div>
  164. </div>
  165. <el-table
  166. :data="tableData"
  167. style="width: 100%"
  168. border
  169. row-class-name="static-bg-row"
  170. :header-cell-style="{
  171. color: '#1D2129',
  172. backgroundColor: '#F2F3F5',
  173. fontWeight: 'normal'
  174. }"
  175. >
  176. <el-table-column label="供应区域" minWidth="200" align="center">
  177. <template #default="scope">
  178. <el-select
  179. @change="(res) => regionChange1(res, scope)"
  180. v-model="scope.row.provinceCode"
  181. placeholder="请选择供应区域"
  182. style="width: 100%"
  183. >
  184. <el-option v-for="(item, index) in regionData" :key="index" :label="item.label" :value="item.value" />
  185. </el-select>
  186. </template>
  187. </el-table-column>
  188. <el-table-column label="供应区域" minWidth="200" align="center">
  189. <template #default="scope">
  190. <el-select
  191. @change="(res) => regionChange2(res, scope)"
  192. v-model="scope.row.cityCode"
  193. placeholder="请选择供应区域"
  194. style="width: 100%"
  195. :disabled="scope.row.disabled"
  196. >
  197. <el-option v-for="(item, index) in scope.row.children" :key="index" :label="item.label" :value="item.value" />
  198. </el-select>
  199. </template>
  200. </el-table-column>
  201. <el-table-column label="操作" width="130" align="center">
  202. <template #default="scope">
  203. <el-button type="primary" link @click="onDel(scope)">删除</el-button>
  204. </template>
  205. </el-table-column>
  206. </el-table>
  207. <el-button style="width: 100%; margin-top: 10px" @click="addTable">添加</el-button>
  208. </div>
  209. <div class="form-head" style="margin-top: 15px">营业执照及相关经营许可证</div>
  210. <div class="flex-row-start">
  211. <el-upload
  212. class="avatar-uploader"
  213. :action="action"
  214. :show-file-list="false"
  215. :on-success="handleAvatarSuccess"
  216. :before-upload="beforeAvatarUpload"
  217. >
  218. <el-icon class="avatar-uploader-icon"><Plus /></el-icon>
  219. </el-upload>
  220. <div v-if="form.businessLicense && form.businessLicense != ''">
  221. <img class="upload-img" v-for="(item, index) in form.businessLicense.split(',')" :key="index" :src="item" />
  222. </div>
  223. </div>
  224. </template>
  225. <template v-if="nextNum == 3">
  226. <div class="register-success flex-column-center">
  227. <img src="@/assets/images/breg.png" alt="" />
  228. <div class="success-text">您的账户还在审核中,如有疑问,请致电400-111-0027</div>
  229. <el-button type="primary">
  230. <a href="http://119.97.180.88:8050/" @click.stop target="_blank">返回登录</a>
  231. </el-button>
  232. <!-- <a href="http://119.97.180.88:8050/" class="zhu" @click.stop target="_blank"> 返回登录&gt;&gt; </a> -->
  233. </div>
  234. </template>
  235. <div class="agreement flex-row-start" v-if="nextNum == 1">
  236. <el-checkbox v-model="radio" />
  237. <span class="agreement1">我已阅读并同意</span>
  238. <span class="agreement2" @click="openDialog">《供应商合作服务协议》</span>
  239. </div>
  240. </div>
  241. <div class="pay-foot" v-if="nextNum != 4">
  242. <div class="foot-bos">
  243. <el-button @click="previousStep" v-if="nextNum == 2" class="bnt1">返回上一步</el-button>
  244. <el-button v-if="nextNum != 3" @click="nextStep" class="bnt2" type="primary" :loading="loading">{{
  245. nextNum == 2 ? '提交并完成注册' : '下一步'
  246. }}</el-button>
  247. </div>
  248. </div>
  249. <el-dialog
  250. v-model="dialogVisible"
  251. title="《供应商合作服务协议》"
  252. width="30%"
  253. :before-close="
  254. () => {
  255. dialogVisible = false;
  256. }
  257. "
  258. >
  259. <div>
  260. <div v-html="content"></div>
  261. </div>
  262. <template #footer>
  263. <span class="dialog-footer">
  264. <el-button type="primary" @click="onAgree">同意</el-button>
  265. <el-button @click="dialogVisible = false">取消</el-button>
  266. </span>
  267. </template>
  268. </el-dialog>
  269. </div>
  270. </template>
  271. <script setup lang="ts">
  272. import {
  273. smsCode,
  274. selectBusinessByCustomerName,
  275. registerCustomer,
  276. enterpriseScale,
  277. getProductCategoryList,
  278. registerSupplier,
  279. selectByPhone
  280. } from '@/api/breg/index';
  281. import { onUnmounted } from 'vue';
  282. import { onPath } from '@/utils/siteConfig';
  283. import { regionData } from 'element-china-area-data';
  284. const nextNum = ref<any>(1);
  285. const codeText = ref<string>('发送验证码');
  286. const countdown = ref<number>(0);
  287. const timer = ref<any>(null);
  288. const enterprise = ref<any>({});
  289. const loading = ref(false);
  290. const radio = ref<any>(false);
  291. const form = ref<any>({
  292. purchaseName: '',
  293. purchasePhone: '',
  294. code: '',
  295. password: '',
  296. confirmPassword: '',
  297. enterpriseName: '',
  298. membershipSize: '',
  299. fixedPhone: '',
  300. fax: '',
  301. url: '',
  302. mailbox: '',
  303. officeProvince: '',
  304. officeCity: '',
  305. officeCounty: '',
  306. officeAddress: '',
  307. yearSales: '',
  308. operatingCategory: '',
  309. supplyAreaList: [],
  310. businessLicense: ''
  311. });
  312. const enterpriseList = ref<any>([]);
  313. const regionCodes = ref<any>([]);
  314. const productCategoryList = ref<any>([]);
  315. const categoryList = ref<any>([]);
  316. const tableData = ref<any>([{ province: '', provinceCode: '', city: '', cityCode: '', disabled: true, children: [] }]);
  317. const action = import.meta.env.VITE_APP_BASE_API + '/resource/oss/upload';
  318. const dialogVisible = ref(false);
  319. const content = ref(
  320. '<p>第1条&nbsp;订购手续</p><p>初次订购用户须按照优易办公规定填写客户信息,通过网站、传真方式提交至优易办公客户服务中心,进行注册登记。</p><p>第2条&nbsp;客户登记注册</p><p>1、优易办公客户服务中心在受理客户登记申请后,将注册号码通知客户并邮寄相关资料。对于信息不符,重复登记等客户的登记申请,优易办公有权拒绝。</p><p>2、本公司将慎重处理您在本公司网站所提供的个人情报,极力保护您的个人信息。</p><p>3、客户登记信息如有变更需由客户向优易办公客户服务中心提交变更委托,月结客户须以书面形式提交变更申请。</p><p>4、客户在一定时间内无订购时,优易办公有权取消客户的登记及相关资料的寄送。</p><p>第3条&nbsp;优易办公的服务</p><p>客户可以根据有效期内的商品目录或优易办公网站的规定,购买目录或网站上的商品或享受优易办公的配送服务。</p><p>优易办公将定期送上商品目录及相关资料,同时还会将商品促销信息通过电话、传真或邮件方式发送至您的邮箱。若您不希望收到此类信息,请随时向我们提出,我们会根据您的要求不再向您发送以上信息。</p><p>第4条&nbsp;商品的订购方式</p><p>1、客户可以通过电话、传真或网上订购。我们在接收您订单的同时,将视为您已接受我们的使用条款。</p><p>①&nbsp;电话订购。&nbsp;打电话至优易办公客户服务中心,订购您所需要的商品。</p><p>②&nbsp;传真订购。&nbsp;按规定填写订购单后发传真至优易办公客户服务中心。客户服务中心会与您电话确认您订购的商品。</p><p>③&nbsp;网上订购。&nbsp;登录优易办公网站,直接从网上挑选商品,直接订购。</p><p>2、当优易办公客户服务中心处理完您的订单后,可视为您与优易办公之间的买卖协议已经成立。但优易办公客户服务中心认为是特殊商品或特殊服务时,则需通过其他方式订购。</p><p>第5条&nbsp;商品的交付</p><p>1、商品交付是指将商品送至客户登记注册的送货地址或客户特别指定的送货地址,并由客户指定收货人签收后视为交付完成。月结客户指定送货地点与登记地址不符时,须书面告知优易办公客户服务中心。</p><p>2、商品到达日期会因商品或服务的不同而有所区别。</p><p>3、当客户填写的订单内容不全或有误时;当由于通讯状况造成优易办公本部无法完成正常的订单处理时;当由于天气、灾害、事故等造成货物运送状况不良时;当客户的订单限额超过时;当春节或其他节假日时,请关注网站信息栏告知。</p><p>4、对于预订商品、断货商品或大批量的订购,我们将会另行通知送达日期。</p><p>第6条&nbsp;配送费</p><p>1、所有优易办公配送范围内需满额即可免运费,未满指定金额时需收取配送费。具体配送地区及运费标准,参见《配送及支付标准》</p><p>2、一次订货若须配送至多个送货地点时,则每处送达地点作为一个订单。订单未满一定金额将加收手续费。</p><p>3、当日追加订单,因商品或订购时间等原因不能合并而造成复数订单时,也同样作为不同订单分别处理。订单未满一定金额将加收手续费。</p><p>4、部分预定商品(包含但不仅限于家具类、白板类、保险箱类)将根据供应商运费标准收取配送费用。</p><p>第7条&nbsp;付款</p><p>商品到货时,客户须支付货款及未满规定免费送货金额时的送货费。部分商品或服务需支付预付款,货款到账确认后发货。家具类商品需全额支付货款金额后发货。订购金额稳定的个别客户根据优易办公的信用评估结果,可签订月结合同,月结付款。</p><p>第8条&nbsp;拒收商品</p><p>1、如因客户外出不在等原因,使商品不能送达时,我们将会在次日为您补送,由此产生的费用,优易办公有权要求客户负担。</p><p>2、如客户无故不接受本公司送至的商品,将视为取消订货,客户可能承担因此而产生的相当于商品货值的违约金。</p><p>第9条&nbsp;不可抗力的责任免除</p><p>因气候灾害、法律修改废除、交通事故、公众处分、运输公司的事故、劳动争议、交通管制等不可抗力造成送货延迟或不能配送,而造成客户损失的,优易办公不承担任何赔偿责任。</p><p>第10条&nbsp;取消订货</p><p>1、因优易办公的销售系统会在接到客户订单后,即刻安排商品的配送,所以无法取消当日的订货。客户如想取消订货,请参照第12条的规定,按照退货的手续办理。</p><p>2、家具商品如已下单定货,订单无法取消。</p><p>第11条&nbsp;商品的退换货处理</p><p>1、客户在优易办公商品交付后15天以内,如遇以下情况,可与优易办公客户服务中心取得联系,凭发票办理免费退换货。月结客户结账期内,未收到货品发票时,可凭借交货单办理退换货手续。</p><p>①&nbsp;您在收到所购商品时,如发现商品缺损、脏污、型号、数量不符或OA耗材类商品无优易办公防伪标识时可当场提出退换货要求,我们将在第二天将新商品免费送至您处。</p><p>②&nbsp;您在使用过程中发现质量问题时,应立即停止该商品的使用,并与优易办公客户服务中心取得联系,优易办公将上门取货,并对商品进行检测,检测结果确定为产品质量时,优易办公将为您办理免费退换货手续。个别商品的质量检测须根据厂家检测报告为准。</p><p>办公耗材类:</p><p>您在优易办公购买的办公耗材15天以内(商品送达之日起算)如发现质量问题,应立即与优易办公客户服务中心取得联系,并停止使用该产品,进行质量&nbsp;检测。客户可以自行将该产品送交厂家相关机构进行检测或将商品递交优易办公售后服务中心,由优易办公代为检测,优易办公将依据厂家检测中心的产品质量证明书进行退换货服务。</p><p>整机类(如传真机、打印机、电脑等):</p><p>您在优易办公购买的整机类产品15天内(商品送达之日起算)如发现质量问题,&nbsp;应立即与优易办公客户服务中心取得联系,&nbsp;并停止使用该产品,&nbsp;优易办公&nbsp;将根据厂家产品检测中心的产品质量证明书为客户提供国家三包规定的退换货服务。家电、手机类产品的退换货按照国家三包规定办理退换货服务。</p><p>2、因客户原因造成退换货的,优易办公将根据具体的情况提供有偿的退换货服务,具体收费标准详询优易办公客服人员。</p><p>3、退款时间:优易办公自收到退回商品并确认退货原因之日起七日内返还客户支付的商品价款。</p><p>4、以下情况不能退换货:</p><p>①&nbsp;因客户原因,造成商品外观及外包装、使用性能损坏等不能再次销售的商品。</p><p>②&nbsp;无故要求将货物随意更换成其他产品时。</p><p>③&nbsp;根据客户的要求、特别购买或订制的商品。</p><p>④&nbsp;合同规定的不可退货商品。</p><p>⑤&nbsp;非质量原因的,食品等有保质期或使用期限的商品。</p><p>⑥&nbsp;超过厂家规定保修期的商品。</p><p>⑦&nbsp;外包装丢失的硒鼓、墨盒等OA消耗品。</p><p>⑧&nbsp;家电、手机和整机类产品按国家规定的三包条款执行,无质量问题不可退货。</p><p>⑨&nbsp;家具类商品除本身质量原因外,不进行退换货。</p><p>第12条&nbsp;取消注册</p><p>1、当客户发生如下情况时,或发生优易办公认为不当事由时,优易办公客户服务中心有权取消客户资格,敬请谅解。</p><p>①&nbsp;客户在订购后无故拖欠货款的,同时优易办公也将用法律手段提起控 &nbsp;  &nbsp;诉。</p><p>②&nbsp;被国家法律部门查封或被监察部门处理的。</p><p>③&nbsp;公司发生重组、破产或者被拍卖、强制执行及民事诉讼的。</p><p>④&nbsp;所开出的票据无法兑现的。</p><p>⑤&nbsp;财产状况恶化或有可能造成财产状况恶化的客观事件发生的。</p><p>⑥&nbsp;违反本条款中任何一项内容的。</p><p>2、当客户违反上述任何一条时,因使用优易办公服务而发生尚未偿付的任何债务须立即付清,否则优易办公有使用司法手段通过法律途径维护正当权益的权利及其他产生的损失的追索权利。</p><p>第13条&nbsp;注册信息的变更</p><p>1、如客户在优易办公登记信息(如公司名称、地址、负责人、电话和传真号码、联系人等)发生变更时,应立即与优易办公客户服务中心联系并提出变更申请。月结客户须以书面形式提交申请。</p><p>2、如您因未及时与客户服务中心联系,造成商品或目录配送时的延迟或没有送到等情况发生的,优易办公将不承担相关责任&nbsp;。</p><p>第14条&nbsp;争议解决</p><p>与客户使用条款相关的一切争议,经协商不能达成一致意见的,应当向我公司所在地的人民法院提起诉讼。</p><p>第15条&nbsp;目录商品的变更</p><p>在商品目录内的部分商品可能会发生式样、价格上的变更,另外也可能发生由于生产商停止生产某种商品而造成无法供货的情况,我们将通过网站第一时间更新信息,敬请谅解。</p><p>第16条&nbsp;使用条款的修订</p><p>本使用条款及商品目录的记载内容可以不经预告而直接修订。客户在条款修订后,对优易办公的使用可视为对本条款修订内容的接受。</p><p>本客户使用条款的最终解释权归武汉优易达科技有限公司所有</p>'
  321. );
  322. onMounted(() => {
  323. //企业规模
  324. enterpriseScale({ limit: 999 }).then((res) => {
  325. if (res.code == 200) {
  326. enterpriseList.value = res.rows;
  327. }
  328. });
  329. //企业规模
  330. getProductCategoryList({}).then((res) => {
  331. if (res.code == 200) {
  332. productCategoryList.value = res.data;
  333. }
  334. });
  335. });
  336. // 启动倒计时
  337. const startCountdown = () => {
  338. countdown.value = 60;
  339. codeText.value = `${countdown.value}s 后重新发送`;
  340. timer.value = setInterval(() => {
  341. countdown.value--;
  342. if (countdown.value > 0) {
  343. codeText.value = `${countdown.value}s 后重新发送`;
  344. } else {
  345. clearInterval(timer.value);
  346. timer.value = null;
  347. codeText.value = '发送验证码';
  348. }
  349. }, 1000);
  350. };
  351. // 获取验证码
  352. const sendSmsCode = () => {
  353. // 防止倒计时期间重复点击
  354. if (countdown.value > 0) return;
  355. const phone = form.value.purchasePhone;
  356. // 1. 基础格式校验
  357. if (!validateMobile(phone)) {
  358. ElMessage({
  359. message: '请输入正确的手机号码',
  360. type: 'warning'
  361. });
  362. return;
  363. }
  364. // 2. 【新增】先调用接口查询用户是否存在
  365. selectByPhone(form.value.purchasePhone, '1')
  366. .then((res: any) => {
  367. // --- 后端返回 200 ---
  368. // 根据你的后端逻辑:返回 200 代表 "用户不存在" (R.ok),允许注册
  369. if (res.code === 200) {
  370. // 手机号可用,继续执行发送验证码逻辑
  371. smsCode({ phonenumber: form.value.purchasePhone })
  372. .then((smsRes: any) => {
  373. if (smsRes.code === 200) {
  374. ElMessage({
  375. message: '验证码已发送',
  376. type: 'success'
  377. });
  378. startCountdown(); // 开始倒计时
  379. } else {
  380. // 发送短信接口业务失败
  381. ElMessage.error(smsRes.msg || '发送验证码失败');
  382. }
  383. })
  384. .catch((err: any) => {
  385. // 发送短信接口网络错误或异常
  386. ElMessage.error(err.msg || '发送验证码请求异常');
  387. });
  388. } else {
  389. }
  390. })
  391. .catch((error: any) => {
  392. // --- 后端返回非 200 (进入 catch) ---
  393. // 根据你的后端逻辑:返回 fail 代表 "用户已存在" (R.fail("该手机号已注册"))
  394. const msg = error.msg || '该手机号已注册,请直接登录';
  395. ElMessage({
  396. message: msg,
  397. type: 'warning' // 或者使用 'error'
  398. });
  399. });
  400. };
  401. //选择省
  402. const regionChange1 = (res: any, scope: any) => {
  403. regionData.forEach((item: any) => {
  404. if (item.value === res) {
  405. scope.row.province = item.label;
  406. scope.row.children = item.children;
  407. scope.row.city = '';
  408. scope.row.cityCode = '';
  409. scope.row.disabled = false;
  410. }
  411. });
  412. };
  413. //选择市
  414. const regionChange2 = (res: any, scope: any) => {
  415. scope.row.children.forEach((item: any) => {
  416. if (item.value === res) {
  417. scope.row.city = item.label;
  418. }
  419. });
  420. };
  421. //新增
  422. const addTable = () => {
  423. tableData.value.push({ province: '', provinceCode: '', city: '', cityCode: '', disabled: true, children: [] });
  424. };
  425. //删除
  426. const onDel = (scope: any) => {
  427. tableData.value.splice(scope.row.$index, 1);
  428. };
  429. // 验证手机号
  430. const validateMobile = (phone: any) => {
  431. const reg = /^1[3-9]\d{9}$/;
  432. return reg.test(phone);
  433. };
  434. // 验证企业名字
  435. const validateStrict = (str: any) => {
  436. if (typeof str !== 'string') return false;
  437. const trimmed = str.trim();
  438. if (trimmed.length === 0) return false; // 去空格后为空
  439. return /^[^a-zA-Z0-9]+$/.test(trimmed);
  440. };
  441. // 处理地区选择变化
  442. const handleRegionChange = (value: string[]) => {
  443. if (value && value.length === 3) {
  444. // 根据选中的代码查找对应的名称
  445. // 根据编码获取名称
  446. const names: string[] = [];
  447. if (value[0]) {
  448. const province = regionData.find((item: any) => item.value === value[0]);
  449. if (province) {
  450. form.value.officeProvince = province.label;
  451. if (value[1] && province.children) {
  452. const city = province.children.find((item: any) => item.value === value[1]);
  453. if (city) {
  454. form.value.officeCity = city.label;
  455. if (value[2] && city.children) {
  456. const county = city.children.find((item: any) => item.value === value[2]);
  457. if (county) {
  458. form.value.officeCounty = county.label;
  459. }
  460. }
  461. }
  462. }
  463. }
  464. }
  465. }
  466. };
  467. //上传成功
  468. const handleAvatarSuccess = (res: any) => {
  469. if (res.code == 200) {
  470. if (form.value.businessLicense == '') {
  471. form.value.businessLicense = res.data.url;
  472. } else {
  473. form.value.businessLicense = form.value.businessLicense + ',' + res.data.url;
  474. }
  475. } else {
  476. ElMessage({
  477. message: res.msg,
  478. type: 'warning'
  479. });
  480. }
  481. };
  482. import type { UploadProps } from 'element-plus';
  483. const beforeAvatarUpload: UploadProps['beforeUpload'] = (rawFile) => {
  484. if (rawFile.size / 1024 / 1024 > 2) {
  485. ElMessage.error('不能大于2MB!');
  486. return false;
  487. }
  488. return true;
  489. };
  490. const nextStep = () => {
  491. if (nextNum.value == 1) {
  492. if (!radio.value) {
  493. ElMessage({
  494. message: '请勾选协议内容~',
  495. type: 'warning'
  496. });
  497. return;
  498. }
  499. const errorMsg1 = {
  500. purchaseName: '请输入姓名',
  501. purchasePhone: '请输入手机号码',
  502. code: '请输入验证码',
  503. password: '请输入密码',
  504. confirmPassword: '请再次输入密码'
  505. };
  506. let next1 = true;
  507. Object.keys(errorMsg1).forEach((key) => {
  508. if ((form.value[key] == '' || form.value[key] == undefined || form.value[key] == null) && next1) {
  509. next1 = false;
  510. ElMessage({
  511. message: `${errorMsg1[key]}`,
  512. type: 'warning'
  513. });
  514. return;
  515. }
  516. });
  517. if (!next1) return;
  518. if (form.value.password != form.value.confirmPassword) {
  519. ElMessage({
  520. message: `密码不一致`,
  521. type: 'warning'
  522. });
  523. return;
  524. }
  525. nextNum.value = 2;
  526. } else if (nextNum.value == 2) {
  527. const errorMsg2 = {
  528. enterpriseName: '请输入供应商名称',
  529. membershipSize: '请选择规模',
  530. fixedPhone: '请输入固定电话',
  531. mailbox: '请输入企业邮箱',
  532. officeCounty: '请选择省市区',
  533. officeAddress: '请输入详细地址',
  534. yearSales: '请输入年销量',
  535. businessLicense: '请上传营业执照'
  536. };
  537. let next2 = true;
  538. Object.keys(errorMsg2).forEach((key) => {
  539. if ((form.value[key] == '' || form.value[key] == undefined || form.value[key] == null) && next2) {
  540. next2 = false;
  541. ElMessage({
  542. message: `${errorMsg2[key]}`,
  543. type: 'warning'
  544. });
  545. return;
  546. }
  547. });
  548. if (!next2) return;
  549. if (!validateStrict(form.value.enterpriseName)) {
  550. ElMessage({
  551. message: '供应商名称不能有数字或字母',
  552. type: 'warning'
  553. });
  554. return;
  555. }
  556. if (categoryList.value.length == 0) {
  557. ElMessage({
  558. message: '请选择主要经营品类',
  559. type: 'warning'
  560. });
  561. return;
  562. }
  563. form.value.operatingCategory = categoryList.value.join(',');
  564. if (tableData.value.length == 0) {
  565. ElMessage({
  566. message: '请新增供应区域',
  567. type: 'warning'
  568. });
  569. return;
  570. }
  571. form.value.supplyAreaList = [];
  572. tableData.value.forEach((item: any) => {
  573. if (item.province && item.provinceCode && item.city && item.cityCode) {
  574. form.value.supplyAreaList.push({
  575. areaCode: item.provinceCode,
  576. areaName: item.province,
  577. parentCode: 0,
  578. level: 1
  579. });
  580. form.value.supplyAreaList.push({
  581. areaCode: item.cityCode,
  582. areaName: item.city,
  583. parentCode: item.provinceCode,
  584. level: 2
  585. });
  586. }
  587. });
  588. if (form.value.supplyAreaList.length == 0) {
  589. ElMessage({
  590. message: '供应区域不能为空',
  591. type: 'warning'
  592. });
  593. return;
  594. }
  595. loading.value = true;
  596. registerSupplier(form.value).then((res: any) => {
  597. loading.value = false;
  598. if (res.code == 200) {
  599. nextNum.value = 3;
  600. }
  601. });
  602. }
  603. };
  604. //上一步
  605. const previousStep = () => {
  606. if (nextNum.value == 2) {
  607. nextNum.value = 1;
  608. }
  609. if (nextNum.value == 3) {
  610. nextNum.value = 2;
  611. }
  612. };
  613. const goLogin = () => {
  614. onPath('/login');
  615. };
  616. const openDialog = () => {
  617. dialogVisible.value = true;
  618. };
  619. const onAgree = () => {
  620. radio.value = true;
  621. dialogVisible.value = false;
  622. };
  623. // 组件卸载时清除定时器
  624. onUnmounted(() => {
  625. if (timer.value) {
  626. clearInterval(timer.value);
  627. timer.value = null;
  628. }
  629. });
  630. </script>
  631. <style lang="scss" scoped>
  632. .register-pages {
  633. width: 100%;
  634. background-color: #ffffff;
  635. display: flex;
  636. flex-direction: column;
  637. .register-bos {
  638. flex: 1;
  639. width: 100%;
  640. min-width: 1200px;
  641. max-width: 1500px;
  642. margin: 0 auto;
  643. padding-top: 20px;
  644. .head-img {
  645. width: 185px;
  646. height: 90px;
  647. }
  648. .register-login {
  649. font-weight: 400;
  650. font-size: 14px;
  651. color: #101828;
  652. margin-top: 20px;
  653. padding-bottom: 10px;
  654. border-bottom: 1px solid #e5e7eb;
  655. .zhu {
  656. color: #e7000b;
  657. cursor: pointer;
  658. }
  659. }
  660. .progress-bos {
  661. padding: 20px;
  662. display: flex;
  663. margin-bottom: 24px;
  664. .progress-bar {
  665. width: 320px;
  666. height: 40px;
  667. background: #f7f8fa;
  668. font-weight: 500;
  669. font-size: 16px;
  670. line-height: 40px;
  671. padding-left: 16px;
  672. color: #4e5969;
  673. position: relative;
  674. &.hig1 {
  675. background: #e7000b;
  676. color: #ffffff;
  677. }
  678. &.hig2 {
  679. background: #ffe8e8;
  680. color: #1d2129;
  681. }
  682. }
  683. .progress-bar2 {
  684. width: 354px;
  685. }
  686. }
  687. .form-head {
  688. width: calc(100% - 40px);
  689. margin: 0 20px 10px 20px;
  690. height: 44px;
  691. background: #f7f8fa;
  692. font-weight: 500;
  693. font-size: 16px;
  694. color: #1d2129;
  695. line-height: 44px;
  696. position: relative;
  697. padding-left: 25px;
  698. &::after {
  699. content: '';
  700. width: 4px;
  701. height: 16px;
  702. background: #e7000b;
  703. position: absolute;
  704. left: 10px;
  705. top: 12px;
  706. }
  707. }
  708. .form-bos {
  709. padding: 0 20px;
  710. // :deep(.el-input__wrapper) {
  711. // border: none;
  712. // box-shadow: none;
  713. // outline: none;
  714. // background: #f4f6f8;
  715. // }
  716. // :deep(.el-select__wrapper) {
  717. // border: none;
  718. // box-shadow: none;
  719. // outline: none;
  720. // background: #f4f6f8;
  721. // }
  722. // :deep(.el-textarea__inner) {
  723. // border: none;
  724. // box-shadow: none;
  725. // outline: none;
  726. // background: #f4f6f8;
  727. // }
  728. .form-title {
  729. font-size: 14px;
  730. color: #1d2129;
  731. margin-bottom: 8px;
  732. .star {
  733. width: 10px;
  734. color: #f53f3f;
  735. }
  736. }
  737. .form-tip {
  738. font-size: 12px;
  739. color: #86909c;
  740. margin-top: 4px;
  741. }
  742. .code {
  743. font-size: 14px;
  744. color: #e7000b;
  745. cursor: pointer;
  746. &.disabled {
  747. color: #999;
  748. cursor: not-allowed;
  749. }
  750. }
  751. }
  752. .form-bos1 {
  753. margin-top: 30px;
  754. }
  755. .agreement {
  756. padding-left: 20px;
  757. margin-top: 30px;
  758. font-size: 13px;
  759. .agreement1 {
  760. color: #999999;
  761. margin-left: 5px;
  762. }
  763. .agreement2 {
  764. color: #e7000b;
  765. cursor: pointer;
  766. }
  767. }
  768. }
  769. .pay-foot {
  770. width: 100%;
  771. height: 82px;
  772. background: #ffffff;
  773. box-shadow: 0px -2px 13px 0px rgba(0, 0, 0, 0.05);
  774. margin-top: 47px;
  775. .foot-bos {
  776. width: 100%;
  777. min-width: 1200px;
  778. max-width: 1500px;
  779. margin: 0 auto;
  780. padding-top: 16px;
  781. padding-left: 20px;
  782. .bnt1 {
  783. width: 120px;
  784. height: 32px;
  785. background: #f7f8fa;
  786. }
  787. .bnt2 {
  788. width: 120px;
  789. height: 32px;
  790. }
  791. }
  792. }
  793. .register-success {
  794. width: 100%;
  795. padding-bottom: 30px;
  796. img {
  797. width: 324px;
  798. }
  799. .success-text {
  800. font-weight: 400;
  801. font-size: 14px;
  802. color: #000000;
  803. margin: 20px 0 30px 0;
  804. }
  805. }
  806. :deep(.is-bordered-label) {
  807. font-weight: 400;
  808. }
  809. /* 核心代码:禁止 hover 变色 */
  810. :deep(.el-table .static-bg-row:hover > td) {
  811. background-color: inherit !important;
  812. }
  813. /* 兼容斑马纹情况 */
  814. :deep(.el-table--striped .static-bg-row:nth-child(2n):hover > td) {
  815. background-color: inherit !important;
  816. }
  817. .avatar-uploader {
  818. margin: 10px 20px;
  819. :deep(.el-upload) {
  820. width: 108px;
  821. height: 108px;
  822. background: #f2f3f5;
  823. border-radius: 2px;
  824. cursor: pointer;
  825. position: relative;
  826. overflow: hidden;
  827. }
  828. }
  829. .upload-img {
  830. width: 108px;
  831. height: 108px;
  832. border-radius: 2px;
  833. margin-right: 15px;
  834. }
  835. .el-icon.avatar-uploader-icon {
  836. font-size: 28px;
  837. color: #8c939d;
  838. width: 178px;
  839. height: 178px;
  840. text-align: center;
  841. }
  842. }
  843. </style>