1、服务指令媒体资源同步

This commit is contained in:
1378012178@qq.com 2025-05-27 14:14:07 +08:00
parent dae83f0919
commit 2ba5056fd9
23 changed files with 1685 additions and 57 deletions

View File

@ -0,0 +1,40 @@
<template>
<div class="media-detail">
<a-descriptions bordered :column="1">
<a-descriptions-item label="资源名称">{{ record.name }}</a-descriptions-item>
<a-descriptions-item label="文件类型">{{ record.fileType_dictText }}</a-descriptions-item>
<a-descriptions-item label="备注">{{ record.descr || '无' }}</a-descriptions-item>
<a-descriptions-item label="预览">
<div class="detail-preview-container">
<PreviewComponent :izNetUrl="record.izNetUrl" :file-type="record.fileType" :file-path="record.filePath" :is-detail="true" />
</div>
</a-descriptions-item>
</a-descriptions>
</div>
</template>
<script lang="ts" setup>
import { defineProps } from 'vue';
import PreviewComponent from './PreviewPickerComponent.vue';
const props = defineProps({
record: {
type: Object,
default: () => ({})
}
});
const { record } = props;
</script>
<style scoped>
.media-detail {
padding: 10px;
}
.detail-preview-container {
width: 100%;
display: flex;
justify-content: center;
}
</style>

View File

@ -0,0 +1,73 @@
import { defHttp } from '/@/utils/http/axios';
import { useMessage } from '/@/hooks/web/useMessage';
const { createConfirm } = useMessage();
enum Api {
list = '/mediamanage/mediaManage/list',
save = '/mediamanage/mediaManage/add',
edit = '/mediamanage/mediaManage/edit',
deleteOne = '/mediamanage/mediaManage/delete',
deleteBatch = '/mediamanage/mediaManage/deleteBatch',
importExcel = '/mediamanage/mediaManage/importExcel',
exportXls = '/mediamanage/mediaManage/exportXls',
getUrl = '/mediamanage/mediaManage/getUrl',
}
/**
* api
* @param params
*/
export const getExportUrl = Api.exportXls;
/**
* api
*/
export const getImportUrl = Api.importExcel;
/**
*
* @param params
*/
export const list = (params) => defHttp.get({ url: Api.list, params });
/**
*
* @param params
* @param handleSuccess
*/
export const deleteOne = (params, handleSuccess) => {
return defHttp.delete({ url: Api.deleteOne, params }, { joinParamsToUrl: true }).then(() => {
handleSuccess();
});
};
/**
*
* @param params
* @param handleSuccess
*/
export const batchDelete = (params, handleSuccess) => {
createConfirm({
iconType: 'warning',
title: '确认删除',
content: '是否删除选中数据',
okText: '确认',
cancelText: '取消',
onOk: () => {
return defHttp.delete({ url: Api.deleteBatch, data: params }, { joinParamsToUrl: true }).then(() => {
handleSuccess();
});
},
});
};
/**
*
* @param params
* @param isUpdate
*/
export const saveOrUpdate = (params, isUpdate) => {
let url = isUpdate ? Api.edit : Api.save;
return defHttp.post({ url: url, params }, { isTransformResponse: false });
};

View File

