123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503 |
- <template>
- <div>
- <div class="absolute inset-0">
- <img src="/assets/images/auth/bg-gradient.png" alt="image" class="h-full w-full object-cover" />
- </div>
- <div
- class="relative flex min-h-screen items-center justify-center bg-[url(/assets/images/auth/map.png)] bg-cover bg-center bg-no-repeat px-6 py-10 dark:bg-[#060818] sm:px-16"
- >
- <img src="/assets/images/auth/coming-soon-object1.png" alt="image" class="absolute left-0 top-1/2 h-full max-h-[893px] -translate-y-1/2" />
- <img src="/assets/images/auth/coming-soon-object2.png" alt="image" class="absolute left-24 top-0 h-40 md:left-[30%]" />
- <img src="/assets/images/auth/coming-soon-object3.png" alt="image" class="absolute right-0 top-0 h-[300px]" />
- <img src="/assets/images/auth/polygon-object.svg" alt="image" class="absolute bottom-0 end-[28%]" />
- <div
- class="relative w-full rounded-md bg-[linear-gradient(45deg,#fff9f9_0%,rgba(255,255,255,0)_25%,rgba(255,255,255,0)_75%,_#fff9f9_100%)] p-2 dark:bg-[linear-gradient(52.22deg,#0E1726_0%,rgba(14,23,38,0)_18.66%,rgba(14,23,38,0)_51.04%,rgba(14,23,38,0)_80.07%,#0E1726_100%)]"
- >
- <!-- max-w-[870px] -->
- <div class="relative flex flex-col justify-center rounded-md bg-white/60 backdrop-blur-lg dark:bg-black/50 px-6 lg:min-h-[758px] py-20">
- <!-- <div class="absolute top-6 end-6">
- <div class="dropdown">
- <Popper :placement="store.state.rtlClass === 'rtl' ? 'bottom-start' : 'bottom-end'" offsetDistance="8">
- <button
- type="button"
- class="flex items-center gap-2.5 rounded-lg border border-white-dark/30 bg-white px-2 py-1.5 text-white-dark hover:border-primary hover:text-primary dark:bg-black"
- >
- <div>
- <img :src="currentFlag" alt="image" class="h-5 w-5 rounded-full object-cover" />
- </div>
- <div class="text-base font-bold uppercase">{{ store.state.locale }}</div>
- <span class="shrink-0">
- <icon-caret-down />
- </span>
- </button>
- <template #content="{ close }">
- <ul class="!px-2 text-dark dark:text-white-dark grid grid-cols-2 gap-2 font-semibold dark:text-white-light/90 w-[280px]">
- <template v-for="item in store.state.languageList" :key="item.code">
- <li>
- <button
- type="button"
- class="w-full hover:text-primary"
- :class="{ 'bg-primary/10 text-primary': i18n.locale === item.code }"
- @click="changeLanguage(item), close()"
- >
- <img
- class="w-5 h-5 object-cover rounded-full"
- :src="`/assets/images/flags/${item.code.toUpperCase()}.svg`"
- alt=""
- />
- <span class="ltr:ml-3 rtl:mr-3">{{ item.name }}</span>
- </button>
- </li>
- </template>
- </ul>
- </template>
- </Popper>
- </div>
- </div> -->
- <!-- mx-automax-w-[440px] -->
- <div class="w-full">
- <div class="mb-10">
- <h1 class="text-3xl font-extrabold uppercase !leading-snug text-primary md:text-4xl">Account registration</h1>
- <p class="text-base font-bold leading-normal text-white-dark">Enter your email and password to register</p>
- </div>
- <el-form :model="companyForm" :rules="stockRules" ref="companyFormRef" label-width="140px">
- <el-row>
- <el-col :span="8">
- <el-form-item label="营业执照:" prop="license">
- <el-upload
- class="avatar-uploader"
- :action="uploadUrl"
- :show-file-list="false"
- :on-success="handleAvatarSuccess"
- :before-upload="beforeAvatarUpload"
- >
- <img v-if="companyForm.license" :src="companyForm.license" class="avatar w-28 h-28" />
- <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
- </el-upload>
- </el-form-item>
- </el-col>
- <el-col :span="8">
- <el-form-item label="身份证正面:" prop="id_card_front">
- <el-upload
- class="avatar-uploader"
- :action="uploadUrl"
- :show-file-list="false"
- :on-success="handleFrontSuccess"
- :before-upload="beforeFrontUpload"
- >
- <img v-if="companyForm.id_card_front" :src="companyForm.id_card_front" class="avatar w-28 h-28" />
- <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
- </el-upload>
- <!-- <p>姓名:{{ companyForm.value.id_card_front.name }}</p>
- <p>身份证号码:{{ companyForm.value.id_card_front.id_card_number }}</p> -->
- </el-form-item>
- </el-col>
- <el-col :span="8">
- <el-form-item label="身份证反面:" prop="id_card_opposite">
- <el-upload
- class="avatar-uploader"
- :action="uploadUrl"
- :show-file-list="false"
- :on-success="handleOppositeSuccess"
- :before-upload="beforeOppositeUpload"
- >
- <img v-if="companyForm.id_card_opposite" :src="companyForm.id_card_opposite" class="avatar w-28 h-28" />
- <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
- </el-upload>
- </el-form-item>
- </el-col>
- <el-col :span="10" v-if="!companyForm.id">
- <el-form-item label="套餐:" prop="company_package_id">
- <el-select v-model="companyForm.company_package_id" clearable placeholder="请选择套餐">
- <el-option v-for="item in packageList" :key="item.id" :label="item.name" :value="item.id" />
- </el-select>
- </el-form-item>
- </el-col>
- <el-col :span="10">
- <el-form-item label="公司名称:" prop="name">
- <el-input v-model="companyForm.name" clearable disabled placeholder="请输入公司名称"></el-input>
- </el-form-item>
- </el-col>
- <el-col :span="10">
- <el-form-item label="统一社会信用代码:" prop="credit_code">
- <el-input v-model="companyForm.credit_code" clearable disabled placeholder="请输入统一社会信用代码"></el-input>
- </el-form-item>
- </el-col>
- <el-col :span="10">
- <el-form-item label="法人:" prop="user_name">
- <el-input v-model="companyForm.user_name" disabled clearable placeholder="请输入联系人"></el-input>
- </el-form-item>
- </el-col>
- <el-col :span="10">
- <el-form-item label="法人电话:" prop="phone">
- <el-input v-model="companyForm.phone" clearable placeholder="请输入联系人电话"></el-input>
- </el-form-item>
- </el-col>
- <el-col :span="10">
- <el-form-item label="验证码:" prop="check_code">
- <el-input v-model="companyForm.check_code" clearable placeholder="请输入验证码">
- <template #append>
- <el-button v-if="showloginCode" type="primary" @click="getCode" class="w-40">获取验证码</el-button>
- <div v-else>{{ companyForm.count }}</div>
- </template>
- </el-input>
- </el-form-item>
- </el-col>
- <el-col :span="10">
- <el-form-item label="行业:" prop="industry">
- <el-input v-model="companyForm.industry" clearable placeholder="请输入行业"></el-input>
- </el-form-item>
- </el-col>
- <el-col :span="10">
- <el-form-item label="邮箱:" prop="email">
- <el-input v-model="companyForm.email" clearable placeholder="请输入邮箱"></el-input>
- </el-form-item>
- </el-col>
- <el-col :span="10">
- <el-form-item label="邮编:" prop="postal_code">
- <el-input v-model="companyForm.postal_code" clearable placeholder="请输入邮箱"></el-input>
- </el-form-item>
- </el-col>
- <el-col :span="10">
- <el-form-item label="官网:" prop="website">
- <el-input v-model="companyForm.website" clearable placeholder="请输入官网地址"></el-input>
- </el-form-item>
- </el-col>
- <el-col :span="10">
- <el-form-item label="地址:" prop="">
- <el-cascader class="w-full" size="default" :options="options" clearable v-model="selectedOptions"> </el-cascader>
- <span>
- <el-input class="!w-full mt-3" v-model="companyForm.address" placeholder="请输入"></el-input>
- </span>
- </el-form-item>
- </el-col>
- </el-row>
- </el-form>
- <div class="flex justify-center">
- <button
- type="submit"
- @click="submitWarehouseForm"
- class="btn btn-gradient !mt-6 w-1/5 border-0 uppercase shadow-[0_10px_20px_-10px_rgba(67,97,238,0.44)]"
- >
- Sign Up
- </button>
- </div>
- <!-- <form class="space-y-5 dark:text-white" @submit.prevent="router.push('/')">
- <div>
- <label for="Name">Name</label>
- <div class="relative text-white-dark">
- <input id="Name" type="text" placeholder="Enter Name" class="form-input ps-10 placeholder:text-white-dark" />
- <span class="absolute start-4 top-1/2 -translate-y-1/2">
- <icon-user :fill="true" />
- </span>
- </div>
- </div>
- <div>
- <label for="Email">Email</label>
- <div class="relative text-white-dark">
- <input id="Email" type="email" placeholder="Enter Email" class="form-input ps-10 placeholder:text-white-dark" />
- <span class="absolute start-4 top-1/2 -translate-y-1/2">
- <icon-mail :fill="true" />
- </span>
- </div>
- </div>
- <div>
- <label for="Password">Password</label>
- <div class="relative text-white-dark">
- <input id="Password" type="password" placeholder="Enter Password" class="form-input ps-10 placeholder:text-white-dark" />
- <span class="absolute start-4 top-1/2 -translate-y-1/2">
- <icon-lock-dots :fill="true" />
- </span>
- </div>
- </div>
- <div>
- <label class="flex cursor-pointer items-center">
- <input type="checkbox" class="form-checkbox bg-white dark:bg-black" />
- <span class="text-white-dark">Subscribe to weekly newsletter</span>
- </label>
- </div>
- <button type="submit" class="btn btn-gradient !mt-6 w-full border-0 uppercase shadow-[0_10px_20px_-10px_rgba(67,97,238,0.44)]">
- Sign Up
- </button>
- </form>
- <div class="relative my-7 text-center md:mb-9">
- <span class="absolute inset-x-0 top-1/2 h-px w-full -translate-y-1/2 bg-white-light dark:bg-white-dark"></span>
- <span class="relative bg-white px-2 font-bold uppercase text-white-dark dark:bg-dark dark:text-white-light">or</span>
- </div>
- <div class="mb-10 md:mb-[60px]">
- <ul class="flex justify-center gap-3.5 text-white">
- <li>
- <a
- href="javascript:"
- class="inline-flex h-8 w-8 items-center justify-center rounded-full p-0 transition hover:scale-110"
- style="background: linear-gradient(135deg, rgba(239, 18, 98, 1) 0%, rgba(67, 97, 238, 1) 100%)"
- >
- <icon-instagram />
- </a>
- </li>
- <li>
- <a
- href="javascript:"
- class="inline-flex h-8 w-8 items-center justify-center rounded-full p-0 transition hover:scale-110"
- style="background: linear-gradient(135deg, rgba(239, 18, 98, 1) 0%, rgba(67, 97, 238, 1) 100%)"
- >
- <icon-facebook-circle />
- </a>
- </li>
- <li>
- <a
- href="javascript:"
- class="inline-flex h-8 w-8 items-center justify-center rounded-full p-0 transition hover:scale-110"
- style="background: linear-gradient(135deg, rgba(239, 18, 98, 1) 0%, rgba(67, 97, 238, 1) 100%)"
- >
- <icon-twitter :fill="true" />
- </a>
- </li>
- <li>
- <a
- href="javascript:"
- class="inline-flex h-8 w-8 items-center justify-center rounded-full p-0 transition hover:scale-110"
- style="background: linear-gradient(135deg, rgba(239, 18, 98, 1) 0%, rgba(67, 97, 238, 1) 100%)"
- >
- <icon-google />
- </a>
- </li>
- </ul>
- </div>
- <div class="text-center dark:text-white">
- Already have an account ?
- <router-link to="/auth/boxed-signin" class="uppercase text-primary underline transition hover:text-black dark:hover:text-white">
- SIGN IN
- </router-link>
- </div>-->
- </div>
- </div>
- </div>
- </div>
- </div>
- </template>
- <script lang="ts" setup>
- import { computed, reactive, ref, onMounted, Ref } from 'vue';
- import { useI18n } from 'vue-i18n';
- import appSetting from '@/app-setting';
- import { useRouter } from 'vue-router';
- import { useMeta } from '@/composables/use-meta';
- import IconInstagram from '@/components/icon/icon-instagram.vue';
- import IconFacebookCircle from '@/components/icon/icon-facebook-circle.vue';
- import IconGoogle from '@/components/icon/icon-google.vue';
- import { Plus } from '@element-plus/icons-vue';
- import * as API_Company from '@/api/company';
- import * as API_Package from '@/api/package';
- import type { UploadProps } from 'element-plus';
- import { ElMessageBox, FormInstance, ElMessage } from 'element-plus';
- import { provinceAndCityData, pcTextArr, regionData, pcaTextArr, codeToText } from 'element-china-area-data';
- import { useStore } from 'vuex';
- useMeta({ title: 'Register Boxed' });
- const router = useRouter();
- const store = useStore();
- const options = ref<any[]>(regionData);
- const selectedOptions = ref<any[]>([]);
- const companyForm = ref<any>({
- role_id: '',
- name: '',
- money: '',
- day: '',
- phone: '',
- use_able: false,
- check_code: '',
- check_code_key: '',
- remark: '',
- address: '',
- license: '',
- company_package_id: '',
- license_msg: {},
- id_card_front: '',
- id_card_msg_front: {},
- id_card_opposite: '',
- id_card_msg_opposite: {},
- id_card_num: '',
- id_card_time: '',
- });
- const stockRules = ref<any>({
- role_id: [{ required: true, message: '请选择权限!', trigger: 'change' }],
- name: [{ required: true, message: '请输入公司名称!', trigger: 'blur' }],
- credit_code: [{ required: true, message: '请输入统一社会信用代码!', trigger: 'blur' }],
- industry: [{ required: true, message: '请输入行业!', trigger: 'blur' }],
- user_name: [{ required: true, message: '请输入联系人姓名!', trigger: 'blur' }],
- phone: [
- { required: true, message: '请输入联系人电话!', trigger: 'blur' },
- { pattern: /^1[3-9]\d{9}$/, message: '请输入有效的手机号', trigger: 'blur' },
- ],
- email: [
- { required: true, message: '请输入邮箱!', trigger: 'blur' },
- { type: 'email', message: '请输入有效的邮箱地址', trigger: ['blur', 'change'] },
- ],
- postal_code: [
- { required: true, message: '请输入邮编!', trigger: 'blur' },
- { pattern: /^[1-9]\d{5}$/, message: '请输入有效的邮政编码', trigger: 'blur' },
- ],
- });
- /* 营业执照 */
- const handleAvatarSuccess: UploadProps['onSuccess'] = (response, uploadFile) => {
- API_Company.checkLicense({ image_url: response.url }).then((res) => {
- companyForm.value.name = res.enterprise_name;
- companyForm.value.credit_code = res.credit_code;
- companyForm.value.license_msg = res;
- companyForm.value.license = response.url;
- });
- };
- const beforeAvatarUpload: UploadProps['beforeUpload'] = (rawFile) => {
- if (rawFile.size / 1024 / 1024 > 10) {
- ElMessage.error('Avatar picture size can not exceed 10MB!');
- return false;
- }
- return true;
- };
- /* 身份证正面 */
- const handleFrontSuccess: UploadProps['onSuccess'] = (response, uploadFile) => {
- API_Company.checkIdCardOpposite({ image_url: response.url }, 'front').then((res) => {
- if(res.name!==companyForm.value.name){
- ElMessage.error('请上传法人身份证!');
- return
- }
- companyForm.value.user_name = res.name;
- companyForm.value.id_card_num = res.id_card_number;
- companyForm.value.id_card_msg_front = res;
- companyForm.value.id_card_front = response.url;
- });
- };
- const beforeFrontUpload: UploadProps['beforeUpload'] = (rawFile) => {
- if (rawFile.size / 1024 / 1024 > 10) {
- ElMessage.error('Avatar picture size can not exceed 10MB!');
- return false;
- }
- return true;
- };
- /* 身份证反面 */
- const handleOppositeSuccess: UploadProps['onSuccess'] = (response, uploadFile) => {
- API_Company.checkIdCardOpposite({ image_url: response.url }, 'opposite').then((res) => {
- companyForm.value.id_card_num = res.valid_date;
- companyForm.value.id_card_msg_opposite = res;
- companyForm.value.id_card_opposite = response.url;
- });
- };
- const beforeOppositeUpload: UploadProps['beforeUpload'] = (rawFile) => {
- if (rawFile.size / 1024 / 1024 > 10) {
- ElMessage.error('Avatar picture size can not exceed 10MB!');
- return false;
- }
- return true;
- };
- const uploadUrl = ref(import.meta.env.VITE_API_URL + '/uploaders');
- /* 获取套餐列表 */
- const packageList = ref<any>([]);
- const GET_PackageList = () => {
- API_Package.packageList({ page_no: 1, page_size: 1000, use_able: true }).then((res) => {
- packageList.value = res.records;
- });
- };
- // multi language
- const i18n = reactive(useI18n());
- const changeLanguage = (item: any) => {
- i18n.locale = item.code;
- appSetting.toggleLanguage(item);
- };
- const currentFlag = computed(() => {
- return `/assets/images/flags/${i18n.locale.toUpperCase()}.svg`;
- });
- const companyFormRef = ref();
- const submitWarehouseForm = () => {
- companyFormRef.value.validate((valid: boolean) => {
- if (valid) {
- const { id } = companyForm.value;
- const params = { ...companyForm.value };
- params.province = selectedOptions.value.join(',');
- API_Company.addCompany(params).then((res) => {
- ElMessageBox.confirm(`此为登录密码,请详细记录:${res}`, '提示', {
- confirmButtonText: '确定',
- cancelButtonText: '取消',
- type: 'warning',
- })
- .then(() => {
- router.push({ path: '/login' }).catch(() => {});
- })
- .catch(() => {});
- /* ElMessage.success('添加成功!'); */
- });
- } else {
- ElMessage.error('表单填写有误,请核对!');
- /* store.dispatch('showMessage', { message: '表单填写有误,请核对!', type: 'error' }); */
- return false;
- }
- });
- };
- const showloginCode = ref(true);
- let timer: Ref<number | null> = ref(null);
- let count = ref<number>(0);
- /* 获取手机号验证码 */
- const getCode = () => {
- if (companyForm.value.phone === '') {
- ElMessage.error('请先输入手机号!');
- return;
- }
- API_Company.loginGetCheckCode(companyForm.value.phone).then((res) => {
- ElMessage.success('验证码已发送,五分钟后失效!');
- companyForm.value.check_code_key = res;
- /* const TIME_COUNT = 60; */
- /* if (!timer.value) {
- showloginCode.value = false;
- count.value = TIME_COUNT;
- timer.value = window.setInterval(() => {
- if (count.value > 0 && count.value <= TIME_COUNT) {
- count.value -= 1;
- } else {
- showloginCode.value = true;
- clearInterval(timer.value as number);
- timer.value = null;
- }
- }, 1000);
- } */
- });
- };
- onMounted(() => {
- GET_PackageList()
- })
- </script>
- <style>
- .avatar-uploader .el-upload {
- border: 1px dashed var(--el-border-color);
- border-radius: 6px;
- cursor: pointer;
- position: relative;
- overflow: hidden;
- transition: var(--el-transition-duration-fast);
- }
- .avatar-uploader .el-upload:hover {
- border-color: var(--el-color-primary);
- }
- .el-icon.avatar-uploader-icon {
- font-size: 28px;
- color: #8c939d;
- width: 112px;
- height: 112px;
- text-align: center;
- }
- </style>
|