Commit 974361041a024011915ce56c2363b3fc0042fbf3

Authored by xingyu
1 parent 0e6c1870

refactor

yudao-ui-admin-vue3/src/views/Profile/components/UserAvatar.vue
1 <template> 1 <template>
2 <div class="user-info-head" @click="editCropper()"> 2 <div class="user-info-head" @click="editCropper()">
3 - <img :src="options.options.img" title="点击上传头像" class="img-circle img-lg" alt="" /> 3 + <img :src="props.img" title="点击上传头像" class="img-circle img-lg" alt="" />
4 </div> 4 </div>
5 <el-dialog 5 <el-dialog
6 v-model="dialogVisible" 6 v-model="dialogVisible"
7 title="编辑头像" 7 title="编辑头像"
  8 + :mask-closable="false"
8 width="800px" 9 width="800px"
9 append-to-body 10 append-to-body
10 - style="padding: 30px 20px"  
11 - @opened="modalOpened" 11 + @opened="cropperVisible = true"
12 > 12 >
13 <el-row> 13 <el-row>
14 - <el-col :xs="24" :md="12" style="height: 350px"> 14 + <el-col :xs="24" :md="12" :style="{ height: '350px' }">
15 <VueCropper 15 <VueCropper
16 ref="cropper" 16 ref="cropper"
17 v-if="cropperVisible" 17 v-if="cropperVisible"
18 - :img="options.options.img" 18 + :img="options.img"
19 :info="true" 19 :info="true"
20 - :autoCrop="options.options.autoCrop"  
21 - :autoCropWidth="options.options.autoCropWidth"  
22 - :autoCropHeight="options.options.autoCropHeight"  
23 - :fixedBox="options.options.fixedBox"  
24 - @real-time="realTime" 20 + :infoTrue="options.infoTrue"
  21 + :autoCrop="options.autoCrop"
  22 + :autoCropWidth="options.autoCropWidth"
  23 + :autoCropHeight="options.autoCropHeight"
  24 + :fixedNumber="options.fixedNumber"
  25 + :fixedBox="options.fixedBox"
  26 + :centerBox="options.centerBox"
  27 + @realTime="realTime"
25 /> 28 />
26 </el-col> 29 </el-col>
27 - <el-col :xs="24" :md="12" style="height: 350px"> 30 + <el-col :xs="24" :md="12" :style="{ height: '350px' }">
28 <div 31 <div
29 class="avatar-upload-preview" 32 class="avatar-upload-preview"
30 :style="{ 33 :style="{
31 - width: options.previews.w + 'px',  
32 - height: options.previews.h + 'px', 34 + width: previews.w + 'px',
  35 + height: previews.h + 'px',
33 overflow: 'hidden', 36 overflow: 'hidden',
34 margin: '5px' 37 margin: '5px'
35 }" 38 }"
36 > 39 >
37 - <div :style="options.previews.div">  
38 - <img  
39 - :src="options.previews.url"  
40 - :style="options.previews.img"  
41 - style="!max-width: 100%"  
42 - alt=""  
43 - /> 40 + <div :style="previews.div">
  41 + <img :src="previews.url" :style="previews.img" style="!max-width: 100%" alt="" />
