123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597 |
- <template>
- <div>
- <div v-if="type !== 'callback'" class="imgcomp-upload-list" v-for="item in uploadList">
- <template v-if="item.status === 'finished'">
- <div class="imgcomp-upload-img" v-bind:style="{ 'background-image': 'url(' + __thumb(item.thumb) + ')' }"></div>
- <div class="imgcomp-upload-list-cover">
- <Icon type="ios-eye-outline" @click.native="handleView(item)"></Icon>
- <Icon type="ios-trash-outline" @click.native="handleRemove(item)"></Icon>
- </div>
- </template>
- <template v-else>
- <Progress v-if="item.showProgress" :percent="item.percentage" hide-info></Progress>
- </template>
- </div>
- <div class="add-box" v-bind:class="{ 'callback-add-box': type === 'callback' }">
- <div class="add-box-icon">
- <Icon type="md-add" size="32"></Icon>
- </div>
- <div class="add-box-upload">
- <div class="add-box-item" @click="browsePicture">
- <span>{{$L('浏览')}}<em v-if="type === 'callback'">{{$L('图片')}}</em></span>
- </div>
- <div class="add-box-item">
- <Upload
- name="image"
- ref="upload"
- accept="image/*"
- :action="actionUrl"
- :data="uploadParams"
- :show-upload-list="false"
- :max-size="maxSize"
- :format="['jpg', 'jpeg', 'gif', 'png']"
- :default-file-list="defaultList"
- :on-progress="handleProgress"
- :on-success="handleSuccess"
- :on-error="handleError"
- :on-format-error="handleFormatError"
- :on-exceeded-size="handleMaxSize"
- :before-upload="handleBeforeUpload"
- :multiple=multiple>
- <span>{{$L('上传')}}<em v-if="type === 'callback'">{{$L('图片')}}</em></span>
- </Upload>
- </div>
- </div>
- </div>
- <Modal :title="$L('浏览图片空间的图片')" v-model="browseVisible" class="img-upload-modal" class-name="simple-modal" width="710" :styles="{top: '35px',paddingBottom: '35px'}">
- <div class="browse-load" v-if="isLoading">{{$L('加载中...')}}</div>
- <div class="browse-list" :class="httpType==='input'?'browse-list-disabled':''" ref="browselistbox">
- <div class="browse-item" v-for="item in browseList" @click="browseItem(item)">
- <Icon v-if="item.active" class="browse-icon" type="ios-checkmark-circle"></Icon>
- <div class="browse-img" v-bind:style="{ 'background-image': 'url(' + item.thumb + ')' }"></div>
- <div class="browse-title">{{item.title}}</div>
- </div>
- </div>
- <div slot="footer" class="img-upload-foot">
- <div v-if="type !== 'callback' && http && httpType===''" class="img-upload-foot-input" @click="httpType='input'">
- <Icon type="ios-image" size="22"/>
- <div class="img-upload-foot-httptitle">{{$L('自定义图片地址')}}</div>
- </div>
- <div v-if="type !== 'callback' && http && httpType==='input'" class="img-upload-foot-input">
- <Input v-model="httpValue" :placeholder="$L('以“http://”或“https://”开头')" @on-search="httpEnter" search :enter-button="$L('确定')">
- <span slot="prepend" @click="httpType=''" style="cursor:pointer">{{$L('自定义地址')}}: </span>
- </Input>
- </div>
- <Button v-if="httpType===''" @click="browseVisible=false">{{$L('关闭')}}</Button>
- <Button v-if="httpType===''" type="primary" @click="handleCallback(true)">{{$L('完成')}}</Button>
- </div>
- </Modal>
- <Modal :title="$L('查看图片')" v-model="visible" class="img-upload-modal" class-name="simple-modal" draggable>
- <div style="max-height:480px;overflow:auto;">
- <a :href="imgVisible" target="_blank"><img :src="imgVisible" v-if="visible" style="max-width:100%;max-height:900px;display:block;margin:0 auto"></a>
- </div>
- </Modal>
- </div>
- </template>
- <style lang="scss">
- .img-upload-modal {
- .ivu-modal-mask {
- z-index: 1001;
- }
- .ivu-modal-no-mask {
- background-color: rgba(55,55,55,.2);
- }
- .ivu-modal-wrap {
- z-index: 1001;
- }
- }
- .imgcomp-upload-list{
- display: inline-block;
- width: 60px;
- height: 60px;
- text-align: center;
- line-height: 60px;
- border: 1px solid transparent;
- border-radius: 4px;
- overflow: hidden;
- background: #fff;
- position: relative;
- box-shadow: 0 1px 1px rgba(0,0,0,.2);
- margin-right: 4px;
- vertical-align: top;
- .imgcomp-upload-img {
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- background-position: center;
- background-size: cover;
- }
- .imgcomp-upload-list-cover{
- display: none;
- position: absolute;
- top: 0;
- bottom: 0;
- left: 0;
- right: 0;
- background: rgba(0,0,0,.6);
- }
- .imgcomp-upload-list-cover i{
- color: #fff;
- font-size: 24px;
- cursor: pointer;
- vertical-align: middle;
- margin: 0;
- transition: all .2s;
- }
- .imgcomp-upload-list-cover i:hover{
- font-size: 28px;
- }
- .ivu-progress-outer {
- background-color: rgba(0, 0, 0, 0.68);
- .ivu-progress-inner{
- width: 88%;
- }
- }
- }
- .imgcomp-upload-list:hover .imgcomp-upload-list-cover{
- display: block;
- }
- .img-upload-foot {
- display: flex;
- align-items: center;
- justify-content: flex-end;
- .img-upload-foot-input {
- flex: 1;
- text-align: left;
- display: flex;
- align-items: center;
- justify-content: flex-end;
- .img-upload-foot-httptitle {
- cursor: pointer;
- padding-left: 3px;
- margin-right: 22px;
- }
- }
- }
- .add-box {
- width: 60px;
- height: 60px;
- line-height: 60px;
- display: inline-block;
- background: #fff;
- border: 1px dashed #dddee1;
- border-radius: 4px;
- text-align: center;
- position: relative;
- overflow: hidden;
- vertical-align: top;
- .add-box-icon {
- i {
- vertical-align:middle;
- padding-bottom: 2px;
- }
- }
- .add-box-upload {
- display: none;
- position: absolute;
- top: 0;
- left: 0;
- height: 100%;
- width: 100%;
- color: #ffffff;
- padding-top: 9px;
- background: rgba(0, 0, 0, 0.6);
- .add-box-item {
- height: 22px;
- line-height: 22px;
- cursor: pointer;
- .ivu-upload-drag,.ivu-upload-drag:hover {
- background:transparent;
- border:0;
- border-radius:0;
- }
- span {
- transition: all .2s;
- font-size: 12px;
- }
- }
- .add-box-item:hover {
- span {
- font-size: 14px;
- }
- }
- }
- em {
- font-style: normal;
- }
- }
- .add-box:hover {
- border-color: rgba(0,0,0,.6);
- .add-box-upload {
- display: block;
- }
- }
- .callback-add-box {
- display: block;
- width: auto;
- height: 25px;
- line-height: 25px;
- border: 0;
- background: transparent;
- .add-box-icon {
- display: none;
- }
- .add-box-upload {
- display: block;
- width: auto;
- background: transparent;
- color: #333;
- padding: 0;
- > div {
- display: inline-block;
- padding-right: 10px;
- }
- }
- }
- .browse-load {
- margin: 20px;
- text-align: center;
- }
- .browse-list {
- max-height: 540px;
- overflow: auto;
- .browse-item {
- margin: 10px 15px;
- display: inline-block;
- text-align: center;
- cursor: pointer;
- position: relative;
- .browse-img {
- width: 64px;
- height: 64px;
- background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKoAAABxCAAAAABg5GeyAAACW0lEQVR4Ae3XVRLjMBAE0L3/rSwKM3OcSNPyLVYOLvM6UD0Bd03LVe9XH+RlhlRSSSWVVFJJJZVUUkkllVRSSSWVVFJJJZVUUkl9WyqppJJKKqmkkgpURP17xngOAR5NxW5wlJ9MaLQh83F4NHWmd/gZtdVBaOldfDB1bq5UpJFbFOC6LKnYrkRO209PAw+hIuzWB8Ep5es8HvYo4z4tE1X8UeRwlMM2D5Bzkc7kj6Bi3VTKDDwEeUcrMxrUvGDXTnHa6kK69SDN9sgq1clxKSbNHqqnYmdri81Q9QHf1JPt1Frncaib2XbiTKL2GkHaurnY9LOulMV0O7G6Kw+g9sw2ohhm62KezVJaaufjWC1TnOkr1exilJ7Ji0vxCCqO9V4UwV4PYr9+apouhGYLKfnahdpqegjmeoXOpXgANe70pKT6Zhu19qkY2nC0PZS527lQOyInqr8Uvc5jqfUb1X+PGh5IhW90S2quh3FQC2XRcF66TUkTXPcLKm5FtdR9RJq+2hWII7UpFtmsQLEyzsdJtkxxpr6gLotbUSlV9yeT0Trmzk2XPdUThLYarUbWOY9j04xXQ2u+pMZLYSumGmNUH3HbM9qOAwSHodN2Pks25F2j3aI7+IxqNsB+YLWb16ukSjiW4xNB0gMoMfApBS/XZQgi3p9/5RsiKNKZEOwYFVIF5VyTyD19sbyjIJiNJRZxpNbx2S8sGKvGZNHJBniBu9Wy5WxjGuQFqIAcBHiRGyt4ua5gSCWVVFJJJZVUUkkllVRSSSWVVFJJJZVUUkkllVRSSSWVVFI/AgO0SXIVYHeGAAAAAElFTkSuQmCC);
- background-position: center;
- background-repeat: no-repeat;
- background-size: cover;
- }
- .browse-title {
- display: block;
- width: 64px;
- margin-top: 5px;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- }
- .browse-icon {
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 64px;
- font-size: 36px;
- padding-top: 15px;
- color: #ffffff;
- background-color: rgba(0, 0, 0, 0.5);
- }
- }
- }
- .browse-list-disabled {
- position: relative;
- }
- .browse-list-disabled:after {
- position: absolute;
- content: '';
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- background-color: rgba(255, 255, 255, 0.9);
- z-index: 1;
- }
- </style>
- <script>
- export default {
- name: 'ImgUpload',
- props: {
- value: {
- },
- num: {
- },
- width: {
- },
- height: {
- },
- type: {
- },
- http: {
- type: Boolean,
- default: false
- },
- otherParams: {
- type: Object,
- default: () => {
- return {};
- }
- },
- uploadIng: {
- type: Number,
- default: 0
- }
- },
- data () {
- return {
- actionUrl: $A.apiUrl('system/imgupload'),
- params: {
- token: $A.getToken(),
- width: this.width,
- height: this.height
- },
- multiple: this.num > 1,
- visible: false,
- browseVisible: false,
- isLoading: false,
- browseList: [],
- browseListNext: [],
- imgVisible: '',
- defaultList: this.initItems(this.value),
- uploadList: [],
- maxNum: Math.min(Math.max($A.runNum(this.num), 1), 99),
- httpValue: '',
- httpType: '',
- maxSize: 204800
- }
- },
- mounted () {
- this.uploadList = this.$refs.upload.fileList;
- this.$emit('input', this.uploadList);
- //
- let browseBox = $A(this.$refs.browselistbox);
- browseBox.scroll(()=>{
- let nHight = browseBox[0].scrollHeight;
- let nTop = browseBox[0].scrollTop;
- let boxHight = browseBox.height();
- if(nTop + boxHight >= nHight) {
- //到底了
- if (this.browseListNext.length > 0) {
- let tmpNext = this.browseListNext;
- this.browseListNext = [];
- this.browsePictureFor(tmpNext);
- }
- }
- });
- },
- watch: {
- value (val) {
- if (typeof val === 'string') {
- this.$emit('input', this.initItems(val));
- return;
- }
- if (val === this.$refs.upload.fileList) {
- return;
- }
- this.$refs.upload.fileList = this.initItems(val);
- this.uploadList = this.$refs.upload.fileList;
- },
- browseVisible() {
- this.httpType = '';
- this.httpValue = '';
- }
- },
- computed: {
- uploadParams() {
- if (Object.keys(this.otherParams).length > 0) {
- return Object.assign(this.params, this.otherParams);
- } else {
- return this.params;
- }
- }
- },
- methods: {
- handleCallback(file) {
- if (this.type === 'callback') {
- if (file === true) {
- this.$emit('on-callback', this.uploadList);
- this.$refs.upload.fileList = [];
- this.uploadList = this.$refs.upload.fileList;
- }else if (typeof file === "object") {
- this.$emit('on-callback', [file]);
- }
- }
- this.browseVisible = false;
- },
- initItems(items) {
- //数据初始化
- if (typeof items === 'string') {
- items = [{'url': items}];
- }
- let lists = [];
- $A.each(items, (index, item)=>{
- if (typeof item === 'string') item = {'url': item};
- if (item.url) {
- item.active = true;
- item.status = 'finished';
- if (typeof item.path === 'undefined') item.path = item.url;
- if (typeof item.thumb === 'undefined') item.thumb = item.url;
- lists.push(item);
- }
- });
- return lists;
- },
- handleView (item) {
- //查看
- this.visible = true;
- this.imgVisible = item.url;
- },
- handleRemove (item) {
- //删除
- let fileList = this.$refs.upload.fileList;
- this.$refs.upload.fileList.splice(fileList.indexOf(item), 1);
- this.$emit('input', this.$refs.upload.fileList);
- },
- handleProgress() {
- //开始上传
- this.$emit('update:uploadIng', this.uploadIng + 1);
- },
- handleSuccess (res, file) {
- //上传完成
- this.$emit('update:uploadIng', this.uploadIng - 1);
- if (res.ret === 1) {
- file.url = res.data.url;
- file.path = res.data.path;
- file.thumb = res.data.thumb;
- this.handleCallback(file);
- }else{
- this.$Modal.warning({
- title: this.$L('上传失败'),
- content: this.$L('文件 % 上传失败 %', file.name, res.msg)
- });
- this.$refs.upload.fileList.pop();
- }
- this.$emit('input', this.$refs.upload.fileList);
- },
- handleError() {
- //上传错误
- this.$emit('update:uploadIng', this.uploadIng - 1);
- },
- handleFormatError (file) {
- //上传类型错误
- this.$Modal.warning({
- title: this.$L('文件格式不正确'),
- content: this.$L('文件 % 格式不正确,请上传 jpg、jpeg、gif、png 格式的图片。', file.name)
- });
- },
- handleMaxSize (file) {
- //上传大小错误
- this.$Modal.warning({
- title: this.$L('超出文件大小限制'),
- content: this.$L('文件 % 太大,不能超过%。', file.name, $A.bytesToSize(this.maxSize * 1024))
- });
- },
- handleBeforeUpload () {
- //上传前判断
- let check = this.uploadList.length < this.maxNum;
- if (!check && this.uploadList.length == 1) {
- this.handleRemove(this.uploadList[0]);
- check = this.uploadList.length < this.maxNum;
- }
- if (!check) {
- this.$Modal.warning({
- title: this.$L('温馨提示'),
- content: this.$L('最多只能上传 % 张图片。', this.maxNum)
- });
- }
- this.params = {
- token: $A.getToken(),
- width: this.width,
- height: this.height
- };
- return check;
- },
- handleClick() {
- //手动上传
- if (this.handleBeforeUpload()) {
- this.$refs.upload.handleClick()
- }
- },
- handleManual(file) {
- //手动传file
- if (this.handleBeforeUpload()) {
- this.$refs.upload.upload(file);
- }
- },
- browsePicture(path) {
- //获取图片空间
- this.browseVisible = true;
- this.browseList = [];
- this.browseListNext = [];
- this.isLoading = true;
- $A.apiAjax({
- url: 'system/imgview',
- data: { path: path?path:'' },
- beforeSend: true,
- complete: true,
- error: true,
- success: (res) => {
- this.isLoading = false;
- if (res.ret === 1) {
- let dirs = res.data['dirs'];
- for (let i = 0; i < dirs.length; i++) {
- this.browseList.push(dirs[i]);
- }
- this.browsePictureFor(res.data['files']);
- }else if (res.ret === -2) {
- this.browseVisible = false;
- this.$Modal.warning({ title: this.$L('温馨提示'), content: res.msg });
- }
- }
- });
- },
- browsePictureFor(files) {
- for (let o = 0; o < files.length; o++) {
- for (let j = 0; j < this.uploadList.length; j++) {
- if (this.uploadList[j]['url'] === files[o]['url']
- || this.uploadList[j]['url'] === files[o]['path']) {
- files[o]['active'] = true;
- break;
- }
- }
- if (o < 100) {
- this.browseList.push(files[o]);
- }else{
- this.browseListNext.push(files[o]);
- }
- }
- },
- browseItem(item) {
- //点击选择图片
- if (item.type === 'dir') {
- //目录
- this.browsePicture(item.path);
- }else if (item.type === 'file') {
- //文件
- if (item.active) {
- let fileList = this.$refs.upload.fileList;
- this.$refs.upload.fileList.splice(fileList.indexOf(item), 1);
- item.active = false;
- }else{
- if (this.maxNum === 1) {
- for (let i = 0; i < this.browseList.length; i++) {
- this.browseList[i].active = false;
- }
- this.$refs.upload.fileList = [];
- this.uploadList = this.$refs.upload.fileList;
- }
- let check = this.uploadList.length < this.maxNum;
- if (!check) {
- this.$Modal.warning({ title: this.$L('温馨提示'), content: this.$L('最多只能选择 % 张图片。', this.maxNum) });
- return;
- }
- item.active = true;
- item.status = 'finished';
- this.$refs.upload.fileList.push(item);
- this.uploadList = this.$refs.upload.fileList;
- }
- this.$emit('input', this.$refs.upload.fileList);
- }
- },
- __thumb(url) {
- if ($A.strExists(url, "?", false)) {
- return url + "&__thumb=true";
- }else{
- return url + "?__thumb=true";
- }
- },
- httpEnter() {
- this.$emit('input', this.initItems(this.httpValue));
- this.browseVisible = false;
- }
- }
- }
- </script>
|