@ -0,0 +1,344 @@
<template>
<a-modal :visible="visible" width="70vw" :title="title" :footer="null" @cancel="handleCancel">
<div class="resource-picker-container">
<!-- 搜索区域 -->
<div class="search-area">
<a-form layout="inline" :model="searchParams" :label-col="{ span: 8 }" :wrapper-col="{ span: 16 }">
<a-form-item label="资源名称">
<a-input v-model:value="searchParams.name" placeholder="请输入资源名称" />
</a-form-item>
<a-form-item label="文件类型" v-if="!fixedFileType">
<j-dict-select-tag v-model:value="searchParams.fileType" dictCode="file_type" placeholder="请选择文件类型"
allowClear />
</a-form-item>
<a-button type="primary" @click="handleSearch">查询</a-button>
<a-button style="margin-left: 8px" @click="resetSearch">重置</a-button>
</a-form>
</div>
<!-- 表格区域 -->
<div class="table-wrapper" :style="{ height: 'calc(50vh - 100px)' }">
<a-table :columns="columns" :data-source="dataSource" :pagination="pagination" :loading="loading" rowKey="id"
@change="handleTableChange" :row-selection="rowSelection" :scroll="{ y: '100%' }" :customRow="customRow"
size="middle">
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'filePath'">
<div>
<PreviewComponent :izNetUrl="record.izNetUrl" :file-type="record.fileType" :file-path="record.filePath"
:file-name="record.name" />
</div>
</template>
<template v-if="column.key === 'action'">
<a-button type="link" @click.stop="handleViewDetail(record)">详情</a-button>
</template>
</template>
</a-table>
</div>
<!-- 底部操作按钮 -->
<div class="footer-area">
<a-button @click="handleCancel">取消</a-button>
<a-button type="primary" @click="handleConfirm" :disabled="!selectedRowKeys.length" style="margin-left: 8px">
确定
</a-button>
</div>
</div>
<!-- 详情弹窗 -->
<a-modal v-model:visible="detailVisible" :title="detailTitle" :width="800" :footer="null">
<MediaDetail :record="currentRecord" />
</a-modal>
</a-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, defineProps, defineEmits, watch, computed, onMounted } from 'vue';
import { list } from './MediaManagePicker.api';
import PreviewComponent from './PreviewPickerComponent.vue';
import MediaDetail from './MediaDetail.vue';
import JDictSelectTag from '/@/components/Form/src/jeecg/components/JDictSelectTag.vue';
import { message } from 'ant-design-vue';
const props = defineProps({
visible: {
type: Boolean,
default: false
},
title: {
type: String,
default: '选择媒体资源'
},
multiple: {
type: Boolean,
default: false
},
maxSelect: {
type: Number,
default: 1
},
//
fileType: {
type: String,
default: ''
}
});
const emit = defineEmits(['update:visible', 'confirm']);
const visible = ref(props.visible);
const loading = ref(false);
const dataSource = ref([]);
const selectedRowKeys = ref<string[]>([]);
const selectedRows = ref<any[]>([]);
const detailVisible = ref(false);
const currentRecord = reactive({});
const detailTitle = ref('资源详情');
//
const fixedFileType = computed(() => {
if (!!props.fileType) {
if (props.fileType == 'any') {
return ''
} else if (props.fileType == 'img') {
return 'image'
} else {
return props.fileType
}
} else {
return ''
}
});
const searchParams = reactive({
name: '',
fileType: props.fileType || '' // 使fileType
});
const pagination = reactive({
current: 1,
pageSize: 10,
total: 0,
showSizeChanger: true,
showQuickJumper: true,
pageSizeOptions: ['10', '20', '30', '50'],
showTotal: total => `${total}`
});
const columns = [
{
title: '资源名称',
dataIndex: 'name',
align: 'center',
key: 'name',
width: '25%'
},
{
title: '文件类型',
dataIndex: 'fileType_dictText',
align: 'center',
key: 'fileType',
width: '15%'
},
{
title: '预览',
align: 'center',
key: 'filePath',
width: '50%'
},
{
title: '操作',
align: 'center',
key: 'action',
width: '10%'
}
];
//
const customRow = (record) => {
return {
onClick: () => {
handleRowClick(record);
}
};
};
//
const rowSelection = computed(() => ({
selectedRowKeys: selectedRowKeys.value,
onChange: onSelectChange,
type: props.maxSelect === 1 ? 'radio' : 'checkbox',
getCheckboxProps: (record) => ({
disabled: props.maxSelect !== -1 && selectedRowKeys.value.length >= props.maxSelect && !selectedRowKeys.value.includes(record.id)
})
}));
// visible
watch(() => props.visible, (val) => {
visible.value = val;
if (val) {
fetchData();
}
});
// fileType
watch(() => props.fileType, (newVal) => {
searchParams.fileType = newVal || '';
if (visible.value) {
fetchData();
}
});
//
const fetchData = async () => {
try {
loading.value = true;
const params = {
...searchParams,
pageNo: pagination.current,
pageSize: pagination.pageSize
};
// 使
if (fixedFileType.value) {
params.fileType = props.fileType;
}
const res = await list(params);
dataSource.value = res.records || [];
pagination.total = res.total || 0;
} catch (error) {
console.error('获取数据失败:', error);
} finally {
loading.value = false;
}
};
//
const handleTableChange = (pag, filters, sorter) => {
pagination.current = pag.current;
pagination.pageSize = pag.pageSize;
fetchData();
};
//
const handleSearch = () => {
pagination.current = 1;
fetchData();
};
//
const resetSearch = () => {
searchParams.name = '';
//
if (!fixedFileType.value) {
searchParams.fileType = '';
}
handleSearch();
};
//
const onSelectChange = (selectedKeys: string[], selectedRowsInfo: any[]) => {
if (props.maxSelect === 1) {
//
selectedRowKeys.value = selectedKeys.slice(-1);
selectedRows.value = selectedRowsInfo.slice(-1);
} else if (props.maxSelect !== -1 && selectedKeys.length > props.maxSelect) {
//
message.warning(`最多只能选择${props.maxSelect}`);
} else {
selectedRowKeys.value = selectedKeys;
selectedRows.value = selectedRowsInfo;
}
};
//
const handleRowClick = (record) => {
const selectedIndex = selectedRowKeys.value.indexOf(record.id);
if (props.maxSelect === 1) {
//
selectedRowKeys.value = [record.id];
selectedRows.value = [record];
} else {
if (selectedIndex >= 0) {
//
selectedRowKeys.value.splice(selectedIndex, 1);
selectedRows.value.splice(selectedIndex, 1);
} else {
//
if (props.maxSelect === -1 || selectedRowKeys.value.length < props.maxSelect) {
selectedRowKeys.value.push(record.id);
selectedRows.value.push(record);
} else {
message.warning(`最多只能选择${props.maxSelect}`);
}
}
}
};
//
const handleViewDetail = (record) => {
Object.assign(currentRecord, record);
detailTitle.value = `资源详情 - ${record.name}`;
detailVisible.value = true;
};
//
const handleConfirm = () => {
emit('confirm', (props.maxSelect != 1) ? selectedRows.value : selectedRows.value[0]);
handleCancel();
};
//
const handleCancel = () => {
selectedRowKeys.value = [];
selectedRows.value = [];
emit('update:visible', false);
};
defineExpose({
fetchData
});
</script>
<style scoped>
.resource-picker-container {
padding: 10px;
display: flex;
flex-direction: column;
height: 100%;
}
.search-area {
margin-bottom: 16px;
}
.table-wrapper {
flex: 1;
overflow: hidden;
margin-bottom: 16px;
}
.footer-area {
text-align: right;
padding-top: 16px;
border-top: 1px solid #f0f0f0;
}
.preview-wrapper {
max-width: 300px;
max-height: 150px;
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
}
/* 添加行点击效果 */
:deep(.ant-table-row) {
cursor: pointer;
}
:deep(.ant-table-row:hover) {
background-color: #f5f5f5;
}
</style>

View File

@ -0,0 +1,216 @@
<template>
<div class="preview-container">
<!-- 图片预览 -->
<div v-if="fileType === 'image' && filePath" class="preview-item image-preview">
<img :src="getFullPath(filePath)" :style="imgStyle" />
</div>
<!-- 视频预览 -->
<div v-if="fileType === 'video' && filePath" class="preview-item video-preview">
<video v-if="props.isDetail" ref="videoPlayer" controls :src="getFullPath(filePath)"
:poster="getVideoPoster(filePath)" :style="imgStyle"></video>
<video v-else ref="videoPlayer" :src="getFullPath(filePath)" :poster="getVideoPoster(filePath)"
:style="imgStyle"></video>
</div>
<!-- 音频预览 -->
<div v-if="fileType === 'audio' && filePath" class="preview-item audio-preview">
<div class="audio-wrapper">
<audio ref="audioPlayer" controls :src="getFullPath(filePath)"></audio>
</div>
</div>
<!-- 文档预览 -->
<div v-if="fileType === 'document' && filePath" class="preview-item doc-preview">
<div class="doc-icon">
<FileOutlined style="font-size: 48px; color: #1890ff;" />
</div>
<div class="doc-info">
<div class="doc-name">{{ fileName }}</div>
<a-button type="link" size="small" @click="handlePreviewDocument">预览</a-button>
</div>
</div>
<!-- 其他类型文件 -->
<div v-if="!['image', 'video', 'audio', 'document'].includes(fileType) && filePath"
class="preview-item other-preview">
<div class="other-icon">
<FileUnknownOutlined style="font-size: 48px; color: #999;" />
</div>
<div class="other-info">
<div class="other-name">{{ fileName }}</div>
<a-button type="link" size="small" @click="handleDownloadFile">下载</a-button>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref, watch, computed, onUnmounted, onMounted } from 'vue';
import { getFileAccessHttpUrl } from '/@/utils/common/compUtils';
import { FileOutlined, FileUnknownOutlined } from '@ant-design/icons-vue';
import { sysUrl } from '/@/utils/sysBaseInfo/MediaManagePicker.api';
const videoPlayer = ref<HTMLVideoElement | null>(null);
const audioPlayer = ref<HTMLAudioElement | null>(null);
const props = defineProps({
fileType: {
type: String,
default: ''
},
filePath: {
type: String,
default: ''
},
fileName: {
type: String,
default: ''
},
isDetail: {
type: Boolean,
default: false
},
izNetUrl: {
type: String,
default: 'local'
},
}); const sysUrlValue = ref('')
const imgStyle = computed(() => ({
maxWidth: props.isDetail ? '100%' : '80px',
maxHeight: props.isDetail ? '120px' : '80px',
objectFit: 'contain'
}));
const getFullPath = (path: string) => {
if (props.izNetUrl == 'net') {
return sysUrlValue.value + path
} else if (props.izNetUrl == 'local') {
return getFileAccessHttpUrl(path);
} else {
return path
}
};
const getVideoPoster = (path: string) => {
//
return '';
};
const handlePreviewDocument = () => {
window.open(getFullPath(props.filePath), '_blank');
};
const handleDownloadFile = () => {
const link = document.createElement('a');
link.href = getFullPath(props.filePath);
link.download = props.fileName || 'download';
link.click();
};
//
const stopAllMedia = () => {
if (videoPlayer.value) {
videoPlayer.value.pause();
videoPlayer.value.currentTime = 0;
}
if (audioPlayer.value) {
audioPlayer.value.pause();
audioPlayer.value.currentTime = 0;
}
};
onMounted(() => {
sysUrl().then(res => {
sysUrlValue.value = res.url
})
})
//
onUnmounted(() => {
stopAllMedia();
});
</script>
<style scoped>
.preview-container {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
}
/* 图片预览样式 */
.image-preview {
max-width: 200px;
max-height: 150px;
}
/* 音频预览样式 */
.audio-preview {
width: 200px;
}
.audio-wrapper {
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
}
.audio-wrapper audio {
width: 100%;
}
.audio-title {
margin-top: 8px;
font-size: 12px;
text-align: center;
word-break: break-all;
}
/* 文档预览样式 */
.doc-preview {
display: flex;
flex-direction: column;
align-items: center;
width: 200px;
}
.doc-icon {
margin-bottom: 8px;
}
.doc-info {
text-align: center;
}
.doc-name {
font-size: 12px;
margin-bottom: 8px;
word-break: break-all;
}
/* 其他文件预览样式 */
.other-preview {
display: flex;
flex-direction: column;
align-items: center;
width: 200px;
}
.other-icon {
margin-bottom: 8px;
}
.other-info {
text-align: center;
}
.other-name {
font-size: 12px;
margin-bottom: 8px;
word-break: break-all;
}
</style>

