123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402 |
- <template>
- <el-dialog v-model="state.dialogVisible" width="70%" draggable title="编辑随手拍信息配置" @close="close">
- <el-form :model="state.ruleForm" label-width="110px" ref="ruleFormRef" :disabled="loading" scroll-to-error>
- <el-row :gutter="10">
- <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
- <el-form-item label="类型" prop="bulletinObj" :rules="[{ required: true, message: '请选择类型', trigger: 'change' }]">
- <el-select
- v-model="state.ruleForm.bulletinObj"
- placeholder="请选择类型"
- value-key="dicDataValue"
- class="w100"
- @change="
- (e:any) => {
- state.ruleForm.bulletinTypeId = e.dicDataValue;
- state.ruleForm.bulletinTypeName = e.dicDataName;
- }
- "
- >
- <el-option v-for="item in bulletinTypeOptions" :value="item" :key="item.dicDataValue" :label="item.dicDataName" />
- </el-select>
- </el-form-item>
- </el-col>
- <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
- <el-form-item label="来源" prop="sourceMode" :rules="[{ required: true, message: '请选择来源', trigger: 'change' }]">
- <el-select v-model="state.ruleForm.sourceMode" placeholder="请选择来源" value-key="dicDataValue" class="w100">
- <el-option v-for="item in bulletinSource" :value="item.dicDataValue" :key="item.dicDataValue" :label="item.dicDataName" />
- </el-select>
- </el-form-item>
- </el-col>
- <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
- <el-form-item label="标题" prop="title" :rules="[{ required: true, message: '请填写标题', trigger: 'blur' }]">
- <el-input v-model="state.ruleForm.title" placeholder="请填写标题" clearable show-word-limit maxlength="200"></el-input>
- </el-form-item>
- </el-col>
- <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
- <el-form-item label="文档编码" prop="no" :rules="[{ required: false, message: '请填写文档编码', trigger: 'blur' }]">
- <el-input v-model="state.ruleForm.no" placeholder="请填写文档编码" clearable></el-input>
- </el-form-item>
- </el-col>
- <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
- <el-form-item label="时间" prop="bulletinTime" :rules="[{ required: false, message: '请选择时间', trigger: 'change' }]">
- <el-date-picker
- v-model="state.ruleForm.bulletinTime"
- type="datetime"
- placeholder="请选择时间"
- value-format="YYYY-MM-DD[T]HH:mm:ss"
- class="w100"
- :disabled-date="disabledDate"
- popper-class="no-atTheMoment"
- />
- </el-form-item>
- </el-col>
- <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
- <el-form-item label="所属部门" prop="departmentId" :rules="[{ required: true, message: '请选择所属部门', trigger: 'change' }]">
- <el-cascader
- :options="orgsOptions"
- filterable
- :props="{ value: 'id', label: 'name', emitPath: false, checkStrictly: true }"
- placeholder="请选择所属部门"
- class="w100"
- v-model="state.ruleForm.departmentId"
- ref="orgRef"
- @change="changeOrg"
- clearable
- >
- </el-cascader>
- </el-form-item>
- </el-col>
- <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
- <el-form-item label="来源部门" prop="sourceOrgName" :rules="[{ required: false, message: '请填写来源部门', trigger: 'change' }]">
- <el-input v-model="state.ruleForm.sourceOrgName" placeholder="请填写来源部门" clearable></el-input>
- </el-form-item>
- </el-col>
- <el-col>
- <el-form-item label="公告标识">
- <el-checkbox v-model="state.ruleForm.isOpen">是否公开</el-checkbox>
- <el-checkbox v-model="state.ruleForm.isBold">是否加粗</el-checkbox>
- <el-checkbox v-model="state.ruleForm.isOpenWebsite">网站公开</el-checkbox>
- <el-checkbox v-model="state.ruleForm.isWeibo">微博公开</el-checkbox>
- <el-checkbox v-model="state.ruleForm.isWeChat">微信公开</el-checkbox>
- <el-checkbox v-model="state.ruleForm.isTop">是否置顶</el-checkbox>
- <el-checkbox v-model="state.ruleForm.isPopup">是否飘窗</el-checkbox>
- </el-form-item>
- </el-col>
- <!-- 安全卫士 -->
- <template v-if="state.ruleForm.bulletinTypeId === 'aqws'">
- <el-col>
- <el-form-item label="志愿者类型" prop="safetyTypeId" :rules="[{ required: true, message: '请选择志愿者类型', trigger: 'change' }]">
- <el-checkbox-group v-model="state.ruleForm.safetyTypeId">
- <el-checkbox :label="item.dicDataName" :value="item.dicDataValue" v-for="item in safetyTypesOptions" :key="item.dicDataValue" />
- </el-checkbox-group>
- </el-form-item>
- </el-col>
- <el-col>
- <el-form-item label="形式" prop="shape" :rules="[{ required: true, message: '请选择形式', trigger: 'change' }]">
- <el-radio-group v-model="state.ruleForm.shape" @change="selectType">
- <el-radio :value="0">消息</el-radio>
- <el-radio :value="1">视频</el-radio>
- </el-radio-group>
- </el-form-item>
- </el-col>
- </template>
- <template v-if="state.ruleForm.shape === 0">
- <el-col>
- <el-form-item label="视频地址" prop="videoPath" :rules="[{ required: false, message: '请填写视频地址', trigger: 'blur' }]">
- <el-input v-model="state.ruleForm.videoPath" placeholder="请填写视频地址" clearable></el-input>
- </el-form-item>
- </el-col>
- <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
- <el-form-item label="内容" prop="content" :rules="[{ required: true, message: '请填写内容', trigger: 'blur' }]">
- <editor v-model:get-html="state.ruleForm.content" placeholder="请填写内容" height="450px" />
- </el-form-item>
- </el-col>
- </template>
- <template v-else>
- <el-col>
- <el-form-item label="视频封面" prop="videoCoverImgUrl" :rules="[{ required: true, message: '请上传视频封面', trigger: 'change' }]">
- <el-upload
- class="avatar-uploader"
- :action="action"
- :show-file-list="false"
- :on-success="updateSuccessCareCell"
- ref="uploadListRefCareCell"
- name="fileData"
- :on-error="onUploadError"
- accept="image/*"
- :disabled="uploadingDisabled"
- >
- <img v-if="careCellImgUrl" :src="careCellImgUrl" class="avatar" alt="" />
- <SvgIcon v-else class="avatar-uploader-icon" name="ele-Plus" size="28px" />
- </el-upload>
- </el-form-item>
- </el-col>
- <el-col>
- <el-form-item label="视频上传" prop="videoPath" :rules="[{ required: true, message: '请上传视频', trigger: 'change' }]">
- <el-upload
- ref="uploadVideoRef"
- class="upload-demo w100"
- :action="action"
- :limit="1"
- name="fileData"
- :on-error="onUploadError"
- :on-exceed="handleExceed"
- accept="video/mp4,video/mov"
- :on-success="updateSuccessVideoPath"
- v-model:file-list="fileList"
- :disabled="uploadingDisabled"
- :before-upload="beforeUpload"
- :on-remove="handRemove"
- >
- <template #trigger>
- <el-button type="primary" :loading="uploadLoading" :disabled="uploadingDisabled">
- <SvgIcon name="ele-Upload" class="mr5" /> {{ uploadLoading ? '上传中,请稍等...' : '视频上传' }}
- </el-button>
- </template>
- <template #tip>
- <div class="el-upload__tip">视频上传:支持上传mp4、mov格式的视频</div>
- </template>
- </el-upload>
- </el-form-item>
- </el-col>
- </template>
- </el-row>
- </el-form>
- <template #footer>
- <span class="dialog-footer">
- <el-button @click="closeDialog" class="default-button">取 消</el-button>
- <el-button type="primary" @click="onSubmit(ruleFormRef)" :loading="loading">确 定</el-button>
- </span>
- </template>
- </el-dialog>
- </template>
- <script setup lang="tsx" name="noticeDetail">
- import { reactive, ref, defineAsyncComponent, computed } from 'vue';
- import { throttle } from '@/utils/tools';
- import { ElMessage, FormInstance, UploadFile, UploadFiles } from 'element-plus';
- import { disabledDate } from '@/utils/constants';
- import { ElCheckbox } from 'element-plus';
- import { editSnapshotBulletin, editSnapshotBulletinBase, getSnapshotBulletinDetail } from '@/api/snapshot/info';
- // 引入组件
- const Editor = defineAsyncComponent(() => import('@/components/Editor/index.vue')); // 富文本编辑器
- // 定义子组件向父组件传值/事件
- const emit = defineEmits(['updateList']);
- // 定义变量内容
- const state = reactive<any>({
- dialogVisible: false,
- ruleForm: {
- bulletinTypeId: null, // 公告类型
- bulletinTypeName: null, // 公告类型名称
- title: null, // 标题
- no: null, // 文档编码
- bulletinTime: null, // 时间
- departmentId: null, // 所属部门ID
- departmentName: null, // 所属部门名称
- sourceOrgName: null, // 来源单位名称
- isOpen: false, // 公开
- isBold: false, // 加粗
- isOpenWebsite: false, // 网站公开
- isWeibo: false, // 微博公开
- isWeChat: false, // 微信公开
- isTop: false, // 置顶
- isPopup: false, // 弹窗
- content: null, // 内容
- videoPath: null, // 视频地址
- sourceMode: '1', // 来源方式 默认自建
- safetyTypeId: [], // 志愿者类型
- shape: 0, // 公告形式
- videoCoverImgUrl: null, // 视频封面
- },
- });
- let loading = ref<boolean>(false); // 加载状态
- // 打开弹窗
- const ruleFormRef = ref<RefType>();
- const bulletinTypeOptions = ref<EmptyArrayType>([]); // 公告类型
- const orgsOptions = ref<EmptyArrayType>([]); // 来源单位
- const bulletinSource = ref<EmptyArrayType>([]); // 来源
- const safetyTypesOptions = ref<EmptyArrayType>([]); // 志愿者类型
- const openDialog = async (id: string) => {
- loading.value = true;
- state.dialogVisible = true;
- try {
- const [responseAnnounce, result] = await Promise.all([editSnapshotBulletinBase(), getSnapshotBulletinDetail(id)]);
- bulletinTypeOptions.value = responseAnnounce.result?.bulletinType ?? [];
- orgsOptions.value = responseAnnounce.result?.orgsOptions ?? [];
- bulletinSource.value = responseAnnounce.result?.bulletinSource ?? [];
- safetyTypesOptions.value = responseAnnounce.result?.safetyTypes ?? [];
- state.ruleForm = result.result ?? {};
- state.ruleForm.bulletinObj = {
- dicDataValue: result.result?.bulletinTypeId,
- dicDataName: result.result?.bulletinTypeName,
- };
- if (result.result?.videoCoverImgUrl) careCellImgUrl.value = import.meta.env.VITE_API_UPLOAD_URL + result.result?.videoCoverImgUrl; // 视频封面
- if (result.result?.videoPath) {
- //视频地址
- fileList.value = [
- {
- name: '视频',
- url: import.meta.env.VITE_API_UPLOAD_URL + result.result?.videoPath,
- },
- ];
- }
- loading.value = false;
- } catch (error) {
- console.log(error);
- loading.value = false;
- }
- };
- const orgRef = ref<RefType>(); // 所属部门
- const changeOrg = () => {
- const currentNode = orgRef.value.getCheckedNodes();
- if (currentNode) state.ruleForm.departmentName = currentNode[0].label;
- else state.ruleForm.departmentName = null;
- };
- // 选择类型
- const selectType = () => {
- if (state.ruleForm.shape === 0) {
- state.ruleForm.videoPath = null;
- careCellImgUrl.value = '';
- state.ruleForm.videoCoverImgUrl = null;
- fileList.value = [];
- } else {
- state.ruleForm.content = null;
- }
- };
- // 上传地址
- const action = computed(() => {
- return import.meta.env.VITE_API_UPLOAD_URL + '/file/upload?source=hotline';
- });
- // 上传视频封面
- const careCellImgUrl = ref('');
- const uploadListRefCareCell = ref<RefType>();
- const updateSuccessCareCell = (response: any, uploadFile: UploadFile, uploadFiles: UploadFiles) => {
- if (response.result.path) {
- careCellImgUrl.value = import.meta.env.VITE_API_UPLOAD_URL + response.result.path;
- // careCellImgUrl.value = URL.createObjectURL(uploadFile.raw!);
- state.ruleForm.videoCoverImgUrl = response.result.path;
- } else {
- uploadListRefCareCell.value.handleRemove(uploadFile);
- ElMessage.error('上传失败');
- }
- setTimeout(() => {
- uploadLoading.value = false; // 模拟上传过程
- uploadingDisabled.value = false;
- }, 100);
- };
- // 上传视频
- const uploadVideoRef = ref<RefType>();
- const fileList = ref<UploadFiles>([
- /*{
- name: '12239_1739325758.mp4',
- url: '/file/files_indefinitely?id=08dd8555-5673-4e45-80eb-12cdc7ac8125&expires=1745739172&clientid=hotline&signature=BF5AD8DBEF553CDA7750BBDF01A07C33689FAB83DB5163CADE787E327E366DD426861371167F86296E6DE9C696F65F3C92F3742DE762EE50',
- },*/
- ]);
- const uploadLoading = ref(false);
- const beforeUpload = () => {
- uploadingDisabled.value = true;
- uploadLoading.value = true; // 模拟上传过程
- };
- const handleExceed = (files: any, uploadFiles: UploadUserFile[]) => {
- ElMessage.warning(`当前限制最多上传1个文件,已经上传了${uploadFiles.length}个文件,本次选择了 ${files.length} 个文件。`);
- setTimeout(() => {
- uploadLoading.value = false; // 模拟上传过程
- }, 100);
- };
- const uploadingDisabled = ref(false);
- const updateSuccessVideoPath = (response: any, uploadFile: UploadFile, uploadFiles: UploadFiles) => {
- if (response.result.path) {
- state.ruleForm.videoPath = response.result.path;
- } else {
- uploadVideoRef.value.handleRemove(uploadFile);
- ElMessage.error('上传失败');
- }
- console.log(fileList.value, state.ruleForm.videoPath, '111');
- setTimeout(() => {
- uploadLoading.value = false; // 模拟上传过程
- uploadingDisabled.value = false;
- }, 100);
- };
- // 删除文件
- const handRemove = (uploadFile: UploadFile, uploadFiles: UploadFiles) => {
- fileList.value = uploadFiles;
- state.ruleForm.videoPath = null;
- };
- // 上传失败
- const onUploadError = (error: Error) => {
- try {
- const errMessage = JSON.parse(error.message)?.message ?? '上传失败';
- ElMessage.error(errMessage);
- } catch (e) {
- ElMessage.error('上传失败');
- }
- setTimeout(() => {
- uploadLoading.value = false; // 模拟上传过程
- uploadingDisabled.value = false;
- }, 100);
- };
- // 保存
- const onSubmit = throttle(async (formEl: FormInstance | undefined) => {
- if (!formEl) return;
- await formEl.validate((valid: boolean) => {
- if (!valid) return;
- loading.value = true;
- const request = {
- ...state.ruleForm,
- };
- editSnapshotBulletin(request)
- .then(() => {
- loading.value = false;
- closeDialog();
- emit('updateList');
- ElMessage.success('操作成功');
- })
- .catch(() => {
- loading.value = false;
- });
- });
- }, 300);
- // 关闭弹窗
- const closeDialog = () => {
- state.dialogVisible = false;
- };
- const close = () => {
- ruleFormRef.value?.clearValidate();
- ruleFormRef.value?.resetFields();
- state.ruleForm.bulletinTypeId = null;
- };
- // 暴露变量
- defineExpose({
- openDialog,
- closeDialog,
- });
- </script>
- <style scoped lang="scss">
- .avatar-uploader .avatar {
- width: 178px;
- height: 178px;
- display: block;
- }
- </style>
- <style>
- .avatar-uploader .el-upload {
- border: 1px dashed var(--el-border-color);
- border-radius: 6px;
- cursor: pointer;
- position: relative;
- overflow: hidden;
- transition: var(--el-transition-duration-fast);
- }
- .avatar-uploader .el-upload:hover {
- border-color: var(--el-color-primary);
- }
- .avatar-uploader-icon {
- font-size: 28px;
- color: #8c939d;
- width: 178px;
- height: 178px;
- text-align: center;
- }
- </style>
|