山东大学软件学院项目实训-创新实训-角色疆界

本文介绍项目前端功能之文件上传的设计开发流程

一、站在巨人的肩膀上:设计参考

可以看出来文件上传按钮一般设置在输入框旁边(当然一般也不会设置在别的地方...),同时一般用图标表达“上传文件”的信息,美观而又易懂。

可以看出来文件上传之后放在了输入框的上部,有图标为衬更加美观,以及有文件相关信息的介绍如文件名、后缀、文件大小等。同时右上角都有小叉叉用以删除上传的文件。

携带文件发送提问时文件信息也要展示。

二、功能分解

1、样式设计:如上述,包括按钮位置、图标、文件信息展示等

2、文件上传按钮:点击按钮能够打开文件选择器选择文件

3、文件信息展示与管理:存在已上传的文件应能展示,应展示已上传的文件的文件名等信息,允许删除上传的文件

4、聊天框文件展示:在携带文件发送提问后,在聊天框应能展示文件的信息

三、解决方案与代码编写

1、样式设计与效果展示:相关图标使用的是Font awesome svg图标库。代码直接复制svg部分即可使用

2、文件上传按钮:支持多文件上传

  • 放置了一个button用于交互提示,一个隐藏状态的input用于打开文件选择器,同时button响应点击事件去触发input以打开文件选择器。
    <button @click.stop.prevent="openFileSelector" class="absolute p-1 rounded-md text-gray-500 bottom-1.5 left-1 md:bottom-2.5 md:left-2 hover:bg-gray-100 dark:hover:text-gray-400 dark:hover:bg-gray-900 disabled:hover:bg-transparent dark:disabled:hover:bg-transparent">
        <svg data-v-11241ba2="" aria-hidden="true" focusable="false" data-prefix="fas" data-icon="folder-open" role="img" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" class="svg-inline--fa fa-folder-open fa-w-18">
            <path data-v-11241ba2="" fill="currentColor" d="M572.694 292.093L500.27 416.248A63.997 63.997 0 0 1 444.989 448H45.025c-18.523 0-30.064-20.093-20.731-36.093l72.424-124.155A64 64 0 0 1 152 256h399.964c18.523 0 30.064 20.093 20.73 36.093zM152 224h328v-48c0-26.51-21.49-48-48-48H272l-64-64H48C21.49 64 0 85.49 0 112v278.046l69.077-118.418C86.214 242.25 117.989 224 152 224z" class="" data-darkreader-inline-fill="" style="--darkreader-inline-fill:currentColor;"></path>
        </svg>
    </button>
    <input type="file" ref="fileInput" @change="handleFileSelection" accept=".doc,.docx,.txt,.pdf,.png,.jpg" style="display: none;" multiple="multiple">