View File

@ -0,0 +1,10 @@
import { defHttp } from '/@/utils/http/axios';
enum Api {
sysUrl = '/api/baseInfo/sysUrl',
}
/**
*
*/
export const sysUrl = () => defHttp.get({ url: Api.sysUrl });

View File

@ -0,0 +1,79 @@
import { defHttp } from '/@/utils/http/axios';
import { useMessage } from '/@/hooks/web/useMessage';
const { createConfirm } = useMessage();
enum Api {
list = '/mediamanage/mediaManage/list',
save = '/mediamanage/mediaManage/add',
edit = '/mediamanage/mediaManage/edit',
deleteOne = '/mediamanage/mediaManage/delete',
deleteBatch = '/mediamanage/mediaManage/deleteBatch',
importExcel = '/mediamanage/mediaManage/importExcel',
exportXls = '/mediamanage/mediaManage/exportXls',
getUrl = '/mediamanage/mediaManage/getUrl',
}
/**
* api
* @param params
*/
export const getExportUrl = Api.exportXls;
/**
* api
*/
export const getImportUrl = Api.importExcel;
/**
*
* @param params
*/
export const list = (params) => defHttp.get({ url: Api.list, params });
/**
*
* @param params
* @param handleSuccess
*/
export const deleteOne = (params, handleSuccess) => {
return defHttp.delete({ url: Api.deleteOne, params }, { joinParamsToUrl: true }).then(() => {
handleSuccess();
});
};
/**
*
* @param params
* @param handleSuccess
*/
export const batchDelete = (params, handleSuccess) => {
createConfirm({
iconType: 'warning',
title: '确认删除',
content: '是否删除选中数据',
okText: '确认',
cancelText: '取消',
onOk: () => {
return defHttp.delete({ url: Api.deleteBatch, data: params }, { joinParamsToUrl: true }).then(() => {
handleSuccess();
});
},
});
};
/**
*
* @param params
* @param isUpdate
*/
export const saveOrUpdate = (params, isUpdate) => {
let url = isUpdate ? Api.edit : Api.save;
return defHttp.post({ url: url, params }, { isTransformResponse: false });
};
/**
*
* @param params
*/
export const getUrl = () => defHttp.get({ url: Api.getUrl });

View File

@ -0,0 +1,41 @@
import {BasicColumn} from '/@/components/Table';
import {FormSchema} from '/@/components/Table';
import { rules} from '/@/utils/helper/validator';
import { render } from '/@/utils/common/renderUtils';
import { getWeekMonthQuarterYear } from '/@/utils';
//列表数据
export const columns: BasicColumn[] = [
{
title: '名称',
align: "center",
dataIndex: 'name'
},
{
title: '备注',
align: "center",
dataIndex: 'descr'
},
{
title: '系统功能',
align: "center",
dataIndex: 'sysFunc_dictText'
},
{
title: '文件类型',
align: "center",
dataIndex: 'fileType_dictText'
},
{
title: '文件预览',
align: "center",
dataIndex: 'filePath'
},
];
// 高级查询数据
export const superQuerySchema = {
name: {title: '名称',order: 0,view: 'text', type: 'string',},
descr: {title: '备注',order: 1,view: 'textarea', type: 'string',},
fileType: {title: '文件类型',order: 2,view: 'text', type: 'string',},
filePath: {title: '文件预览',order: 3,view: 'text', type: 'string',},
};

View File

