registration.vue 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. <script setup name="registration">
  2. import Container from "../../components/Container/Container.vue";
  3. import CustomerService from "../../components/CustomerService/CustomerService.vue";
  4. import RadioBlock from "../../components/RadioBlock/RadioBlock.vue";
  5. import Modal from "../../components/Modal/Modal.vue";
  6. import { onShow } from "@dcloudio/uni-app";
  7. import { request } from "../../utils/request";
  8. import { getRoute, router } from "../../utils/router";
  9. import { ref, getCurrentInstance } from "vue";
  10. import ext from "../../ext.json";
  11. const instance = getCurrentInstance();
  12. const context = ref("");
  13. const permissions = ref(false);
  14. const formData = ref({
  15. contact_name: "",
  16. contact_information: "",
  17. pharmacist_type: 0,
  18. });
  19. const loading = ref(false);
  20. const show = ref(false);
  21. const price = ref("");
  22. const rules = {
  23. contact_name: [
  24. {
  25. required: true,
  26. message: "请输入姓名",
  27. },
  28. ],
  29. contact_information: [
  30. {
  31. required: true,
  32. message: "请输入联系方式",
  33. type: "phone",
  34. },
  35. ],
  36. pharmacist_type: [
  37. {
  38. required: true,
  39. message: "请选择报考药师类型",
  40. },
  41. ],
  42. };
  43. onShow(() => {
  44. const { id } = getRoute().params;
  45. request("api/question_bank/question_reception/recharge_package/detail", {
  46. id,
  47. }).then((res) => {
  48. context.value = res.data.instructions || "";
  49. price.value = res.data.package_preferential_price;
  50. });
  51. });
  52. const validate = ({ value, message, type = "text" }) =>
  53. new Promise((resolve, reject) => {
  54. if (!value) {
  55. uni.showToast({
  56. title: message,
  57. icon: "none",
  58. });
  59. loading.value = false;
  60. return reject(message);
  61. }
  62. if (type === "phone") {
  63. const phoneReg =
  64. /^(?:(?:\+|00)86)?1(?:(?:3[\d])|(?:4[5-79])|(?:5[0-35-9])|(?:6[5-7])|(?:7[0-8])|(?:8[\d])|(?:9[1589]))\d{8}$/;
  65. if (!phoneReg.test(value)) {
  66. uni.showToast({
  67. title: "请输入正确的手机号码",
  68. icon: "none",
  69. });
  70. loading.value = false;
  71. return reject("请输入正确的手机号码");
  72. }
  73. }
  74. resolve();
  75. });
  76. const onSubmit = async () => {
  77. loading.value = true;
  78. for (const key in formData.value) {
  79. await validate({
  80. value: formData.value[key],
  81. message: rules[key][0].message,
  82. type: rules[key][0].type,
  83. });
  84. }
  85. if (!permissions.value) {
  86. show.value = true;
  87. return;
  88. }
  89. const { id } = getRoute().params;
  90. uni.login({
  91. provider: instance.proxy.$mpPlatform.substring(3),
  92. success: async ({ code }) => {
  93. const order = await request(
  94. "api/question_bank/question_reception/challenge_registration_log/add",
  95. {
  96. package_id: id,
  97. ...formData.value,
  98. }
  99. );
  100. const e = await request(
  101. "api/question_bank/question_reception/orders/wechat_pay",
  102. {
  103. code,
  104. order_id: order.data.order_id,
  105. app_id: ext.extAppid,
  106. }
  107. );
  108. uni.requestPayment({
  109. provider: "wxpay",
  110. timeStamp: e.data.timeStamp, //时间戳
  111. nonceStr: e.data.nonceStr, //随机字符串
  112. package: e.data.package, //prepay_id
  113. signType: e.data.signType, //签名算法MD5
  114. paySign: e.data.paySign, //签名,
  115. success() {
  116. router.redirectTo({
  117. url: "/pages/challenge/addContant",
  118. params: {
  119. type: formData.value.pharmacist_type,
  120. },
  121. });
  122. },
  123. fail(err) {
  124. console.log(err);
  125. },
  126. complete() {
  127. loading.value = false;
  128. },
  129. });
  130. },
  131. });
  132. };
  133. </script>
  134. <template>
  135. <Container
  136. title="报名"
  137. :scrollStyle="{
  138. padding: 0,
  139. }"
  140. bgColor="#a8e0fd"
  141. bottomBgColor="#fff"
  142. headerColor="#fff"
  143. v-if="!show"
  144. >
  145. <view class="bg">
  146. <view class="bg-1">
  147. <form>
  148. <view class="uni-form-item">
  149. <view class="title required">姓名</view>
  150. <input
  151. class="uni-input"
  152. name="contact_name"
  153. placeholder="请输入真实姓名"
  154. v-model="formData.contact_name"
  155. />
  156. </view>
  157. <view class="uni-form-item">
  158. <view class="title required">联系方式</view>
  159. <input
  160. class="uni-input"
  161. name="contact_information"
  162. placeholder="请输入电话号码"
  163. v-model="formData.contact_information"
  164. />
  165. </view>
  166. <view class="uni-form-item">
  167. <view class="title required">报考药师类型(请选择)</view>
  168. <RadioBlock
  169. v-model="formData.pharmacist_type"
  170. name="pharmacist_type"
  171. :columns="[
  172. {
  173. label: '西药',
  174. value: 2,
  175. },
  176. {
  177. label: '中药',
  178. value: 1,
  179. },
  180. ]"
  181. />
  182. </view>
  183. </form>
  184. </view>
  185. </view>
  186. <div class="permissions">
  187. <label>
  188. <checkbox class="checkbox" :value="permissions" />
  189. 阅读并确认
  190. </label>
  191. <span
  192. class="text-primary"
  193. @click="
  194. () => {
  195. router.push({
  196. url: '/pages/richpage/index',
  197. params: {
  198. title: '会员服务权益',
  199. content_code: 'service_rights',
  200. },
  201. });
  202. }
  203. "
  204. >《会员服务权益》</span
  205. >
  206. <span
  207. class="text-primary"
  208. @click="
  209. () => {
  210. router.push({
  211. url: '/pages/challenge/rule',
  212. params: {
  213. id: getRoute().params.id,
  214. },
  215. });
  216. }
  217. "
  218. >《活动规则》</span
  219. >
  220. </div>
  221. <view class="service">
  222. <CustomerService>联系客服</CustomerService>
  223. </view>
  224. <template #footer>
  225. <button
  226. :loading="loading"
  227. :disabled="loading"
  228. class="btn"
  229. @click="onSubmit"
  230. >
  231. ¥{{ price }} 立即开通
  232. </button>
  233. </template>
  234. </Container>
  235. <Modal
  236. v-model:open="show"
  237. title="温馨提示"
  238. :submitter="{
  239. closeText: '不同意',
  240. text: '同意并支付',
  241. }"
  242. :onClose="() => (show = false)"
  243. :onSubmit="
  244. () => {
  245. permissions = true;
  246. show = false;
  247. onSubmit();
  248. }
  249. "
  250. >
  251. <div class="text">
  252. <span> 阅读并确认 </span>
  253. <span
  254. class="text-primary"
  255. @click="
  256. () => {
  257. router.push({
  258. url: '/pages/richpage/index',
  259. params: {
  260. title: '会员服务权益',
  261. content_code: 'service_rights',
  262. },
  263. });
  264. }
  265. "
  266. >《会员服务权益》</span
  267. >
  268. <span
  269. class="text-primary"
  270. @click="
  271. () => {
  272. router.push({
  273. url: '/pages/challenge/rule',
  274. params: {
  275. id: getRoute().params.id,
  276. },
  277. });
  278. }
  279. "
  280. >《活动规则》</span
  281. >
  282. </div>
  283. </Modal>
  284. </template>
  285. <style scoped lang="scss">
  286. .bg {
  287. width: 100%;
  288. background: url("https://openwork-oss.oss-cn-shenzhen.aliyuncs.com/uploads/question/2025/05/yz2eTeqIRv60IEe6kOQBOYlHr75wiFIpeFqrJmgZ.png")
  289. no-repeat;
  290. background-size: 100%;
  291. padding: 216rpx 10rpx 0;
  292. box-sizing: border-box;
  293. display: flex;
  294. flex-direction: column;
  295. justify-content: space-between;
  296. .bg-1 {
  297. width: 730.71rpx;
  298. height: 841rpx;
  299. background: url("https://openwork-oss.oss-cn-shenzhen.aliyuncs.com/uploads/question/2025/06/3P7CBvlUNmunkIM1PA5voYhrGpIIgeqgy30pLb1z.png")
  300. no-repeat;
  301. background-size: 100% 100%;
  302. position: relative;
  303. box-sizing: border-box;
  304. padding: 170rpx 50rpx;
  305. .uni-form-item .title {
  306. padding: 20rpx 0;
  307. }
  308. .uni-input {
  309. border-radius: 8rpx 8rpx 8rpx 8rpx;
  310. border: 1rpx solid #dddddd;
  311. padding: 14rpx 9rpx;
  312. }
  313. }
  314. }
  315. .text {
  316. font-size: 30rpx;
  317. margin: 20rpx 0;
  318. }
  319. .service {
  320. position: absolute;
  321. bottom: 20%;
  322. right: 5%;
  323. color: $uni-primary;
  324. font-size: 28rpx;
  325. margin-bottom: 40rpx;
  326. text-align: right;
  327. }
  328. .permissions {
  329. position: absolute;
  330. bottom: 15%;
  331. left: 32rpx;
  332. display: flex;
  333. align-items: center;
  334. font-weight: 500;
  335. font-size: 28rpx;
  336. color: #333333;
  337. }
  338. .btn {
  339. margin: 32rpx 0;
  340. font-weight: 400;
  341. font-size: 32rpx;
  342. color: #ffffff;
  343. }
  344. </style>