congming_huose-apk/pages/company/apply.vue

497 lines
12 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="page">
<app-top-push-notice />
<view class="tabback">
<view class="rtjt" @click="back"></view>
<view class="name">{{ $i18n.t('companyApplyTitle') }}</view>
<view class="tabback-placeholder"></view>
</view>
<scroll-view scroll-y class="form-scroll" :show-scrollbar="false">
<view class="form">
<!-- logo -->
<view class="field">
<text class="label">{{ $i18n.t('companyFieldLogo') }}</text>
<view class="logo-box" @click="openSheet">
<image v-if="logo" class="logo-img" :src="logo" mode="aspectFill" />
<text v-else class="logo-placeholder">{{ $i18n.t('companyTapUploadLogo') }}</text>
</view>
</view>
<view class="field">
<text class="label">{{ $i18n.t('companyFieldName') }}</text>
<input
class="input"
v-model="name"
:placeholder="$i18n.t('companyFieldNamePlaceholder')"
placeholder-style="color:#BFBFBF"
/>
</view>
<view class="field">
<text class="label">{{ $i18n.t('companyFieldType') }}</text>
<picker mode="selector" :range="typeLabels" :value="typeIndex" @change="onTypeChange">
<view class="picker-val">{{ typeLabels[typeIndex] }}</view>
</picker>
</view>
<view class="field">
<text class="label">{{ $i18n.t('companyFieldDescription') }}</text>
<textarea
class="textarea"
v-model="description"
:placeholder="$i18n.t('companyFieldDescriptionPlaceholder')"
placeholder-style="color:#BFBFBF"
auto-height
/>
</view>
<view class="field">
<text class="label">{{ $i18n.t('companyFieldEmail') }}</text>
<input
class="input"
v-model="email"
type="text"
:placeholder="$i18n.t('companyFieldEmailPlaceholder')"
placeholder-style="color:#BFBFBF"
/>
</view>
<view class="field">
<text class="label">{{ $i18n.t('companyFieldWebsite') }}</text>
<input
class="input"
v-model="website"
:placeholder="$i18n.t('companyFieldWebsitePlaceholder')"
placeholder-style="color:#BFBFBF"
/>
</view>
<view class="field">
<text class="label">{{ $i18n.t('companyFieldPhoneCode') }}</text>
<picker mode="selector" :range="phoneCodeLabels" :value="phoneCodeIndex" @change="onPhoneCodeChange">
<view class="picker-val">{{ phoneCodeLabels[phoneCodeIndex] }}</view>
</picker>
</view>
<view class="field">
<text class="label">{{ $i18n.t('companyFieldPhone') }}</text>
<input
class="input"
v-model="phone"
type="number"
:placeholder="$i18n.t('companyFieldPhonePlaceholder')"
placeholder-style="color:#BFBFBF"
/>
</view>
</view>
</scroll-view>
<view class="submit-footer">
<view class="submit-btn" :class="{ disabled: submitting }" @click="submit">{{ $i18n.t('companyApplySubmit') }}</view>
</view>
<view class="action-sheet" v-if="showActionSheet" @click="hideActionSheet">
<view class="action-sheet-content" @click.stop>
<view class="action-sheet-item" @click="takePhoto">
<text class="action-sheet-text">{{ $i18n.t('takePhoto') }}</text>
</view>
<view class="action-sheet-item" @click="chooseFromAlbum">
<text class="action-sheet-text">{{ $i18n.t('chooseFromAlbum') }}</text>
</view>
<view class="action-sheet-cancel" @click="hideActionSheet">
<text class="action-sheet-text">{{ $i18n.t('actionSheetCancel') }}</text>
</view>
</view>
</view>
</view>
</template>
<script>
const TYPE_OPTS = () => [
{ value: 1, labelKey: 'companyTypeSecurity' },
{ value: 2, labelKey: 'companyTypeInstall' }
]
const PHONE_CODES = () => [
{ code: '+86', regionKey: 'regionCN' },
{ code: '+852', regionKey: 'regionHK' },
{ code: '+853', regionKey: 'regionMO' },
{ code: '+886', regionKey: 'regionTW' },
{ code: '+81', regionKey: 'regionJP' },
{ code: '+82', regionKey: 'regionKorea' },
{ code: '+1', regionKey: 'regionUS' },
{ code: '+1', regionKey: 'regionCA' },
{ code: '+44', regionKey: 'regionGB' },
{ code: '+7', regionKey: 'regionRU' },
{ code: '+65', regionKey: 'regionSG' },
{ code: '+61', regionKey: 'regionAU' },
{ code: '+49', regionKey: 'regionDE' },
{ code: '+33', regionKey: 'regionFR' },
{ code: '+39', regionKey: 'regionIT' },
{ code: '+34', regionKey: 'regionES' }
]
export default {
data() {
return {
logo: '',
name: '',
description: '',
email: '',
website: '',
phone: '',
typeIndex: 0,
phoneCodeIndex: 0,
typeOptions: TYPE_OPTS(),
phoneCodes: PHONE_CODES(),
qiniuToken: '',
showActionSheet: false,
submitting: false
}
},
computed: {
typeLabels() {
const t = this.$i18n.t.bind(this.$i18n)
return this.typeOptions.map((o) => t(o.labelKey))
},
phoneCodeLabels() {
const t = this.$i18n.t.bind(this.$i18n)
const lang = this.$i18n.getCurrentLanguage && this.$i18n.getCurrentLanguage()
return this.phoneCodes.map((p) => {
let region = t(p.regionKey)
// 日语下韩国名称使用 Unicode避免 ja 语言包该行编码异常
if (p.regionKey === 'regionKorea' && lang === 'ja') {
region = '\u97d3\u56fd'
}
return `${p.code} ${region}`
})
}
},
onLoad() {
this.getQiniuToken()
},
methods: {
back() {
uni.navigateBack({ delta: 1 })
},
onTypeChange(e) {
const i = Number(e.detail.value)
if (!Number.isNaN(i)) this.typeIndex = i
},
onPhoneCodeChange(e) {
const i = Number(e.detail.value)
if (!Number.isNaN(i)) this.phoneCodeIndex = i
},
openSheet() {
this.showActionSheet = true
},
hideActionSheet() {
this.showActionSheet = false
},
generateGuid(length) {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
let result = ''
for (let i = 0; i < length; i++) {
result += chars.charAt(Math.floor(Math.random() * chars.length))
}
return result
},
getQiniuToken() {
this.$http.get('/common/qiniuToken').then((res) => {
if (res.code == 200) {
this.qiniuToken = res.data
}
})
},
uploadPath(tempPath) {
if (!this.qiniuToken) {
uni.showToast({ title: this.$i18n.t('uploadFailed'), icon: 'none' })
return
}
const math = 'static/' + this.generateGuid(20)
uni.uploadFile({
url: 'https://up-z2.qiniup.com',
name: 'file',
filePath: tempPath,
formData: {
token: this.qiniuToken,
key: 'smartmeter/img/' + math
},
success: (res) => {
try {
const str = JSON.parse(res.data)
this.logo = 'https://api.ccttiot.com/' + str.key
uni.showToast({ title: this.$i18n.t('imageSelectedSuccess'), icon: 'success' })
} catch (err) {
uni.showToast({ title: this.$i18n.t('uploadFailed'), icon: 'none' })
}
},
fail: () => {
uni.showToast({ title: this.$i18n.t('uploadFailed'), icon: 'none' })
}
})
},
takePhoto() {
this.hideActionSheet()
uni.chooseImage({
count: 1,
sizeType: ['compressed'],
sourceType: ['camera'],
success: (imgRes) => {
this.uploadPath(imgRes.tempFilePaths[0])
},
fail: () => {
uni.showToast({ title: this.$i18n.t('imageOperationCancelled'), icon: 'none' })
}
})
},
chooseFromAlbum() {
this.hideActionSheet()
uni.chooseImage({
count: 1,
sizeType: ['compressed'],
sourceType: ['album'],
success: (imgRes) => {
this.uploadPath(imgRes.tempFilePaths[0])
},
fail: () => {
uni.showToast({ title: this.$i18n.t('imageOperationCancelled'), icon: 'none' })
}
})
},
submit() {
if (this.submitting) return
const name = (this.name || '').trim()
if (!name) {
uni.showToast({ title: this.$i18n.t('companyPleaseName'), icon: 'none' })
return
}
if (!this.logo) {
uni.showToast({ title: this.$i18n.t('companyPleaseLogo'), icon: 'none' })
return
}
const email = (this.email || '').trim()
if (email && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
uni.showToast({ title: this.$i18n.t('companyEmailInvalid'), icon: 'none' })
return
}
const type = this.typeOptions[this.typeIndex].value
const phoneCode = this.phoneCodes[this.phoneCodeIndex].code
const payload = {
logo: this.logo,
name,
type,
description: (this.description || '').trim(),
email,
website: (this.website || '').trim(),
phoneCode,
phone: (this.phone || '').trim()
}
this.submitting = true
this.$http
.post('/bst/company', payload)
.then((res) => {
if (res.code == 200) {
uni.showToast({
title: res.msg || this.$i18n.t('companyApplySuccess'),
icon: 'success'
})
setTimeout(() => {
uni.navigateBack({ delta: 1 })
}, 1500)
} else {
uni.showToast({ title: res.msg || this.$i18n.t('requestFailed'), icon: 'none' })
}
})
.catch(() => {
uni.showToast({ title: this.$i18n.t('requestFailed'), icon: 'none' })
})
.finally(() => {
this.submitting = false
})
}
}
}
</script>
<style scoped lang="scss">
.page {
min-height: 100vh;
background-color: #f3f5f6;
box-sizing: border-box;
}
.tabback {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
height: 160rpx;
padding: 0 20rpx;
padding-top: 80rpx;
box-sizing: border-box;
position: fixed;
top: 0;
left: 0;
z-index: 999;
background-color: #fff;
.rtjt {
font-size: 36rpx;
color: #333;
min-width: 48rpx;
}
.name {
font-size: 32rpx;
font-weight: 600;
color: #333;
}
.tabback-placeholder {
width: 48rpx;
height: 1rpx;
}
}
.form-scroll {
height: calc(100vh - 160rpx);
margin-top: 160rpx;
box-sizing: border-box;
}
.form {
padding: 24rpx;
/* 为底部固定按钮留出可滚动空间按钮区约 96+40+40rpx + 安全区 */
padding-bottom: calc(200rpx + env(safe-area-inset-bottom));
}
.field {
margin-bottom: 28rpx;
}
.label {
display: block;
font-size: 26rpx;
color: #5c6370;
margin-bottom: 12rpx;
}
.logo-box {
width: 200rpx;
height: 200rpx;
border-radius: 16rpx;
background: #fff;
border: 2rpx dashed #d0d4dc;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
}
.logo-img {
width: 100%;
height: 100%;
}
.logo-placeholder {
font-size: 24rpx;
color: #8b9199;
padding: 16rpx;
text-align: center;
}
.input {
background: #fff;
border-radius: 12rpx;
padding: 24rpx 28rpx;
font-size: 28rpx;
color: #1a1a1a;
}
.textarea {
background: #fff;
border-radius: 12rpx;
padding: 24rpx 28rpx;
font-size: 28rpx;
color: #1a1a1a;
min-height: 160rpx;
width: 100%;
box-sizing: border-box;
}
.picker-val {
background: #fff;
border-radius: 12rpx;
padding: 24rpx 28rpx;
font-size: 28rpx;
color: #1a1a1a;
}
.submit-footer {
position: fixed;
left: 0;
right: 0;
bottom: 0;
z-index: 998;
padding: 20rpx 24rpx calc(20rpx + env(safe-area-inset-bottom));
background-color: #fff;
box-shadow: 0 -4rpx 24rpx rgba(0, 0, 0, 0.06);
box-sizing: border-box;
}
.submit-btn {
height: 96rpx;
line-height: 96rpx;
text-align: center;
background: #0f0f0f;
color: #fff;
font-size: 32rpx;
font-weight: 600;
border-radius: 48rpx;
}
.submit-btn.disabled {
opacity: 0.5;
}
.action-sheet {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
z-index: 9999;
display: flex;
align-items: flex-end;
justify-content: center;
}
.action-sheet-content {
width: 100%;
background-color: #fff;
border-radius: 20rpx 20rpx 0 0;
padding-bottom: 40rpx;
}
.action-sheet-item {
padding: 30rpx 40rpx;
border-bottom: 1rpx solid #f0f0f0;
text-align: center;
}
.action-sheet-cancel {
padding: 30rpx 40rpx;
text-align: center;
margin-top: 20rpx;
background-color: #f8f8f8;
}
.action-sheet-text {
font-size: 32rpx;
color: #333;
}
</style>