@ -0,0 +1,305 @@
<template>
<div class="p-2">
<!--查询区域-->
<div class="jeecg-basic-table-form-container">
<a-form ref="formRef" @keyup.enter.native="searchQuery" :model="queryParam" :label-col="labelCol"
:wrapper-col="wrapperCol">
<a-row :gutter="24">
<a-col :lg="6">
<a-form-item name="name">
<template #label><span title="名称">名称</span></template>
<JInput v-model:value="queryParam.name" placeholder="请输入名称" />
</a-form-item>
</a-col>
<a-col :lg="6">
<a-form-item name="sysFunc">
<template #label><span title="系统功能">系统功能</span></template>
<j-dict-select-tag type='list' v-model:value="queryParam.sysFunc" dictCode="sys_function"
placeholder="请选择系统功能" allowClear />
</a-form-item>
</a-col>
<a-col :lg="6">
<a-form-item name="fileType">
<template #label><span title="文件类型">文件类型</span></template>
<j-dict-select-tag type='list' v-model:value="queryParam.fileType" dictCode="file_type"
placeholder="请选择文件类型" allowClear />
</a-form-item>
</a-col>
<a-col :xl="6" :lg="7" :md="8" :sm="24">
<span style="float: left; overflow: hidden" class="table-page-search-submitButtons">
<a-col :lg="6">
<a-button type="primary" preIcon="ant-design:search-outlined" @click="searchQuery">查询</a-button>
<a-button type="primary" preIcon="ant-design:reload-outlined" @click="searchReset"
style="margin-left: 8px">重置</a-button>
</a-col>
</span>
</a-col>
</a-row>
</a-form>
</div>
<!--引用表格-->
<BasicTable @register="registerTable" :rowSelection="rowSelection">
<!--插槽:table标题-->
<template #tableTitle>
<a-button type="primary" v-auth="'mediamanage:nu_media_manage:add'" @click="handleAdd"
preIcon="ant-design:plus-outlined"> 新增</a-button>
<a-dropdown v-if="selectedRowKeys.length > 0">
<template #overlay>
<a-menu>
<a-menu-item key="1" @click="batchHandleDelete">
<Icon icon="ant-design:delete-outlined"></Icon>
删除
</a-menu-item>
</a-menu>
</template>
<a-button v-auth="'mediamanage:nu_media_manage:deleteBatch'">批量操作
<Icon icon="mdi:chevron-down"></Icon>
</a-button>
</a-dropdown>
</template>
<!--操作栏-->
<template #action="{ record }">
<TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)" />
</template>
<template v-slot:bodyCell="{ column, record, index, text }">
<template v-if="column.dataIndex === 'filePath'">
<!-- 图片 -->
<img style="max-width: 120px; max-height: 80px;" v-if="record.fileType === 'image'"
:src="transPreviewUrl(record)" :alt="record.fileName || 'Image'">
<!-- 音频 -->
<audio style="max-width: 120px; max-height: 80px;" v-if="record.fileType === 'audio'" controls
:src="transPreviewUrl(record)">
您的浏览器不支持 audio 标签
</audio>
<!-- 视频 -->
<video style="max-width: 120px; max-height: 80px;" v-if="record.fileType === 'video'" controls
:src="transPreviewUrl(record)">
您的浏览器不支持 video 标签
</video>
<!-- 文档 -->
<span v-if="record.fileType === 'document'">-</span>
</template>
</template>
</BasicTable>
<!-- 表单区域 -->
<MediaManageModal ref="registerModal" :urlPrefix="urlPrefix" @success="handleSuccess"></MediaManageModal>
</div>
</template>
<script lang="ts" name="mediamanage-mediaManage" setup>
import { ref, reactive, onMounted } from 'vue';
import { BasicTable, useTable, TableAction } from '/@/components/Table';
import { useListPage } from '/@/hooks/system/useListPage';
import { columns, superQuerySchema } from './MediaManage.data';
import { list, deleteOne, batchDelete, getImportUrl, getExportUrl, getUrl } from './MediaManage.api';
import { downloadFile } from '/@/utils/common/renderUtils';
import MediaManageModal from './components/MediaManageModal.vue'
import { useUserStore } from '/@/store/modules/user';
import JDictSelectTag from '/@/components/Form/src/jeecg/components/JDictSelectTag.vue';
import JInput from "/@/components/Form/src/jeecg/components/JInput.vue";
import { getFileAccessHttpUrl } from '/@/utils/common/compUtils';
const formRef = ref();
const queryParam = reactive<any>({});
const toggleSearchStatus = ref<boolean>(false);
const registerModal = ref();
const userStore = useUserStore();
//table
const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
tableProps: {
title: '媒体资源管理',
api: list,
columns,
canResize: false,
useSearchForm: false,
actionColumn: {
width: 150,
fixed: 'right',
},
beforeFetch: async (params) => {
return Object.assign(params, queryParam);
},
},
exportConfig: {
name: "媒体资源管理",
url: getExportUrl,
params: queryParam,
},
importConfig: {
url: getImportUrl,
success: handleSuccess
},
});
const [registerTable, { reload, collapseAll, updateTableDataRecord, findTableDataRecord, getDataSource }, { rowSelection, selectedRowKeys }] = tableContext;
const labelCol = reactive({
xs: 24,
sm: 4,
xl: 6,
xxl: 4
});
const wrapperCol = reactive({
xs: 24,
sm: 20,
});
const urlPrefix = ref('')//+
//
const superQueryConfig = reactive(superQuerySchema);
/**
* 高级查询事件
*/
function handleSuperQuery(params) {
Object.keys(params).map((k) => {
queryParam[k] = params[k];
});
searchQuery();
}
/**
* 新增事件
*/
function handleAdd() {
registerModal.value.disableSubmit = false;
registerModal.value.add();
}
/**
* 编辑事件
*/
function handleEdit(record: Recordable) {
registerModal.value.disableSubmit = false;
registerModal.value.edit(record);
}
/**
* 详情
*/
function handleDetail(record: Recordable) {
registerModal.value.disableSubmit = true;
registerModal.value.edit(record);
}
/**
* 删除事件
*/
async function handleDelete(record) {
await deleteOne({ id: record.id }, handleSuccess);
}
/**
* 批量删除事件
*/
async function batchHandleDelete() {
await batchDelete({ ids: selectedRowKeys.value }, handleSuccess);
}
/**
* 成功回调
*/
function handleSuccess() {
(selectedRowKeys.value = []) && reload();
}
/**
* 操作栏
*/
function getTableAction(record) {
return [
{
label: '编辑',
onClick: handleEdit.bind(null, record),
auth: 'mediamanage:nu_media_manage:edit'
}, {
label: '详情',
onClick: handleDetail.bind(null, record),
}, {
label: '删除',
popConfirm: {
title: '是否确认删除',
confirm: handleDelete.bind(null, record),
placement: 'topLeft',
},
auth: 'mediamanage:nu_media_manage:delete'
}
];
}
/**
* 下拉操作栏
*/
function getDropDownAction(record) {
return [
]
}
/**
* 查询
*/
function searchQuery() {
reload();
}
/**
* 重置
*/
function searchReset() {
formRef.value.resetFields();
selectedRowKeys.value = [];
//
reload();
}
/**
* 转化资源路径
* @param url_ 路径
*/
function transPreviewUrl(record) {
if (record.izNetUrl == 'net') {
return urlPrefix.value + record.filePath
} else {
return record.filePath
}
}
onMounted(() => {
getUrl().then(res => {
urlPrefix.value = res.url
})
})
</script>
<style lang="less" scoped>
.jeecg-basic-table-form-container {
padding: 0;
.table-page-search-submitButtons {
display: block;
margin-bottom: 24px;
white-space: nowrap;
}
.query-group-cust {
min-width: 100px !important;
}
.query-group-split-cust {
width: 30px;
display: inline-block;
text-align: center
}
.ant-form-item:not(.ant-form-item-with-help) {
margin-bottom: 16px;
height: 32px;
}
:deep(.ant-picker),
:deep(.ant-input-number) {
width: 100%;
}
}
</style>

View File

@ -0,0 +1,313 @@
<template>
<a-spin :spinning="confirmLoading">
<JFormContainer :disabled="disabled">
<template #detail>
<a-form ref="formRef" class="antd-modal-form" :labelCol="labelCol" :wrapperCol="wrapperCol"
name="MediaManageForm">
<a-row>
<a-col :span="24">
<a-form-item label="名称" v-bind="validateInfos.name" id="MediaManageForm-name" name="name">
<a-input v-model:value="formData.name" placeholder="请输入名称" allow-clear></a-input>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="备注" v-bind="validateInfos.descr" id="MediaManageForm-descr" name="descr">
<a-textarea v-model:value="formData.descr" :rows="4" placeholder="请输入备注" />
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="系统功能" v-bind="validateInfos.sysFunc" id="MediaManageForm-sysFunc" name="sysFunc">
<j-dict-select-tag type='list' v-model:value="formData.sysFunc" dictCode="sys_function"
placeholder="请选择系统功能" allowClear />
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="文件类型" v-bind="validateInfos.fileType" id="MediaManageForm-fileType" name="fileType">
<j-dict-select-tag type='list' v-model:value="formData.fileType" dictCode="file_type"
placeholder="请选择文件类型" allowClear @change="handleFileTypeChange" />
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="资源类型" v-bind="validateInfos.izNetUrl" id="MediaManageForm-izNetUrl" name="izNetUrl">
<j-dict-select-tag type='radio' v-model:value="formData.izNetUrl" dictCode="iz_net_url" allowClear
@change="handleFileTypeChange" />
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item :label="handleFileUploadLableName(formData.izNetUrl)" v-bind="validateInfos.filePath"
id="MediaManageForm-filePath">
<div v-if="formData.fileType && formData.izNetUrl == 'net'"
style="color: #999; margin-bottom: 8px; padding-left: 8px;">
当前协议域名为{{ urlPrefix }}
</div>
<a-textarea v-if="formData.fileType && (formData.izNetUrl == 'net' || formData.izNetUrl == 'full_url')"
v-model:value="formData.filePath" :rows="2" placeholder="请输入资源地址" style="margin-bottom: 10px;" />
<!-- 未选择文件类型时的提示 -->
<div v-if="!formData.fileType" class="upload-tip">
<span style="color: red; line-height: 32px;">请先选择文件类型</span>
</div>
<!-- 图片上传组件 -->
<template v-if="formData.fileType === 'image'">
<j-image-upload v-if="formData.izNetUrl == 'local'" v-model:value="formData.filePath" :number="1"
multiple="1" :fileSize="10" accept=".png,.jpg,.jpeg" @change="handleFileChange">
</j-image-upload>
<!-- 图片预览 -->
<div v-if="formData.filePath && formData.izNetUrl != 'local'" class="media-preview">
<img :src="transUrl(formData)" style="max-width: 100%; max-height: 300px;">
</div>
</template>
<!-- 视频上传组件 -->
<template v-if="formData.fileType === 'video'">
<j-upload v-if="formData.izNetUrl == 'local'" v-model:value="formData.filePath" :fileSize="100"
:multiple="false" :maxCount="1" accept=".mp4" @change="handleFileChange">
</j-upload>
<!-- 视频预览 -->
<div v-if="formData.filePath && previewShow" class="media-preview">
<video controls style="max-width: 100%; max-height: 300px;">
<source :src="transUrl(formData)" type="video/mp4">
您的浏览器不支持视频播放
</video>
</div>
</template>
<!-- 音频上传组件 -->
<template v-if="formData.fileType === 'audio'">
<j-upload v-if="formData.izNetUrl == 'local'" v-model:value="formData.filePath" :fileSize="50"
:multiple="false" :maxCount="1" accept=".mp3" @change="handleFileChange">
</j-upload>
<!-- 音频预览 -->
<div v-if="formData.filePath && previewShow" class="media-preview">
<audio controls style="width: 100%;">
<source :src="transUrl(formData)" type="audio/mpeg">
您的浏览器不支持音频播放
</audio>
</div>
</template>
<!-- 文档上传组件 -->
<j-upload v-if="formData.fileType === 'document'" v-model:value="formData.filePath" :fileSize="20"
:multiple="false" :maxCount="1" accept=".pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.txt"
@change="handleFileChange">
</j-upload>
</a-form-item>
</a-col>
</a-row>
</a-form>
</template>
</JFormContainer>
</a-spin>
</template>
<script lang="ts" setup>
import { ref, reactive, defineExpose, nextTick, defineProps, computed, watch } from 'vue';
import { defHttp } from '/@/utils/http/axios';
import { useMessage } from '/@/hooks/web/useMessage';
import { getValueType } from '/@/utils';
import { saveOrUpdate } from '../MediaManage.api';
import { Form } from 'ant-design-vue';
import JFormContainer from '/@/components/Form/src/container/JFormContainer.vue';
import JDictSelectTag from '/@/components/Form/src/jeecg/components/JDictSelectTag.vue';
import JImageUpload from '/@/components/Form/src/jeecg/components/JImageUpload.vue';
import JUpload from '/@/components/Form/src/jeecg/components/JUpload/JUpload.vue';
import { getFileAccessHttpUrl } from '/@/utils/common/compUtils';
const props = defineProps({
formDisabled: { type: Boolean, default: false },
formData: { type: Object, default: () => ({}) },
formBpm: { type: Boolean, default: true },
urlPrefix: { type: String, default: '' },
});
const formRef = ref();
const useForm = Form.useForm;
const emit = defineEmits(['register', 'ok']);
const formData = reactive<Record<string, any>>({
id: '',
name: '',
descr: '',
fileType: '',
filePath: '',
izNetUrl: 'local',
});
const { createMessage } = useMessage();
const labelCol = ref<any>({ xs: { span: 24 }, sm: { span: 6 } });
const wrapperCol = ref<any>({ xs: { span: 24 }, sm: { span: 16 } });
const confirmLoading = ref<boolean>(false);
//
const validatorRules = reactive({
fileType: [{ required: true, message: '请输入文件类型!' },],
filePath: [{ required: true, message: '请上传文件/填写资源路径' },],
});
const { resetFields, validate, validateInfos } = useForm(formData, validatorRules, { immediate: false });
//
const handleFileTypeChange = () => {
//
formData.filePath = '';
};
//
const handleFileChange = (value) => {
formData.filePath = value;
};
//
const disabled = computed(() => {
if (props.formBpm === true) {
if (props.formData.disabled === false) {
return false;
} else {
return true;
}
}
return props.formDisabled;
});
/**
* 新增
*/
function add() {
edit({});
}
/**
* 编辑
*/
function edit(record) {
nextTick(() => {
resetFields();
const tmpData = {};
Object.keys(formData).forEach((key) => {
if (record.hasOwnProperty(key)) {
tmpData[key] = record[key]
}
})
//
Object.assign(formData, tmpData);
});
}
/**
* 提交数据
*/
async function submitForm() {
try {
//
await validate();
} catch ({ errorFields }) {
if (errorFields) {
const firstField = errorFields[0];
if (firstField) {
formRef.value.scrollToField(firstField.name, { behavior: 'smooth', block: 'center' });
}
}
return Promise.reject(errorFields);
}
confirmLoading.value = true;
const isUpdate = ref<boolean>(false);
//
let model = formData;
if (model.id) {
isUpdate.value = true;
}
//
for (let data in model) {
//
if (model[data] instanceof Array) {
let valueType = getValueType(formRef.value.getProps, data);
//
if (valueType === 'string') {
model[data] = model[data].join(',');
}
}
}
// +filePath
if (model.izNetUrl == 'net') {
if (props.urlPrefix.endsWith('/')) {
if (model.filePath.startsWith('/')) {
model.filePath = model.filePath.replace('/', '')
}
} else {
if (!model.filePath.startsWith('/')) {
model.filePath = '/' + model.filePath
}
}
}
await saveOrUpdate(model, isUpdate.value)
.then((res) => {
if (res.success) {
createMessage.success(res.message);
emit('ok');
} else {
createMessage.warning(res.message);
}
})
.finally(() => {
confirmLoading.value = false;
});
}
function handleFileUploadLableName(v_) {
if (v_ == 'local') {
return '文件上传'
} else if (v_ == 'net') {
return '网络资源路径(不包含协议域名)'
} else if (v_ == 'full_url') {
return '完整网络资源地址'
} else {
return '文件上传'
}
}
const previewShow = ref(false)
watch(
() => formData.filePath,
(newVal, oldVal) => {
previewShow.value = false
setTimeout(() => {
previewShow.value = true
}, 500)
},
{
immediate: false,
deep: true
}
);
function transUrl(record) {
if (record.izNetUrl == 'local') {
return getFileAccessHttpUrl(record.filePath)
} else if (record.izNetUrl == 'net') {
return props.urlPrefix + record.filePath
} else {
return record.filePath
}
}
defineExpose({
add,
edit,
submitForm,
});
</script>
<style lang="less" scoped>
.antd-modal-form {
padding: 14px;
}
.upload-tip {
display: flex;
align-items: center;
height: 32px;
}
.media-preview {
margin-top: 16px;
padding: 8px;
border: 1px dashed #d9d9d9;
border-radius: 4px;
background-color: #fafafa;
}
</style>

