Commit d88596f9 authored by hanfeng zhang's avatar hanfeng zhang

Merge branch 'main' of gitlab.33.cn:HF_web/NFT

parents da465b75 dd2b2aa0
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
"@tailwindcss/line-clamp": "^0.2.1", "@tailwindcss/line-clamp": "^0.2.1",
"ant-design-vue": "^1.7.5", "ant-design-vue": "^1.7.5",
"axios": "^0.21.1", "axios": "^0.21.1",
"clipboard": "^2.0.8",
"core-js": "^3.6.5", "core-js": "^3.6.5",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"register-service-worker": "^1.7.1", "register-service-worker": "^1.7.1",
......
<template> <template>
<div class="cell flex justify-between py-3 " :class="boxType ==='border'?' border-b px-0 border-font-gray border-opacity-25':'bg-font-gray bg-opacity-20 px-2 rounded-md'" > <div
<div class="left flex items-center "> class="cell flex justify-between py-3 px-2 overflow-hidden"
<app-icon v-if='labelIcon' :name="labelIcon" size='18px'></app-icon> :class="
<div class=" text-font-dark-blue px-3"> boxType === 'border'
{{text}} ? ' border-b border-font-gray border-opacity-25'
: 'bg-font-gray bg-opacity-20 rounded-md'
"
>
<div class="left flex items-center">
<app-icon v-if="labelIcon" :name="labelIcon" size="18px"></app-icon>
<div class="px-2">
{{ text }}
</div> </div>
</div> </div>
<div class="right flex items-center"> <div class="right flex items-center overflow-hidden">
<div v-if="type=='click'" @click="eventEmit(type)"> <div v-if="type == 'click'" @click="eventEmit(type)">
<div class='flex flex-row items-center'> <div class="flex flex-row items-center">
<div>{{value}}</div> <div>{{ value }}</div>
<app-icon v-if="icon" :name='icon' class='self-center'></app-icon> <app-icon v-if="icon" :name="icon" class="self-center"></app-icon>
</div> </div>
</div> </div>
<div v-else-if="type=='input'"> <div v-else-if="type == 'input'">
<input v-model="inputValue" type="text" class=" bg-transparent" placeholder='输入' @input="cellOnChange"> <input
v-model="inputValue"
type="text"
class="bg-transparent"
:placeholder="placeholder"
@input="cellOnChange"
/>
</div> </div>
<div v-else-if="type==='pick'"> <input
<div class='flex flex-row items-center'> v-if="type === 'input-num'"
<div>sdf</div> :value="inputValue"
type="number"
@input="handleInput"
class="bg-transparent"
:placeholder="placeholder"
/>
<div v-else-if="type === 'pick'">
<div class="flex flex-row items-center">
<input
@click="eventEmit(type)"
v-if="$store.state.create.pickedList.length === 0"
type="text"
class="bg-transparent"
:placeholder="placeholder"
/>
<app-tag
v-for="item in $store.state.create.pickedList"
:key="item.id"
:text="item.text"
:id="item.id"
class="text-sm rounded-xl text-font-white bg-app-red"
:active="true"
></app-tag>
<div @click="eventEmit(type)"> <div @click="eventEmit(type)">
<app-icon name="icon-xiayibu" size='18px'></app-icon> <app-icon name="icon-xiayibu" size="18px"></app-icon>
</div> </div>
</div> </div>
</div> </div>
<div v-else-if="type === 'upload'" class="overflow-hidden">
<div class="flex flex-row items-center overflow-hidden">
<div v-if="name" class="overflow-hidden overflow-ellipsis">
{{ name }}
</div> </div>
<input
v-else
@click="cellOnChange"
type="text"
class="bg-transparent"
:placeholder="placeholder"
/>
<div @click="cellOnChange">
<app-icon name="icon-xiayibu" size="18px"></app-icon>
</div>
</div>
</div>
<div v-else-if="type === 'showText'" class="overflow-hidden">
<div class="flex flex-row items-center overflow-hidden">
<div
v-if="name"
class="overflow-hidden overflow-ellipsis"
id="copyNodeId"
:data-clipboard-text="name"
>
{{ name }}
</div>
<div
data-clipboard-target="#copyNodeId"
ref="btn"
@click="handleClickCopy"
>
<app-icon name="icon-fuzhi" size="18px"></app-icon>
</div>
</div>
</div>
<div v-else-if="type === 'select'" class="overflow-hidden">
<div class="flex flex-row items-center overflow-hidden">
<div class="overflow-hidden overflow-ellipsis">
{{ getNameOfSelect(selected) }}
</div>
<div @click="eventEmit(type)">
<app-icon name="icon-xiayibu" size="18px"></app-icon>
</div>
</div>
</div>
</div>
<ActionSheet
v-model="show"
:actions="actions"
cancel-text="取消"
close-on-click-action
@cancel="onCancel"
@select="onSelect"
>
</ActionSheet>
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import Vue from "vue";
// import { Switch } from 'ant-design-vue' import Clipboard from "clipboard";
// Vue.use(Switch) import { ActionSheet } from "vant";
export default Vue.extend({ export default Vue.extend({
components:{ components: {
'app-icon':()=>import('@/components/common/Icon.vue') "app-icon": () => import("@/components/common/Icon.vue"),
ActionSheet,
"app-tag": () => import("@/components/common/Tag2.vue"),
}, },
props: { props: {
value: String, value: [String, Number],
pickValue:Array, pickValue: Array,
size: String, size: String,
type: { type: {
type:String, type: String,
default:'click' default: "click",
}, },
boxType:{ boxType: {
type: String, type: String,
default:'background' default: "background",
},
disabled: {
type: Boolean,
default: false,
}, },
disabled:{ text: {
type:Boolean, type: String,
default:false required: true,
}, },
text:{ icon: String,
labelIcon: String,
placeholder: {
type: String, type: String,
required: true default: "输入",
}, },
icon:String, name: [String, Number],
labelIcon: String selected: [String, Number, Object],
list: Array,
}, },
data(){ data() {
return{ return {
inputValue:this.value, inputValue: this.value,
} show: false,
};
},
mounted() {
console.log(this.value, "show value");
},
methods: {
handleInput(e: any) {
const temp = this.inputValue;
const value = e.target.value as string;
this.inputValue = value;
this.$emit("cellOnChange", Number(this.inputValue));
}, },
methods:{ eventEmit(v: any) {
eventEmit(v:any){ console.log(this.type);
if(this.disabled){
return if (this.disabled) {
return;
} }
if(this.type === 'click'){ if (this.type === "click") {
this.$emit('onClick',v) this.$emit("onClick", v);
} }
if(this.type === 'pick'){ if (this.type === "pick") {
this.$emit('onClick',(cb:any)=>{ this.$emit("onClick", (cb: any) => {
console.log(cb); console.log(cb);
return cb return cb;
}) });
} }
}, if (this.type === "select") {
cellOnChange(){ this.show = true;
this.$emit('cellOnChange',this.inputValue)
} }
}, },
computed:{ cellOnChange() {
getSize(){ this.$emit("cellOnChange", this.inputValue);
},
handleClickCopy() {
const btn = this.$refs.btn as HTMLElement;
new Clipboard(btn);
},
onCancel() {},
onSelect(value: any) {
this.$emit("cellOnChange", value.value);
},
getNameOfSelect(selected: string) {
const item = this.list.find(
(item: any) => item.value === selected
) as any;
console.log(item, selected);
return item && item.name
},
},
computed: {
getSize() {
switch (this.size) { switch (this.size) {
case 'full': case "full":
return 'w-full' return "w-full";
default: default:
return 'w-20'; return "w-20";
} }
}, },
actions(): any[] {
// getBoxType(){ return this.list || [];
// switch (this.boxType) { },
// case 'border': },
// return 'border-t border-b border-gray-500'
// // case 'background':
// // return ' '
// }
// }
}
}); });
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
input[type='text'], input[type='password'], input[type='number'], textarea{ input[type="text"],
input[type="password"],
input[type="number"],
textarea {
text-align: right; text-align: right;
padding: 0 25px; padding: 0 25px;
} }
input:not([type='range']), textarea{ input:not([type="range"]),
textarea {
padding: 0 10px; padding: 0 10px;
} }
</style> </style>
\ No newline at end of file
<template>
<div
class="tag flex justify-center text-2xs px-3 py-1 rounded-md"
:class="!active ? 'bg-opacity-0 border' : ''"
@click="tagOnclick"
>
{{ text }}
</div>
</template>
<script lang="ts">
import Vue from "vue";
export default Vue.extend({
name: "AppTag",
props: {
disabled: {
type: Boolean,
default: false,
},
id: {
type: Number,
required: true,
},
text: {
type: String,
required: true,
},
active: {
type: Boolean,
default: false,
},
},
methods: {
tagOnclick() {
if (this.disabled === false) {
this.$emit("onclick", {
id: this.id,
text: this.text,
});
}
},
},
});
</script>
...@@ -46,6 +46,14 @@ const routes: Array<RouteConfig> = [ ...@@ -46,6 +46,14 @@ const routes: Array<RouteConfig> = [
title: '剧本题材' title: '剧本题材'
} }
}, },
{
path: '/Nft/create/upload',
name:'NftUpload',
component: () => import('@/view/NFT/Create/upload.vue'),
meta: {
title: '剧本附件'
}
},
] ]
}, },
{ {
......
import { Service } from './Service'
import {Service} from './Service' import { NFT_CREATE } from '@/types/Dto'
import {NFT_CREATE} from '@/types/Dto'
import { token } from '@/util/userInfoUtils' import { token } from '@/util/userInfoUtils'
export class NFTService extends Service { export class NFTService extends Service {
router = { router = {
create:{ path:'/nft/publish'}, create: { path: '/nft/publish' },
getMyList:{ path:'/nft/list/current',dataType:'application/x-www-form-urlencoded'}, getMyList: {
getList:{path:'/nft/list',dataType:'application/x-www-form-urlencoded'}, path: '/nft/list/current',
genId:{ path:'/nft/generateNftId', dataType:'application/x-www-form-urlencoded'}, dataType: 'application/x-www-form-urlencoded',
detail:{ path:'/nft/get/{id}', dataType:'application/x-www-form-urlencoded'}, },
themes:{ path:'/label/list',dataType:'application/x-www-form-urlencoded'}, getList: {
getCategory:{path:'/category/list',dataType:'application/x-www-form-urlencoded'} path: '/nft/list',
dataType: 'application/x-www-form-urlencoded',
},
genId: {
path: '/nft/generateNftId',
dataType: 'application/x-www-form-urlencoded',
},
detail: {
path: '/nft/get/{id}',
dataType: 'application/x-www-form-urlencoded',
},
themes: {
path: '/label/list',
dataType: 'application/x-www-form-urlencoded',
},
getMd5: { path: '/nft/file/md5', dataType: 'multipart/form-data' },
save: { path: '/nft/save', dataType: 'multipart/form-data' },
publish: { path: '/nft/publish', dataType: 'application/json' },
getCategory: {
path: '/category/list',
dataType: 'application/x-www-form-urlencoded',
},
} }
auth = 'Bearer ' + token.getToken() auth = 'Bearer ' + token.getToken()
constructor(){ constructor() {
super() super()
} }
...@@ -22,42 +42,42 @@ export class NFTService extends Service { ...@@ -22,42 +42,42 @@ export class NFTService extends Service {
* @param phone * @param phone
* @param codeType 短信模板, 1:登录短信 2:修改密码 3:修改手机号 * @param codeType 短信模板, 1:登录短信 2:修改密码 3:修改手机号
*/ */
async create(data:NFT_CREATE){ async create(data: NFT_CREATE) {
return await this.service.post(this.router.create.path,data,{ return await this.service.post(this.router.create.path, data, {
headers:{ headers: {
"Authorization": this.auth Authorization: this.auth,
} },
}) })
} }
async getCategory():Promise<any[]>{
return await this.service.get(this.router.getCategory.path)
}
/** /**
* *
* @returns 获取剧目主题表 * @returns 获取剧目主题表
*/ */
async getThemeList(){ async getThemeList() {
return await this.service.get(this.router.themes.path,{ return await this.service.get(this.router.themes.path, {
headers:{ headers: {
"Authorization": this.auth, Authorization: this.auth,
"Content-Type": this.router.themes.dataType} 'Content-Type': this.router.themes.dataType,
},
}) })
} }
async getCategory(): Promise<any[]> {
return await this.service.get(this.router.getCategory.path)
}
/** /**
* 获取我的NFT列表 * 获取我的NFT列表
* @param categoryId * @param categoryId
* @returns * @returns
*/ */
async getMyList(categoryId?:number){ async getMyList(categoryId?: number) {
return await this.service.get(this.router.getMyList.path,{ return await this.service.get(this.router.getMyList.path, {
headers:{ headers: {
"Authorization": this.auth, Authorization: this.auth,
"Content-Type": this.router.getMyList.dataType}, 'Content-Type': this.router.getMyList.dataType,
params:{"categoryId":categoryId?categoryId:null} },
params: { categoryId: categoryId ? categoryId : null },
}) })
} }
...@@ -68,12 +88,17 @@ export class NFTService extends Service { ...@@ -68,12 +88,17 @@ export class NFTService extends Service {
* @param categoryId * @param categoryId
* @returns * @returns
*/ */
async getList(pageNum?:number,pageSize?:number,categoryId?:number){ async getList(pageNum?: number, pageSize?: number, categoryId?: number) {
return await this.service.get(this.router.getList.path,{ return await this.service.get(this.router.getList.path, {
headers:{ headers: {
"Authorization": this.auth, Authorization: this.auth,
"Content-Type": this.router.getList.dataType}, 'Content-Type': this.router.getList.dataType,
params:{"categoryId":categoryId?categoryId:null,"pageNum":pageNum,'pageSize':pageSize } },
params: {
categoryId: categoryId ? categoryId : null,
pageNum: pageNum,
pageSize: pageSize,
},
}) })
} }
...@@ -82,12 +107,13 @@ export class NFTService extends Service { ...@@ -82,12 +107,13 @@ export class NFTService extends Service {
* @param categoryId * @param categoryId
* @returns * @returns
*/ */
async generateNftId(categoryId:number){ async generateNftId(categoryId: number) {
return await this.service.get(this.router.genId.path,{ return await this.service.get(this.router.genId.path, {
headers:{ headers: {
"Authorization": this.auth, Authorization: this.auth,
"Content-Type": this.router.genId.dataType}, 'Content-Type': this.router.genId.dataType,
params:{"categoryId":categoryId} },
params: { categoryId: categoryId },
}) })
} }
...@@ -95,16 +121,86 @@ export class NFTService extends Service { ...@@ -95,16 +121,86 @@ export class NFTService extends Service {
* 按照id查找nft详情 * 按照id查找nft详情
* @param id * @param id
*/ */
async detail(id:number){ async detail(id: number) {
return await this.service.get(this.router.detail.path,{ return await this.service.get(this.router.detail.path, {
headers:{ headers: {
"Authorization": this.auth, Authorization: this.auth,
"Content-Type": this.router.detail.dataType 'Content-Type': this.router.detail.dataType,
}, },
params:{"id":id} params: { id: id },
}) })
} }
} /**
* 获取md5
* @param id
*/
async getMd5(file: File) {
const fd = new FormData()
fd.append('file', file)
return await this.service.post(this.router.getMd5.path, fd, {
headers: {
Authorization: this.auth,
'Content-Type': this.router.getMd5.dataType,
},
})
}
/**
* 发布
* @param id
*/
async publish(obj: {
fileHash: string
id: number
nftId: string
wallet: string
}) {
return await this.service.post(this.router.publish.path, obj, {
headers: {
Authorization: this.auth,
'Content-Type': this.router.publish.dataType,
},
})
}
/**
* nft基本信息保存
* @param id
*/
async save(
author: string,
categoryId: number,
fileHash: string,
isArchives: number,
name: string,
synopsis: string,
theme: string,
file: File,
isGrant: number,
) {
const fd = new FormData()
fd.append('author', author)
fd.append('categoryId', categoryId.toString())
fd.append('fileHash', fileHash)
fd.append('isArchives', isArchives.toString())
fd.append('name', name)
fd.append('synopsis', synopsis)
fd.append('theme', theme)
fd.append('file', file)
fd.append('isGrant', String(isGrant))
return (await this.service.post(this.router.save.path, fd, {
headers: {
Authorization: this.auth,
'Content-Type': this.router.save.dataType,
},
})) as {
fileHash: string
id: number
nftId: string
wallet: string
}
}
}
const stateData = {
pickedList: [],
fileHash: '',
fileName: '',
file: undefined as undefined | File,
}
export type AppType = typeof stateData
export const create = {
namespaced: true,
state: () => ({
...stateData,
}),
mutations: {
SET_STATE(state: AppType, payload: any) {
Object.assign(state, payload)
},
},
actions: {},
getters: {},
}
import Vue from 'vue' import Vue from 'vue'
import Vuex from 'vuex' import Vuex from 'vuex'
import {appStore} from './app' import {appStore} from './app'
import {create} from "./create"
Vue.use(Vuex) Vue.use(Vuex)
export default new Vuex.Store({ export default new Vuex.Store({
modules: { modules: {
app:appStore app:appStore,
create
} }
}) })
<template> <template>
<Layout-Child class='page-scroll'> <Layout-Child class="page-scroll">
<div class="w-7/12 mx-auto my-6"> <div class="w-7/12 mx-auto my-6">
<app-steps :data='mySteps' :currentStep='currentStep' @stepOnChange="stepOnChange" @stepOnFinished='stepOnFinished'></app-steps> <app-steps
:data="mySteps"
:currentStep="currentStep"
@stepOnChange="stepOnChange"
@stepOnFinished="stepOnFinished"
></app-steps>
</div> </div>
<div class="w-11/12 mx-auto"> <div class="w-11/12 mx-auto">
<div class="step-one" v-if="currentStep==1"> <div class="step-one" v-if="currentStep == 1">
<app-cell v-model="createNFT.value_name" type="input" text='剧本名称' class="text-font-white my-3" @cellOnChange="getValue"></app-cell> <app-cell
<app-cell v-model="createNFT.value_publisher" type="input" text='发行人' class="text-font-white my-3" @cellOnChange="getValue"></app-cell> v-model="createNFT.value_name"
<app-cell :pickValue="mySteps" type="pick" text='剧本题材' class="text-font-white my-3" @onClick="what"></app-cell> type="input"
text="剧本名称"
placeholder="请输入剧本名称"
class="text-font-white my-3"
@cellOnChange="(v) => setCreateNFT({ value_name: v })"
></app-cell>
<app-cell
v-model="createNFT.value_publisher"
type="input"
text="发行人"
placeholder="请输入发行人名称"
class="text-font-white my-3"
@cellOnChange="(v) => setCreateNFT({ value_publisher: v })"
></app-cell>
<app-cell
:pickValue="mySteps"
type="pick"
text="剧本题材"
placeholder="请选择剧本题材"
class="text-font-white my-3"
@onClick="what"
></app-cell>
<!-- <app-cell
text="分类"
type="select"
:selected="createNFT.categoryType"
:list="categoryTypes2"
class="text-font-white my-3"
@cellOnChange="(v) => (createNFT.categoryType = v)"
></app-cell> -->
<div> <div>
<div class="text-font-white my-2">剧本简介</div> <div class="text-font-white my-2">剧本简介</div>
<textarea v-model="createNFT.value_des" name="des" id="nft-des" cols="30" rows="10" class=" w-full bg-font-gray bg-opacity-20 text-font-white p-3 text-sm"></textarea> <textarea
v-model="createNFT.value_des"
name="des"
id="nft-des"
cols="30"
rows="10"
class="
w-full
bg-font-gray bg-opacity-20
text-font-white
p-3
text-sm
"
></textarea>
</div> </div>
<div class="fixed bottom-0 w-full left-0 z-30"> <div class="fixed bottom-0 w-full left-0 z-30">
<app-btn text="下一步" class="w-11/12 mx-auto text-font-white rounded-2xl bg-font-blue" border='none' @btnClicked='currentStepChange(1)'></app-btn> <app-btn
text="下一步"
class="w-11/12 mx-auto text-font-white rounded-2xl bg-font-blue"
:disabled="validation"
border="none"
@btnClicked="currentStepChange(1)"
></app-btn>
</div> </div>
</div> </div>
<div class="step-two" v-if="currentStep==2"> <div class="step-two" v-if="currentStep == 2">
<app-cell text='剧本上传' class="text-font-white my-3" @cellOnChange="getValue"></app-cell> <app-cell
<app-cell text='剧本HASH' class="text-font-white my-3" @cellOnChange="getValue"></app-cell> text="剧本上传"
<app-cell text='平台存档' class="text-font-white my-3" @cellOnChange="getValue"></app-cell> class="text-font-white my-3"
<app-cell text='授权阅读' class="text-font-white my-3" @cellOnChange="getValue"></app-cell> type="upload"
placeholder="请上传剧本"
:name="fileName"
@cellOnChange="$router.push({ name: 'NftUpload' })"
></app-cell>
<app-cell
text="剧本HASH"
class="text-font-white my-3"
type="showText"
:name="fileHash"
@cellOnChange="getValue"
></app-cell>
<app-cell
text="平台存档"
type="select"
:selected="createNFT.archives"
:list="archivesList"
class="text-font-white my-3"
@cellOnChange="(v) => (createNFT.archives = v)"
></app-cell>
<app-cell
text="授权阅读"
type="select"
:selected="createNFT.grant"
:list="grantList"
class="text-font-white my-3"
@cellOnChange="(v) => (createNFT.grant = v)"
></app-cell>
<div class="fixed bottom-0 w-full left-0 flex flex-row z-30"> <div class="fixed bottom-0 w-full left-0 flex flex-row z-30">
<app-btn text="上一步" class=" w-5/12 mx-auto text-font-white rounded-2xl bg-font-blue" border='none' @btnClicked='currentStepChange(-1)'></app-btn> <app-btn
<app-btn text="下一步" class="w-5/12 mx-auto text-font-white rounded-2xl bg-font-blue" border='none' @btnClicked='currentStepChange(1)'></app-btn> text="上一步"
class="w-5/12 mx-auto text-font-white rounded-2xl bg-font-blue"
border="none"
@btnClicked="currentStepChange(-1)"
></app-btn>
<app-btn
text="下一步"
class="w-5/12 mx-auto text-font-white rounded-2xl bg-font-blue"
:disabled="validation"
border="none"
@btnClicked="currentStepChange(1)"
></app-btn>
</div> </div>
</div> </div>
<div class="step-three" v-if="currentStep==3"> <div class="step-three" v-if="currentStep == 3">
<app-cell text='NFT编号' class="text-font-white my-3" @cellOnChange="getValue"></app-cell> <app-cell
<app-cell text='剧本HASH' class="text-font-white my-3" @cellOnChange="getValue"></app-cell> text="NFT编号"
<app-cell text='发行人地址' class="text-font-white my-3" @cellOnChange="getValue"></app-cell> type="showText"
<app-cell text='数量' class="text-font-white my-3" @cellOnChange="getValue"></app-cell> :name="publish.nftId"
class="text-font-white my-3"
></app-cell>
<app-cell
text="剧本HASH"
type="showText"
:name="publish.fileHash"
class="text-font-white my-3"
@cellOnChange="getValue"
></app-cell>
<app-cell
text="发行人地址"
type="showText"
:name="publish.wallet"
class="text-font-white my-3"
@cellOnChange="getValue"
></app-cell>
<app-cell
key="count"
text="数量"
:value="1"
type="input-num"
class="text-font-white my-3"
@cellOnChange="
(v) => {
publish.count = v;
}
"
></app-cell>
<div class="fixed bottom-0 w-full left-0 flex flex-row z-30"> <div class="fixed bottom-0 w-full left-0 flex flex-row z-30">
<app-btn text="上一步" class=" w-5/12 mx-auto text-font-white rounded-2xl bg-font-blue" border='none' @btnClicked='currentStepChange(-1)'></app-btn> <app-btn
<app-btn text="发行NFT" class="w-5/12 mx-auto text-font-white rounded-2xl bg-font-blue" border='none' @btnClicked='currentStepChange(1)'></app-btn> text="上一步"
class="w-5/12 mx-auto text-font-white rounded-2xl bg-font-blue"
border="none"
@btnClicked="currentStepChange(-1)"
></app-btn>
<app-btn
text="发行NFT"
class="w-5/12 mx-auto text-font-white rounded-2xl bg-font-blue"
border="none"
:disabled="validation"
@btnClicked="currentStepChange(1)"
></app-btn>
</div> </div>
</div> </div>
</div> </div>
</Layout-Child> </Layout-Child>
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import Vue from "vue";
import { mapState } from "vuex";
export default Vue.extend({ export default Vue.extend({
data(){ data() {
return{ return {
createNFT:{ a: "",
value_name:'', createNFT: {
value_publisher:'', value_name: "",
value_picker:[], value_publisher: "",
value_des:'' value_picker: [],
}, value_des: "",
// validation:{ archives: 0,
// step_one:true, grant: 0,
// step_two:true, categoryType: NaN,
// step_three:true },
// }, publish: {
nftId: "",
mySteps:[ id: NaN,
fileHash: "",
wallet: "",
count: 1,
},
archivesList: [
{ value: 0, name: "加密存档" },
{ value: 1, name: "不存档" },
],
grantList: [
{ value: 0, name: "不需要授权" },
{ value: 1, name: "需要授权" },
],
categoryTypes: [] as any[],
mySteps: [
{ {
text:'step1' text: "step1",
}, },
{ {
text:'step2' text: "step2",
}, },
{ {
text:'step3' text: "step3",
}, },
], ],
currentStep:1 currentStep: 1,
};
},
components: {
"Layout-Child": () => import("@/layout/Child.vue"),
"app-steps": () => import("@/components/common/Steps.vue"),
"app-cell": () => import("@/components/common/Cell.vue"),
"app-btn": () => import("@/components/common/Btn.vue"),
},
async mounted() {
const list = await this.$service.nftService.getCategory();
this.categoryTypes = list;
this.createNFT.categoryType = (list.length !== 0 && list[0].id) || NaN;
},
computed: {
...mapState("create", {
fileHash: "fileHash",
fileName: "fileName",
file: "file",
pickedList: "pickedList",
}),
validation(): boolean {
let disabled = true;
const { value_name, value_publisher } = this.createNFT;
if (this.currentStep === 1) {
if (
value_name &&
value_publisher &&
this.$store.state.create.pickedList.length !== 0
) {
disabled = false;
}
} else if (this.currentStep === 2) {
if (this.fileHash && this.fileName) {
disabled = false;
}
} else if (this.currentStep === 3) {
disabled = !(this.publish.count > 0);
} }
return disabled;
}, },
components:{ categoryTypes2(): any[] {
'Layout-Child':()=>import('@/layout/Child.vue'), return this.categoryTypes.map((item: any) => {
'app-steps':()=>import('@/components/common/Steps.vue'), return {
'app-cell':()=>import('@/components/common/Cell.vue'), name: item.categoryName,
'app-btn':()=>import('@/components/common/Btn.vue') value: item.id,
}, };
computed:{ });
// validation:function(){ },
// let disabled = true },
// const {value_name,value_publisher } = this.createNFT methods: {
// if(this.currentStep === 1){ setCreateNFT(obj: any) {
// if(value_name&&value_publisher){ this.createNFT = {
// disabled = false ...this.createNFT,
// } ...obj,
// disabled = true };
// } },
// return disabled addStep() {
// } this.currentStep++;
}, },
methods:{ stepOnFinished(e: boolean) {
addStep(){ console.log(e, "finished");
this.currentStep ++ },
}, stepOnChange(e: string) {
stepOnFinished(e:boolean){ console.log(e, "change");
console.log(e,'finished'); },
}, getValue(val: string) {
stepOnChange(e:string){
console.log(e,'change');
},
getValue(val:string){
console.log(val); console.log(val);
}, },
what(item:Function){ what(item: Function) {
item(this.$router.push('/Nft/create/pick')) item(this.$router.push("/Nft/create/pick"));
}, },
currentStepChange(val:number){ async currentStepChange(val: number) {
console.log(1111,this.currentStep, this.mySteps.length+1,this.currentStep + val); if (this.currentStep === 2 && val === 1) {
if(this.currentStep < this.mySteps.length+1){ let mistake = false;
this.currentStep += val try {
const { id, nftId, wallet, fileHash } =
await this.$service.nftService.save(
this.createNFT.value_publisher,
1,
this.fileHash,
this.createNFT.archives,
this.createNFT.value_name,
this.createNFT.value_des,
this.pickedList.map((i: any) => i.id as string).toString(),
this.file,
this.createNFT.grant
);
this.publish.fileHash = fileHash;
this.publish.nftId = nftId;
this.publish.id = id;
this.publish.wallet = wallet;
} catch (err) {
mistake = true;
return;
} }
}, if (mistake) return;
} else if (this.currentStep === 3 && val === 1) {
const ret = await this.$service.nftService.publish({
fileHash: this.fileHash,
id: this.publish.id,
wallet: this.publish.wallet,
nftId: this.publish.nftId,
});
this.$router.back()
}
if (this.currentStep < this.mySteps.length + 1) {
this.currentStep += val;
} }
},
},
}); });
</script> </script>
<template> <template>
<Layout-Child> <Layout-Child>
<div class="pt-6"> <div class="pt-6">
<div class="text-font-red text-sm text-center">*最多支持三个选项</div> <div class="text-font-red text-sm text-center">*最多支持三个选项</div>
<div class=" grid grid-cols-3 w-11/12 mx-auto mt-6"> <div class="grid grid-cols-3 w-11/12 mx-auto mt-6">
<div class="box px-5 py-3" v-for="(i,index) in serviceData" :key="index"> <div
<app-tag :text='i.name' class="text-sm rounded-xl text-font-white bg-app-red" :active='isTagActived(i.id)' @onclick='tagOnclick' :id='i.id'></app-tag> class="box px-5 py-3"
v-for="(i, index) in serviceData"
:key="index"
>
<app-tag
:text="i.name"
class="text-sm rounded-xl text-font-white bg-app-red"
@onclick="tagOnclick"
:active="isActive(i.id)"
:id="i.id"
></app-tag>
</div> </div>
</div> </div>
<div class="fixed bottom-0 w-full left-0 flex flex-row z-30"> <div class="fixed bottom-0 w-full left-0 flex flex-row z-30">
<app-btn text="取消" class=" w-5/12 mx-auto text-font-white rounded-2xl bg-font-blue" border='none' ></app-btn> <app-btn
<app-btn text="确认" class="w-5/12 mx-auto text-font-white rounded-2xl bg-font-blue" border='none' :disabled='pickValid'></app-btn> text="取消"
@btnClicked="clickCancel"
class="w-5/12 mx-auto text-font-white rounded-2xl bg-font-blue"
border="none"
></app-btn>
<app-btn
text="确认"
class="w-5/12 mx-auto text-font-white rounded-2xl bg-font-blue"
border="none"
@btnClicked="clickConfirm"
:disabled="!pickValid"
></app-btn>
</div> </div>
</div> </div>
</Layout-Child> </Layout-Child>
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import Vue from "vue";
import {remove as _remove} from 'lodash'
export default Vue.extend({ export default Vue.extend({
data(){ data() {
return{ return {
picked:[] as Array<{id:number,text:string}>, picked: [] as Array<{ id: number; text: string }>,
serviceData:{}, serviceData: {},
pickValid:true maxNum: 3,
} };
}, },
async mounted(){ async mounted() {
this.serviceData = await this.$service.nftService.getThemeList() this.serviceData = await this.$service.nftService.getThemeList();
}, },
components:{ components: {
'Layout-Child':()=>import('@/layout/Child.vue'), "Layout-Child": () => import("@/layout/Child.vue"),
'app-tag':()=>import('@/components/common/Tag.vue'), "app-tag": () => import("@/components/common/Tag2.vue"),
'app-btn':()=>import('@/components/common/Btn.vue') "app-btn": () => import("@/components/common/Btn.vue"),
}, },
methods: { methods: {
tagOnclick(item:any){ tagOnclick(item: any) {
if(this.picked.includes(item.id)){ if (!!this.picked.find((i) => i.id === item.id)) {
_remove(this.picked,(i)=>{ this.picked = this.picked.filter((i) => i.id !== item.id);
return i === item.id; return;
})
console.log(this.picked,'remove');
return
} }
this.picked.push(item.id) if (this.picked.length >= this.maxNum) {
return;
} }
this.picked.push({
id: item.id,
text: item.text,
});
},
isActive(id: number) {
return !!this.picked.find((i) => i.id === id);
},
clickCancel() {
this.$router.back();
},
clickConfirm() {
this.$store.commit("create/SET_STATE", {
pickedList: this.picked,
});
this.$router.back();
},
},
computed: {
pickValid(): boolean {
return this.picked.length > 0 && this.picked.length <= this.maxNum;
}, },
computed:{
isTagDisabled(){
const that = this;
return function(id:any){
const exist = that.picked.includes(id)
if(that.picked.length>2 || exist){
return true
}
return false
}
}, },
isTagActived(){
const that = this
return function(id:any){
if(that.picked.includes(id)){
return false
}
return true
}
}
}
}); });
</script> </script>
<template>
<Layout-Child class="page-scroll text-center">
<div class="text-font-white mt-20 text-center mb-20">请上传剧本附件</div>
<input
type="file"
id="upload"
class="hidden"
@change="handleFileChange"
ref="inputFile"
accept=".pdf"
/>
<label for="upload">
<div
ref="uploadBox"
class="
upload-box
text-center
flex
items-center
justify-center
mx-auto
text-font-white
"
>
<img
v-if="!fileName"
src="@/assets/icons/upload.png"
alt=""
class="mx-auto"
/>
<img v-else src="@/assets/icons/file.png" alt="" class="mx-auto" />
</div>
</label>
<div class="text-center text-font-white">
<div v-if="!fileName">支持扩展名格式:PDF</div>
<div v-if="fileName">
{{ fileName }}
</div>
<label for="upload">
<div v-if="fileName">重新上传</div>
</label>
</div>
<div class="flex justify-between fixed bottom-0 left-0 right-0">
<app-btn
text="取消"
class="w-5/12 mx-auto text-font-white rounded-2xl bg-font-blue"
border="none"
@btnClicked="$router.back()"
></app-btn>
<app-btn
text="确定"
class="w-5/12 mx-auto text-font-white rounded-2xl bg-font-blue"
border="none"
:disabled="nextBtnDisabled"
@btnClicked="$router.back()"
></app-btn>
</div>
</Layout-Child>
</template>
<script lang="ts">
import { Uploader } from "vant";
import Vue from "vue";
import { mapMutations, mapState } from "vuex";
export default Vue.extend({
data() {
return {};
},
components: {
"Layout-Child": () => import("@/layout/Child.vue"),
"app-btn": () => import("@/components/common/Btn.vue"),
Uploader,
},
computed: {
...mapState("create", ["fileName"]),
nextBtnDisabled(): boolean {
return !this.fileName;
},
},
methods: {
handleFileChange() {
const ele = this.$refs.inputFile as HTMLInputElement;
const files = ele.files;
if (files && files.length >= 1) {
this.afterRead(files[0]);
}
},
...mapMutations("create", {
setState: "SET_STATE",
}),
async afterRead(file: File) {
try {
const ret = await this.$service.nftService.getMd5(file);
this.setState({
fileName: file.name,
fileHash: ret,
file: file
});
} catch (err) {}
},
},
});
</script>
<style scoped>
.upload-box {
width: 140px;
height: 71px;
background: #1d2649;
border-radius: 15px;
border: 1px solid #0078ff;
}
</style>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment