Commit a534e3c8 authored by hanfeng zhang's avatar hanfeng zhang

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

parents 834de053 1a2f5989
......@@ -19,6 +19,7 @@
"html-to-image": "^1.6.2",
"lodash": "^4.17.21",
"md5": "^2.3.0",
"moment": "^2.29.1",
"register-service-worker": "^1.7.1",
"validator": "^13.6.0",
"vant": "^2.12.22",
......
......@@ -29,6 +29,7 @@
<app-icon v-if="icon" :name="icon" class="self-center"></app-icon>
</div>
</div>
<div v-else-if="type == 'input'">
<input
v-model="inputValue"
......@@ -52,7 +53,7 @@
<input
@click="eventEmit(type)"
:disabled="true"
v-if="$store.state.create.pickedList.length === 0"
v-if="!$store.state.create.pickedList || $store.state.create.pickedList.length === 0"
type="text"
class="bg-transparent"
:placeholder="placeholder"
......@@ -193,6 +194,7 @@ export default Vue.extend({
// const temp = this.inputValue;
const value = e.target.value as string;
this.inputValue = value;
this.$emit("cellOnChange", Number(this.inputValue));
},
eventEmit(v: any) {
......@@ -211,7 +213,10 @@ export default Vue.extend({
this.show = true;
}
},
cellOnChange() {
cellOnChange(e:any) {
if(e.target.value && e.target.value.length >= 15) {
this.inputValue = (this.inputValue as string).slice(0,15)
}
this.$emit("cellOnChange", this.inputValue);
},
handleClickCopy(text: string | number) {
......@@ -266,7 +271,7 @@ input[type="password"],
input[type="number"],
textarea {
text-align: right;
padding: 0 25px;
padding: 0 25px 0 0;
}
input:not([type="range"]),
textarea {
......
......@@ -4,7 +4,7 @@ const stateData = {
fileName: '',
file: undefined as undefined | File,
coverName:'',
coverFile: undefined as undefined | File
coverFile: undefined as undefined | File,
}
export type AppType = typeof stateData
......
......@@ -29,11 +29,12 @@
</div>
</div>
</div>
<div class='app-icons w-11/12 mx-auto grid grid-cols-4 gap-4 my-3'>
<div class='app-icons w-11/12 mx-auto grid grid-cols-4 gap-4'>
<div v-for="(i,index) in apps" :key="index" class="flex justify-center">
<div class="flex flex-col items-center gap-y-2">
<div class="flex content-center">
<app-icon :name="i.icon" size='24px' class='p-5 bg-table-light-blue shadow-md rounded-full'></app-icon>
<!-- <app-icon :name="i.icon" size='24px' class='p-5 bg-table-light-blue shadow-md rounded-full'></app-icon> -->
<img :src="i.icon" alt="">
</div>
<div class='text-xs text-font-white'>
{{i.text}}
......@@ -65,25 +66,28 @@
import Vue from 'vue';
import { Badge } from 'vant';
import { token } from '@/util/userInfoUtils'
import anquanzhongxin89 from "../../assets/img/img-anquanzhongxin89.png"
import chakan from "../../assets/img/img-chakan.png"
import atupian from "../../assets/img/img-a-tupian.png"
import bossyingyetingchushi from "../../assets/img/img-BOSS-yingyeting-chushi.png"
Vue.use(Badge)
const apps=[
{
text:'版权授权',
icon:'icon-anquanzhongxin89'
icon: anquanzhongxin89
},
{
text:'区块链浏览器',
icon:'icon-chakan'
icon: chakan
},
{
text:'制片管理',
icon:'icon-a-tupian'
icon: atupian
},
{
text:'我的投资',
icon:'icon-BOSS-yingyeting-chushi'
icon: bossyingyetingchushi
},
]
......
......@@ -11,15 +11,16 @@
<div>影视区块链版权电子数据确权书</div>
</div>
<div>
<img src="/img/cover.png" class=" w-20 xs:w-24 mx-auto mt-4" />
<img v-if="!coverName" src="/img/cover.png" class=" w-20 xs:w-24 mx-auto mt-4" />
<img id="coverImg" :src="showUploadFile" v-else class=" w-20 xs:w-24 mx-auto mt-4" />
</div>
<div class="float-box w-full absolute -bottom-10 text-3xs xs:text-2xs">
<div class="w-11/12 p-2 flex-wrap mx-auto flex break-all bg-font-white shadow-md rounded text-font-black">
<div class="w-full text-left ">
<div>NFT哈希</div>
<div>{{NFTHASH}}</div>
<div>{{certificateData?certificateData.nftId:'无'}}</div>
<div class="pt-1">剧本哈希</div>
<div>{{fileHash}}</div>
<div>{{certificateData?certificateData.fileHash:'无'}}</div>
</div>
</div>
</div>
......@@ -27,27 +28,27 @@
<div class="bot bg-font-white text-font-black px-3 py-10 pt-12 text-3xs xs:text-2xs">
<div class="ceritfy-item flex py-1">
<div class="w-4/12 text-left">剧本名称</div>
<div>{{ name }}</div>
<div class="flex-1 text-left break-all">{{ certificateData?certificateData.value_name:'无'}}</div>
</div>
<div class="ceritfy-item flex py-1">
<div class="w-4/12 text-left">发行人地址</div>
<div>{{ addr }}</div>
<div class="flex-1 text-left break-all">{{ certificateData?certificateData.wallet:'无' }}</div>
</div>
<div class="ceritfy-item flex py-1">
<div class="w-4/12 text-left">发行人</div>
<div>{{ publisher }}</div>
<div class="flex-1 text-left break-all">{{ certificateData?certificateData.value_publisher:'无' }}</div>
</div>
<div class="ceritfy-item flex py-1">
<div class="w-4/12 text-left">存证时间</div>
<div>{{ timeStamp }}</div>
<div class="flex-1 text-left break-all">{{ createTime }}</div>
</div>
<div class="ceritfy-item flex py-1">
<div class="w-4/12 text-left">剧本审核</div>
<div v-if="auditing === 0">剧本未审核</div>
<div class="flex-1 text-left break-all" v-if="auditing === 0">剧本未审核</div>
</div>
<div class="ceritfy-item flex py-1">
<div class="w-4/12 text-left">版权证明</div>
<div v-if="copyRight === 0">版权未审核</div>
<div class="flex-1 text-left break-all" v-if="copyRight === 0">版权未审核</div>
</div>
</div>
</div>
......@@ -59,8 +60,32 @@
<script lang="ts">
import Vue from "vue";
import download from 'downloadjs'
import moment from 'moment'
import { toPng } from 'html-to-image';
import { mapState } from "vuex";
export default Vue.extend({
data(){
return {
createTime: moment(new Date()).format('YYYY-MM-DD hh:mm:ss')
}
},
computed:{
...mapState("create", ["coverFile","coverName"]),
showUploadFile(){
if(this.coverFile) {
return window.URL.createObjectURL(this.coverFile)
}else {
return ''
}
}
},
mounted(){
const fileReader = new FileReader();
fileReader.readAsDataURL(this.coverFile);
fileReader.onload = function (){
(document.getElementById("coverImg") as any).src = fileReader.result;
}
},
props: {
name: {
type: String,
......@@ -93,7 +118,8 @@ export default Vue.extend({
fileHash:{
type:String,
default: "1z9e1beb62e754ff7666hgjggFFHHKJJKKKK5a0ddd7879774757474974"
}
},
certificateData:Object,
},
methods:{
async downloadImg(){
......@@ -108,6 +134,6 @@ export default Vue.extend({
console.error('oops, something went wrong!', error);
});
}
}
},
});
</script>
......@@ -9,6 +9,7 @@
@stepOnFinished="stepOnFinished"
></app-steps>
</div>
<div class="w-11/12 mx-auto">
<div class="step-one" v-if="currentStep == 1">
<app-cell
......@@ -55,6 +56,7 @@
rounded-md
text-sm
"
@input="textareaChange"
></textarea>
</div>
<div class="fixed bottom-0 w-full left-0 z-30">
......@@ -67,6 +69,7 @@
></app-btn>
</div>
</div>
<div class="step-two" v-if="currentStep == 2">
<app-cell
:text="fromText.fileUploadText"
......@@ -74,16 +77,16 @@
type="upload"
:placeholder="fromText.filePlaceholder"
:name="fileName"
@cellOnChange="$router.push({ name: 'NftUpload' })"
@cellOnChange="$router.push({ name: 'NftUpload',params:{type:getPreText()}})"
></app-cell>
<!-- <app-cell
<app-cell
text="封面上传(非必填)"
class="text-font-white my-3"
class="text-font-white my-3 "
type="upload"
placeholder="请上传相关封面"
:name="fileName"
@cellOnChange="$router.push({ name: 'NftUpload' })"
></app-cell> -->
:name="coverName"
@cellOnChange="$router.push({ name: 'NftUpload',params:{type:'封面图片'}})"
></app-cell>
<app-cell
:text="fromText.fileHashText"
class="text-font-white my-3"
......@@ -129,12 +132,13 @@
></app-btn>
</div>
</div>
<div class="step-three" v-if="currentStep == 3">
<app-cell
text="NFT编号"
type="showText"
:name="publish.nftId"
class="text-font-white my-3"
class="text-font-white my-3 break-all"
></app-cell>
<app-cell
:text="fromText.fileHashText"
......@@ -180,6 +184,7 @@
></app-btn>
</div>
</div>
<div v-if="currentStep == 4" class="text-font-white">
<div
v-if="loading4"
......@@ -192,12 +197,12 @@
/>
<div class="mt-6 text-font-white">发行中...</div>
</div>
<div v-else class="text-center">
<div v-if="success" >
<van-overlay :show="showOverlay" class=" full-height flex items-center z-50" >
<div class="w-10/12 mx-auto">
<certificate />
<certificate :certificateData="certificateData"/>
<img
@click='showOverlay = !showOverlay;'
src="@/assets/icons/close_publish.png"
......@@ -214,6 +219,7 @@
<app-btn text="确认" class=' bg-font-blue' @click.native="$router.push('/Home')"></app-btn>
</div>
</div>
<div
v-else
class="flex flex-col items-center w-full pt-16 justify-center"
......@@ -301,6 +307,7 @@ export default Vue.extend({
loading4: false,
success: true,
errorMsg: "",
certificateData:{},
};
},
components: {
......@@ -312,7 +319,6 @@ export default Vue.extend({
BreedingRhombusSpinner
},
async mounted() {
const data = await this.getPreText()
this.fromText = this.concatFormText(data)
const list = await this.$service.nftService.getCategory();
......@@ -336,6 +342,7 @@ export default Vue.extend({
fileName: "fileName",
file: "file",
pickedList: "pickedList",
coverName: 'coverName'
}),
validation(): boolean {
let disabled = true;
......@@ -372,7 +379,6 @@ export default Vue.extend({
setState: "SET_STATE",
}),
getPreText():string{
console.log(this.categoryId,typeof this.categoryId);
switch (this.categoryId) {
case '1':
return '剧本'
......@@ -447,6 +453,7 @@ export default Vue.extend({
.then((ret: any) => {
this.success = ret === true;
this.loading4 = false;
this.certificateData = Object.assign({},this.createNFT,this.publish)
ret !== true && (this.errorMsg = ret);
})
.catch((err) => {
......@@ -519,6 +526,11 @@ export default Vue.extend({
clickRepublish() {
this.currentStep = 1;
},
textareaChange(e:any){
if(e.target.value.length >= 500) {
this.createNFT.value_des = e.target.value.slice(0,500)
}
}
},
});
</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="application/pdf,application/msword,text/plain"
/>
<label for="upload" class="inline-block">
<div class="text-font-white mt-20 text-center mb-20">{{uploadAccept.acceptTitle}}</div>
<input type="file" id="upload" class="hidden" @change="handleFileChange('inputFile')" ref="inputFile" :accept="uploadAccept.acceptType"/>
<input type="file" id="upload" accept="image/*" class=" hidden" ref='localImgElem' @change="handleFileChange('localImgElem')"/>
<input type="file" id="upload" accept="image/*" capture="camera" class=" hidden" ref='cameraElem' @change="handleFileChange('cameraElem')"/>
<van-action-sheet v-model="show" :actions="actions" @select="onSelect" />
<label @click="initUpload" class="inline-block">
<div
ref="uploadBox"
class="
......@@ -23,38 +20,52 @@
"
>
<img
v-if="status === uploadStatus.NULL"
v-if="showNotUploadImg "
src="@/assets/icons/upload.png"
alt=""
class="mx-auto"
/>
<img
v-else-if="status === uploadStatus.success"
src="@/assets/icons/file.png"
v-else-if="showImgUploadImg"
:src="showUploadFile"
alt=""
class="mx-auto"
/>
<Loading type="spiner" v-else-if="status === uploadStatus.uploading" />
<div v-else-if="status === uploadStatus.failed">上传失败</div>
<img
v-else-if="status === uploadStatus.success && uploadType !== '图片' && uploadType !== '封面图片'"
src="@/assets/icons/upload.png"
alt=""
class="mx-auto"
/>
<Loading type="spiner" v-else-if="status === uploadStatus.uploading || coverstatus === uploadStatus.uploading" />
<div v-else-if="status === uploadStatus.failed || coverstatus === uploadStatus.uploading">上传失败</div>
</div>
</label>
<div class="text-center text-font-white">
<div v-if="!fileName" class="mt-2">支持扩展名格式:PDF</div>
<div v-if="fileName" class="mt-2">
{{ fileName }}
<div v-if="(uploadType == '封面图片' && !coverName) || (uploadType !== '封面图片' && !fileName)" class="mt-2">{{uploadAccept.acceptText}}</div>
<div v-else class="mt-2">
{{ (uploadType == '封面图片' && coverName)?coverName:fileName }}
</div>
<!-- <div v-if="uploadType == '封面图片' && coverName" class="mt-2">
{{ coverName }}
</div>
<div v-else-if="uploadType !== '封面图片' && fileName" class="mt-2">
{{ fileName }}
</div> -->
<label for="upload" class="mt-2">
<div
v-if="
status === uploadStatus.failed || status === uploadStatus.success
"
v-if="showReUpload"
style="color: #0076ff"
class="inline-block"
>
重新上传
</div>
</label>
</div>
<div class="flex justify-between fixed bottom-0 left-0 right-0">
<app-btn
text="取消"
......@@ -70,6 +81,7 @@
@btnClicked="$router.back()"
></app-btn>
</div>
</Layout-Child>
</template>
......@@ -79,6 +91,9 @@ import Vue from "vue";
import { Uploader, Loading } from "vant";
import { mapMutations, mapState } from "vuex";
import md5 from "md5";
import { ActionSheet } from 'vant';
Vue.use(ActionSheet);
enum uploadStatus {
NULL,
......@@ -94,7 +109,13 @@ export default Vue.extend({
uploading: false,
uploadStatus,
status: uploadStatus.NULL,
coverstatus: uploadStatus.NULL,
// accept:
show: false,
actions: [
{ name: '本地相册'},
{ name: '拍照'},
],
};
},
components: {
......@@ -104,14 +125,78 @@ export default Vue.extend({
Loading,
},
computed: {
...mapState("create", ["fileName"]),
...mapState("create", ["fileName","coverName",'coverFile','file']),
nextBtnDisabled(): boolean {
return !this.fileName;
if(this.uploadType == '封面图片') {
return !this.coverName
}else {
return !this.fileName;
}
},
uploadType():any{
return this.$route.params.type
},
uploadAccept():object{
switch(this.uploadType){
case '剧本':
return {acceptTitle:'请上传剧本附件',acceptType:'application/pdf,application/msword,text/plain',acceptText:'支持扩展名格式PDF'}
case '视频':
return {acceptTitle:'请上传视频附件',acceptType:'video/*',acceptText:'上传视频仅支持MOV、MP4格式文件,大小限制为100M以内'}
case '电影':
return {acceptTitle:'请上传电影附件',acceptType:'video/*',acceptText:'上传视频仅支持MOV、MP4格式文件,大小限制为100M以内'}
case '音频':
return {acceptTitle:'请上传音频附件',acceptType:"audio/*",acceptText:'上传音频仅支持MP3格式文件'}
case '图片':
return {acceptTitle:'请上传图片附件',acceptType:'image/*',acceptText:'仅支持png、jpg图片'}
case '封面图片':
return {acceptTitle:'请上传封面图片',acceptType:'image/*',acceptText:'仅支持png、jpg图片'}
default:
return {acceptTitle:'',acceptType:'',acceptText:''}
}
},
showUploadFile():string{
if(this.uploadType == '封面图片' && this.coverFile) {
return window.URL.createObjectURL(this.coverFile)
}else if(this.uploadType !== '图片' && this.file) {
return window.URL.createObjectURL(this.file)
}else {
return ''
}
},
showNotUploadImg():boolean{
return (this.uploadType !== '封面图片' && this.status === uploadStatus.NULL) || (this.uploadType == '封面图片' && this.coverstatus === uploadStatus.NULL)
},
showImgUploadImg():boolean{
return (this.status === uploadStatus.success && this.uploadType == '图片') || (this.coverstatus === uploadStatus.success && this.uploadType == '封面图片')
},
showReUpload():boolean{
return ((this.uploadType !== '封面图片') && (this.status === uploadStatus.failed || this.status === uploadStatus.success))||((this.uploadType == '封面图片') && (this.coverstatus === uploadStatus.failed || this.coverstatus === uploadStatus.success))
}
},
methods: {
handleFileChange() {
const ele = this.$refs.inputFile as HTMLInputElement;
initUpload(){
if(this.uploadType == '图片' || this.uploadType == '封面图片') {
this.show = true
}else {
(this.$refs.inputFile as HTMLInputElement).click()
}
},
onSelect(item:any){
this.show = false;
let cEl =this.$refs.cameraElem as HTMLInputElement
let fEl =this.$refs.localImgElem as HTMLInputElement
switch(item.name){
case '拍照':
cEl.click();
break;
case '本地相册':
fEl.click();
break;
}
this.$toast(item.name);
},
handleFileChange(ref:any) {
const ele = this.$refs[ref] as HTMLInputElement;
const files = ele.files;
if (files && files.length >= 1) {
this.afterRead(files[0]);
......@@ -124,21 +209,37 @@ export default Vue.extend({
try {
const ab = await file.arrayBuffer();
const fileMd5 = md5(Buffer.from(ab));
this.status = uploadStatus.uploading;
// const ossRet = await this.$service.nftService.ossPolicy();
// const uploadRet = await this.$service.nftService.uploadFileToOss(
// file,
// ossRet
// );
this.setState({
fileName: file.name,
fileHash: fileMd5,
file: file,
});
this.status = uploadStatus.success;
if(this.uploadType == '封面图片') {
this.coverstatus = uploadStatus.uploading;
this.setState({
coverName: file.name,
coverFile: file,
});
this.coverstatus = uploadStatus.success;
}else {
this.status = uploadStatus.uploading;
this.setState({
fileName: file.name,
fileHash: fileMd5,
file: file,
});
this.status = uploadStatus.success;
}
} catch (err) {
console.log(err, "show err");
this.status = uploadStatus.failed;
if(this.uploadType == '封面图片') {
this.coverstatus = uploadStatus.failed;
}else {
this.status = uploadStatus.failed;
}
}
},
afterRead2(file: any) {
......@@ -153,6 +254,7 @@ export default Vue.extend({
},
});
</script>
<style scoped>
.upload-box {
width: 140px;
......
......@@ -35,7 +35,8 @@
:name="i.icon"
size="24px"
class="p-5 bg-table-light-blue shadow-md rounded-full"
></app-icon>
></app-icon> -->
<img :src="i.icon" alt="">
</div>
<div class="text-xs mt-3 text-font-white">
{{ i.text }}
......@@ -162,23 +163,28 @@
import Vue from "vue";
import SkeletonNftDetail from "@/components/common/Skeleton/SkeletonNftDetail.vue"
import { token } from '@/util/userInfoUtils'
import anquanzhongxin89 from "@/assets/img/img-anquanzhongxin89.png"
import chakan from "@/assets/img/img-chakan.png"
import atupian from "@/assets/img/img-a-tupian.png"
import BOSSyingyetingchushi from "@/assets/img/img-BOSS-yingyeting-chushi.png"
const apps = [
{
text: "版权认证",
icon: "icon-anquanzhongxin89",
icon: anquanzhongxin89,
},
{
text: "大厅下架",
icon: "icon-chakan",
icon: chakan,
},
{
text: "NFT转让",
icon: "icon-a-tupian",
icon: atupian,
action: 'pushToTransfer'
},
{
text: "查看证书",
icon: "icon-BOSS-yingyeting-chushi",
icon: BOSSyingyetingchushi,
},
];
......
<template>
<Layout-Child>
<div class=" w-11/12 mx-auto py-6 text-font-white">
<input type="file" accept="image/*" capture="camera" class="hidden" ref='fileElem2' @change="fileUpload"/>
<input type="file" accept="image/*" class=" hidden" ref='fileElem' @change="fileUpload"/>
<input type="file" accept="image/*" capture="camera" class=" hidden" ref='cameraElem' @change="fileUpload"/>
<input type="file" accept="image/*" class=" hidden" ref='fileElem' @change="fileUpload"/>
<van-action-sheet v-model="show" :actions="actions" @select="onSelect" />
<app-cell text='头像' boxType='border' type='image' :value='avatarImgUrl?avatarImgUrl:this.userInfo.avatar?this.userInfo.avatar : "/img/mokeImg/avatar.png"' icon='icon-xiayibu' @click.native='uploadImg'></app-cell>
<app-cell text='昵称' boxType='border' :value='userInfo.nickname?userInfo.nickname:"无昵称"' icon='icon-xiayibu' @click.native="goEdit({type:'nickname',title:'设置昵称'})"></app-cell>
......@@ -29,8 +29,9 @@ export default Vue.extend({
userInfo:this.$util.userMsg.getUserMsg(),
show:false,
actions: [
{ name: '拍摄头像',router:'/photo' },
{ name: '从图片夹上传',router:'/photoEdit' },
{ name: '拍摄头像',router:'/photo' },
],
file:{},
avatarImgUrl:''
......@@ -60,6 +61,7 @@ export default Vue.extend({
this.show= true
},
async fileUpload(event:any){
this.$toast.loading('头像更新中...')
this.file = event.target.files[0]
// this.$store.commit('app/SET_FILEDATA',event.target.files)
const upload = await this.$service.userService.avatarUpload(event.target.files[0])
......@@ -72,15 +74,15 @@ export default Vue.extend({
},
onSelect(item:any){
this.show = false;
let cEl =this.$refs.cameraElem as HTMLInputElement
let fEl =this.$refs.fileElem as HTMLInputElement
let fEl2 =this.$refs.fileElem as HTMLInputElement
switch(item.name){
case '拍摄头像':
cEl.click();
break;
case '从图片夹上传':
fEl.click();
break;
case '拍摄头像':
fEl2.click();
break;
break;
}
this.$toast(item.name);
}
......
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