View File

@ -0,0 +1,83 @@
<template>
<j-modal :title="title" :width="width" :visible="visible" @ok="handleOk"
:okButtonProps="{ class: { 'jee-hidden': disableSubmit } }" @cancel="handleCancel" cancelText="关闭">
<MediaManageForm ref="registerForm" :urlPrefix="urlPrefix" @ok="submitCallback" :formDisabled="disableSubmit"
:formBpm="false" v-if="visible">
</MediaManageForm>
</j-modal>
</template>
<script lang="ts" setup>
import { ref, nextTick, defineExpose, defineProps } from 'vue';
import MediaManageForm from './MediaManageForm.vue'
import JModal from '/@/components/Modal/src/JModal/JModal.vue';
const props = defineProps({
urlPrefix: { type: String, default: '' },
});
const title = ref<string>('');
const width = ref<number>(1000);
const visible = ref<boolean>(false);
const disableSubmit = ref<boolean>(false);
const registerForm = ref();
const emit = defineEmits(['register', 'success']);
/**
* 新增
*/
function add() {
title.value = '新增';
visible.value = true;
nextTick(() => {
registerForm.value.add();
});
}
/**
* 编辑
* @param record
*/
function edit(record) {
title.value = disableSubmit.value ? '详情' : '编辑';
visible.value = true;
nextTick(() => {
registerForm.value.edit(record);
});
}
/**
* 确定按钮点击事件
*/
function handleOk() {
registerForm.value.submitForm();
}
/**
* form保存回调事件
*/
function submitCallback() {
handleCancel();
emit('success');
}
/**
* 取消按钮回调事件
*/
function handleCancel() {
visible.value = false;
}
defineExpose({
add,
edit,
disableSubmit,
});
</script>
<style lang="less">
/**隐藏样式-modal确定按钮 */
.jee-hidden {
display: none !important;
}
</style>
<style lang="less" scoped></style>

View File

@ -0,0 +1,57 @@
<template>
<div class="preview-container">
<!-- 图片预览 -->
<div v-if="fileType === 'image' && filePath" class="preview-item">
<a-image :width="200" :src="getFullPath(filePath)" />
</div>
<!-- 视频预览 -->
<div v-if="fileType === 'video' && filePath" class="preview-item">
<video controls :src="getFullPath(filePath)" style="width: 200px; height: auto;"></video>
</div>
<!-- 音频预览 -->
<div v-if="fileType === 'audio' && filePath" class="preview-item">
<audio controls :src="getFullPath(filePath)"></audio>
</div>
<!-- 文档预览 -->
<div v-if="fileType === 'document' && filePath" class="preview-item">
<a-button @click="handlePreviewDocument">预览文档</a-button>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref, watch } from 'vue';
import { getFileAccessHttpUrl } from '/@/utils/common/compUtils';
const props = defineProps({
fileType: {
type: String,
default: ''
},
filePath: {
type: String,
default: ''
}
});
const getFullPath = (path) => {
return getFileAccessHttpUrl(path);
};
const handlePreviewDocument = () => {
window.open(getFullPath(props.filePath), '_blank');
};
</script>
<style scoped>
.preview-container {
margin-top: 10px;
}
.preview-item {
margin-bottom: 10px;
}
</style>

View File

@ -182,14 +182,6 @@ function getTableAction(record) {
{
label: '详情',
onClick: handleDetail.bind(null, record),
}, {
label: '删除',
popConfirm: {
title: '是否确认删除',
confirm: handleDelete.bind(null, record),
placement: 'topLeft',
},
auth: 'sysconfig:nu_sys_config:delete'
}
];
}

View File

@ -12,7 +12,7 @@
</a-col>
<a-col :span="24">
<a-form-item label="键名" v-bind="validateInfos.configKey" id="SysConfigForm-configKey" name="configKey">
<a-input v-model:value="formData.configKey" placeholder="请输入键名" allow-clear></a-input>
<a-input v-model:value="formData.configKey" placeholder="请输入键名" allow-clear :disabled="!!formData.id"></a-input>
</a-form-item>
</a-col>
<a-col :span="24">

View File