3、输入框文件信息展示:

  • 首先需要设置一个变量用于存储上传的文件,作为之后文件信息展示的基础
    data(){
        return{
            ......
            file_list:{},     //存储打开的文件
            now_file_num:0,   //当前打开文件数
            max_file_num:9,   //最大上传文件数
        }
    }
  • 定义一个函数处理上传文件这一事件,input组件绑定到这一函数上来
    handleFileSelection(event) {
        // 获取选择的文件
        const files = event.target.files; 
        var now_file_num=this.now_file_num;
        //判断文件数是否超限
        if((now_file_num+files.length)>this.max_file_num){
            alert(`最多允许上传${this.max_file_num}个文件哦!还可以上传${this.max_file_num-now_file_num}个文件`);
            return;
        }
        for(let i=0;i<files.length;i++){
            // 将选择的文件存储,将时间戳作为唯一id
            this.file_list[Date.now().toString(36)+i]=files[i]; 
            now_file_num++;
        }
        this.now_file_num=now_file_num;
        this.$refs.fileInput.value = "";    
    },
  • 文件信息的展示、文件删除,关键在于布局设置,力求和谐美观
    <div v-show="now_file_num>0"  class="flex flex-row gap-2 w-full py-2 flex-grow md:py-3 md:pl-4 relative border border-black/10 bg-white dark:border-gray-900/50 dark:text-white dark:bg-gray-700 rounded-md shadow-[0_0_10px_rgba(0,0,0,0.10)] dark:shadow-[0_0_15px_rgba(0,0,0,0.10)]" >
        <div v-for="(file,file_id,index) in file_list" :key="index" style="display: flex; align-items: center; width: calc(1/10 * 100%); position: relative; padding: 8px; " class="bg-gray-200 rounded-lg">
            <svg data-v-11241ba2="" aria-hidden="true" focusable="false" data-prefix="fas" data-icon="file" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512" class="svg-inline--fa fa-file fa-w-12" height="1em" width="1em">
            <path data-v-11241ba2="" fill="currentColor" d="M224 136V0H24C10.7 0 0 10.7 0 24v464c0 13.3 10.7 24 24 24h336c13.3 0 24-10.7 24-24V160H248c-13.2 0-24-10.8-24-24zm160-14.1v6.1H256V0h6.1c6.4 0 12.5 2.5 17 7l97.9 98c4.5 4.5 7 10.6 7 16.9z" class="" data-darkreader-inline-fill="" style="--darkreader-inline-fill:currentColor;"></path>
            </svg>
            <!--文件信息框-->
            <div class="file-info text-gray-600" style="margin-left: 10px; flex-grow: 1; display: flex; flex-direction: column;overflow:hidden;width: calc(3/4 * 100%);height: 40px; padding:1px;">
            <!-- 文件名 -->
            <span style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis;max-width:100%;line-height: 20px;">{{ fileNameWithoutExtension(file?.name) }}</span>
            <!-- 文件扩展 -->
            <span style="line-height: 20px;">{{ fileExtension(file?.name) }}</span>
            </div>
            <!--删除文件按钮-->
            <button @click.stop.prevent="deleteFile(file_id)" class="btn-right-top dark:hover:text-gray-400 dark:hover:bg-gray-900 disabled:hover:bg-transparent dark:disabled:hover:bg-transparent" style="position: absolute;top:0;right:0;">
            <svg data-v-11241ba2="" aria-hidden="true" focusable="false" data-prefix="far" data-icon="times-circle" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="svg-inline--fa fa-times-circle fa-w-16" height="1em" width="1em">
                <path data-v-11241ba2="" fill="currentColor" d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm0 448c-110.5 0-200-89.5-200-200S145.5 56 256 56s200 89.5 200 200-89.5 200-200 200zm101.8-262.2L295.6 256l62.2 62.2c4.7 4.7 4.7 12.3 0 17l-22.6 22.6c-4.7 4.7-12.3 4.7-17 0L256 295.6l-62.2 62.2c-4.7 4.7-12.3 4.7-17 0l-22.6-22.6c-4.7-4.7-4.7-12.3 0-17l62.2-62.2-62.2-62.2c-4.7-4.7-4.7-12.3 0-17l22.6-22.6c4.7-4.7 12.3-4.7 17 0l62.2 62.2 62.2-62.2c4.7-4.7 12.3-4.7 17 0l22.6 22.6c4.7 4.7 4.7 12.3 0 17z" class="" data-darkreader-inline-fill="" style="--darkreader-inline-fill:currentColor;"></path>
            </svg>
            </button>
        </div>
    </div>

    效果:

4、发送消息后,聊天框文件信息展示,表示该消息是带有文件的,但是不负责具体的文件管理。关键也是布局设置,力求和谐美观

<div v-show="conv.has_file">        <!--若聊天信息有文件则展示-->
    <div class="flex flex-row gap-2 w-full py-2 md:py-3 md:pl-4 relative border border-black/10 bg-white dark:border-gray-900/50 dark:text-white dark:bg-gray-700 rounded-md shadow-[0_0_10px_rgba(0,0,0,0.10)] dark:shadow-[0_0_15px_rgba(0,0,0,0.10)]" >
        <div v-for="(file,file_id,index) in conv.file_list" :key="index" style="display: inline-flex; align-items: center;  width: calc(10%); padding: 8px;" class="bg-gray-200 rounded-lg ">
        <!--图标-->
        <svg data-v-11241ba2="" aria-hidden="true" focusable="false" data-prefix="fas" data-icon="file" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512" class="svg-inline--fa fa-file fa-w-12" height="1em" width="1em">
            <path data-v-11241ba2="" fill="currentColor" d="M224 136V0H24C10.7 0 0 10.7 0 24v464c0 13.3 10.7 24 24 24h336c13.3 0 24-10.7 24-24V160H248c-13.2 0-24-10.8-24-24zm160-14.1v6.1H256V0h6.1c6.4 0 12.5 2.5 17 7l97.9 98c4.5 4.5 7 10.6 7 16.9z" class="" data-darkreader-inline-fill="" style="--darkreader-inline-fill:currentColor;"></path>
        </svg>
        <!--文件信息框-->
        <div class="file-info text-gray-600" style="margin-left: 10px;  display: inline-flex;  overflow: hidden; padding: 1px;width: calc(3/4 * 100%)">
            <span style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis; vertical-align: middle;min-width: 100px;">{{ file||index }}</span>
        </div>
        </div>
    </div>
</div>

效果:

至此大功告成。最麻烦耗时的还是样式的不居中、不对齐、撑大、缩小等问题,需要不断判断调试、追根溯源、解决问题,代码逻辑倒在其次。

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值