123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693 |
- <template>
- <div class="club-device">
- <template v-for="(formItem, index) in formList">
- <div :key="formItem.uid" class="device-section">
- <span
- class="remove-btn"
- @click="removeOne(formItem)"
- v-if="formList.length > 1"
- >删除这台设备</span
- >
- <el-form :model="formItem" :rules="rules" ref="form">
- <el-form-item label="认证方式:">
- <el-radio-group
- v-model="formItem.authType"
- @change="onAuthTypeChange(formItem, index)"
- >
- <el-radio :label="1">新设备认证</el-radio>
- <el-radio :label="2">关联已认证设备</el-radio>
- </el-radio-group>
- </el-form-item>
- <template
- v-if="
- formItem.authType === 1 ||
- (formItem.authType === 2 && formItem.snCode)
- "
- >
- <el-form-item
- prop="productName"
- :label="`设备名称${formItem.uuid}:`"
- >
- <el-select
- v-model="formItem.productName"
- filterable
- allow-create
- placeholder="请输入新设备名称或选择已有设备"
- @change="onProductNameChange(formItem, $event)"
- clearable
- :disabled="formItem.authType === 2"
- >
- <el-option
- v-for="item in deviceList"
- :key="item.productTypeId"
- :label="item.name"
- :value="item.productTypeId"
- />
- </el-select>
- </el-form-item>
- <el-form-item prop="productImage" label="设备图片:">
- <br />
- <el-input
- v-show="false"
- v-model="formItem.productImage"
- ></el-input>
- <SimpleUploadImage
- :disabled="Boolean(formItem.productTypeId)"
- :limit="1"
- :image-list="formItem.productImageList"
- :before-upload="beforeProductImageUpload"
- @success="uploadProductImageSuccess(formItem, $event)"
- @remove="handleProductImageRemove(formItem, $event)"
- />
- </el-form-item>
- <el-form-item label="所属品牌:" prop="infoId" v-if="editPrams">
- <el-select
- v-model="formItem.infoId"
- placeholder="请选择品牌"
- :disabled="formItem.authType === 2"
- >
- <el-option
- v-for="item in brandList"
- :key="item.infoId"
- :label="item.brandName"
- :value="item.infoId"
- />
- </el-select>
- </el-form-item>
- <el-form-item prop="purchaseWay" label="购买渠道:">
- <el-input
- placeholder="请输入购买渠道"
- v-model="formItem.purchaseWay"
- :disabled="formItem.authType === 2"
- ></el-input>
- </el-form-item>
- <el-form-item prop="invoiceImage" label="发票:">
- <br />
- <el-input
- v-show="false"
- v-model="formItem.invoiceImage"
- ></el-input>
- <SimpleUploadImage
- :disabled="formItem.authType === 2"
- :limit="1"
- :image-list="formItem.invoiceImageList"
- :before-upload="beforeInvoiceImageUpload"
- @success="uploadInvoiceImageSuccess(formItem, $event)"
- @remove="handleInvoiceImageRemove(formItem, $event)"
- />
- </el-form-item>
- </template>
- <el-form-item prop="snCode" :label="`设备SN码${formItem.uuid}:`">
- <el-input
- :placeholder="
- formItem.authType === 1
- ? '请输入设备SN码'
- : '请输入已认证过的设备SN码'
- "
- @blur="onSnCodeBlur(formItem)"
- v-model.lazy="formItem.snCode"
- ></el-input>
- </el-form-item>
- <template v-if="formItem.authType === 1">
- <el-form-item prop="paramList" label="设备参数:" v-if="editPrams">
- <br />
- <div class="device-param-list">
- <span class="add-param" @click="insertParam(formItem)"
- >添加参数</span
- >
- <template v-for="(param, index) in formItem.paramList">
- <div :key="index">
- <div class="param flex justify-between mb-4">
- <el-input
- style="width: 40%"
- placeholder="例如:品牌"
- class="mr-2"
- v-model="param.paramName"
- ></el-input>
- <el-input
- placeholder="请输入参数信息"
- v-model="param.paramContent"
- ></el-input>
- <span
- class="remove el-icon-close"
- @click="removeParam(formItem, index)"
- v-if="formItem.paramList.length > 4"
- ></span>
- </div>
- </div>
- </template>
- </div>
- </el-form-item>
- </template>
- </el-form>
- <el-divider></el-divider>
- </div>
- </template>
- <div class="add-device" @click="insertOne" v-if="formType !== 'edit'">
- <div class="add-icon"></div>
- 添加设备
- </div>
- <SimpleDialog
- v-if="formType !== 'edit'"
- v-model="active"
- @confirm="active = false"
- confirmText="好的"
- :cancel="false"
- description="请慎重填写设备信息,认证通过后将无法更改!"
- :center="true"
- />
- </div>
- </template>
- <script>
- import SimpleUploadImage from '@/components/SimpleUploadImage'
- import { mapGetters } from 'vuex'
- export default {
- components: {
- SimpleUploadImage,
- },
- props: {
- formType: {
- type: String,
- default: 'add',
- },
- },
- data() {
- const productNameValidate = (rule, value, callback) => {
- if (value.toString().length > 50) {
- callback(new Error('设备名称长度需要在50个字符内'))
- } else {
- callback()
- }
- }
- const paramListValidate = (rule, value, callback) => {
- const notEmptyList = value.filter(
- (item) => item.paramName.trim() && item.paramContent.trim()
- )
- if (notEmptyList.length === 0) {
- callback(new Error('参数列表不能为空'))
- } else if (notEmptyList.length < 4) {
- callback(new Error('请填写至少4项参数'))
- } else {
- callback()
- }
- }
- return {
- active: true,
- uuid: 0, // 表单id
- productImageList: [],
- rules: {
- productName: [
- { required: true, message: '设备名称不能为空', trigger: ['change'] },
- { validator: productNameValidate, trigger: ['change'] },
- ],
- productImage: [
- { required: true, message: '设备图片不能为空', trigger: ['change'] },
- ],
- infoId: [
- { required: true, message: '所属品牌不能为空', trigger: ['change'] },
- ],
- snCode: [
- { required: true, message: '设备SN码不能为空', trigger: ['blur'] },
- ],
- paramList: [
- { required: true, message: '参数不能为空', trigger: ['blur'] },
- { validator: paramListValidate, trigger: ['change'] },
- ],
- purchaseWay: [
- {
- required: true,
- message: '请输入购买渠道不能为空',
- trigger: ['blur'],
- },
- {
- max: 50,
- message: '最大长度为50个字符',
- trigger: ['blur'],
- },
- ],
- invoiceImage: [
- { required: true, message: '请上传发票', trigger: ['change'] },
- ],
- authType: [
- { required: true, message: '请选择认证方式', trigger: ['change'] },
- ],
- },
- formList: [],
- brandList: [],
- deviceList: [],
- editPrams: true,
- }
- },
- computed: {
- ...mapGetters(['authUserId']),
- },
- created() {
- this.fetchBrandList()
- this.fetchDeviceList()
- this.initFormList()
- },
- methods: {
- // sn码输入框是去焦点
- async onSnCodeBlur(formItem) {
- if (formItem.authType === 1) return
- if (!formItem.snCode) return
- try {
- const res = await this.$http.api.fetchDetialBySnCode({
- snCode: formItem.snCode,
- })
- formItem.invoiceImage = res.data.invoiceImage
- formItem.purchaseWay = res.data.purchaseWay
- formItem.productTypeId = res.data.productTypeId
- formItem.productName = res.data.productName
- formItem.infoId = res.data.infoId
- formItem.productImage = res.data.productImage
- if (res.data.invoiceImage) {
- formItem.invoiceImageList = [
- { name: '发票', url: res.data.invoiceImage },
- ]
- }
- if (res.data.productImage) {
- formItem.productImageList = [
- { name: '产品图片', url: res.data.productImage },
- ]
- }
- } catch (error) {
- console.log(error)
- }
- },
- // 认证方式切换
- onAuthTypeChange(formItem, index) {
- formItem.purchaseWay = ''
- formItem.invoiceImage = ''
- formItem.productName = ''
- formItem.productTypeId = ''
- formItem.productImageList = []
- formItem.invoiceImageList = []
- formItem.paramList = this.initParams()
- this.$refs.form[index]?.resetFields()
- },
- // 表单验证
- validate() {
- this.$emit('step', this.formatFormList())
- return Promise.all(this.$refs.form.map((item) => item.validate()))
- },
- async init(formData) {
- console.log('formData', formData)
- const obj = {}
- const productImageList = [
- {
- name: '',
- url: formData?.productImage,
- },
- ]
- const invoiceImageList = [
- {
- name: '',
- url: formData.invoiceImage,
- },
- ]
- obj.uuid = ++this.uuid
- obj.authType = formData.authType
- obj.productImageList = productImageList
- obj.invoiceImageList = invoiceImageList
- obj.productImage = formData.productImage
- obj.productName = formData.productName
- obj.snCode = formData.snCode
- obj.infoId = formData.infoId
- obj.productId = formData.productId
- obj.productTypeId = formData.productTypeId
- obj.purchaseWay = formData.purchaseWay
- obj.invoiceImage = formData.invoiceImage
- obj.paramList = formData.paramList
- this.formList.splice(0, 1, obj)
- console.log('formList', this.formList)
- },
- formatFormList() {
- const list = []
- this.formList.forEach((formItem) => {
- const obj = {}
- obj.productImage = formItem.productImage
- obj.authType = formItem.authType
- obj.productName = formItem.productName
- obj.snCode = formItem.snCode
- obj.infoId = formItem.infoId
- obj.productId = formItem.productId
- obj.source = 2
- obj.productTypeId = formItem.productTypeId
- obj.purchaseWay = formItem.purchaseWay
- obj.invoiceImage = formItem.invoiceImage
- obj.paramList = formItem.paramList
- list.push(obj)
- })
- return list
- },
- generateFormData() {
- return {
- uuid: ++this.uuid,
- authUserId: '',
- authId: '', // 授权id
- createBy: '', // 创建人id
- // 设备参数列表
- paramList: this.initParams(),
- productId: '', // 授权设备id
- productImage: '', // 设备图片
- productName: '', // 设备名称
- snCode: '', // 设备SN码
- infoId: '',
- productTypeId: '',
- purchaseWay: '', // 购买渠道
- invoiceImage: '', // 发票
- productImageList: [],
- invoiceImageList: [],
- authType: 1,
- }
- },
- generageProductParam() {
- return {
- paramContent: '',
- paramName: '',
- }
- },
- initParams() {
- const list = []
- for (let i = 0; i < 4; i++) {
- list.push(this.generageProductParam())
- }
- return list
- },
- insertParam(formItem) {
- formItem.paramList.push(this.generateFormData())
- },
- removeParam(formItem, index) {
- formItem.paramList.splice(index, 1)
- },
- initFormList() {
- this.formList.push(this.generateFormData())
- console.log(this.formList)
- },
- insertOne() {
- this.formList.push(this.generateFormData())
- },
- removeOne(formItem) {
- const index = this.formList.findIndex(
- (item) => item.uuid === formItem.uuid
- )
- this.formList.splice(index, 1)
- },
- onProductNameChange(formItem, value) {
- if (typeof value === 'number') {
- formItem.productTypeId = value
- const deviceInfo = this.deviceList.find(
- (item) => item.productTypeId === value
- )
- formItem.productImage = deviceInfo.image
- formItem.productImageList = [{ name: '', url: deviceInfo.image }]
- this.editPrams = false
- } else {
- formItem.productTypeId = ''
- formItem.productImage = ''
- formItem.productImageList = []
- this.editPrams = true
- }
- },
- // 获取品牌列表
- async fetchBrandList() {
- try {
- const res = await this.$http.api.fetchBrandList({
- type: 3,
- authUserId: this.authUserId,
- })
- this.brandList = res.data
- } catch (error) {
- console.log(error)
- }
- },
- // 获取设备列表
- async fetchDeviceList() {
- try {
- const res = await this.$http.api.fetchProductSelectList({
- authUserId: this.authUserId,
- })
- this.deviceList = res.data
- } catch (error) {
- console.log(error)
- }
- },
- // 产品图片上传
- beforeProductImageUpload(file) {
- const flag = file.size / 1024 / 1024 < 5
- if (!flag) {
- this.$message.error('上传产品图片大小不能超过 5MB!')
- }
- return flag
- },
- uploadProductImageSuccess(formItem, { response, file, fileList }) {
- formItem.productImageList = fileList
- formItem.productImage = response.data
- },
- handleProductImageRemove(formItem, { file, fileList }) {
- formItem.productImageList = fileList
- formItem.productImage = ''
- },
- // 发票上传
- beforeInvoiceImageUpload(file) {
- const flag = file.size / 1024 / 1024 < 5
- if (!flag) {
- this.$message.error('发票图片大小不能超过 5MB!')
- }
- return flag
- },
- uploadInvoiceImageSuccess(formItem, { response, file, fileList }) {
- formItem.invoiceImageList = fileList
- formItem.invoiceImage = response.data
- },
- handleInvoiceImageRemove(formItem, { file, fileList }) {
- formItem.invoiceImageList = fileList
- formItem.invoiceImage = ''
- },
- },
- }
- </script>
- <style lang="scss" scoped>
- .club-device {
- @include useTheme() {
- ::v-deep {
- .el-input.is-active .el-input__inner,
- .el-input__inner:focus {
- border-color: fetch('color');
- }
- .el-radio__input.is-checked + .el-radio__label {
- color: fetch('color');
- }
- .el-radio__input.is-checked .el-radio__inner {
- background-color: fetch('color');
- border-color: fetch('color');
- }
- }
- }
- }
- // pc端
- @media screen and (min-width: 768px) {
- .club-device {
- @include useTheme() {
- .el-select {
- width: 100%;
- }
- .device-section {
- position: relative;
- .el-form {
- padding-bottom: 10px;
- }
- .remove-btn {
- position: absolute;
- right: 0;
- bottom: 24px;
- font-size: 16px;
- color: #f94b4b;
- text-decoration: underline;
- cursor: pointer;
- }
- }
- .device-param-list {
- position: relative;
- .add-param {
- position: absolute;
- cursor: pointer;
- top: -40px;
- right: 0;
- text-decoration: underline;
- font-size: 14px;
- color: fetch('color');
- }
- .param {
- position: relative;
- .remove {
- position: absolute;
- right: 0;
- top: 0;
- width: 20px;
- height: 20px;
- background: #f94b4b;
- border-radius: 2px;
- cursor: pointer;
- color: #fff;
- font-size: 14px;
- text-align: center;
- line-height: 20px;
- }
- }
- }
- .add-device {
- display: flex;
- justify-content: center;
- align-items: center;
- width: 162px;
- height: 46px;
- border-radius: 4px;
- box-sizing: border-box;
- font-size: 18px;
- margin: 0 auto;
- cursor: pointer;
- border: 1px solid fetch('color');
- color: fetch('color');
- .add-icon {
- width: 20px;
- height: 20px;
- position: relative;
- margin-right: 16px;
- &::before,
- &::after {
- position: absolute;
- width: 3px;
- height: 20px;
- left: 50%;
- top: 50%;
- transform: translate(-50%, -50%);
- border-radius: 1px;
- content: '';
- display: block;
- background: fetch('color');
- }
- &::after {
- transform: translate(-50%, -50%) rotateZ(90deg);
- }
- }
- }
- }
- }
- }
- // 移动端
- @media screen and (max-width: 768px) {
- .club-device {
- @include useTheme() {
- ::v-deep {
- .el-form-item__label {
- font-size: 3.4vw;
- }
- }
- .el-select {
- width: 100%;
- }
- .device-param-list {
- position: relative;
- .add-param {
- position: absolute;
- cursor: pointer;
- top: -40px;
- right: 0;
- font-size: 3.4vw;
- color: fetch('color');
- }
- .param {
- position: relative;
- .remove {
- position: absolute;
- right: 0;
- top: 0;
- width: 4.4vw;
- height: 4.4vw;
- background: #f94b4b;
- border-radius: 0.2vw;
- cursor: pointer;
- color: #fff;
- font-size: 3.4vw;
- text-align: center;
- line-height: 4.4vw;
- }
- }
- }
- .add-device {
- display: flex;
- justify-content: center;
- align-items: center;
- width: 31vw;
- height: 8.8vw;
- border-radius: 0.4vw;
- box-sizing: border-box;
- font-size: 3.4vw;
- margin: 0 auto;
- cursor: pointer;
- border: 1px solid fetch('color');
- color: fetch('color');
- .add-icon {
- width: 20px;
- height: 20px;
- position: relative;
- margin-right: 16px;
- &::before,
- &::after {
- position: absolute;
- width: 0.6vw;
- height: 4.1vw;
- left: 50%;
- top: 50%;
- transform: translate(-50%, -50%);
- border-radius: 1px;
- content: '';
- display: block;
- background: fetch('color');
- }
- &::after {
- transform: translate(-50%, -50%) rotateZ(90deg);
- }
- }
- }
- }
- }
- }
- </style>
|