@ -136,7 +136,6 @@ function handleSuccess() {
*/
function queryList() {
list({ pageNo: pageParams.value.pageNo, pageSize: pageParams.value.pageSize, packageName: searchForm.value.packageName }).then(res => {
console.log("🌊 ~ list ~ res:", res)
tableData.value = res
})
}

View File

@ -87,15 +87,15 @@
<div class="directiveInfoClass">体型标签{{ handleBodyTags('', derectiveInfo, '') }}</div>
<div class="directiveInfoClass">情绪标签{{ handleEmotionTags('', derectiveInfo, '') }}</div>
<div class="directiveInfoClass">语音文件
<span v-if="!derectiveInfo.mp3File">暂无文件</span>
<span v-if="!derectiveInfo.mp3FileMedia">暂无文件</span>
<audio controls disabled="false" v-else>
<source :src="getFileAccessHttpUrl(derectiveInfo.mp3File)">
<source :src="getFileAccessHttpUrl(derectiveInfo.mp3FileMedia)">
</audio>
</div>
<div class="directiveInfoClass">视频文件
<span v-if="!derectiveInfo.mp4File">暂无文件</span>
<span v-if="!derectiveInfo.mp4FileMedia">暂无文件</span>
<video controls v-else>
<source :src="getFileAccessHttpUrl(derectiveInfo.mp4File)">
<source :src="getFileAccessHttpUrl(derectiveInfo.mp4FileMedia)">
</video>
</div>
</div>

View File

@ -125,15 +125,27 @@ export const columns: BasicColumn[] = [
dataIndex: 'izEnabled_dictText',
width: 100,
},
// {
// title: '语音文件',
// align: 'center',
// dataIndex: 'mp3FileMedia',
// },
// {
// title: '视频文件',
// align: 'center',
// dataIndex: 'mp4FileMedia',
// },
{
title: '语音文件',
title: '预览图片',
align: 'center',
dataIndex: 'mp3File',
dataIndex: 'previewFileMedia',
customRender: render.renderImage,
},
{
title: '视频文件',
title: '即时指令图片',
align: 'center',
dataIndex: 'mp4File',
dataIndex: 'immediateFileMedia',
customRender: render.renderImage,
},
// {
// title: '创建人',
@ -157,18 +169,6 @@ export const columns: BasicColumn[] = [
// sorter: true,
// dataIndex: 'updateTime'
// },
{
title: '预览图片',
align: 'center',
dataIndex: 'previewFile',
customRender: render.renderImage,
},
{
title: '即时指令图片',
align: 'center',
dataIndex: 'immediateFile',
customRender: render.renderImage,
},
];
// 高级查询数据

View File

@ -168,7 +168,7 @@
</template>
</BasicTable>
<!-- 表单区域 -->
<ConfigServiceDirectiveModal ref="registerModal" @success="handleSuccess"></ConfigServiceDirectiveModal>
<ConfigServiceDirectiveModal :sysUrlValue="sysUrlValue" ref="registerModal" @success="handleSuccess"></ConfigServiceDirectiveModal>
</div>
<!-- 服务类别 -->
@ -214,7 +214,7 @@
</template>
<script lang="ts" name="serviceDirective-configServiceDirective" setup>
import { ref, reactive } from 'vue';
import { ref, reactive,onMounted } from 'vue';
import { BasicTable, useTable, TableAction } from '/@/components/Table';
import { useListPage } from '/@/hooks/system/useListPage';
import { columns, superQuerySchema } from './ConfigServiceDirective.data';
@ -232,8 +232,10 @@ import BodyTagList from '/@/views/services/directivetag/bodytag/BodyTagList.vue'
import EmotionTagList from '/@/views/services/directivetag/emotiontag/EmotionTagList.vue';
import { getFileAccessHttpUrl } from '/@/utils/common/compUtils';
import JSelectMultiple from '/@/components/Form/src/jeecg/components/JSelectMultiple.vue';
import { sysUrl } from '/@/utils/sysBaseInfo/MediaManagePicker.api';
const formRef = ref();
const sysUrlValue = ref('')
const queryParam = reactive<any>({});
const toggleSearchStatus = ref<boolean>(false);
const registerModal = ref();
@ -474,6 +476,12 @@ const closeVideoModal = () => {
showVideoModal.value = false;
videoUrl.value = '';
};
onMounted(() => {
sysUrl().then(res => {
sysUrlValue.value = res.url
})
})
</script>
<style lang="less" scoped>

View File

@ -145,26 +145,52 @@
<a-row>
<a-col :span="12">
<a-form-item label="预览图片" v-bind="validateInfos.previewFile">
<JImageUpload :fileMax="1" v-model:value="formData.previewFile"></JImageUpload>
<a-button @click="showResourcePicker('previewFile', { maxSelect: 1, fileType: 'image' })" type="link"
size="small">选取图片</a-button>
<!-- <JImageUpload :fileMax="1" v-model:value="formData.previewFileMedia"
@change="formData.previewFileChanged = true">
</JImageUpload> -->
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="即时指令图片" v-bind="validateInfos.immediateFile">
<JImageUpload :fileMax="1" v-model:value="formData.immediateFile"></JImageUpload>
<a-button @click="showResourcePicker('immediateFile', { maxSelect: 1, fileType: 'image' })" type="link"
size="small">选取图片</a-button>
<!-- <JImageUpload :fileMax="1" v-model:value="formData.immediateFileMedia"
@change="formData.immediateFileChanged = true">
</JImageUpload> -->
</a-form-item>
</a-col>
</a-row>
<a-row>
<a-col :span="12" v-if="!!formData.previewFile">
<a-form-item label="预览图片" id="ConfigServiceDirectiveForm-previewFile">
<img :src="getFileAccessHttpUrl(formData.previewFileMedia)"
style="max-width: 200px; max-height: 200px;" />
</a-form-item>
</a-col>
<a-col :span="12" v-if="!!formData.immediateFile" :push="!!formData.previewFile ? 0 : 12">
<a-form-item label="即时指令图片" id="ConfigServiceDirectiveForm-immediateFile">
<img :src="getFileAccessHttpUrl(formData.immediateFileMedia)"
style="max-width: 200px; max-height: 200px;" />
</a-form-item>
</a-col>
</a-row>
<a-row>
<a-col :span="12">
<a-form-item label="语音文件" v-bind="validateInfos.mp3File" id="ConfigServiceDirectiveForm-mp3File"
name="mp3File">
<j-upload v-model:value="formData.mp3File" accept=".mp3" :maxCount="1"></j-upload>
<a-form-item label="语音文件" v-bind="validateInfos.mp3File" id="ConfigServiceDirectiveForm-mp3File">
<a-button @click="showResourcePicker('mp3File', { maxSelect: 1, fileType: 'audio' })" type="link"
size="small">选取文件</a-button>
<!-- <j-upload v-model:value="formData.mp3FileMedia" accept=".mp3" :maxCount="1"
@change="formData.mp3FileChanged = true"></j-upload> -->
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="视频文件" v-bind="validateInfos.mp4File" id="ConfigServiceDirectiveForm-mp4File"
name="mp4File">
<j-upload v-model:value="formData.mp4File" accept=".mp4" :maxCount="1"></j-upload>
<a-form-item label="视频文件" v-bind="validateInfos.mp4File" id="ConfigServiceDirectiveForm-mp4File">
<a-button @click="showResourcePicker('mp4File', { maxSelect: 1, fileType: 'video' })" type="link"
size="small">选取文件</a-button>
<!-- <j-upload v-model:value="formData.mp4FileMedia" accept=".mp4" :maxCount="1"
@change="formData.mp4FileChanged = true"></j-upload> -->
</a-form-item>
</a-col>
</a-row>
@ -177,16 +203,16 @@
name="ConfigServiceDirectiveForm">
<a-row>
<a-col :span="12" v-if="!!formData.mp3File">
<a-form-item label="语音预览" id="ConfigServiceDirectiveForm-mp3File" name="mp3File">
<a-form-item label="语音预览" id="ConfigServiceDirectiveForm-mp3File">
<audio controls disabled="false">
<source :src="getFileAccessHttpUrl(formData.mp3File)">
<source :src="getFileAccessHttpUrl(formData.mp3FileMedia)">
</audio>
</a-form-item>
</a-col>
<a-col :span="12" v-if="!!formData.mp4File" :push="!!formData.mp3File ? 0 : 12">
<a-form-item label="视频预览" id="ConfigServiceDirectiveForm-mp4File" name="mp4File">
<a-form-item label="视频预览" id="ConfigServiceDirectiveForm-mp4File">
<video controls>
<source :src="getFileAccessHttpUrl(formData.mp4File)">
<source :src="getFileAccessHttpUrl(formData.mp4FileMedia)">
</video>
</a-form-item>
</a-col>
@ -195,6 +221,9 @@
</template>
</JFormContainer>
</a-spin>
<MediaResourcePicker :maxSelect="mediaParams.maxSelect" :fileType="mediaParams.fileType"
v-model:visible="pickerVisible" @confirm="handleResourceSelected" />
</template>
<script lang="ts" setup>
@ -210,12 +239,34 @@ import { saveOrUpdate } from '../ConfigServiceDirective.api';
import { Form } from 'ant-design-vue';
import JFormContainer from '/@/components/Form/src/container/JFormContainer.vue';
import { getFileAccessHttpUrl } from '/@/utils/common/compUtils';
import MediaResourcePicker from '/@/utils/midiaManage/MediaResourcePicker.vue';
const handleUploadSuccess = (res) => {
}
const props = defineProps({
formDisabled: { type: Boolean, default: false },
formData: { type: Object, default: () => ({}) },
formBpm: { type: Boolean, default: true }
formBpm: { type: Boolean, default: true },
sysUrlValue: { type: String, default: '' },
});
const pickerVisible = ref(false);
const mediaParams = ref({ maxSelect: 1, fileType: 'any' })
const changedMediaObjStr = ref('')
const showResourcePicker = (obj, param) => {
changedMediaObjStr.value = obj
mediaParams.value = param
pickerVisible.value = true;
};
const handleResourceSelected = (selectedResource) => {
formData[changedMediaObjStr.value] = selectedResource.id
if (selectedResource.izNetUrl == 'net') {
formData[changedMediaObjStr.value + 'Media'] = props.sysUrlValue + selectedResource.filePath
} else {
formData[changedMediaObjStr.value + 'Media'] = selectedResource.filePath
}
};
const formRef = ref();
const useForm = Form.useForm;
const emit = defineEmits(['register', 'ok']);
@ -243,6 +294,10 @@ const formData = reactive<Record<string, any>>({
mp4File: '',
previewFile: '',
immediateFile: '',
mp3FileMedia: '',
mp4FileMedia: '',
previewFileMedia: '',
immediateFileMedia: '',
});
const { createMessage } = useMessage();
const labelCol = ref<any>({ xs: { span: 24 }, sm: { span: 6 } });

View File

@ -1,15 +1,17 @@
<template>
<j-modal :title="title" width="70vw" :visible="visible" @ok="handleOk" :okButtonProps="{ class: { 'jee-hidden': disableSubmit } }" @cancel="handleCancel" cancelText="关闭" :maskClosable="false">
<ConfigServiceDirectiveForm ref="registerForm" v-if="visible" @ok="submitCallback" :formDisabled="disableSubmit" :formBpm="false"></ConfigServiceDirectiveForm>
<ConfigServiceDirectiveForm ref="registerForm" v-if="visible" @ok="submitCallback" :sysUrlValue="sysUrlValue" :formDisabled="disableSubmit" :formBpm="false"></ConfigServiceDirectiveForm>
</j-modal>
</template>
<script lang="ts" setup>
import { ref, nextTick, defineExpose } from 'vue';
import { ref, nextTick, defineExpose , defineProps} from 'vue';
import ConfigServiceDirectiveForm from './ConfigServiceDirectiveForm.vue'
import JModal from '/@/components/Modal/src/JModal/JModal.vue';
import { array } from 'vue-types';
const props = defineProps({
sysUrlValue: { type: String, default: '' },
});
const title = ref<string>('');
const visible = ref<boolean>(false);
const disableSubmit = ref<boolean>(false);

View File

@ -129,7 +129,6 @@ function handleSuccess() {
*/
function queryList() {
list({ pageNo: pageParams.value.pageNo, pageSize: pageParams.value.pageSize, tagName: searchForm.value.tagName }).then(res => {
console.log("🌊 ~ list ~ res:", res)
tableData.value = res
})
}

View File

@ -59,15 +59,15 @@
<div class="directiveInfoClass">体型标签{{ handleBodyTags('', derectiveInfo, '') }}</div>
<div class="directiveInfoClass">情绪标签{{ handleEmotionTags('', derectiveInfo, '') }}</div>
<div class="directiveInfoClass">语音文件
<span v-if="!derectiveInfo.mp3File">暂无文件</span>
<span v-if="!derectiveInfo.mp3FileMedia">暂无文件</span>
<audio controls disabled="false" v-else>
<source :src="getFileAccessHttpUrl(derectiveInfo.mp3File)">
<source :src="getFileAccessHttpUrl(derectiveInfo.mp3FileMedia)">
</audio>
</div>
<div class="directiveInfoClass">视频文件
<span v-if="!derectiveInfo.mp4File">暂无文件</span>
<span v-if="!derectiveInfo.mp4FileMedia">暂无文件</span>
<video controls v-else>
<source :src="getFileAccessHttpUrl(derectiveInfo.mp4File)">
<source :src="getFileAccessHttpUrl(derectiveInfo.mp4FileMedia)">
</video>
</div>
</a-card>
@ -144,7 +144,6 @@ function handleBodyTags(prefix, directive_, suffix) {
* @param directive_
*/
function handleEmotionTags(prefix, directive_, suffix) {
console.log("🌊 ~ handleEmotionTags ~ directive_:", directive_)
if (!!directive_.emotionTagList && directive_.emotionTagList.length > 0) {
let str = directive_.emotionTagList.map(item => item.tagName).join('、 ');
return prefix + str + suffix

View File

@ -56,6 +56,10 @@
field: 'orgCategory',
componentProps: { options: categoryOptions },
},
{
field: 'url',
show: !isChild,
},
]);
let record = unref(data?.record);

View File

@ -42,6 +42,17 @@ export function useBasicFormSchema() {
component: 'InputNumber',
componentProps: {},
},
{
field: 'url',
label: '协议域名',
component: 'Input',
dynamicDisabled: ({ values }) => {
return values.orgCategory != '1'
},
componentProps: {
placeholder: '请输入协议域名',
},
},
{
field: 'mobile',
label: '电话',
@ -83,7 +94,5 @@ export const orgCategoryOptions = {
// 一级部门
root: [{ value: '1', label: '机构' }],
// 子级部门
child: [
{ value: '2', label: '区域' },
],
child: [{ value: '2', label: '区域' }],
};