44 </div> 42 </div>
45 </div> 43 </div>
46 </el-col> 44 </el-col>
@@ -88,9 +86,9 @@ @@ -88,9 +86,9 @@
88 </el-dialog> 86 </el-dialog>
89 </template> 87 </template>
90 <script setup lang="ts"> 88 <script setup lang="ts">
91 -import { ref, reactive, watch } from 'vue' 89 +import { ref, reactive, watch, Ref, UnwrapNestedRefs } from 'vue'
92 import 'vue-cropper/dist/index.css' 90 import 'vue-cropper/dist/index.css'
93 -import { VueCropper } from 'vue-cropper' 91 +import VueCropper from 'vue-cropper/lib/vue-cropper.vue'
94 import { ElRow, ElCol, ElUpload, ElMessage, ElDialog } from 'element-plus' 92 import { ElRow, ElCol, ElUpload, ElMessage, ElDialog } from 'element-plus'
95 import { propTypes } from '@/utils/propTypes' 93 import { propTypes } from '@/utils/propTypes'
96 import { uploadAvatarApi } from '@/api/system/user/profile' 94 import { uploadAvatarApi } from '@/api/system/user/profile'
@@ -101,30 +99,47 @@ const cropperVisible = ref(false) @@ -101,30 +99,47 @@ const cropperVisible = ref(false)
101 const props = defineProps({ 99 const props = defineProps({
102 img: propTypes.string.def('') 100 img: propTypes.string.def('')
103 }) 101 })
104 -const options = reactive({  
105 - options: {  
106 - img: props.img, //裁剪图片的地址  
107 - autoCrop: true, // 是否默认生成截图框  
108 - autoCropWidth: 200, // 默认生成截图框宽度  
109 - autoCropHeight: 200, // 默认生成截图框高度  
110 - fixedBox: true // 固定截图框大小 不允许改变  
111 - },  
112 - previews: {  
113 - img: '',  
114 - url: '',  
115 - w: 0,  
116 - h: 0,  
117 - div: ''  
118 - } 102 +interface Options {
  103 + img: string | ArrayBuffer | null // 裁剪图片的地址
  104 + info: true // 裁剪框的大小信息
  105 + outputSize: number // 裁剪生成图片的质量 [1至0.1]
  106 + outputType: 'jpeg' // 裁剪生成图片的格式
  107 + canScale: boolean // 图片是否允许滚轮缩放
  108 + autoCrop: boolean // 是否默认生成截图框
  109 + autoCropWidth: number // 默认生成截图框宽度
  110 + autoCropHeight: number // 默认生成截图框高度
  111 + fixedBox: boolean // 固定截图框大小 不允许改变
  112 + fixed: boolean // 是否开启截图框宽高固定比例
  113 + fixedNumber: Array<number> // 截图框的宽高比例 需要配合centerBox一起使用才能生效
  114 + full: boolean // 是否输出原图比例的截图
  115 + canMoveBox: boolean // 截图框能否拖动
  116 + original: boolean // 上传图片按照原始比例渲染
  117 + centerBox: boolean // 截图框是否被限制在图片里面
  118 + infoTrue: boolean // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
  119 +}
  120 +const options: UnwrapNestedRefs<Options> = reactive({
  121 + img: '', // 需要剪裁的图片
  122 + autoCrop: true, // 是否默认生成截图框
  123 + autoCropWidth: 200, // 默认生成截图框的宽度
  124 + autoCropHeight: 200, // 默认生成截图框的长度
  125 + fixedBox: false, // 是否固定截图框的大小 不允许改变
  126 + info: true, // 裁剪框的大小信息
  127 + outputSize: 1, // 裁剪生成图片的质量 [1至0.1]
  128 + outputType: 'jpeg', // 裁剪生成图片的格式
  129 + canScale: false, // 图片是否允许滚轮缩放
  130 + fixed: true, // 是否开启截图框宽高固定比例
  131 + fixedNumber: [1, 1], // 截图框的宽高比例 需要配合centerBox一起使用才能生效
  132 + full: true, // 是否输出原图比例的截图
  133 + canMoveBox: false, // 截图框能否拖动
  134 + original: false, // 上传图片按照原始比例渲染
  135 + centerBox: true, // 截图框是否被限制在图片里面
  136 + infoTrue: true // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
119 }) 137 })
  138 +const previews: Ref<any> = ref({})
