497 lines
12 KiB
Vue
497 lines
12 KiB
Vue
<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>
|