Files
tuanwei-admin/src/views/oa/app/components/app-edit.vue
T
南宁网宿科技 13bed2bafb Initial commit
2023-06-03 23:57:39 +08:00

1204 lines
36 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!-- 用户编辑弹窗 -->
<template>
<ele-modal
width="80%"
:visible="visible"
:maskClosable="false"
:maxable="maxable"
:title="isUpdate ? '编辑应用' : '添加应用'"
:body-style="{ paddingBottom: '28px' }"
@update:visible="updateVisible"
@ok="save"
>
<div style="background-color: #f3f3f3; padding: 8px">
<a-form
ref="formRef"
:model="form"
:rules="rules"
:label-col="{ md: { span: 7 }, sm: { span: 4 }, xs: { span: 24 } }"
:wrapper-col="{ md: { span: 17 }, sm: { span: 20 }, xs: { span: 24 } }"
>
<a-card title="基本信息" :bordered="false">
<a-row :gutter="16">
<a-col
v-bind="styleResponsive ? { md: 8, sm: 24, xs: 24 } : { span: 8 }"
>
<div class="upload-image">
<ele-image-upload
v-model:value="logo"
:item-style="{ width: '120px', height: '120px' }"
:limit="1"
@upload="onUploadIcon"
/>
</div>
<a-form-item label="AppId" name="appId">
<span>{{ form.appId }}</span>
</a-form-item>
<a-form-item label="AppSecret" name="appSecret">
<span style="margin-right: 10px;">{{ showAppSecret ? form.appSecret : '********' }}</span>
<a-space>
<a @click="onAppSecret(data.appId)">查看</a>
<a-divider type="vertical" />
<a @click="onUpdateAppSecret(data.appId)">重置</a>
</a-space>
</a-form-item>
<a-form-item label="企业ID" name="tenantId">
<span>{{ form.tenantId }}</span>
</a-form-item>
</a-col>
<a-col
v-bind="styleResponsive ? { md: 8, sm: 24, xs: 24 } : { span: 8 }"
>
<a-form-item label="应用名称" name="appName">
<a-input
allow-clear
placeholder="请输入应用名称"
v-model:value="form.appName"
/>
</a-form-item>
<a-form-item label="业主单位" name="companyName">
<SelectCompany
:placeholder="`请选择业主单位`"
v-model:value="form.companyName"
@done="chooseCompanyName"
/>
</a-form-item>
<a-form-item label="开发者单位" name="developer">
<SelectCompany
:placeholder="`请选择开发者企业`"
v-model:value="form.developer"
@done="chooseDeveloper"
/>
</a-form-item>
<a-form-item label="应用地址" name="appUrl">
<a-input
allow-clear
placeholder="请输入应用地址"
v-model:value="form.appUrl"
/>
</a-form-item>
<a-form-item label="后台管理" name="adminUrl">
<DictSelect
dict-code="AdminUrl"
placeholder="请选择后台管理地址"
v-model:value="form.adminUrl"
/>
</a-form-item>
</a-col>
<a-col
v-bind="styleResponsive ? { md: 8, sm: 24, xs: 24 } : { span: 8 }"
>
<a-form-item label="应用状态" name="appStatus">
<DictSelect
dict-code="appstoreStatus"
placeholder="请选择应用状态"
v-model:value="form.appStatus"
/>
</a-form-item>
<a-form-item label="应用类型" name="appTypeMultiple">
<DictSelect
dict-code="AppTypeMultiple"
placeholder="请选择应用类型"
multiple="multiple"
v-model:value="form.appTypeMultiple"
/>
</a-form-item>
<a-form-item label="应用描述" name="comments">
<a-textarea
:rows="4"
:maxlength="200"
placeholder="请输入应用描述"
v-model:value="form.comments"
/>
</a-form-item>
</a-col>
</a-row>
</a-card>
<a-divider style="height: 8px" />
<a-card title="开发设置" :bordered="false">
<a-row :gutter="16">
<a-col
v-bind="styleResponsive ? { md: 8, sm: 24, xs: 24 } : { span: 8 }"
>
<a-form-item label="应用标识" name="appCode">
<a-input
allow-clear
placeholder="请输入应用标识(英文字母)"
v-model:value="form.appCode"
@change="changeAppCode"
/>
</a-form-item>
<a-form-item label="应用包名" name="packageName">
<a-input
allow-clear
placeholder="请输入应用包名"
v-model:value="form.packageName"
/>
</a-form-item>
<a-form-item label="IP白名单" name="ipAddress">
<a-input
allow-clear
placeholder="请输入IP白名单"
v-model:value="form.ipAddress"
/>
</a-form-item>
</a-col>
<a-col
v-bind="styleResponsive ? { md: 8, sm: 24, xs: 24 } : { span: 8 }"
>
<a-form-item label="接口地址" name="serverUrl">
<DictSelect
dict-code="ServerApi"
placeholder="请选择管理地址"
v-model:value="form.serverUrl"
/>
</a-form-item>
<a-form-item label="文件服务器" name="fileUrl">
<DictSelect
dict-code="FileUrl"
placeholder="请选择文件服务器地址"
v-model:value="form.fileUrl"
/>
</a-form-item>
<a-form-item label="授权回调地址" name="callbackUrl">
<a-input
allow-clear
placeholder="请输入授权回调地址"
v-model:value="form.callbackUrl"
/>
</a-form-item>
</a-col>
<a-col
v-bind="styleResponsive ? { md: 8, sm: 24, xs: 24 } : { span: 8 }"
>
<a-form-item label="代码仓库" name="gitUrl">
<a-input
allow-clear
placeholder="请输入git仓库地址"
v-model:value="form.gitUrl"
/>
</a-form-item>
<a-form-item label="允许被搜索" name="gitUrl">
<a-switch v-model:checked="form.search" />
</a-form-item>
</a-col>
</a-row>
</a-card>
<a-divider style="height: 8px" />
<a-card title="成员管理" :bordered="false">
<div class="content">
<a-space
style="margin-bottom: 15px"
v-if="isUpdate"
>
<SelectUser
:placeholder="`添加开发成员`"
@done="addAppDevUser"
/>
<SelectUser
:placeholder="`添加体验成员`"
@done="addAppExpUser"
/>
</a-space>
<table
class="ele-table ele-table-border ele-table-stripe ele-table-medium"
>
<thead>
<tr>
<th>角色</th>
<th>用户</th>
<th>邮箱</th>
<th>手机号码</th>
<th>加入时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="user in appUsers">
<td>
<a-tag color="green" v-if="user.role === 10">体验成员</a-tag>
<a-tag color="orange" v-if="user.role === 20">开发成员</a-tag>
<a-tag color="red" v-if="user.role === 30">管理员</a-tag>
</td>
<td>
<a-avatar :src="user.avatar">
<template #icon>
<user-outlined />
</template>
</a-avatar>
<span style="padding-left: 5px">{{ user.nickname }}</span>
</td>
<td>{{ user.email }}</td>
<td>{{ user.phone }}</td>
<td>{{ user.createTime }}</td>
<td>
<div v-if="user.role !== 30">
<a
@click="removeUser(user)"
v-if="user.status === 0"
>
移除
</a>
<a v-else>待确认</a>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</a-card>
<a-divider style="height: 8px" />
<a-card title="项目需求" :bordered="false">
<a-row :gutter="16">
<a-col
v-bind="styleResponsive ? { md: 8, sm: 24, xs: 24 } : { span: 8 }"
>
<a-form-item label="原型图地址" name="prototypeUrl">
<a-input
allow-clear
placeholder="请输入原型图地址"
v-model:value="form.prototypeUrl"
/>
</a-form-item>
<a-form-item label="需求文档" name="parentId">
<a-upload
v-model:file-list="file3"
name="file"
action="https://file.wsdns.cn/api/file/image"
:headers="{ Authorization: token }"
@change="onFile3"
>
<a-button>
<upload-outlined />
上传
</a-button>
</a-upload>
</a-form-item>
</a-col>
<a-col
v-bind="styleResponsive ? { md: 8, sm: 24, xs: 24 } : { span: 8 }"
>
<a-form-item label="项目需求文档" name="docsUrl">
<a-input
allow-clear
placeholder="请输入腾讯文档地址"
v-model:value="form.docsUrl"
/>
</a-form-item>
</a-col>
<a-col
v-bind="styleResponsive ? { md: 8, sm: 24, xs: 24 } : { span: 8 }"
>
<a-form-item label="维护文档" name="docsUrl">
<a-input
allow-clear
placeholder="请输入腾讯文档地址"
v-model:value="form.docsUrl"
/>
</a-form-item>
</a-col>
</a-row>
</a-card>
<a-divider style="height: 8px" />
<a-card title="开发资料" :bordered="false">
<template #extra><a-button type="link" @click="handleEditStatus">{{ editStatus ? '预览' : '编辑'}}</a-button></template>
<!-- 编辑器 -->
<byte-md-editor
v-if="editStatus"
v-model:value="requirement"
placeholder="请输入您的内容,图片请直接粘贴"
:locale="zh_Hans"
mode="split"
:plugins="plugins"
height="500px"
:editorConfig="{ lineNumbers: true }"
@paste="onPaste"
/>
<!-- 编辑器 -->
<byte-md-viewer v-else :value="requirement" :plugins="plugins" />
</a-card>
<a-divider style="height: 8px" />
<a-card title="工单信息" :bordered="false">
<table
class="ele-table ele-table-border ele-table-stripe ele-table-medium"
>
<thead>
<tr>
<th>工单号</th>
<th>工单标题</th>
<th>工单类型</th>
<th>工单状态</th>
<th>最后回复时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="user in tasks">
<td>
1766
</td>
<td>
发现一个bug,请帮忙核实并修复
</td>
<td>维护工单</td>
<td>待处理</td>
<td>{{ user.createTime }}</td>
<td>
<div>
<a>
去处理
</a>
</div>
</td>
</tr>
</tbody>
</table>
</a-card>
<a-divider style="height: 8px" />
<a-card title="应用截图" :bordered="false">
<!-- <template #extra><a-button type="link" @click="handleEditStatus">上传</a-button></template>-->
<div class="content">
<ele-image-upload
v-model:value="images"
:limit="6"
:drag="true"
:item-style="{ width: '150px', height: '267px' }"
:upload-handler="uploadHandler"
@upload="onUpload"
/>
<small class="ele-text-placeholder">
请上传应用截图(最多6张),建议宽度300*533像素,小于2M/张
</small>
</div>
</a-card>
<a-divider style="height: 8px" />
<a-card title="应用介绍" :bordered="false">
<template #extra><a-button type="link" @click="handleEditStatus">{{ editStatus ? '预览' : '编辑'}}</a-button></template>
<!-- 编辑器 -->
<byte-md-editor
v-if="editStatus"
v-model:value="content"
placeholder="请输入您的内容,图片请直接粘贴"
:locale="zh_Hans"
mode="split"
:plugins="plugins"
height="500px"
:editorConfig="{ lineNumbers: true }"
@paste="onPaste"
/>
<!-- 编辑器 -->
<byte-md-viewer v-else :value="content" :plugins="plugins" />
</a-card>
<!-- <a-divider style="height: 8px" />-->
<!-- <a-card title="订单信息" :bordered="false" v-any-role="['superAdmin','admin']">-->
<!-- <table-->
<!-- class="ele-table ele-table-border ele-table-stripe ele-table-medium"-->
<!-- >-->
<!-- <thead>-->
<!-- <tr>-->
<!-- <th>订单号</th>-->
<!-- <th>订单类型</th>-->
<!-- <th>订单金额</th>-->
<!-- <th>支付状态</th>-->
<!-- <th>创建时间</th>-->
<!-- </tr>-->
<!-- </thead>-->
<!-- <tbody>-->
<!-- <tr v-for="user in appUsers">-->
<!-- <td>-->
<!-- 20230385162-->
<!-- </td>-->
<!-- <td>续费</td>-->
<!-- <td>-->
<!-- ¥880-->
<!-- </td>-->
<!-- <td>已支付</td>-->
<!-- <td>{{ user.createTime }}</td>-->
<!-- </tr>-->
<!-- </tbody>-->
<!-- </table>-->
<!-- </a-card>-->
<a-divider style="height: 8px" />
<a-card title="合同文件" :bordered="false" v-any-role="['superAdmin','admin']">
<a-row :gutter="16">
<a-col
v-bind="styleResponsive ? { md: 8, sm: 24, xs: 24 } : { span: 8 }"
>
<a-form-item label="合同文件" name="parentId">
<a-upload
v-model:file-list="file1"
name="file"
action="https://file.wsdns.cn/api/file/image"
:headers="{ Authorization: token }"
@change="onFile1"
>
<a-button>
<upload-outlined />
上传
</a-button>
</a-upload>
</a-form-item>
</a-col>
<a-col
v-bind="styleResponsive ? { md: 8, sm: 24, xs: 24 } : { span: 8 }"
>
<a-form-item label="报价单" name="parentId">
<a-upload
v-model:file-list="file2"
name="file"
action="https://file.wsdns.cn/api/file/image"
:headers="{ Authorization: token }"
@change="onFile2"
>
<a-button>
<upload-outlined />
上传
</a-button>
</a-upload>
</a-form-item>
</a-col>
<a-col
v-bind="styleResponsive ? { md: 8, sm: 24, xs: 24 } : { span: 8 }"
>
<a-form-item label="其他" name="parentId">
<a-upload
v-model:file-list="file3"
name="file"
action="https://file.wsdns.cn/api/file/image"
:headers="{ Authorization: token }"
@change="onFile3"
>
<a-button>
<upload-outlined />
上传
</a-button>
</a-upload>
</a-form-item>
</a-col>
</a-row>
</a-card>
</a-form>
</div>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, watch, createVNode, computed } from 'vue';
import { Form, message } from 'ant-design-vue';
import { assignObject, ipReg, toDateString } from "ele-admin-pro";
import { addApp, updateApp, getAppSecret, updateAppSecret } from '@/api/oa/app';
import type { App } from '@/api/oa/app/model';
import { useUserStore } from '@/store/modules/user';
import { useThemeStore } from '@/store/modules/theme';
import { storeToRefs } from 'pinia';
// 中文语言文件
import zh_Hans from 'bytemd/locales/zh_Hans.json';
// 链接、删除线、复选框、表格等的插件
// 插件的中文语言文件
import zh_HansGfm from '@bytemd/plugin-gfm/locales/zh_Hans.json';
import 'bytemd/dist/index.min.css';
import 'github-markdown-css/github-markdown-light.css';
import { Modal } from 'ant-design-vue';
// import TinymceEditor from '@/components/TinymceEditor/index.vue';
import highlight from '@bytemd/plugin-highlight';
// 中文语言文件
import gfm from '@bytemd/plugin-gfm';
// // 预览界面的样式,这里用的 github 的 markdown 主题
import 'github-markdown-css/github-markdown-light.css';
import {
EyeOutlined,
EyeInvisibleOutlined,
ExclamationCircleOutlined
} from '@ant-design/icons-vue';
import { UploadOutlined } from '@/layout/menu-icons';
import { FormInstance } from 'ant-design-vue/es/form';
import { Company } from '@/api/system/company/model';
import { ItemType } from 'ele-admin-pro/es/ele-image-upload/types';
import DictSelect from '@/views/search/components/dict-select.vue';
import { User } from '@/api/system/user/model';
import { uploadFile } from "@/api/system/file";
import { FILE_SERVER, FILE_THUMBNAIL, TOKEN_STORE_NAME } from "@/config/setting";
import { listAppUser, addAppUser, removeAppUser } from "@/api/oa/app/user";
import { AppUser } from '@/api/oa/app/user/model'
import { pageCompany } from "@/api/system/company";
import { Task } from "@/api/oa/task/model";
// 是否是修改
const isUpdate = ref(false);
const useForm = Form.useForm;
// 是否开启响应式布局
const themeStore = useThemeStore();
const { styleResponsive } = storeToRefs(themeStore);
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 修改回显的数据
data?: App | null;
}>();
const emit = defineEmits<{
(e: 'done'): void;
(e: 'update:visible', visible: boolean): void;
}>();
// 提交状态
const loading = ref(false);
// 是否显示最大化切换按钮
const maxable = ref(true);
// 当期时间
const dayTime = toDateString(new Date());
// 已上传数据
const logo = ref<ItemType[]>([]);
const images = ref<ItemType[]>([]);
const appUsers = ref<AppUser[]>([]);
const tasks = ref<Task[]>([]);
const selectUser = ref<string>();
const editStatus = ref(false);
// 类型 single|multiple
// const type = ref<string>('single');
// 日期范围选择
const dateRange = ref<[string, string]>(['', '']);
const content = ref('');
const requirement = ref('');
// 插件
const plugins = ref([
gfm({
locale: zh_HansGfm
}),
highlight()
]);
// 穿梭框数据
const breakfast = ref<any[]>();
const lunch = ref<any[]>();
const targetKeys2 = ref<any[]>([]);
const showAppSecret = ref(false);
const dinner = ref<any[]>();
const targetKeys3 = ref<any[]>([]);
const selectedKeys3 = ref<any[]>();
const selectedGoodsIds = ref<any[]>([]);
const showAddUserForm = ref(false);
const token = localStorage.getItem(TOKEN_STORE_NAME);
const formRef = ref<FormInstance | null>(null);
// 文件模型
interface FileItem {
uid: string;
name?: string;
status?: string;
response?: Response;
thumbUrl?: string;
downloadUrl?: string;
url: string;
}
interface FileInfo {
file: FileItem;
fileList: FileItem[];
}
// 文件上传
const file1 = ref<FileItem[]>();
const file2 = ref<FileItem[]>();
const file3 = ref<FileItem[]>();
// 用户信息
const form = reactive<App>({
// 应用id
appId: undefined,
// 应用秘钥
appSecret: '',
enName: '',
// 应用名称
appName: '',
// 上级id, 0是顶级
parentId: undefined,
// 应用编号
appCode: '',
// 应用图标
appIcon: '',
appQrcode: '',
// 应用截图
images: '',
// 应用类型
appType: '',
appTypeMultiple: undefined,
// 菜单类型
menuType: undefined,
// 应用地址
appUrl: '',
// 后台管理地址
adminUrl: undefined,
// 下载地址
downUrl: undefined,
serverUrl: undefined,
callbackUrl: undefined,
gitUrl: undefined,
docsUrl: undefined,
prototypeUrl: undefined,
ipAddress: undefined,
fileUrl: undefined,
// 应用包名
packageName: '',
// 点击次数
clicks: '',
// 安装次数
installs: '',
// 应用介绍
content: '',
// 开发者(个人)
developer: '',
director: '',
projectDirector: '',
salesman: '',
// 软件定价
price: '',
// 评分
score: '',
// 星级
star: '',
// 菜单组件地址
component: '',
// 菜单路由地址
path: '',
// 权限标识
authority: '',
// 打开位置
target: '',
// 是否隐藏, 0否, 1是(仅注册路由不显示在左侧菜单)
hide: undefined,
// 菜单侧栏选中的path
active: '',
// 其它路由元信息
meta: '',
// 版本
edition: '',
// 版本号
version: '',
// 是否已安装
isUse: undefined,
// 排序
sortNumber: undefined,
// 备注
comments: '',
tenantName: '',
companyName: '',
// 租户编号
tenantCode: '',
// 租户id
tenantId: undefined,
// 创建时间
createTime: '',
appStatus: '开发中',
// 状态
status: undefined,
// 发布者
userId: '',
// 发布者昵称
nickname: '',
// 子菜单
children: [],
// 权限树回显选中状态, 0未选中, 1选中
checked: false,
//
key: undefined,
//
value: undefined,
//
parentIds: [],
//
openType: undefined,
//
search: undefined,
// 成员管理
users: [],
// 项目需求
requirement: '',
file1: '[]',
file2: '[]',
file3: '[]',
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
appName: [
{
required: true,
type: 'string',
message: '请输入应用名称',
trigger: 'blur'
}
],
appCode: [
{
required: true,
type: 'string',
message: '请输入应用标识(英文字母)',
trigger: 'blur'
}
],
ipAddress: [
{
pattern: ipReg,
message: 'IP地址不合法',
type: 'string'
}
],
appStatus: [
{
required: true,
type: 'string',
message: '请选择应用状态',
trigger: 'blur'
}
],
// progress: [
// {
// required: true,
// type: 'string',
// message: '请选择跟进状态',
// trigger: 'blur'
// }
// ],
// securityStatus: [
// {
// required: true,
// type: 'string',
// message: '请选择安全状态',
// trigger: 'blur'
// }
// ],
// companyName: [
// {
// required: true,
// type: 'string',
// message: '请选择租赁单位',
// trigger: 'blur'
// }
// ],
// appRegion: [
// {
// required: true,
// type: 'string',
// message: '请输入应用地址',
// trigger: 'blur'
// }
// ]
});
const { resetFields, validate, validateInfos } = useForm(form, rules);
const addUser = () => {
showAddUserForm.value = true;
};
const chooseCompanyName = (data: Company) => {
form.companyName = data.companyName;
form.companyId = data.companyId;
form.tenantId = data.tenantId;
};
// 添加开发成员
const addAppDevUser = (data: User) => {
addAppUser({
userId: data.userId,
appId: props.data?.appId,
role: 20
}).then((msg) => {
message.success(msg);
reload();
})
.catch((e) => {
message.error(e.message);
});
}
// 添加体验成员
const addAppExpUser = (data: User) => {
addAppUser({
userId: data.userId,
appId: props.data?.appId,
role: 10
}).then((msg) => {
message.success(msg);
reload();
})
.catch((e) => {
message.error(e.message);
});
}
// 移除成员
const removeUser = (data: AppUser) => {
removeAppUser(data.appUserId)
.then((msg) => {
message.success(msg);
reload();
})
.catch((e) => {
message.error(e.message);
});
};
const handleEditStatus = () => {
editStatus.value = !editStatus.value;
}
const chooseDirector = (data: User) => {
form.director = data.nickname;
};
const chooseDeveloper = (data: Company) => {
form.developer = data.companyName;
};
const chooseSalesman = (data: User) => {
form.salesman = data.nickname;
};
const changeAppCode = (e) => {
form.packageName = `com.gxwebsoft.${form.appCode}`;
form.appUrl = `https://apps.gxwebsoft.com/${form.appCode}`;
}
const onFile1 = (info: FileInfo) => {
let resFileList = [...info.fileList];
file1.value = resFileList.map((file) => {
if (file.response) {
file.url = file.response.url;
}
return file;
});
form.file1 = JSON.stringify(file1.value);
};
const onFile2 = (info: FileInfo) => {
let resFileList = [...info.fileList];
file2.value = resFileList.map((file) => {
if (file.response) {
file.url = file.response.url;
}
return file;
});
form.file2 = JSON.stringify(file2.value);
};
const onFile3 = (info: FileInfo) => {
let resFileList = [...info.fileList];
file3.value = resFileList.map((file) => {
if (file.response) {
file.url = file.response.url;
}
return file;
});
form.file3 = JSON.stringify(file3.value);
};
// 查看秘钥
const onAppSecret = (appId) => {
getAppSecret({ appId }).then((res) => {
console.log(res);
form.appSecret = res.data?.appSecret
showAppSecret.value = !showAppSecret.value;
});
};
// 重置秘钥
const onUpdateAppSecret = (appId) => {
Modal.confirm({
title: '提示',
content:
'重置AppSecret将会影响应用的正常运行,重置成功后请及时更换新的秘钥!确定要重置吗?',
icon: createVNode(ExclamationCircleOutlined),
maskClosable: true,
onOk: () => {
updateAppSecret({ appId }).then((res) => {
form.appSecret = res.data?.appSecret
message.success(res.message);
});
}
});
};
const config = ref({
height: 500,
images_upload_handler: (blobInfo, success, error) => {
const file = blobInfo.blob();
// 使用 axios 上传,实际开发这段建议写在 api 中再调用 api
const formData = new FormData();
formData.append('file', file, file.name);
uploadFile(<File>file)
.then((result) => {
if (result.length) {
if (file.size / 1024 / 1024 > 2) {
error('图片大小不能超过 2MB');
}
success(FILE_SERVER + result.path);
} else {
error('上传失败');
}
})
.catch((e) => {
message.error(e.message);
});
},
// 自定义文件上传(这里使用把选择的文件转成 blob 演示)
// file_picker_callback: (callback: any, _value: any, meta: any) => {
// const input = document.createElement("input");
// input.setAttribute("type", "file");
// // 设定文件可选类型
// if (meta.filetype === "image") {
// input.setAttribute("accept", "image/*");
// } else if (meta.filetype === "media") {
// input.setAttribute("accept", "video/*");
// }
// input.onchange = () => {
// const file = input.files?.[0];
// console.log(file);
// if (!file) {
// return;
// }
// if (meta.filetype === "media") {
// if (!file.type.startsWith("video/")) {
// editorRef.value?.alert({ content: "只能选择视频文件" });
// return;
// }
// }
// if (file.size / 1024 / 1024 > 20) {
// editorRef.value?.alert({ content: "大小不能超过 20MB" });
// return;
// }
// const reader = new FileReader();
// reader.onload = (e) => {
// if (e.target?.result != null) {
// const blob = new Blob([e.target.result], { type: file.type });
// callback(URL.createObjectURL(blob));
// }
// };
// reader.readAsArrayBuffer(file);
// };
// input.click();
// }
});
/* 粘贴图片上传服务器并插入编辑器 */
const onPaste = (e) => {
console.log(e);
const items = (e.clipboardData || e.originalEvent.clipboardData).items;
console.log(items);
let hasFile = false;
for (let i = 0; i < items.length; i++) {
if (items[i].type.indexOf('image') !== -1) {
let file = items[i].getAsFile();
const item: ItemType = {
file,
uid: (file as any).lastModified,
name: file.name
};
uploadFile(<File>item.file)
.then((result) => {
const addPath = '!['+result.name+']('+FILE_SERVER + result.path+')\n\r';
content.value = content.value + addPath
})
.catch((e) => {
message.error(e.message);
});
hasFile = true;
}
}
if (hasFile) {
e.preventDefault();
}
}
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form,
content: content.value,
requirement: requirement.value,
search: form.search ? 1 : 0,
images: JSON.stringify(images.value),
appTypeMultiple: JSON.stringify(form.appTypeMultiple)
};
const saveOrUpdate = isUpdate.value ? updateApp : addApp;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
// 上传文件:应用图标
const onUploadIcon = (item) => {
const { file } = item;
logo.value = [];
uploadFile(file)
.then((data) => {
logo.value.push({
uid: data.id,
url: FILE_THUMBNAIL + data.path,
status: 'done'
});
form.appIcon = data.path;
message.success('上传成功');
})
.catch((e) => {
message.error(e.message);
});
};
/* 上传事件 */
const uploadHandler = (file: File) => {
const item: ItemType = {
file,
uid: (file as any).uid,
name: file.name
};
if (!file.type.startsWith('image')) {
message.error('只能选择图片');
return;
}
if (file.size / 1024 / 1024 > 2) {
message.error('大小不能超过 2MB');
return;
}
onUpload(item);
};
// 上传文件
const onUpload = (item) => {
const { file } = item;
uploadFile(file)
.then((data) => {
images.value.push({
uid: data.id,
url: FILE_SERVER + data.path,
status: 'done'
});
})
.catch((e) => {
message.error(e.message);
});
};
const reload = () => {
loading.value = true;
// 加载项目成员
listAppUser({appId:props.data?.appId}).then(data => {
appUsers.value = data
})
// 加载企业信息
const companyId = props.data?.companyId;
pageCompany({companyId}).then(res => {
form.tenantId = undefined;
const list = res?.list;
if(list && list.length > 0){
form.tenantId = list[0].tenantId;
}
})
};
watch(
() => props.visible,
(visible) => {
if (visible) {
content.value = '';
requirement.value = '';
if (props.data) {
assignObject(form, props.data);
logo.value = [];
images.value = [];
if(props.data.appIcon){
logo.value.push({
uid: 0,
url: FILE_THUMBNAIL + props.data.appIcon,
status: 'done'
});
}
if(props.data.images){
const arr = JSON.parse(props.data.images);
arr.map((d, i) => {
images.value.push({
uid: d.uid,
url: d.url,
status: 'done'
});
});
}
if(props.data.appTypeMultiple){
form.appTypeMultiple = JSON.parse(props.data.appTypeMultiple)
}
if(props.data.search){
form.search = props.data.search == 1 ? true : 0;
}
if (props.data.content) {
content.value = props.data.content;
}
if (props.data.requirement){
requirement.value = props.data.requirement;
}
if (props.data.file1) {
file1.value = JSON.parse(props.data.file1);
}
if (props.data.file2) {
file2.value = JSON.parse(props.data.file2);
}
if (props.data.file3) {
file3.value = JSON.parse(props.data.file3);
}
isUpdate.value = true;
reload();
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
}
);
</script>
<style lang="less"></style>
<style lang="less">
.tab-pane {
min-height: 300px;
}
.ml-10 {
margin-left: 5px;
}
.upload-text {
margin-right: 70px;
}
.upload-image {
margin-bottom: 30px;
display: flex;
justify-content: center;
}
</style>