@@ -719,6 +719,10 @@ var ( | |||
GPUCombatDataSetName string | |||
GPUCombatDataSetUUID string | |||
}{} | |||
ModelApp = struct { | |||
DesensitizationUrl string | |||
}{} | |||
) | |||
// DateLang transforms standard language locale name to corresponding value in datetime plugin. | |||
@@ -1540,6 +1544,7 @@ func NewContext() { | |||
getModelartsCDConfig() | |||
getModelConvertConfig() | |||
getModelSafetyConfig() | |||
getModelAppConfig() | |||
} | |||
func getModelSafetyConfig() { | |||
@@ -1573,6 +1578,12 @@ func getModelConvertConfig() { | |||
ModelConvert.NPU_TENSORFLOW_IMAGE_ID = sec.Key("NPU_TENSORFLOW_IMAGE_ID").MustInt(35) | |||
} | |||
func getModelAppConfig() { | |||
sec := Cfg.Section("model_app") | |||
ModelApp.DesensitizationUrl = sec.Key("desensitization_url").MustString("") | |||
} | |||
func getModelartsCDConfig() { | |||
sec := Cfg.Section("modelarts-cd") | |||
@@ -3272,3 +3272,9 @@ no_data = No Data | |||
untargetted = Untargetted | |||
targetted = targetted | |||
new_model_security_evaluation_tips = Model Security Evaluation just used for image classification | |||
[model_app] | |||
get_file_fail= Can not get the image content, please try again later. | |||
content_type_unsupported=Allowed image type is jpg, jpeg or png. | |||
process_image_fail=Fail to process image, please try again later. | |||
@@ -3291,3 +3291,9 @@ no_data = 无数据 | |||
untargetted = 非定向 | |||
targetted = 定向 | |||
new_model_security_evaluation_tips = 模型安全评测只适用于图像分类 | |||
[model_app] | |||
get_file_fail= 获取上传文件失败,请稍后再试。 | |||
content_type_unsupported=请上传jpg、jpeg或png图片。 | |||
process_image_fail=图片处理失败,请稍后再试。 | |||
@@ -0,0 +1,78 @@ | |||
package modelapp | |||
import ( | |||
"bytes" | |||
"code.gitea.io/gitea/models" | |||
"crypto/tls" | |||
"image" | |||
"image/png" | |||
"net/http" | |||
"strconv" | |||
"code.gitea.io/gitea/modules/setting" | |||
"code.gitea.io/gitea/modules/base" | |||
"code.gitea.io/gitea/modules/context" | |||
"github.com/go-resty/resty/v2" | |||
) | |||
var restyClient *resty.Client | |||
var tplExploreUpload base.TplName = "model/tuomin/upload" | |||
var uploadUrl = "/extension/tuomin/upload" | |||
var allowedContentType = []string{"image/jpeg", "image/jpg", "image/png"} | |||
func ProcessImageUI(ctx *context.Context) { | |||
ctx.HTML(200, tplExploreUpload) | |||
} | |||
func ProcessImage(ctx *context.Context) { | |||
file, header, err := ctx.GetFile("file") | |||
if err != nil { | |||
ctx.JSON(http.StatusBadRequest,models.BaseErrorMessage(ctx.Tr("model_app.get_file_fail"))) | |||
return | |||
} | |||
defer file.Close() | |||
contentType := header.Header.Get("Content-Type") | |||
if !isInAllowedContentType(contentType) { | |||
ctx.JSON(http.StatusBadRequest,models.BaseErrorMessage(ctx.Tr("model_app.content_type_unsupported"))) | |||
return | |||
} | |||
client := getRestyClient() | |||
res, err := client.R().SetMultipartField( | |||
"file", header.Filename, contentType, file).Post(setting.ModelApp.DesensitizationUrl + "?mode=" + strconv.Itoa(ctx.QueryInt("mode"))) | |||
if err != nil { | |||
ctx.JSON(http.StatusBadRequest,models.BaseErrorMessage(ctx.Tr("model_app.process_image_fail"))) | |||
return | |||
} | |||
image, _, err := image.Decode(bytes.NewReader(res.Body())) | |||
if err != nil { | |||
ctx.JSON(http.StatusBadRequest,models.BaseErrorMessage(ctx.Tr("model_app.process_image_fail"))) | |||
return | |||
} | |||
png.Encode(ctx.Resp, image) | |||
return | |||
} | |||
func isInAllowedContentType(contentType string) bool { | |||
for _, allowType := range allowedContentType { | |||
if allowType == contentType { | |||
return true | |||
} | |||
} | |||
return false | |||
} | |||
func getRestyClient() *resty.Client { | |||
if restyClient == nil { | |||
restyClient = resty.New() | |||
restyClient.SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true}) | |||
} | |||
return restyClient | |||
} |
@@ -12,6 +12,7 @@ import ( | |||
"text/template" | |||
"time" | |||
"code.gitea.io/gitea/routers/modelapp" | |||
"code.gitea.io/gitea/routers/reward/point" | |||
"code.gitea.io/gitea/routers/task" | |||
"code.gitea.io/gitea/services/reward" | |||
@@ -347,6 +348,8 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
m.Post("/user/login/kanban", user.SignInPostAPI) | |||
m.Get("/home/term", routers.HomeTerm) | |||
m.Get("/home/privacy", routers.HomePrivacy) | |||
m.Get("/extension/tuomin/upload", modelapp.ProcessImageUI) | |||
m.Post("/extension/tuomin/upload", reqSignIn, modelapp.ProcessImage) | |||
m.Group("/explore", func() { | |||
m.Get("", func(ctx *context.Context) { | |||
ctx.Redirect(setting.AppSubURL + "/explore/repos") | |||
@@ -32,9 +32,15 @@ | |||
</div> | |||
</div> | |||
</div> | |||
<a class="item" href="{{AppSubUrl}}/explore/repos">{{.i18n.Tr "custom.head.project"}}</a> | |||
<a class="item" href="{{AppSubUrl}}/explore/datasets">{{.i18n.Tr "custom.head.dataset"}}</a> | |||
<div class="ui simple dropdown item" > | |||
{{.i18n.Tr "repo.model_manager"}} | |||
<i class="dropdown icon"></i> | |||
<div class="menu"> | |||
<a class="item" href="{{AppSubUrl}}/extension/tuomin/upload">模型体验</a> | |||
</div> | |||
</div> | |||
<div class="ui simple dropdown item" id='dropdown_explore'> | |||
{{.i18n.Tr "explore"}} | |||
<i class="dropdown icon"></i> | |||
@@ -68,6 +74,14 @@ | |||
<a class="item" href="{{AppSubUrl}}/explore/repos">{{.i18n.Tr "custom.head.project"}}</a> | |||
<a class="item" href="{{AppSubUrl}}/explore/datasets">{{.i18n.Tr "custom.head.dataset"}}</a> | |||
<div class="ui simple dropdown item" > | |||
{{.i18n.Tr "repo.model_manager"}} | |||
<i class="dropdown icon"></i> | |||
<div class="menu"> | |||
<a class="item" href="{{AppSubUrl}}/extension/tuomin/upload">模型体验</a> | |||
</div> | |||
</div> | |||
<div class="ui simple dropdown item" id='dropdown_PageHome'> | |||
{{.i18n.Tr "explore"}} | |||
<i class="dropdown icon"></i> | |||
@@ -34,6 +34,13 @@ | |||
</div> | |||
<a class="item" href="{{AppSubUrl}}/explore/repos">{{.i18n.Tr "custom.head.project"}}</a> | |||
<a class="item" href="{{AppSubUrl}}/explore/datasets">{{.i18n.Tr "custom.head.dataset"}}</a> | |||
<div class="ui simple dropdown item" > | |||
{{.i18n.Tr "repo.model_manager"}} | |||
<i class="dropdown icon"></i> | |||
<div class="menu"> | |||
<a class="item" href="{{AppSubUrl}}/extension/tuomin/upload">模型体验</a> | |||
</div> | |||
</div> | |||
<div class="ui dropdown item" id='dropdown_explore'> | |||
{{.i18n.Tr "explore"}} | |||
<i class="dropdown icon"></i> | |||
@@ -66,6 +73,13 @@ | |||
</div> | |||
<a class="item" href="{{AppSubUrl}}/explore/repos">{{.i18n.Tr "custom.head.project"}}</a> | |||
<a class="item" href="{{AppSubUrl}}/explore/datasets">{{.i18n.Tr "custom.head.dataset"}}</a> | |||
<div class="ui simple dropdown item" > | |||
{{.i18n.Tr "repo.model_manager"}} | |||
<i class="dropdown icon"></i> | |||
<div class="menu"> | |||
<a class="item" href="{{AppSubUrl}}/extension/tuomin/upload">模型体验</a> | |||
</div> | |||
</div> | |||
<div class="ui dropdown item" id='dropdown_PageHome'> | |||
{{.i18n.Tr "explore"}} | |||
<i class="dropdown icon"></i> | |||
@@ -26,6 +26,13 @@ | |||
</div> | |||
<a class="item" href="{{AppSubUrl}}/explore/repos">{{.i18n.Tr "custom.head.project"}}</a> | |||
<a class="item" href="{{AppSubUrl}}/explore/datasets">{{.i18n.Tr "custom.head.dataset"}}</a> | |||
<div class="ui simple dropdown item" > | |||
{{.i18n.Tr "repo.model_manager"}} | |||
<i class="dropdown icon"></i> | |||
<div class="menu"> | |||
<a class="item" href="{{AppSubUrl}}/extension/tuomin/upload">模型体验</a> | |||
</div> | |||
</div> | |||
<div class="ui dropdown item" id='dropdown_explore'> | |||
{{.i18n.Tr "explore"}} | |||
<i class="dropdown icon"></i> | |||
@@ -59,6 +66,13 @@ | |||
<a class="item" href="{{AppSubUrl}}/explore/repos">{{.i18n.Tr "custom.head.project"}}</a> | |||
<a class="item" href="{{AppSubUrl}}/explore/datasets">{{.i18n.Tr "custom.head.dataset"}}</a> | |||
<div class="ui simple dropdown item" > | |||
{{.i18n.Tr "repo.model_manager"}} | |||
<i class="dropdown icon"></i> | |||
<div class="menu"> | |||
<a class="item" href="{{AppSubUrl}}/extension/tuomin/upload">模型体验</a> | |||
</div> | |||
</div> | |||
<div class="ui dropdown item" id='dropdown_PageHome'> | |||
{{.i18n.Tr "explore"}} | |||
<i class="dropdown icon"></i> | |||
@@ -36,6 +36,13 @@ | |||
<a class="item" href="{{AppSubUrl}}/explore/repos">{{.i18n.Tr "custom.head.project"}}</a> | |||
<a class="item" href="{{AppSubUrl}}/explore/datasets">{{.i18n.Tr "custom.head.dataset"}}</a> | |||
<div class="ui simple dropdown item" > | |||
{{.i18n.Tr "repo.model_manager"}} | |||
<i class="dropdown icon"></i> | |||
<div class="menu"> | |||
<a class="item" href="{{AppSubUrl}}/extension/tuomin/upload">模型体验</a> | |||
</div> | |||
</div> | |||
<div class="ui dropdown item" id='dropdown_explore'> | |||
{{.i18n.Tr "explore"}} | |||
<i class="dropdown icon"></i> | |||
@@ -69,6 +76,13 @@ | |||
<a class="item" href="{{AppSubUrl}}/explore/repos">{{.i18n.Tr "custom.head.project"}}</a> | |||
<a class="item" href="{{AppSubUrl}}/explore/datasets">{{.i18n.Tr "custom.head.dataset"}}</a> | |||
<div class="ui simple dropdown item" > | |||
{{.i18n.Tr "repo.model_manager"}} | |||
<i class="dropdown icon"></i> | |||
<div class="menu"> | |||
<a class="item" href="{{AppSubUrl}}/extension/tuomin/upload">模型体验</a> | |||
</div> | |||
</div> | |||
<div class="ui dropdown item" id='dropdown_PageHome'> | |||
{{.i18n.Tr "explore"}} | |||
<i class="dropdown icon"></i> | |||
@@ -0,0 +1,12 @@ | |||
{{template "base/head" .}} | |||
<link rel="stylesheet" href="{{StaticUrlPrefix}}/css/vp-model-tuomin.css?v={{MD5 AppVer}}" /> | |||
<div> | |||
{{if .Flash}} | |||
<div class="sixteen wide column"> | |||
{{template "base/alert" .}} | |||
</div> | |||
{{end}} | |||
<div id="__vue-root"></div> | |||
</div> | |||
<script src="{{StaticUrlPrefix}}/js/vp-model-tuomin.js?v={{MD5 AppVer}}"></script> | |||
{{template "base/footer" .}} |
@@ -1,80 +0,0 @@ | |||
{{template "base/head" .}} | |||
<div class="organization members"> | |||
{{template "org/header" .}} | |||
<div class="ui container"> | |||
{{template "base/alert" .}} | |||
{{template "org/navber" .}} | |||
<div class="ui stackable grid"> | |||
<div class="ui sixteen wide computer column list"> | |||
{{ range .Members}} | |||
<div class="item ui grid"> | |||
<div class="three wide mobile two wide tablet one wide computer column"> | |||
<img class="ui avatar" src="{{.SizedRelAvatarLink 48}}"> | |||
</div> | |||
<div class="seven wide mobile three wide tablet three wide computer column"> | |||
<div class="meta"><a href="{{.HomeLink}}">{{.Name}}</a></div> | |||
<div class="meta">{{.FullName}}</div> | |||
</div> | |||
<div class="ui three wide tablet four wide computer column center tablet only computer only"> | |||
<div class="meta"> | |||
{{$.i18n.Tr "org.members.membership_visibility"}} | |||
</div> | |||
<div class="meta"> | |||
{{ $isPublic := index $.MembersIsPublicMember .ID}} | |||
{{if $isPublic}} | |||
<strong>{{$.i18n.Tr "org.members.public"}}</strong> | |||
{{if or (eq $.SignedUser.ID .ID) $.IsOrganizationOwner}}(<a class="link-action" href data-url="{{$.OrgLink}}/members/action/private?uid={{.ID}}">{{$.i18n.Tr "org.members.public_helper"}}</a>){{end}} | |||
{{else}} | |||
<strong>{{$.i18n.Tr "org.members.private"}}</strong> | |||
{{if or (eq $.SignedUser.ID .ID) $.IsOrganizationOwner}}(<a class="link-action" href data-url="{{$.OrgLink}}/members/action/public?uid={{.ID}}">{{$.i18n.Tr "org.members.private_helper"}}</a>){{end}} | |||
{{end}} | |||
</div> | |||
</div> | |||
<div class="five wide mobile three wide tablet three wide computer column"> | |||
<div class="meta"> | |||
{{$.i18n.Tr "org.members.member_role"}} | |||
</div> | |||
<div class="meta"> | |||
<strong>{{if index $.MembersIsUserOrgOwner .ID}}{{svg "octicon-shield-lock" 16}} {{$.i18n.Tr "org.members.owner"}}{{else}}{{$.i18n.Tr "org.members.member"}}{{end}}</strong> | |||
</div> | |||
</div> | |||
<div class="ui one wide column center tablet only computer only"> | |||
<div class="meta"> | |||
2FA | |||
</div> | |||
<div class="meta"> | |||
<strong> | |||
{{if index $.MembersTwoFaStatus .ID}} | |||
<span class="text green">{{svg "octicon-check" 16}}</span> | |||
{{else}} | |||
{{svg "octicon-x" 16}} | |||
{{end}} | |||
</strong> | |||
</div> | |||
</div> | |||
<div class="ui three wide column tablet only computer only"> | |||
<div class="text right"> | |||
{{if eq $.SignedUser.ID .ID}} | |||
<form method="post" action="{{$.OrgLink}}/members/action/leave"> | |||
{{$.CsrfTokenHtml}} | |||
<button type="submit" class="ui red small button" name="uid" value="{{.ID}}">{{$.i18n.Tr "org.members.leave"}}</button> | |||
</form> | |||
{{else if $.IsOrganizationOwner}} | |||
<form method="post" action="{{$.OrgLink}}/members/action/remove"> | |||
{{$.CsrfTokenHtml}} | |||
<button type="submit" class="ui red small button" name="uid" value="{{.ID}}">{{$.i18n.Tr "org.members.remove"}}</button> | |||
</form> | |||
{{end}} | |||
</div> | |||
</div> | |||
</div> | |||
{{end}} | |||
</div> | |||
{{template "base/paginate" .}} | |||
</div> | |||
</div> | |||
</div> | |||
{{template "base/footer" .}} |
@@ -176,6 +176,22 @@ const en = { | |||
Activated: 'Activated', | |||
notActive: 'Not active', | |||
}, | |||
tranformImageFailed:'Picture desensitization failed', | |||
originPicture:'Origin picture', | |||
desensitizationPicture:'Desensitization picture', | |||
desensitizationObject:'Desensitization object', | |||
example:'Example', | |||
startDesensitization:'Start desensitization', | |||
all:'All', | |||
onlyFace:'Only face', | |||
onlyLicensePlate:'Only license plate', | |||
dragThePictureHere:'Drag the picture here', | |||
or:'or', | |||
clickUpload:'Click upload', | |||
dataDesensitizationModelExperience:'Data desensitization model experience', | |||
dataDesensitizationModelDesc:'Use AI technology to desensitize the face and license plate number in the picture. For more information about this model, please visit the project', | |||
limitFilesUpload:'Only jpg/jpeg/png files can be uploaded', | |||
limitSizeUpload:'The size of the uploaded file cannot exceed 20M!', | |||
} | |||
export default en; |
@@ -176,6 +176,22 @@ const zh = { | |||
Activated: '已激活', | |||
notActive: '未激活', | |||
}, | |||
tranformImageFailed:'图片脱敏失败', | |||
originPicture:'原始图片', | |||
desensitizationPicture:'脱敏图片', | |||
desensitizationObject:'脱敏对象', | |||
example:'示例', | |||
startDesensitization:'开始处理', | |||
all:'全部', | |||
onlyFace:'仅人脸', | |||
onlyLicensePlate:'仅车牌', | |||
dragThePictureHere:'拖动图片到这里', | |||
or:'或', | |||
clickUpload:'点击上传', | |||
dataDesensitizationModelExperience:'数据脱敏模型体验', | |||
dataDesensitizationModelDesc:'利用人工智能AI技术,把图片中的人脸、车牌号码进行脱敏处理。该模型更多信息请访问项目', | |||
limitFilesUpload:'只能上传 jpg/jpeg/png 格式的文件', | |||
limitSizeUpload:'上传文件大小不能超过 20M !', | |||
} | |||
export default zh; |
@@ -0,0 +1,380 @@ | |||
<template> | |||
<div class="ui container"> | |||
<div class="tuomin-title"> | |||
<h2>{{ $t("dataDesensitizationModelExperience") }}</h2> | |||
<p> | |||
{{ $t("dataDesensitizationModelDesc") }} <a | |||
href="https://git.openi.org.cn/tengxiao/tuomin" | |||
target="_blank" | |||
>tengxiao / tuomin</a | |||
> | |||
</p> | |||
</div> | |||
<el-row :gutter="12" style="margin-top: 33px"> | |||
<el-col :xs="24" :span="12"> | |||
<div class="tuomin-content-image"> | |||
<div class="tuomin-icon"> | |||
<i | |||
class="ri-image-line" | |||
style="font-size: 16px; margin-right: 2px" | |||
></i> | |||
<span style="font-size: 12px">img</span> | |||
</div> | |||
<div style="height: 230px; width: 96%; margin: 0 auto"> | |||
<el-upload | |||
action="#" | |||
accept=".jpg,.jpeg,.png,.JPG,.JPEG,.PNG" | |||
:show-file-list="false" | |||
:on-change="handleChangePicture" | |||
list-type="picture-card" | |||
:file-list="fileList" | |||
:style="{ display: ImageUrl ? 'none' : 'block' }" | |||
:auto-upload="false" | |||
drag | |||
> | |||
<div class="el-upload__text"> | |||
{{ $t("dragThePictureHere") | |||
}}<span style="color: rgba(136, 136, 136, 0.87)">{{ | |||
$t("or") | |||
}}</span | |||
>{{ $t("clickUpload") }} | |||
</div> | |||
</el-upload> | |||
<img class="preview-image" v-if="ImageUrl" :src="ImageUrl" alt="" /> | |||
</div> | |||
<div> | |||
<div class="tuomin-radio-model"> | |||
<label class="radio-label" | |||
>{{ $t("desensitizationObject") }}:</label | |||
> | |||
<div> | |||
<el-radio-group v-model="radio"> | |||
<el-radio :label="2">{{ $t("all") }}</el-radio> | |||
<el-radio :label="1">{{ $t("onlyFace") }}</el-radio> | |||
<el-radio :label="0">{{ $t("onlyLicensePlate") }}</el-radio> | |||
</el-radio-group> | |||
</div> | |||
</div> | |||
<div class="tuomin-button-model"> | |||
<el-button @click="cancelUpload">{{ $t("cancel") }}</el-button> | |||
<el-button | |||
:disabled="fileList.length < 1" | |||
@click="startTranform" | |||
type="primary" | |||
>{{ $t("startDesensitization") }}</el-button | |||
> | |||
</div> | |||
</div> | |||
</div> | |||
</el-col> | |||
<el-col :xs="24" :span="12"> | |||
<div class="tuomin-content-image" v-loading="tranformImageLoading"> | |||
<div class="tuomin-icon"> | |||
<i | |||
class="ri-image-line" | |||
style="font-size: 16px; margin-right: 2px" | |||
></i> | |||
<span style="font-size: 12px">output</span> | |||
</div> | |||
<div | |||
v-if="resultImgSrc" | |||
class="tuomin-icon-download" | |||
@click="downImg" | |||
> | |||
<i | |||
class="ri-download-2-line" | |||
style="font-size: 16px; margin-right: 2px" | |||
></i> | |||
<span style="font-size: 14px">下载</span> | |||
</div> | |||
<div style="height: 358px"> | |||
<el-image | |||
style="height: 100%; width: 100%" | |||
:src="resultImgSrc" | |||
:preview-src-list="[resultImgSrc]" | |||
> | |||
<div slot="error" class="image-slot"> | |||
<i style="font-size: 0" class="el-icon-picture-outline"></i> | |||
</div> | |||
</el-image> | |||
</div> | |||
</div> | |||
</el-col> | |||
</el-row> | |||
<div style="margin: 39px 0 21px 0"> | |||
<span>{{ $t("example") }}:</span> | |||
</div> | |||
<div class="table-container"> | |||
<div> | |||
<el-table border :data="tableData1" style="width: 100%"> | |||
<el-table-column :label="$t('originPicture')" align="center"> | |||
<template slot-scope="scope"> | |||
<div style="width: 100%; height: 200px"> | |||
<el-image | |||
style="height: 100%; width: 100%" | |||
:src="scope.row.imgSrc1" | |||
:preview-src-list="[scope.row.imgSrc1]" | |||
> | |||
<div slot="error" class="image-slot"> | |||
<i style="font-size: 0" class="el-icon-picture-outline"></i> | |||
</div> | |||
</el-image> | |||
</div> | |||
</template> | |||
</el-table-column> | |||
<el-table-column :label="$t('desensitizationPicture')" align="center"> | |||
<template slot-scope="scope"> | |||
<div style="width: 100%; height: 200px"> | |||
<el-image | |||
style="height: 100%; width: 100%" | |||
:src="scope.row.imgSrc2" | |||
:preview-src-list="[scope.row.imgSrc2]" | |||
> | |||
<div slot="error" class="image-slot"> | |||
<i style="font-size: 0" class="el-icon-picture-outline"></i> | |||
</div> | |||
</el-image> | |||
</div> | |||
</template> | |||
</el-table-column> | |||
<el-table-column | |||
prop="mode" | |||
:label="$t('desensitizationObject')" | |||
align="center" | |||
header-align="center" | |||
> | |||
</el-table-column> | |||
</el-table> | |||
</div> | |||
</div> | |||
</div> | |||
</template> | |||
<script> | |||
import axios from "axios"; | |||
export default { | |||
data() { | |||
return { | |||
ImageUrl: "", | |||
radio: 2, | |||
file: "", | |||
fileList: [], | |||
resultImgSrc: "", | |||
tranformImageLoading: false, | |||
tableData1: [ | |||
{ | |||
imgSrc1: "/img/origin.png", | |||
imgSrc2: "/img/tuomin.png", | |||
mode: this.$t("all"), | |||
}, | |||
], | |||
}; | |||
}, | |||
components: {}, | |||
methods: { | |||
// 选择文件、移除文件、上传文件成功/失败后,都会触发 | |||
handleChangePicture(file, fileList) { | |||
let acceptList = ["jpg", "jpeg", "png"]; | |||
// 根据文件名获取文件的后缀名 | |||
let fileType = file.name.split(".").pop().toLowerCase(); | |||
// 判断文件格式是否符合要求 | |||
if (acceptList.indexOf(fileType) === -1) { | |||
this.$message.error(this.$t("limitFilesUpload")); | |||
return false; | |||
} | |||
// 判断文件大小是否符合要求 | |||
if (file.size / 1024 / 1024 > 20) { | |||
this.$message.error(this.$t("limitSizeUpload")); | |||
return false; | |||
} | |||
this.ImageUrl = URL.createObjectURL(file.raw); | |||
this.file = file; | |||
this.fileList = fileList; | |||
}, | |||
cancelUpload() { | |||
this.ImageUrl = ""; | |||
this.file = ""; | |||
this.fileList = []; | |||
}, | |||
downImg() { | |||
const a = document.createElement("a"); | |||
a.download = "result.png"; | |||
a.style.display = "none"; | |||
a.href = this.resultImgSrc; | |||
document.body.appendChild(a); | |||
a.click(); | |||
document.body.removeChild(a); | |||
}, | |||
startTranform() { | |||
if (!this.file) return; | |||
let fd = new FormData(); | |||
fd.append("file", this.file.raw); | |||
this.tranformImageLoading = true; | |||
axios({ | |||
method: "POST", | |||
url: "/extension/tuomin/upload", | |||
headers: { Accept: "image/png" }, | |||
responseType: "blob", | |||
params: { mode: this.radio }, | |||
data: fd, | |||
}) | |||
.then((res) => { | |||
const objectURL = URL.createObjectURL(res.data); | |||
this.resultImgSrc = objectURL; | |||
this.tranformImageLoading = false; | |||
}) | |||
.catch((err) => { | |||
this.tranformImageLoading = false; | |||
if (err.response.status === 400) { | |||
const fr = new FileReader(); | |||
fr.onload = (e) => { | |||
try { | |||
const jsonResult = JSON.parse(e.target.result); | |||
this.$message({ | |||
type: "error", | |||
message: jsonResult.Message, | |||
}); | |||
} catch (e) { | |||
this.$message({ | |||
type: "error", | |||
message: this.$t("tranformImageFailed"), | |||
}); | |||
} | |||
}; | |||
fr.readAsText(err.response.data); | |||
} else { | |||
this.$message({ | |||
type: "error", | |||
message: this.$t("tranformImageFailed"), | |||
}); | |||
} | |||
}); | |||
}, | |||
}, | |||
mounted() {}, | |||
beforeDestroy() {}, | |||
}; | |||
</script> | |||
<style scoped lang="less"> | |||
.tuomin-title { | |||
margin-top: 34px; | |||
h2 { | |||
display: flex; | |||
justify-content: center; | |||
} | |||
p { | |||
display: flex; | |||
justify-content: center; | |||
color: rgba(136, 136, 136, 0.87); | |||
} | |||
} | |||
.tuomin-content-image { | |||
border: 1px solid rgba(0, 0, 0, 0.1); | |||
border-radius: 5px; | |||
min-height: 358px; | |||
position: relative; | |||
.tuomin-icon { | |||
z-index: 99; | |||
display: flex; | |||
align-items: center; | |||
position: absolute; | |||
left: 0; | |||
top: 0; | |||
width: 66px; | |||
height: 22px; | |||
justify-content: center; | |||
color: rgba(136, 136, 136, 0.87); | |||
border-radius: 5px 0px 10px 0px; | |||
border: 1px solid rgba(0, 0, 0, 0.1); | |||
} | |||
.tuomin-icon-download { | |||
z-index: 99; | |||
display: flex; | |||
align-items: center; | |||
position: absolute; | |||
right: 10px; | |||
bottom: 10px; | |||
width: 66px; | |||
height: 30px; | |||
justify-content: center; | |||
color: rgba(255, 255, 255, 1); | |||
background-color: rgba(0, 0, 0, 0); | |||
background: transparent; | |||
border: 1px solid rgba(136, 136, 136, 0.5); | |||
border-radius: 4px; | |||
cursor: pointer; | |||
} | |||
.el-upload__text { | |||
height: 100%; | |||
display: flex; | |||
align-items: center; | |||
justify-content: center; | |||
} | |||
.preview-image { | |||
height: 100%; | |||
width: 100%; | |||
} | |||
.tuomin-radio-model { | |||
display: flex; | |||
margin: 25px 12px 0 12px; | |||
.radio-label { | |||
font-weight: 600; | |||
margin-right: 4px; | |||
color: rgba(16, 16, 16, 1); | |||
} | |||
} | |||
.tuomin-button-model { | |||
text-align: right; | |||
margin: 22px 12px 0 12px; | |||
} | |||
} | |||
/deep/ .el-upload--picture-card { | |||
width: 100%; | |||
background: #ffff; | |||
border: none; | |||
border-bottom: 1px dashed #888; | |||
border-radius: 0; | |||
min-height: 230px; | |||
} | |||
/deep/ .el-upload-dragger { | |||
width: 100%; | |||
background: #ffff; | |||
border: none; | |||
border-radius: 0; | |||
height: 100%; | |||
} | |||
.table-container { | |||
margin-bottom: 16px; | |||
/deep/ .el-table__header { | |||
th { | |||
background: rgb(245, 245, 246); | |||
font-size: 14px; | |||
color: rgb(36, 36, 36); | |||
font-weight: 400; | |||
} | |||
} | |||
/deep/ .el-table__body { | |||
td { | |||
font-size: 14px; | |||
} | |||
} | |||
} | |||
.center { | |||
display: flex; | |||
justify-content: center; | |||
} | |||
@media screen and (max-width: 768px) { | |||
body { | |||
background-color: black; | |||
} | |||
} | |||
</style> |
@@ -0,0 +1,17 @@ | |||
import Vue from 'vue'; | |||
import ElementUI from 'element-ui'; | |||
import 'element-ui/lib/theme-chalk/index.css'; | |||
import localeEn from 'element-ui/lib/locale/lang/en'; | |||
import localeZh from 'element-ui/lib/locale/lang/zh-CN'; | |||
import { i18n, lang } from '~/langs'; | |||
import App from './index.vue'; | |||
Vue.use(ElementUI, { | |||
locale: lang === 'zh-CN' ? localeZh : localeEn, | |||
size: 'small', | |||
}); | |||
new Vue({ | |||
i18n, | |||
render: (h) => h(App), | |||
}).$mount('#__vue-root'); |