120 /** 编辑头像 */ 139 /** 编辑头像 */
121 const editCropper = () => { 140 const editCropper = () => {
122 dialogVisible.value = true 141 dialogVisible.value = true
123 } 142 }
124 -// 打开弹出层结束时的回调  
125 -const modalOpened = () => {  
126 - cropperVisible.value = true  
127 -}  
128 /** 向左旋转 */ 143 /** 向左旋转 */
129 const rotateLeft = () => { 144 const rotateLeft = () => {
130 cropper.value.rotateLeft() 145 cropper.value.rotateLeft()
@@ -146,11 +161,14 @@ const beforeUpload = (file: Blob) =&gt; { @@ -146,11 +161,14 @@ const beforeUpload = (file: Blob) =&gt; {
146 ElMessage('文件格式错误,请上传图片类型,如:JPG,PNG后缀的文件。') 161 ElMessage('文件格式错误,请上传图片类型,如:JPG,PNG后缀的文件。')
147 } else { 162 } else {
148 const reader = new FileReader() 163 const reader = new FileReader()
  164 + // 转化为base64
149 reader.readAsDataURL(file) 165 reader.readAsDataURL(file)
150 reader.onload = () => { 166 reader.onload = () => {
151 if (reader.result) { 167 if (reader.result) {
152 - options.options.img = reader.result as string 168 + // 获取到需要剪裁的图片 展示到剪裁框中
  169 + options.img = reader.result as string
153 } 170 }
  171 + return false
154 } 172 }
155 } 173 }
156 } 174 }
@@ -160,7 +178,8 @@ const uploadImg = () =&gt; { @@ -160,7 +178,8 @@ const uploadImg = () =&gt; {
160 let formData = new FormData() 178 let formData = new FormData()
161 formData.append('avatarFile', data) 179 formData.append('avatarFile', data)
162 uploadAvatarApi(formData).then((res) => { 180 uploadAvatarApi(formData).then((res) => {
163 - options.options.img = res 181 + options.img = res
  182 + window.location.reload()
164 }) 183 })
165 dialogVisible.value = false 184 dialogVisible.value = false
166 cropperVisible.value = false 185 cropperVisible.value = false
@@ -168,15 +187,15 @@ const uploadImg = () =&gt; { @@ -168,15 +187,15 @@ const uploadImg = () =&gt; {
168 } 187 }
169 /** 实时预览 */ 188 /** 实时预览 */
170 const realTime = (data: any) => { 189 const realTime = (data: any) => {
171 - options.previews = data 190 + previews.value = data
172 } 191 }
173 watch( 192 watch(
174 () => props.img, 193 () => props.img,
175 () => { 194 () => {
176 if (props.img) { 195 if (props.img) {
177 - options.options.img = props.img  
178 - options.previews.img = props.img  
179 - options.previews.url = props.img 196 + options.img = props.img
  197 + previews.value.img = props.img
  198 + previews.value.url = props.img
180 } 199 }
181 } 200 }
182 ) 201 )
yudao-ui-admin-vue3/src/views/Profile/components/UserSocial.vue
@@ -3,19 +3,19 @@ @@ -3,19 +3,19 @@
3 <el-table-column type="seq" title="序号" width="60" fixed="left" /> 3 <el-table-column type="seq" title="序号" width="60" fixed="left" />
4 <el-table-column label="社交平台" align="left" width="120"> 4 <el-table-column label="社交平台" align="left" width="120">
5 <template #default="{ row }"> 5 <template #default="{ row }">
6 - <img style="height: 20px; vertical-align: middle" :src="row.img" alt="" />  
7 - {{ row.title }} 6 + <img class="h-5 align-middle" :src="row.img" alt="" />
  7 + <p class="mr-5">{{ row.title }}</p>
8 </template> 8 </template>
9 </el-table-column> 9 </el-table-column>
10 <el-table-column label="操作" align="center"> 10 <el-table-column label="操作" align="center">
11 <template #default="{ row }"> 11 <template #default="{ row }">
12 <template v-if="row.openid"> 12 <template v-if="row.openid">
13 已绑定 13 已绑定
14 - <XTextButton type="primary" @click="unbind(row)" title="(解绑)" /> 14 + <XTextButton type="primary" class="mr-5" @click="unbind(row)" title="(解绑)" />
15 </template> 15 </template>
16 <template v-else> 16 <template v-else>
17 未绑定 17 未绑定
18 - <XTextButton type="primary" @click="bind(row)" title="(绑定)" /> 18 + <XTextButton type="primary" class="mr-5" @click="bind(row)" title="(绑定)" />
19 </template> 19 </template>
20 </template> 20 </template>
21 </el-table-column> 21 </el-table-column>