mirror of
https://github.com/jeecgboot/JeecgBoot.git
synced 2026-01-03 12:05:28 +08:00
v3.8.2 版本前端代码
This commit is contained in:
@ -65,7 +65,7 @@
|
||||
<a @click="handleDetail(record)">详情</a>
|
||||
</a-menu-item>
|
||||
<a-menu-item>
|
||||
<Popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)">
|
||||
<Popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)" placement="left">
|
||||
<a>删除</a>
|
||||
</Popconfirm>
|
||||
</a-menu-item>
|
||||
|
||||
@ -1,230 +1,234 @@
|
||||
<template>
|
||||
<a-spin :spinning="confirmLoading">
|
||||
<a-form class="antd-modal-form" ref="formRef" :model="formState" :rules="validatorRules">
|
||||
<a-row>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="文本" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.name">
|
||||
<a-input v-model:value="formState.name" placeholder="请输入文本"></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="密码" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.miMa">
|
||||
<a-input-password v-model:value="formState.miMa" placeholder="请输入密码" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="字典下拉" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.xiala">
|
||||
<JDictSelectTag type="select" v-model:value="formState.xiala" dictCode="sex" placeholder="请选择字典下拉" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="字典单选" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.danxuan">
|
||||
<JDictSelectTag type="radio" v-model:value="formState.danxuan" dictCode="sex" placeholder="请选择字典单选" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="字典多选" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.duoxuan">
|
||||
<JCheckbox v-model:value="formState.duoxuan" dictCode="urgent_level" placeholder="请选择字典多选" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="开关" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.kaiguan">
|
||||
<JSwitch v-model:value="formState.kaiguan" :options="['1', '0']"></JSwitch>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="日期" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.riqi">
|
||||
<a-date-picker placeholder="请选择日期" format="YYYY-MM-DD" valueFormat="YYYY-MM-DD" v-model:value="formState.riqi" style="width: 100%" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="年月日时分秒" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.nyrsfm">
|
||||
<a-date-picker show-time v-model:value="formState.nyrsfm" style="width: 100%" valueFormat="YYYY-MM-DD HH:mm:ss" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="时间" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.shijian">
|
||||
<TimePicker placeholder="请选择时间" v-model:value="formState.shijian" style="width: 100%" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="文件" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.wenjian">
|
||||
<JUpload v-model:value="formState.wenjian"></JUpload>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="图片" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.tupian">
|
||||
<JImageUpload :fileMax="2" v-model:value="formState.tupian"></JImageUpload>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="多行文本框" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.dhwb">
|
||||
<a-textarea v-model:value="formState.dhwb" rows="4" placeholder="请输入多行文本框" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="字典表下拉搜索框" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.xlss">
|
||||
<JSearchSelect v-model:value="formState.xlss" dict="sys_user,realname,username" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="popup弹窗" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.popup">
|
||||
<JPopup
|
||||
v-model:value="formState.popup"
|
||||
:fieldConfig="[
|
||||
{ source: 'name', target: 'popup' },
|
||||
{ source: 'id', target: 'popback' },
|
||||
]"
|
||||
code="report_user"
|
||||
:multi="true"
|
||||
:setFieldsValue="setFieldsValue"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="popback" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.popback">
|
||||
<a-input v-model:value="formState.popback" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="分类字典树" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.flzds">
|
||||
<JCategorySelect
|
||||
@change="(value) => handleFormChange('flzds', value)"
|
||||
v-model:value="formState.flzds"
|
||||
pcode="B02"
|
||||
placeholder="请选择分类字典树"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="部门选择" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.bmxz">
|
||||
<JSelectDept v-model:value="formState.bmxz" :multi="true" type="array" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="用户选择" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.yhxz">
|
||||
<JSelectUserByDept v-model:value="formState.yhxz" :multi="true" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="富文本" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.fwb">
|
||||
<JEditor v-model:value="formState.fwb" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="markdown" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.markdownString">
|
||||
<JMarkdownEditor v-model:value="formState.markdownString"></JMarkdownEditor>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="省市区JAreaSelect" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.shq">
|
||||
<JAreaSelect v-model:value="formState.shq" placeholder="请输入省市区" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<a-col :span="24">
|
||||
<a-form-item label="省市区JAreaLinkage" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.jssq">
|
||||
<JAreaLinkage v-model:value="formState.jssq" placeholder="请输入省市区" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<a-col :span="24">
|
||||
<a-form-item label="JInputPop" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.ldzje">
|
||||
<JInputPop
|
||||
v-model:value="formState.ldzje"
|
||||
placeholder="请输入JInputPop"
|
||||
@change="(value) => handleFormChange('ldzje', value)"
|
||||
></JInputPop>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="JSelectInput" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.ldzjs">
|
||||
<JSelectInput
|
||||
v-model:value="formState.ldzjs"
|
||||
placeholder="请选择JSelectInput"
|
||||
:options="ldzjsOptions"
|
||||
@change="(value) => handleFormChange('ldzjs', value)"
|
||||
></JSelectInput>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="下拉多选" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.zddtjxl">
|
||||
<JSelectMultiple v-model:value="formState.zddtjxl" placeholder="请选择下拉多选" dictCode="sex"></JSelectMultiple>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="用户" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.yongHu">
|
||||
<JSelectUser v-model:value="formState.yongHu" placeholder="请选择用户"></JSelectUser>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="职务" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.zhiWu">
|
||||
<JSelectPosition
|
||||
v-model:value="formState.zhiWu"
|
||||
placeholder="请选择职务"
|
||||
@change="(value) => handleFormChange('zhiWu', value)"
|
||||
></JSelectPosition>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="角色" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.jueSe">
|
||||
<JSelectRole v-model:value="formState.jueSe" placeholder="请选择角色" @change="(value) => handleFormChange('jueSe', value)"></JSelectRole>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="自定义树" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.zdys">
|
||||
<JTreeSelect
|
||||
ref="treeSelect"
|
||||
placeholder="请选择自定义树"
|
||||
v-model:value="formState.zdys"
|
||||
dict="sys_category,name,id"
|
||||
pidValue="0"
|
||||
loadTriggleChange
|
||||
>
|
||||
</JTreeSelect>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<a-col :span="24">
|
||||
<a-form-item label="数值" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.yuanjia">
|
||||
<a-input-number v-model:value="formState.yuanjia" placeholder="请输入double类型" style="width: 100%" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="输入2到10位的字母" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.ywzz">
|
||||
<a-input v-model:value="formState.ywzz" placeholder="请输入2到10位的字母"></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="JTreeDict" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.zdbxl">
|
||||
<JTreeDict
|
||||
v-model:value="formState.zdbxl"
|
||||
placeholder="请选择JTreeDict"
|
||||
@change="(value) => handleFormChange('zdbxl', value)"
|
||||
></JTreeDict>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="JCodeEditor" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.zdmrz">
|
||||
<JCodeEditor
|
||||
v-model:value="formState.zdmrz"
|
||||
placeholder="请输入JCodeEditor"
|
||||
@change="(value) => handleFormChange('zdmrz', value)"
|
||||
></JCodeEditor>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="参数" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.jsonParam">
|
||||
<JAddInput v-model:value="formState.jsonParam" placeholder="参数"></JAddInput>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
<JFormContainer :disabled="disabled">
|
||||
<template #detail>
|
||||
<a-form class="antd-modal-form" ref="formRef" :model="formState" :rules="validatorRules">
|
||||
<a-row>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="文本" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.name">
|
||||
<a-input v-model:value="formState.name" placeholder="请输入文本"></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="密码" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.miMa">
|
||||
<a-input-password v-model:value="formState.miMa" placeholder="请输入密码" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="字典下拉" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.xiala">
|
||||
<JDictSelectTag type="select" v-model:value="formState.xiala" dictCode="sex" placeholder="请选择字典下拉" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="字典单选" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.danxuan">
|
||||
<JDictSelectTag type="radio" v-model:value="formState.danxuan" dictCode="sex" placeholder="请选择字典单选" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="字典多选" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.duoxuan">
|
||||
<JCheckbox v-model:value="formState.duoxuan" dictCode="urgent_level" placeholder="请选择字典多选" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="开关" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.kaiguan">
|
||||
<JSwitch v-model:value="formState.kaiguan" :options="['1', '0']"></JSwitch>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="日期" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.riqi">
|
||||
<a-date-picker placeholder="请选择日期" format="YYYY-MM-DD" valueFormat="YYYY-MM-DD" v-model:value="formState.riqi" style="width: 100%" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="年月日时分秒" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.nyrsfm">
|
||||
<a-date-picker show-time v-model:value="formState.nyrsfm" style="width: 100%" valueFormat="YYYY-MM-DD HH:mm:ss" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="时间" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.shijian">
|
||||
<TimePicker placeholder="请选择时间" v-model:value="formState.shijian" style="width: 100%" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="文件" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.wenjian">
|
||||
<JUpload v-model:value="formState.wenjian"></JUpload>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="图片" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.tupian">
|
||||
<JImageUpload :fileMax="2" v-model:value="formState.tupian"></JImageUpload>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="多行文本框" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.dhwb">
|
||||
<a-textarea v-model:value="formState.dhwb" rows="4" placeholder="请输入多行文本框" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="字典表下拉搜索框" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.xlss">
|
||||
<JSearchSelect v-model:value="formState.xlss" dict="sys_user,realname,username" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="popup弹窗" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.popup">
|
||||
<JPopup
|
||||
v-model:value="formState.popup"
|
||||
:fieldConfig="[
|
||||
{ source: 'name', target: 'popup' },
|
||||
{ source: 'id', target: 'popback' },
|
||||
]"
|
||||
code="report_user"
|
||||
:multi="true"
|
||||
:setFieldsValue="setFieldsValue"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="popback" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.popback">
|
||||
<a-input v-model:value="formState.popback" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="分类字典树" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.flzds">
|
||||
<JCategorySelect
|
||||
@change="(value) => handleFormChange('flzds', value)"
|
||||
v-model:value="formState.flzds"
|
||||
pcode="B02"
|
||||
placeholder="请选择分类字典树"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="部门选择" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.bmxz">
|
||||
<JSelectDept v-model:value="formState.bmxz" :multi="true" type="array" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="用户选择" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.yhxz">
|
||||
<JSelectUserByDept v-model:value="formState.yhxz" :multi="true" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="富文本" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.fwb">
|
||||
<JEditor v-model:value="formState.fwb" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="markdown" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.markdownString">
|
||||
<JMarkdownEditor v-model:value="formState.markdownString"></JMarkdownEditor>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="省市区JAreaSelect" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.shq">
|
||||
<JAreaSelect v-model:value="formState.shq" placeholder="请输入省市区" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<a-col :span="24">
|
||||
<a-form-item label="省市区JAreaLinkage" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.jssq">
|
||||
<JAreaLinkage v-model:value="formState.jssq" placeholder="请输入省市区" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<a-col :span="24">
|
||||
<a-form-item label="JInputPop" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.ldzje">
|
||||
<JInputPop
|
||||
v-model:value="formState.ldzje"
|
||||
placeholder="请输入JInputPop"
|
||||
@change="(value) => handleFormChange('ldzje', value)"
|
||||
></JInputPop>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="JSelectInput" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.ldzjs">
|
||||
<JSelectInput
|
||||
v-model:value="formState.ldzjs"
|
||||
placeholder="请选择JSelectInput"
|
||||
:options="ldzjsOptions"
|
||||
@change="(value) => handleFormChange('ldzjs', value)"
|
||||
></JSelectInput>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="下拉多选" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.zddtjxl">
|
||||
<JSelectMultiple v-model:value="formState.zddtjxl" placeholder="请选择下拉多选" dictCode="sex"></JSelectMultiple>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="用户" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.yongHu">
|
||||
<JSelectUser v-model:value="formState.yongHu" placeholder="请选择用户"></JSelectUser>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="职务" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.zhiWu">
|
||||
<JSelectPosition
|
||||
v-model:value="formState.zhiWu"
|
||||
placeholder="请选择职务"
|
||||
@change="(value) => handleFormChange('zhiWu', value)"
|
||||
></JSelectPosition>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="角色" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.jueSe">
|
||||
<JSelectRole v-model:value="formState.jueSe" placeholder="请选择角色" @change="(value) => handleFormChange('jueSe', value)"></JSelectRole>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="自定义树" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.zdys">
|
||||
<JTreeSelect
|
||||
ref="treeSelect"
|
||||
placeholder="请选择自定义树"
|
||||
v-model:value="formState.zdys"
|
||||
dict="sys_category,name,id"
|
||||
pidValue="0"
|
||||
loadTriggleChange
|
||||
>
|
||||
</JTreeSelect>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<a-col :span="24">
|
||||
<a-form-item label="数值" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.yuanjia">
|
||||
<a-input-number v-model:value="formState.yuanjia" placeholder="请输入double类型" style="width: 100%" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="输入2到10位的字母" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.ywzz">
|
||||
<a-input v-model:value="formState.ywzz" placeholder="请输入2到10位的字母"></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="JTreeDict" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.zdbxl">
|
||||
<JTreeDict
|
||||
v-model:value="formState.zdbxl"
|
||||
placeholder="请选择JTreeDict"
|
||||
@change="(value) => handleFormChange('zdbxl', value)"
|
||||
></JTreeDict>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="JCodeEditor" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.zdmrz">
|
||||
<JCodeEditor
|
||||
v-model:value="formState.zdmrz"
|
||||
placeholder="请输入JCodeEditor"
|
||||
@change="(value) => handleFormChange('zdmrz', value)"
|
||||
></JCodeEditor>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="参数" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validateInfos.jsonParam">
|
||||
<JAddInput v-model:value="formState.jsonParam" placeholder="参数"></JAddInput>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</template>
|
||||
</JFormContainer>
|
||||
</a-spin>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, nextTick } from 'vue';
|
||||
import { ref, reactive, nextTick, computed } from 'vue';
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import dayjs from 'dayjs';
|
||||
@ -255,7 +259,15 @@
|
||||
import JCodeEditor from '/@/components/Form/src/jeecg/components/JCodeEditor.vue';
|
||||
import JAddInput from '/@/components/Form/src/jeecg/components/JAddInput.vue';
|
||||
import { getValueType } from '/@/utils';
|
||||
import JFormContainer from '/@/components/Form/src/container/JFormContainer.vue';
|
||||
|
||||
const props = defineProps({
|
||||
formDisabled: { type: Boolean, default: false },
|
||||
});
|
||||
// 表单禁用
|
||||
const disabled = computed(()=>{
|
||||
return props.formDisabled;
|
||||
});
|
||||
const emit = defineEmits(['register', 'ok']);
|
||||
//update-begin---author:wangshuai ---date:20220616 for:报表示例验证修改--------------
|
||||
const formState = reactive<Record<string, any>>({
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
@cancel="handleCancel"
|
||||
cancelText="关闭"
|
||||
>
|
||||
<OneNativeForm ref="realForm" @ok="submitCallback" :disabled="disableSubmit"></OneNativeForm>
|
||||
<OneNativeForm ref="realForm" @ok="submitCallback" :formDisabled="disableSubmit"></OneNativeForm>
|
||||
</BasicModal>
|
||||
</template>
|
||||
|
||||
@ -61,5 +61,9 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
<style lang="less">
|
||||
/**隐藏样式-modal确定按钮 */
|
||||
.jee-hidden {
|
||||
display: none !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<BasicModal v-bind="$attrs" @register="registerModal" :title="getTitle" @ok="handleSubmit" :width="500" :minHeight="20" :maxHeight="20">
|
||||
<BasicModal v-bind="$attrs" @register="registerModal" :title="getTitle" @ok="handleSubmit" :width="500" :minHeight="20" :maxHeight="100">
|
||||
<BasicForm @register="registerForm" />
|
||||
</BasicModal>
|
||||
</template>
|
||||
@ -16,7 +16,7 @@
|
||||
const isUpdate = ref(true);
|
||||
//表单配置
|
||||
const [registerForm, { resetFields, setFieldsValue, validate }] = useForm({
|
||||
labelWidth: 150,
|
||||
// labelWidth: 150,
|
||||
schemas: ticketFormSchema,
|
||||
showActionButtonGroup: false,
|
||||
});
|
||||
|
||||
@ -227,6 +227,7 @@ export const ticketFormSchema: FormSchema[] = [
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
valueFormat: 'YYYY-MM-DD',
|
||||
getPopupContainer:()=>document.body,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@ -1,92 +1,340 @@
|
||||
<template>
|
||||
<BasicModal v-bind="$attrs" @register="registerModal" title="查看详情" :minHeight="600" :showCancelBtn="false" :showOkBtn="false" :height="88" :destroyOnClose="true">
|
||||
<BasicModal
|
||||
v-bind="$attrs"
|
||||
@register="registerModal"
|
||||
title="查看详情"
|
||||
:width="800"
|
||||
:minHeight="600"
|
||||
:showCancelBtn="false"
|
||||
:showOkBtn="false"
|
||||
:height="88"
|
||||
:destroyOnClose="true"
|
||||
@visible-change="handleVisibleChange"
|
||||
>
|
||||
<div class="print-btn" @click="onPrinter">
|
||||
<Icon icon="ant-design:printer-filled" />
|
||||
<span class="print-text">打印</span>
|
||||
</div>
|
||||
<a-card class="daily-article">
|
||||
<a-card-meta :title="content.titile" :description="'发布人:' + content.sender + ' 发布时间: ' + content.sendTime"> </a-card-meta>
|
||||
<a-card-meta :title="content.titile">
|
||||
<template #description>
|
||||
<div class="article-desc">
|
||||
<span>发布人:{{ content.sender }}</span>
|
||||
<span>发布时间:{{ content.sendTime }}</span>
|
||||
<span v-if="content.visitsNum">
|
||||
<a-tooltip placement="top" title="访问次数" :autoAdjustOverflow="true">
|
||||
<eye-outlined class="item-icon" /> {{ content.visitsNum }}
|
||||
</a-tooltip>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
</a-card-meta>
|
||||
<a-divider />
|
||||
<div v-html="content.msgContent" class="article-content"></div>
|
||||
<div>
|
||||
<a-button v-if="hasHref" @click="jumpToHandlePage">前往办理<ArrowRightOutlined /></a-button>
|
||||
</div>
|
||||
</a-card>
|
||||
<template v-if="noticeFiles && noticeFiles.length > 0">
|
||||
<div class="files-title">相关附件:</div>
|
||||
<template v-for="(file, index) in noticeFiles" :key="index">
|
||||
<div class="files-area">
|
||||
<div class="files-area-text">
|
||||
<span>
|
||||
<paper-clip-outlined />
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
:title="file.fileName"
|
||||
:href="getFileAccessHttpUrl(file.filePath)"
|
||||
class="ant-upload-list-item-name"
|
||||
>{{ file.fileName }}</a
|
||||
>
|
||||
</span>
|
||||
</div>
|
||||
<div class="files-area-operate">
|
||||
<download-outlined class="item-icon" @click="handleDownloadFile(file.filePath)" />
|
||||
<eye-outlined class="item-icon" @click="handleViewFile(file.filePath)" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
</BasicModal>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { BasicModal, useModalInner } from '/@/components/Modal';
|
||||
import { propTypes } from '/@/utils/propTypes';
|
||||
import { ArrowRightOutlined } from '@ant-design/icons-vue';
|
||||
import { useRouter } from 'vue-router'
|
||||
import xss from 'xss'
|
||||
import { options } from './XssWhiteList'
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
import { ArrowRightOutlined, PaperClipOutlined, DownloadOutlined, EyeOutlined } from '@ant-design/icons-vue';
|
||||
import { addVisitsNum } from '@/views/system/notice/notice.api';
|
||||
import { useRouter } from 'vue-router';
|
||||
import xss from 'xss';
|
||||
import { options } from './XssWhiteList';
|
||||
import { ref, unref } from 'vue';
|
||||
import { getFileAccessHttpUrl } from '@/utils/common/compUtils';
|
||||
import { useGlobSetting } from '@/hooks/setting';
|
||||
import { encryptByBase64 } from '@/utils/cipher';
|
||||
const router = useRouter();
|
||||
const glob = useGlobSetting();
|
||||
const isUpdate = ref(true);
|
||||
const content = ref({});
|
||||
const content = ref<any>({});
|
||||
const noticeFiles = ref([]);
|
||||
const emit = defineEmits(['close', 'register']);
|
||||
//表单赋值
|
||||
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
|
||||
isUpdate.value = !!data?.isUpdate;
|
||||
if (unref(isUpdate)) {
|
||||
//data.record.msgContent = '<p>2323</p><input onmouseover=alert(1)>xss test';
|
||||
//update-begin-author:taoyan date:2022-7-14 for: VUEN-1702 【禁止问题】sql注入漏洞
|
||||
if(data.record.msgContent){
|
||||
if (data.record.msgContent) {
|
||||
//update-begin---author:wangshuai---date:2023-11-15---for:【QQYUN-7049】3.6.0版本 通知公告中发布的富文本消息,在我的消息中查看没有样式---
|
||||
data.record.msgContent = xss(data.record.msgContent,options);
|
||||
data.record.msgContent = xss(data.record.msgContent, options);
|
||||
//update-end---author:wangshuai---date:2023-11-15---for:【QQYUN-7049】3.6.0版本 通知公告中发布的富文本消息,在我的消息中查看没有样式---
|
||||
}
|
||||
//update-end-author:taoyan date:2022-7-14 for: VUEN-1702 【禁止问题】sql注入漏洞
|
||||
|
||||
//update-begin-author:liusq---date:2025-06-17--for: [QQYUN-12521]通知公告消息增加访问量
|
||||
if (!data.record?.busId) {
|
||||
await addVisitsNum({ id: data.record.id });
|
||||
}
|
||||
//update-end-author:liusq---date:2025-06-17--for: [QQYUN-12521]通知公告消息增加访问量
|
||||
|
||||
content.value = data.record;
|
||||
console.log('data---------->>>', data);
|
||||
if (data.record?.files && data.record?.files.length > 0) {
|
||||
noticeFiles.value = data.record.files.split(',').map((item) => {
|
||||
return {
|
||||
fileName: item.split('/').pop(),
|
||||
filePath: item,
|
||||
};
|
||||
});
|
||||
}
|
||||
showHrefButton();
|
||||
}
|
||||
});
|
||||
|
||||
const hasHref = ref(false)
|
||||
|
||||
const hasHref = ref(false);
|
||||
//查看消息详情可以跳转
|
||||
function showHrefButton(){
|
||||
if(content.value.busId){
|
||||
function showHrefButton() {
|
||||
if (content.value.busId) {
|
||||
hasHref.value = true;
|
||||
}
|
||||
}
|
||||
//跳转至办理页面
|
||||
function jumpToHandlePage(){
|
||||
let temp:any = content.value
|
||||
if(temp.busId){
|
||||
//这个busId是 任务ID
|
||||
function jumpToHandlePage() {
|
||||
let temp: any = content.value;
|
||||
if (temp.busId) {
|
||||
//这个busId是 任务ID
|
||||
let jsonStr = temp.msgAbstract;
|
||||
let query = {};
|
||||
try {
|
||||
if(jsonStr){
|
||||
let temp = JSON.parse(jsonStr)
|
||||
if(temp){
|
||||
Object.keys(temp).map(k=>{
|
||||
query[k] = temp[k]
|
||||
if (jsonStr) {
|
||||
let temp = JSON.parse(jsonStr);
|
||||
if (temp) {
|
||||
Object.keys(temp).map((k) => {
|
||||
query[k] = temp[k];
|
||||
});
|
||||
}
|
||||
}
|
||||
}catch(e){
|
||||
console.log('参数解析异常', e)
|
||||
} catch (e) {
|
||||
console.log('参数解析异常', e);
|
||||
}
|
||||
|
||||
console.log('query', query, jsonStr)
|
||||
console.log('busId', temp.busId)
|
||||
|
||||
if(Object.keys(query).length>0){
|
||||
|
||||
console.log('query', query, jsonStr);
|
||||
console.log('busId', temp.busId);
|
||||
|
||||
if (Object.keys(query).length > 0) {
|
||||
// taskId taskDefKey procInsId
|
||||
router.push({ path: '/task/handle/' + temp.busId, query: query })
|
||||
}else{
|
||||
router.push({ path: '/task/handle/' + temp.busId })
|
||||
router.push({ path: '/task/handle/' + temp.busId, query: query });
|
||||
} else {
|
||||
router.push({ path: '/task/handle/' + temp.busId });
|
||||
}
|
||||
}
|
||||
closeModal();
|
||||
}
|
||||
|
||||
//打印
|
||||
function onPrinter() {
|
||||
// 获取要打印的内容
|
||||
const printContent = document.querySelector('.daily-article');
|
||||
|
||||
if (!printContent) return;
|
||||
|
||||
// 创建一个iframe来处理打印
|
||||
const printFrame = document.createElement('iframe');
|
||||
printFrame.style.position = 'absolute';
|
||||
printFrame.style.width = '0';
|
||||
printFrame.style.height = '0';
|
||||
printFrame.style.border = 'none';
|
||||
printFrame.style.left = '-9999px';
|
||||
|
||||
printFrame.onload = function () {
|
||||
const frameDoc = printFrame.contentDocument || printFrame.contentWindow?.document;
|
||||
if (!frameDoc) return;
|
||||
|
||||
// 复制内容到iframe
|
||||
const clone = printContent.cloneNode(true);
|
||||
frameDoc.body.appendChild(clone);
|
||||
|
||||
// 添加打印样式
|
||||
const style = frameDoc.createElement('style');
|
||||
style.innerHTML = `
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 15px;
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
@page {
|
||||
size: auto;
|
||||
margin: 15mm;
|
||||
}
|
||||
@media print {
|
||||
body {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
`;
|
||||
frameDoc.head.appendChild(style);
|
||||
|
||||
// 确保图片加载完成
|
||||
const images = frameDoc.getElementsByTagName('img');
|
||||
let imagesToLoad = images.length;
|
||||
|
||||
const printWhenReady = () => {
|
||||
if (imagesToLoad === 0) {
|
||||
setTimeout(() => {
|
||||
printFrame.contentWindow?.focus();
|
||||
printFrame.contentWindow?.print();
|
||||
document.body.removeChild(printFrame);
|
||||
}, 300);
|
||||
}
|
||||
};
|
||||
|
||||
if (imagesToLoad === 0) {
|
||||
printWhenReady();
|
||||
} else {
|
||||
Array.from(images).forEach((img) => {
|
||||
img.onload = () => {
|
||||
imagesToLoad--;
|
||||
printWhenReady();
|
||||
};
|
||||
// 处理可能已经缓存的图片
|
||||
if (img.complete && img.naturalWidth !== 0) {
|
||||
imagesToLoad--;
|
||||
printWhenReady();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
document.body.appendChild(printFrame);
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载文件
|
||||
* @param filePath
|
||||
*/
|
||||
function handleDownloadFile(filePath) {
|
||||
window.open(getFileAccessHttpUrl(filePath), '_blank');
|
||||
}
|
||||
/**
|
||||
* 预览文件
|
||||
* @param filePath
|
||||
*/
|
||||
function handleViewFile(filePath) {
|
||||
if (filePath) {
|
||||
console.log('glob.onlineUrl', glob.viewUrl);
|
||||
let url = encodeURIComponent(encryptByBase64(filePath));
|
||||
let previewUrl = `${glob.viewUrl}?url=` + url;
|
||||
window.open(previewUrl, '_blank');
|
||||
}
|
||||
}
|
||||
|
||||
function handleVisibleChange(visible: boolean) {
|
||||
if (!visible) {
|
||||
emit('close');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.daily-article {
|
||||
:deep(.ant-card-meta-detail) {
|
||||
display: flex !important;
|
||||
justify-content: center !important;
|
||||
align-items: center !important;
|
||||
flex-direction: column !important;
|
||||
}
|
||||
:deep(.ant-card-meta-detail .ant-card-meta-title) {
|
||||
font-size: 22px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.print-btn {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
cursor: pointer;
|
||||
color: #a3a3a5;
|
||||
z-index: 999;
|
||||
.print-text {
|
||||
margin-left: 5px;
|
||||
}
|
||||
&:hover {
|
||||
color: #40a9ff;
|
||||
}
|
||||
}
|
||||
.detail-iframe {
|
||||
border: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: 600px;
|
||||
}
|
||||
.files-title {
|
||||
font-size: 16px;
|
||||
margin: 10px;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
}
|
||||
.files-area {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
margin: 6px;
|
||||
&:hover {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
.files-area-text {
|
||||
display: flex;
|
||||
.ant-upload-list-item-name {
|
||||
margin: 0 6px;
|
||||
color: #56befa;
|
||||
}
|
||||
}
|
||||
.files-area-operate {
|
||||
display: flex;
|
||||
margin-left: 10px;
|
||||
.item-icon {
|
||||
cursor: pointer;
|
||||
margin: 0 6px;
|
||||
&:hover {
|
||||
color: #56befa;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.article-desc {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
span:not(:first-child) {
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
/* 确保打印内容中的图片有最大宽度限制 */
|
||||
.article-content img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -33,9 +33,20 @@
|
||||
import { useAppStore } from '/@/store/modules/app';
|
||||
import { useMessageHref } from '/@/views/system/message/components/useSysMessage';
|
||||
const appStore = useAppStore();
|
||||
|
||||
const {goPage} = useMessageHref()
|
||||
|
||||
const router = useRouter();
|
||||
const { currentRoute } = useRouter();
|
||||
const { goPage } = useMessageHref();
|
||||
// update-begin--author:liaozhiyang---date:20250709---for:【QQYUN-13058】我的消息区分类型且支持根据url参数查询类型
|
||||
const querystring = currentRoute.value.query;
|
||||
const findItem: any = searchFormSchema.find((item: any) => item.field === 'msgCategory');
|
||||
if (findItem) {
|
||||
if (querystring?.msgCategory) {
|
||||
findItem.componentProps.defaultValue = querystring.msgCategory
|
||||
} else {
|
||||
findItem.componentProps.defaultValue = null
|
||||
}
|
||||
}
|
||||
// update-end--author:liaozhiyang---date:20250709---for:【QQYUN-13058】我的消息区分类型且支持根据url参数查询类型
|
||||
const { prefixCls, tableContext } = useListPage({
|
||||
designScope: 'mynews-list',
|
||||
tableProps: {
|
||||
@ -48,6 +59,14 @@
|
||||
fieldMapToTime: [['sendTime', ['sendTimeBegin', 'sendTimeEnd'], 'YYYY-MM-DD']],
|
||||
//update-end---author:wangshuai---date:2024-06-11---for:【TV360X-545】我的消息列表不能通过时间范围查询---
|
||||
},
|
||||
beforeFetch: (params) => {
|
||||
// update-begin--author:liaozhiyang---date:20250709---for:【QQYUN-13058】我的消息区分类型且支持根据url参数查询类型
|
||||
if (querystring?.msgCategory) {
|
||||
params.msgCategory = querystring.msgCategory;
|
||||
}
|
||||
return params;
|
||||
// update-end--author:liaozhiyang---date:20250709---for:【QQYUN-13058】我的消息区分类型且支持根据url参数查询类型
|
||||
},
|
||||
},
|
||||
});
|
||||
const [registerTable, { reload }] = tableContext;
|
||||
|
||||
@ -81,4 +81,16 @@ export const searchFormSchema: FormSchema[] = [
|
||||
},
|
||||
colProps: { span: 6 },
|
||||
},
|
||||
{
|
||||
field: 'msgCategory',
|
||||
label: '消息类型',
|
||||
component: 'Select',
|
||||
componentProps: {
|
||||
options: [
|
||||
{ label: '通知公告', value: '1' },
|
||||
{ label: '系统消息', value: '2' },
|
||||
],
|
||||
},
|
||||
colProps: { span: 6 },
|
||||
},
|
||||
];
|
||||
|
||||
@ -34,7 +34,7 @@
|
||||
></chat>
|
||||
</div>
|
||||
</template>
|
||||
<Spin v-else :spinning="true"></Spin>
|
||||
<Loading :loading="loading" tip="加载中,请稍后"></Loading>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -48,6 +48,7 @@
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useAppInject } from "@/hooks/web/useAppInject";
|
||||
import Loading from '@/components/Loading/src/Loading.vue';
|
||||
|
||||
const router = useRouter();
|
||||
const userId = useUserStore().getUserInfo?.id;
|
||||
@ -67,6 +68,8 @@
|
||||
const chatActiveKey = ref<number>(0);
|
||||
//预置开场白
|
||||
const presetQuestion = ref<string>('');
|
||||
//加载
|
||||
const loading = ref<any>(true);
|
||||
|
||||
const handleToggle = () => {
|
||||
expand.value = !expand.value;
|
||||
@ -179,10 +182,13 @@
|
||||
})
|
||||
.catch(() => {
|
||||
priming();
|
||||
});
|
||||
}).finally(()=>{
|
||||
loading.value = false
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loading.value = true;
|
||||
let params: any = router.currentRoute.value.params;
|
||||
if (params.appId) {
|
||||
appId.value = params.appId;
|
||||
|
||||
@ -84,6 +84,8 @@
|
||||
}
|
||||
//倒计时执行前的函数
|
||||
function sendCodeApi() {
|
||||
return getCaptcha({ mobile: formData.mobile, smsmode: SmsEnum.FORGET_PASSWORD });
|
||||
//update-begin---author:wangshuai---date:2025-07-15---for:【issues/8567】严重:修改密码存在水平越权问题:登录应该用登录模板不应该用忘记密码的模板---
|
||||
return getCaptcha({ mobile: formData.mobile, smsmode: SmsEnum.LOGIN });
|
||||
//update-end---author:wangshuai---date:2025-07-15---for:【issues/8567】严重:修改密码存在水平越权问题:登录应该用登录模板不应该用忘记密码的模板---
|
||||
}
|
||||
</script>
|
||||
|
||||
197
jeecgboot-vue3/src/views/system/appVersion/SysAppVersion.vue
Normal file
197
jeecgboot-vue3/src/views/system/appVersion/SysAppVersion.vue
Normal file
@ -0,0 +1,197 @@
|
||||
<template>
|
||||
<PageWrapper contentFullHeight>
|
||||
<a-card :bordered="false" title="版本管理">
|
||||
<!--编辑模式-->
|
||||
<a-spin v-if="active" :spinning="confirmLoading">
|
||||
<a-form ref="formRef" :model="model" :labelCol="labelCol" :wrapperCol="wrapperCol" :rules="validatorRules">
|
||||
<a-row>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="版本" name="appVersion">
|
||||
<a-input v-model:value="model.appVersion" placeholder="请输入版本" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="APP安装apk" name="downloadUrl">
|
||||
<a-input placeholder="设置APP安装apk" v-model:value="model.downloadUrl">
|
||||
<template #addonAfter>
|
||||
<Icon icon="ant-design:upload-outlined" style="cursor: pointer" @click="showUploadModal('apk')" />
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="APP热更新文件" name="wgtUrl">
|
||||
<a-input placeholder="设置APP热更新文件" v-model:value="model.wgtUrl">
|
||||
<template #addonAfter>
|
||||
<Icon icon="ant-design:upload-outlined" style="cursor: pointer" @click="showUploadModal('wgt')" />
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="更新内容">
|
||||
<a-textarea :rows="4" v-model:value="model.updateNote" placeholder="请输入更新内容" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
<JUploadModal :value="modalValue" :bizPath="filePath" :maxCount="1" @register="registerModel" @change="uploadBack" />
|
||||
</a-spin>
|
||||
<!--详情模式-->
|
||||
<Description v-else class="desc" :column="1" :data="model" :schema="schema" />
|
||||
<!--底部按钮-->
|
||||
<div class="anty-form-btn" v-if="hasPermission('app:edit:version')">
|
||||
<a-button v-if="active" @click="handleSubmit" type="primary" preIcon="ant-design:save-outlined">保存</a-button>
|
||||
<a-button v-else @click="active = true" type="primary" preIcon="ant-design:edit-outlined">开启编辑模式</a-button>
|
||||
</div>
|
||||
</a-card>
|
||||
</PageWrapper>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="portalapp-sysAppVersion">
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import { usePermission } from '@/hooks/web/usePermission';
|
||||
import { JUploadModal } from '@/components/Form/src/jeecg/components/JUpload';
|
||||
import { useModal } from '@/components/Modal';
|
||||
import { reactive, ref, toRaw, unref, onMounted } from 'vue';
|
||||
import { PageWrapper } from '@/components/Page';
|
||||
import { queryAppVersion, saveAppVersion } from './appVersion.api';
|
||||
import { Description, DescItem } from '/@/components/Description/index';
|
||||
|
||||
const { hasPermission } = usePermission();
|
||||
const { createMessage } = useMessage();
|
||||
|
||||
const [registerModel, { openModal }] = useModal();
|
||||
const confirmLoading = ref(false);
|
||||
const active = ref(false);
|
||||
const formRef = ref<any>(null);
|
||||
const appKey = 'E0CC280';
|
||||
const filePath = 'appVersion';
|
||||
const uploadType = ref('');
|
||||
const modalValue = ref('');
|
||||
const labelCol = {
|
||||
xs: { span: 24 },
|
||||
sm: { span: 5 },
|
||||
};
|
||||
const wrapperCol = {
|
||||
xs: { span: 24 },
|
||||
sm: { span: 16 },
|
||||
};
|
||||
const model = reactive({
|
||||
id: 'E0CC280',
|
||||
appVersion: '',
|
||||
versionNum: 0,
|
||||
updateNote: '',
|
||||
downloadUrl: '',
|
||||
wgtUrl: '',
|
||||
});
|
||||
|
||||
/**
|
||||
* 初始化表单数据
|
||||
* @param record
|
||||
*/
|
||||
async function initFormData() {
|
||||
const appVersion = await queryAppVersion({ key: appKey });
|
||||
if (appVersion) {
|
||||
Object.assign(model, appVersion);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交保存版本信息
|
||||
*/
|
||||
function handleSubmit() {
|
||||
const form = unref(formRef);
|
||||
form.validate().then(async () => {
|
||||
let obj = toRaw(model);
|
||||
if (obj.appVersion.indexOf('.') != -1) {
|
||||
obj.versionNum = Number(obj.appVersion.replace(/\./g, ''));
|
||||
}
|
||||
obj.id = appKey;
|
||||
confirmLoading.value = true;
|
||||
await saveAppVersion(obj);
|
||||
createMessage.success('保存成功');
|
||||
confirmLoading.value = false;
|
||||
active.value = false;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示设置弹窗
|
||||
* @param type
|
||||
*/
|
||||
function showUploadModal(type) {
|
||||
uploadType.value = type;
|
||||
modalValue.value = type == 'apk' ? model.downloadUrl : model.wgtUrl;
|
||||
openModal(true, {
|
||||
maxCount: 1,
|
||||
bizPath: filePath,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*上传返回
|
||||
*/
|
||||
function uploadBack(value) {
|
||||
if (unref(uploadType) == 'apk') {
|
||||
model.downloadUrl = value;
|
||||
} else {
|
||||
model.wgtUrl = value;
|
||||
}
|
||||
}
|
||||
//表单校验规则
|
||||
const validatorRules = {
|
||||
appVersion: [{ required: true, message: '版本不能为空', trigger: 'blur' }],
|
||||
downloadUrl: [{ required: true, message: 'APP安装apk不能为空', trigger: 'change' }],
|
||||
wgtUrl: [{ required: true, message: 'APP热更新文件不能为空', trigger: 'change' }],
|
||||
};
|
||||
// 显示字段
|
||||
const schema: DescItem[] = [
|
||||
{
|
||||
field: 'appVersion',
|
||||
label: '版本',
|
||||
},
|
||||
{
|
||||
field: 'downloadUrl',
|
||||
label: 'APP安装apk',
|
||||
},
|
||||
{
|
||||
field: 'wgtUrl',
|
||||
label: 'APP热更新文件',
|
||||
},
|
||||
{
|
||||
field: 'updateNote',
|
||||
label: '更新内容',
|
||||
},
|
||||
];
|
||||
|
||||
onMounted(() => {
|
||||
initFormData();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.anty-form-btn {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
.anty-form-btn button {
|
||||
margin: 20px;
|
||||
}
|
||||
.approveDiv span {
|
||||
margin: 0 20px;
|
||||
}
|
||||
.desc {
|
||||
width: 80%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
:deep(.ant-descriptions-item-label) {
|
||||
width: 30% !important;
|
||||
min-width: 150px !important;
|
||||
}
|
||||
:deep(.ant-descriptions-item-content) {
|
||||
padding: 16px !important;
|
||||
width: 60% !important;
|
||||
}
|
||||
</style>
|
||||
20
jeecgboot-vue3/src/views/system/appVersion/appVersion.api.ts
Normal file
20
jeecgboot-vue3/src/views/system/appVersion/appVersion.api.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
|
||||
enum Api {
|
||||
//查询app版本
|
||||
queryAppVersion = '/sys/version/app3version',
|
||||
//保存app版本
|
||||
saveAppVersion = '/sys/version/saveVersion',
|
||||
}
|
||||
/**
|
||||
* 查询APP版本
|
||||
* @param params
|
||||
*/
|
||||
export const queryAppVersion = (params) => defHttp.get({ url: Api.queryAppVersion, params });
|
||||
/**
|
||||
* 保存APP版本
|
||||
* @param params
|
||||
*/
|
||||
export const saveAppVersion = (params) => {
|
||||
return defHttp.post({ url: Api.saveAppVersion, params });
|
||||
};
|
||||
@ -10,6 +10,7 @@ enum Api {
|
||||
wechatEnterpriseToLocal = '/sys/thirdApp/sync/wechatEnterprise/departAndUser/toLocal',
|
||||
getThirdUserBindByWechat = '/sys/thirdApp/getThirdUserBindByWechat',
|
||||
deleteThirdAccount = '/sys/thirdApp/deleteThirdAccount',
|
||||
deleteThirdAppConfig = '/sys/thirdApp/deleteThirdAppConfig',
|
||||
}
|
||||
|
||||
/**
|
||||
@ -66,4 +67,15 @@ export const getThirdUserBindByWechat = () => {
|
||||
*/
|
||||
export const deleteThirdAccount = (params) => {
|
||||
return defHttp.delete({ url: Api.deleteThirdAccount, params }, { isTransformResponse:false, joinParamsToUrl: true });
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* 根据配置表的id删除第三方配置
|
||||
* @param params
|
||||
* @param handleSuccess
|
||||
*/
|
||||
export const deleteThirdAppConfig = (params, handleSuccess) => {
|
||||
return defHttp.delete({ url: Api.deleteThirdAppConfig, params }, { joinParamsToUrl: true }).then(() => {
|
||||
handleSuccess();
|
||||
});
|
||||
};
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
<a-collapse-panel key="2">
|
||||
<template #header>
|
||||
<div style="width: 100%; justify-content: space-between; display: flex">
|
||||
<div style="font-size: 16px"> 2.对接信息录入</div>
|
||||
<div style="font-size: 16px"> 2.对接信息录入及解绑</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="base-desc">完成步骤1后,填入Agentld、 AppKey、AppSecret后 可对接应用与同步通讯录</div>
|
||||
@ -47,6 +47,7 @@
|
||||
</div>
|
||||
<div style="margin-top: 20px; width: 100%; text-align: right">
|
||||
<a-button @click="dingEditClick">编辑</a-button>
|
||||
<a-button v-if="appConfigData.id" @click="cancelBindClick" danger style="margin-left: 10px">取消绑定</a-button>
|
||||
</div>
|
||||
</a-collapse-panel>
|
||||
</a-collapse>
|
||||
@ -76,7 +77,7 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, h, inject, onMounted, reactive, ref, watch } from 'vue';
|
||||
import { getThirdConfigByTenantId, syncDingTalkDepartUserToLocal } from './ThirdApp.api';
|
||||
import { getThirdConfigByTenantId, syncDingTalkDepartUserToLocal, deleteThirdAppConfig } from './ThirdApp.api';
|
||||
import { useModal } from '/@/components/Modal';
|
||||
import ThirdAppConfigModal from './ThirdAppConfigModal.vue';
|
||||
import { Modal } from 'ant-design-vue';
|
||||
@ -122,6 +123,8 @@
|
||||
let values = await getThirdConfigByTenantId(params);
|
||||
if (values) {
|
||||
appConfigData.value = values;
|
||||
} else {
|
||||
appConfigData.value = "";
|
||||
}
|
||||
}
|
||||
|
||||
@ -214,6 +217,25 @@
|
||||
function handleIconClick(){
|
||||
window.open("https://help.qiaoqiaoyun.com/expand/dingdingsyn.html","_target")
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消绑定
|
||||
*/
|
||||
function cancelBindClick() {
|
||||
if(!appConfigData.value.id){
|
||||
createMessage.warning("请先绑定钉钉应用!");
|
||||
return;
|
||||
}
|
||||
Modal.confirm({
|
||||
title: '取消绑定',
|
||||
content: '是否要解除当前组织的钉钉应用配置绑定?',
|
||||
okText: '确认',
|
||||
cancelText: '取消',
|
||||
onOk: () => {
|
||||
deleteThirdAppConfig({ id: appConfigData.value.id }, handleSuccess);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
let tenantId = getTenantId();
|
||||
@ -229,6 +251,7 @@
|
||||
syncDingTalk,
|
||||
btnLoading,
|
||||
handleIconClick,
|
||||
cancelBindClick,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
<a-collapse-panel key="2">
|
||||
<template #header>
|
||||
<div style="width: 100%; justify-content: space-between; display: flex">
|
||||
<div style="font-size: 16px"> 2.对接信息录入</div>
|
||||
<div style="font-size: 16px"> 2.对接信息录入及解绑</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="flex-flow">
|
||||
@ -40,6 +40,7 @@
|
||||
</div>
|
||||
<div style="margin-top: 20px; width: 100%; text-align: right">
|
||||
<a-button @click="weEnterpriseEditClick">编辑</a-button>
|
||||
<a-button v-if="appConfigData.id" @click="cancelBindClick" danger style="margin-left: 10px">取消绑定</a-button>
|
||||
</div>
|
||||
</a-collapse-panel>
|
||||
</a-collapse>
|
||||
@ -61,7 +62,7 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, onMounted, ref } from 'vue';
|
||||
import { getThirdConfigByTenantId } from './ThirdApp.api';
|
||||
import { getThirdConfigByTenantId, deleteThirdAppConfig } from './ThirdApp.api';
|
||||
import ThirdAppConfigModal from './ThirdAppConfigModal.vue';
|
||||
import { useModal } from '/@/components/Modal';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
@ -97,6 +98,8 @@
|
||||
let values = await getThirdConfigByTenantId(params);
|
||||
if (values) {
|
||||
appConfigData.value = values;
|
||||
} else {
|
||||
appConfigData.value = "";
|
||||
}
|
||||
}
|
||||
|
||||
@ -159,6 +162,25 @@
|
||||
function seeBindWeChat() {
|
||||
openBindModal(true,{ izBind: true })
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消绑定
|
||||
*/
|
||||
function cancelBindClick() {
|
||||
if(!appConfigData.value.id){
|
||||
createMessage.warning("请先绑定企业微信应用!");
|
||||
return;
|
||||
}
|
||||
Modal.confirm({
|
||||
title: '取消绑定',
|
||||
content: '是否要解除当前组织的企业微信应用配置绑定?',
|
||||
okText: '确认',
|
||||
cancelText: '取消',
|
||||
onOk: () => {
|
||||
deleteThirdAppConfig({ id: appConfigData.value.id }, handleSuccess);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
let tenantId = getTenantId();
|
||||
@ -175,6 +197,7 @@
|
||||
thirdUserByWechat,
|
||||
handleBindSuccess,
|
||||
seeBindWeChat,
|
||||
cancelBindClick,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
@ -0,0 +1,60 @@
|
||||
<template>
|
||||
<BasicModal v-bind="$attrs" @register="registerModal" title="首页配置" @ok="handleSubmit" :width="600">
|
||||
<BasicForm @register="registerForm" />
|
||||
</BasicModal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, unref } from 'vue';
|
||||
import { BasicModal, useModalInner } from '/@/components/Modal';
|
||||
import { BasicForm, useForm } from '/@/components/Form/index';
|
||||
import { formSchema } from '../home.data';
|
||||
import { saveOrUpdate } from '../home.api';
|
||||
// Emits声明
|
||||
const emit = defineEmits(['register', 'success']);
|
||||
const isUpdate = ref(false);
|
||||
//表单配置
|
||||
const [registerForm, { resetFields, setFieldsValue, validate }] = useForm({
|
||||
labelWidth: 100,
|
||||
baseRowStyle: { marginTop: '10px' },
|
||||
schemas: formSchema,
|
||||
showActionButtonGroup: false,
|
||||
});
|
||||
//表单赋值
|
||||
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
|
||||
//重置表单
|
||||
await resetFields();
|
||||
setModalProps({ confirmLoading: false });
|
||||
isUpdate.value = !!data?.isUpdate;
|
||||
if (unref(isUpdate)) {
|
||||
//表单赋值
|
||||
if (data.values.relationType == 'USER') {
|
||||
data.values.userCode = data.values.roleCode;
|
||||
}
|
||||
await setFieldsValue({
|
||||
...data.values,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
//表单提交事件
|
||||
async function handleSubmit() {
|
||||
try {
|
||||
let values = await validate();
|
||||
setModalProps({ confirmLoading: true });
|
||||
//提交表单
|
||||
if(values.relationType == 'USER'){
|
||||
values.roleCode = values.userCode;
|
||||
}
|
||||
await saveOrUpdate(values, isUpdate.value);
|
||||
//关闭弹窗
|
||||
closeModal();
|
||||
//刷新列表
|
||||
emit('success');
|
||||
} finally {
|
||||
setModalProps({ confirmLoading: false });
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
55
jeecgboot-vue3/src/views/system/homeConfig/home.api.ts
Normal file
55
jeecgboot-vue3/src/views/system/homeConfig/home.api.ts
Normal file
@ -0,0 +1,55 @@
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
import { Modal } from 'ant-design-vue';
|
||||
|
||||
enum Api {
|
||||
list = '/sys/sysRoleIndex/list',
|
||||
save = '/sys/sysRoleIndex/add',
|
||||
edit = '/sys/sysRoleIndex/edit',
|
||||
deleteIndex = '/sys/sysRoleIndex/delete',
|
||||
deleteBatch = '/sys/sysRoleIndex/deleteBatch',
|
||||
queryIndexByCode = '/sys/sysRoleIndex/queryByCode',
|
||||
}
|
||||
/**
|
||||
* 系统角色列表
|
||||
* @param params
|
||||
*/
|
||||
export const list = (params) => defHttp.get({ url: Api.list, params });
|
||||
|
||||
/**
|
||||
* 删除角色
|
||||
*/
|
||||
export const deleteIndex = (params, handleSuccess) => {
|
||||
return defHttp.delete({ url: Api.deleteIndex, params }, { joinParamsToUrl: true }).then(() => {
|
||||
handleSuccess();
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 批量删除角色
|
||||
* @param params
|
||||
*/
|
||||
export const batchDelete = (params, handleSuccess) => {
|
||||
Modal.confirm({
|
||||
title: '确认删除',
|
||||
content: '是否删除选中数据',
|
||||
okText: '确认',
|
||||
cancelText: '取消',
|
||||
onOk: () => {
|
||||
return defHttp.delete({ url: Api.deleteBatch, data: params }, { joinParamsToUrl: true }).then(() => {
|
||||
handleSuccess();
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 保存或者更新首页配置
|
||||
* @param params
|
||||
*/
|
||||
export const saveOrUpdate = (params, isUpdate) => {
|
||||
const url = isUpdate ? Api.edit : Api.save;
|
||||
return defHttp.post({ url: url, params });
|
||||
};
|
||||
/**
|
||||
* 查询首页配置
|
||||
* @param params
|
||||
*/
|
||||
export const queryIndexByCode = (params) => defHttp.get({ url: Api.queryIndexByCode, params }, { isTransformResponse: false });
|
||||
129
jeecgboot-vue3/src/views/system/homeConfig/home.data.ts
Normal file
129
jeecgboot-vue3/src/views/system/homeConfig/home.data.ts
Normal file
@ -0,0 +1,129 @@
|
||||
import { FormSchema } from '/@/components/Table';
|
||||
|
||||
//列配置
|
||||
export const columns = [
|
||||
{
|
||||
title: '关联类型(用户/角色)',
|
||||
dataIndex: 'relationType_dictText',
|
||||
width: 80,
|
||||
slots: { customRender: 'relationType' },
|
||||
},
|
||||
{
|
||||
title: '用户/角色编码',
|
||||
dataIndex: 'roleCode',
|
||||
width: 80,
|
||||
slots: { customRender: 'roleCode' },
|
||||
},
|
||||
{
|
||||
title: '首页路由',
|
||||
dataIndex: 'url',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: '组件地址',
|
||||
dataIndex: 'component',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: '是否开启',
|
||||
dataIndex: 'status',
|
||||
slots: { customRender: 'status' },
|
||||
width: 60,
|
||||
},
|
||||
];
|
||||
//查询配置
|
||||
export const searchFormSchema: FormSchema[] = [
|
||||
{
|
||||
field: 'relationType',
|
||||
label: '关联类型',
|
||||
component: 'JDictSelectTag',
|
||||
componentProps: {
|
||||
dictCode: 'relation_type',
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'route',
|
||||
label: '是否路由菜单',
|
||||
helpMessage: '非路由菜单设置成首页,需开启',
|
||||
component: 'Switch',
|
||||
show: false,
|
||||
},
|
||||
];
|
||||
|
||||
export const formSchema: FormSchema[] = [
|
||||
{
|
||||
field: 'id',
|
||||
label: '',
|
||||
component: 'Input',
|
||||
show: false,
|
||||
},
|
||||
{
|
||||
field: 'relationType',
|
||||
label: '关联类型',
|
||||
component: 'JDictSelectTag',
|
||||
required: true,
|
||||
defaultValue: 'ROLE',
|
||||
componentProps: {
|
||||
dictCode: 'relation_type',
|
||||
type: 'radioButton',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '角色编码',
|
||||
field: 'roleCode',
|
||||
component: 'JSelectRole',
|
||||
required: true,
|
||||
componentProps: {
|
||||
rowKey: 'roleCode',
|
||||
isRadioSelection: true,
|
||||
},
|
||||
ifShow: ({ values }) => values.relationType == 'ROLE',
|
||||
},
|
||||
{
|
||||
label: '用户编码',
|
||||
field: 'userCode',
|
||||
component: 'JSelectUser',
|
||||
required: true,
|
||||
componentProps: {
|
||||
isRadioSelection: true,
|
||||
},
|
||||
ifShow: ({ values }) => values.relationType == 'USER',
|
||||
},
|
||||
{
|
||||
label: '首页路由',
|
||||
field: 'url',
|
||||
component: 'Input',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
label: '组件地址',
|
||||
field: 'component',
|
||||
component: 'Input',
|
||||
componentProps: {
|
||||
placeholder: '请输入前端组件',
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
label: '优先级',
|
||||
field: 'priority',
|
||||
component: 'InputNumber',
|
||||
},
|
||||
{
|
||||
field: 'route',
|
||||
label: '是否路由菜单',
|
||||
helpMessage: '非路由菜单设置成首页,需开启',
|
||||
component: 'Switch',
|
||||
defaultValue: true,
|
||||
show: false,
|
||||
},
|
||||
{
|
||||
label: '是否开启',
|
||||
field: 'status',
|
||||
component: 'JSwitch',
|
||||
defaultValue: '1',
|
||||
componentProps: {
|
||||
options: ['1', '0'],
|
||||
},
|
||||
},
|
||||
];
|
||||
126
jeecgboot-vue3/src/views/system/homeConfig/index.vue
Normal file
126
jeecgboot-vue3/src/views/system/homeConfig/index.vue
Normal file
@ -0,0 +1,126 @@
|
||||
<template>
|
||||
<div>
|
||||
<BasicTable @register="registerTable" :rowSelection="rowSelection">
|
||||
<template #tableTitle>
|
||||
<a-button type="primary" preIcon="ant-design:plus-outlined" @click="handleCreate">新增</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" /> 删除
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
<a-button>批量操作<Icon icon="mdi:chevron-down" /></a-button>
|
||||
</a-dropdown>
|
||||
</template>
|
||||
<template #action="{ record }">
|
||||
<TableAction :actions="getTableAction(record)" />
|
||||
</template>
|
||||
<template #status="{ text }">
|
||||
<a-tag color="pink" v-if="text == 0">禁用</a-tag>
|
||||
<a-tag color="#87d068" v-if="text == 1">启用</a-tag>
|
||||
</template>
|
||||
<template #relationType="{ text, record }">
|
||||
<span>{{ record.roleCode == 'DEF_INDEX_ALL' ? '--' : text }}</span>
|
||||
</template>
|
||||
<template #roleCode="{ text, record }">
|
||||
<span>{{ record.roleCode == 'DEF_INDEX_ALL' ? '菜单默认首页' : text }}</span>
|
||||
</template>
|
||||
</BasicTable>
|
||||
<!--角色首页配置-->
|
||||
<HomeConfigModal @register="register" @success="reload" />
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" name="home-config" setup>
|
||||
import { BasicTable, TableAction } from '/@/components/Table';
|
||||
import { useModal } from '/@/components/Modal';
|
||||
import HomeConfigModal from './components/HomeConfigModal.vue';
|
||||
import { columns, searchFormSchema } from './home.data';
|
||||
import { useListPage } from '/@/hooks/system/useListPage';
|
||||
import { list, deleteIndex, batchDelete } from './home.api';
|
||||
|
||||
//弹窗配置
|
||||
const [register, { openModal }] = useModal();
|
||||
|
||||
// 列表页面公共参数、方法
|
||||
const { tableContext } = useListPage({
|
||||
designScope: 'home-config',
|
||||
tableProps: {
|
||||
title: '首页配置',
|
||||
api: list,
|
||||
columns: columns,
|
||||
formConfig: {
|
||||
labelAlign: 'left',
|
||||
labelWidth: 80,
|
||||
schemas: searchFormSchema,
|
||||
baseRowStyle: {
|
||||
marginLeft: '2px',
|
||||
},
|
||||
},
|
||||
actionColumn: {
|
||||
width: 80,
|
||||
},
|
||||
//自定义默认排序
|
||||
defSort: {
|
||||
column: 'id',
|
||||
order: 'desc',
|
||||
},
|
||||
},
|
||||
});
|
||||
const [registerTable, { reload, clearSelectedRowKeys }, { rowSelection, selectedRowKeys }] = tableContext;
|
||||
|
||||
/**
|
||||
* 新增事件
|
||||
*/
|
||||
async function handleCreate() {
|
||||
openModal(true, {
|
||||
isUpdate: false,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 编辑事件
|
||||
*/
|
||||
async function handleEdit(record) {
|
||||
openModal(true, {
|
||||
isUpdate: true,
|
||||
values: record,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 删除事件
|
||||
*/
|
||||
async function handleDelete(record) {
|
||||
await deleteIndex({ id: record.id }, () => {
|
||||
reload();
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 批量删除事件
|
||||
*/
|
||||
async function batchHandleDelete() {
|
||||
await batchDelete({ ids: selectedRowKeys.value }, () => {
|
||||
clearSelectedRowKeys();
|
||||
reload();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 操作栏
|
||||
*/
|
||||
function getTableAction(record) {
|
||||
return [
|
||||
{
|
||||
label: '编辑',
|
||||
onClick: handleEdit.bind(null, record),
|
||||
},
|
||||
{
|
||||
label: '删除',
|
||||
popConfirm: {
|
||||
title: '是否确认删除',
|
||||
confirm: handleDelete.bind(null, record),
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
</script>
|
||||
@ -344,7 +344,9 @@
|
||||
return;
|
||||
}
|
||||
//update-begin---author:wangshuai---date:2024-04-18---for:【QQYUN-9005】同一个IP,1分钟超过5次短信,则提示需要验证码---
|
||||
const result = await getCaptcha({ mobile: phoneFormData.mobile, smsmode: SmsEnum.FORGET_PASSWORD }).catch((res) =>{
|
||||
//update-begin---author:wangshuai---date:2025-07-15---for:【issues/8567】严重:修改密码存在水平越权问题:登录应该用登录模板不应该用忘记密码的模板---
|
||||
const result = await getCaptcha({ mobile: phoneFormData.mobile, smsmode: SmsEnum.LOGIN }).catch((res) =>{
|
||||
//update-end---author:wangshuai---date:2025-07-15---for:【issues/8567】严重:修改密码存在水平越权问题:登录应该用登录模板不应该用忘记密码的模板---
|
||||
if(res.code === ExceptionEnum.PHONE_SMS_FAIL_CODE){
|
||||
openCaptchaModal(true, {});
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<BasicModal @register="registerModal" :title="title" :width="800" v-bind="$attrs" @ok="onSubmit">
|
||||
<BasicModal @register="registerModal" :title="title" :width="600" v-bind="$attrs" @ok="onSubmit">
|
||||
<BasicForm @register="registerForm" />
|
||||
</BasicModal>
|
||||
</template>
|
||||
@ -21,6 +21,15 @@
|
||||
//update-end---author:wangshuai ---date:20221123 for:[VUEN-2807]消息模板加一个查看功能--------------z
|
||||
schemas: formSchemas,
|
||||
showActionButtonGroup: false,
|
||||
baseRowStyle: {
|
||||
marginTop: '10px',
|
||||
},
|
||||
labelCol: {
|
||||
span: 5,
|
||||
},
|
||||
wrapperCol: {
|
||||
span: 17,
|
||||
},
|
||||
});
|
||||
// 注册 modal
|
||||
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
|
||||
|
||||
@ -86,12 +86,23 @@ export const formSchemas: FormSchema[] = [
|
||||
label: '模板类型',
|
||||
field: 'templateType',
|
||||
component: 'JDictSelectTag',
|
||||
defaultValue: '1',
|
||||
componentProps: {
|
||||
dictCode: 'msgType',
|
||||
type: 'radio',
|
||||
placeholder: '请选择模板类型',
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
label: '模板分类',
|
||||
field: 'templateCategory',
|
||||
component: 'JDictSelectTag',
|
||||
componentProps: {
|
||||
dictCode: 'msgCategory',
|
||||
placeholder: '请选择模板分类',
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '是否应用',
|
||||
field: 'useStatus',
|
||||
|
||||
@ -1,20 +1,113 @@
|
||||
<template>
|
||||
<BasicModal v-bind="$attrs" @register="registerModal" title="查看详情" :showCancelBtn="false" :showOkBtn="false" :maxHeight="500">
|
||||
<iframe :src="frameSrc" class="detail-iframe" />
|
||||
<BasicModal v-bind="$attrs" @register="registerModal" :width="800" title="查看详情" :showCancelBtn="false" :showOkBtn="false" :maxHeight="500">
|
||||
<div class="print-btn" @click="onPrinter">
|
||||
<Icon icon="ant-design:printer-filled" />
|
||||
<span class="print-text">打印</span>
|
||||
</div>
|
||||
<iframe ref="iframeRef" :src="frameSrc" class="detail-iframe" @load="onIframeLoad"></iframe>
|
||||
<template v-if="noticeFiles && noticeFiles.length > 0">
|
||||
<div class="files-title">相关附件:</div>
|
||||
<template v-for="(file, index) in noticeFiles" :key="index">
|
||||
<div class="files-area">
|
||||
<div class="files-area-text">
|
||||
<span>
|
||||
<paper-clip-outlined />
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
:title="file.fileName"
|
||||
:href="getFileAccessHttpUrl(file.filePath)"
|
||||
class="ant-upload-list-item-name"
|
||||
>{{ file.fileName }}</a
|
||||
>
|
||||
</span>
|
||||
</div>
|
||||
<div class="files-area-operate">
|
||||
<download-outlined class="item-icon" @click="handleDownloadFile(file.filePath)" />
|
||||
<eye-outlined class="item-icon" @click="handleViewFile(file.filePath)" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
</BasicModal>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { BasicModal, useModalInner } from '/@/components/Modal';
|
||||
import { propTypes } from '/@/utils/propTypes';
|
||||
import { ref } from 'vue';
|
||||
import { buildUUID } from '@/utils/uuid';
|
||||
import { getFileAccessHttpUrl } from '@/utils/common/compUtils';
|
||||
import { DownloadOutlined, EyeOutlined, PaperClipOutlined } from '@ant-design/icons-vue';
|
||||
import { encryptByBase64 } from '@/utils/cipher';
|
||||
import { useGlobSetting } from '@/hooks/setting';
|
||||
const glob = useGlobSetting();
|
||||
// 获取props
|
||||
defineProps({
|
||||
frameSrc: propTypes.string.def(''),
|
||||
});
|
||||
//附件内容
|
||||
const noticeFiles = ref([]);
|
||||
//表单赋值
|
||||
const [registerModal] = useModalInner();
|
||||
const [registerModal] = useModalInner((data) => {
|
||||
noticeFiles.value = [];
|
||||
if (data.record?.files && data.record?.files.length > 0) {
|
||||
noticeFiles.value = data.record.files.split(',').map((item) => {
|
||||
return {
|
||||
fileName: item.split('/').pop(),
|
||||
filePath: item,
|
||||
};
|
||||
});
|
||||
}
|
||||
});
|
||||
// iframe引用
|
||||
const iframeRef = ref<HTMLIFrameElement>();
|
||||
// 存储当前打印会话ID
|
||||
const printSessionId = ref<string>('');
|
||||
// iframe加载完成后初始化通信
|
||||
const onIframeLoad = () => {
|
||||
printSessionId.value = buildUUID(); // 每次加载生成新的会话ID
|
||||
};
|
||||
//打印
|
||||
function onPrinter() {
|
||||
if (!iframeRef.value) return;
|
||||
console.log('onPrinter', iframeRef.value);
|
||||
iframeRef.value?.contentWindow?.postMessage({ printSessionId: printSessionId.value, type: 'action:print' }, '*');
|
||||
}
|
||||
/**
|
||||
* 下载文件
|
||||
* @param filePath
|
||||
*/
|
||||
function handleDownloadFile(filePath) {
|
||||
window.open(getFileAccessHttpUrl(filePath), '_blank');
|
||||
}
|
||||
/**
|
||||
* 预览文件
|
||||
* @param filePath
|
||||
*/
|
||||
function handleViewFile(filePath) {
|
||||
if (filePath) {
|
||||
let url = encodeURIComponent(encryptByBase64(filePath));
|
||||
let previewUrl = `${glob.viewUrl}?url=` + url;
|
||||
window.open(previewUrl, '_blank');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.print-btn {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
cursor: pointer;
|
||||
color: #a3a3a5;
|
||||
z-index: 999;
|
||||
.print-text {
|
||||
margin-left: 5px;
|
||||
}
|
||||
&:hover {
|
||||
color: #40a9ff;
|
||||
}
|
||||
}
|
||||
.detail-iframe {
|
||||
border: 0;
|
||||
width: 100%;
|
||||
@ -24,4 +117,37 @@
|
||||
display: block;
|
||||
// -update-end--author:liaozhiyang---date:20240702---for:【TV360X-1685】通知公告查看出现两个滚动条
|
||||
}
|
||||
.files-title {
|
||||
font-size: 16px;
|
||||
margin: 10px;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
}
|
||||
.files-area {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
margin: 6px;
|
||||
&:hover {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
.files-area-text {
|
||||
display: flex;
|
||||
.ant-upload-list-item-name {
|
||||
margin: 0 6px;
|
||||
color: #56befa;
|
||||
}
|
||||
}
|
||||
.files-area-operate {
|
||||
display: flex;
|
||||
margin-left: 10px;
|
||||
.item-icon {
|
||||
cursor: pointer;
|
||||
margin: 0 6px;
|
||||
&:hover {
|
||||
color: #56befa;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
116
jeecgboot-vue3/src/views/system/notice/NoticeForm.vue
Normal file
116
jeecgboot-vue3/src/views/system/notice/NoticeForm.vue
Normal file
@ -0,0 +1,116 @@
|
||||
<template>
|
||||
<div style="min-height: 400px">
|
||||
<BasicForm @register="registerForm">
|
||||
<template #msgTemplate="{ model, field }">
|
||||
<a-select v-model:value="model[field]" placeholder="请选择消息模版" :options="templateOption" @change="handleChange" />
|
||||
</template>
|
||||
<template #msgContent="{ model, field }">
|
||||
<div v-html="model[field]" class="article-content"></div>
|
||||
</template>
|
||||
</BasicForm>
|
||||
<div class="footer-btn" v-if="!formDisabled">
|
||||
<a-button @click="submitForm" pre-icon="ant-design:check" type="primary">提 交</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { BasicForm, useForm } from '/@/components/Form/index';
|
||||
import { getBpmFormSchema } from './notice.data';
|
||||
import { getTempList, queryById, saveOrUpdate } from './notice.api';
|
||||
import { computed, ref } from 'vue';
|
||||
// 定义属性
|
||||
const props = defineProps({
|
||||
formData: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
});
|
||||
//表单禁用
|
||||
const formDisabled = computed(() => {
|
||||
if (props.formData.disabled === false) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
const templateOption = ref([]);
|
||||
//表单配置
|
||||
const [registerForm, { resetFields, setFieldsValue, validate }] = useForm({
|
||||
schemas: getBpmFormSchema(props.formData),
|
||||
showActionButtonGroup: false,
|
||||
disabled: formDisabled.value,
|
||||
labelWidth: 100,
|
||||
baseRowStyle: { marginTop: '10px' },
|
||||
baseColProps: { xs: 24, sm: 12, md: 12, lg: 12, xl: 12, xxl: 12 },
|
||||
});
|
||||
|
||||
//表单提交
|
||||
async function submitForm() {
|
||||
let values = await validate();
|
||||
if (values.msgType === 'ALL') {
|
||||
values.userIds = '';
|
||||
} else {
|
||||
values.userIds += ',';
|
||||
}
|
||||
console.log('表单数据', values);
|
||||
await saveOrUpdate(values, true);
|
||||
}
|
||||
//初始化模板
|
||||
async function initTemplate() {
|
||||
const res = await getTempList({ templateCategory: 'notice', pageSize: 100 });
|
||||
console.log('res', res);
|
||||
if (res.records && res.records.length > 0) {
|
||||
templateOption.value = res.records.map((item) => {
|
||||
return {
|
||||
label: item.templateName,
|
||||
value: item.templateCode,
|
||||
content: item.templateContent,
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 模版修改
|
||||
* @param val
|
||||
*/
|
||||
function handleChange(val) {
|
||||
const content = templateOption.value.find((item: any) => item.value === val)?.content;
|
||||
if (content) {
|
||||
setFieldsValue({
|
||||
msgContent: content,
|
||||
});
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 加载数据
|
||||
*/
|
||||
async function initFormData() {
|
||||
let res = await queryById({ id: props.formData.dataId });
|
||||
if (res.success) {
|
||||
//重置表单
|
||||
await resetFields();
|
||||
const record = res.result;
|
||||
if (record.userIds) {
|
||||
record.userIds = record.userIds.substring(0, record.userIds.length - 1);
|
||||
}
|
||||
//表单赋值
|
||||
await setFieldsValue({
|
||||
...record,
|
||||
});
|
||||
}
|
||||
}
|
||||
//加载模版
|
||||
initTemplate();
|
||||
//加载数据
|
||||
initFormData();
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.footer-btn {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
.article-content {
|
||||
max-width: 100%;
|
||||
max-height: 500px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
</style>
|
||||
@ -1,6 +1,19 @@
|
||||
<template>
|
||||
<BasicModal v-bind="$attrs" @register="registerModal" :title="title" @ok="handleSubmit" width="900px" destroyOnClose>
|
||||
<BasicForm @register="registerForm" />
|
||||
<BasicModal
|
||||
v-bind="$attrs"
|
||||
@register="registerModal"
|
||||
@ok="handleSubmit"
|
||||
:title="title"
|
||||
width="900px"
|
||||
wrapClassName="notice-cls-modal"
|
||||
:maxHeight="800"
|
||||
destroyOnClose
|
||||
>
|
||||
<BasicForm @register="registerForm">
|
||||
<template #msgTemplate="{ model, field }">
|
||||
<a-select v-model:value="model[field]" placeholder="请选择消息模版" :options="templateOption" @change="handleChange" />
|
||||
</template>
|
||||
</BasicForm>
|
||||
</BasicModal>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
@ -8,17 +21,24 @@
|
||||
import { BasicModal, useModalInner } from '/@/components/Modal';
|
||||
import { BasicForm, useForm } from '/@/components/Form/index';
|
||||
import { formSchema } from './notice.data';
|
||||
import { saveOrUpdate } from './notice.api';
|
||||
import { getTempList, saveOrUpdate } from './notice.api';
|
||||
// 声明Emits
|
||||
const emit = defineEmits(['register', 'success']);
|
||||
const isUpdate = ref(true);
|
||||
const record = ref<any>({});
|
||||
const templateOption = ref([]);
|
||||
//表单配置
|
||||
const [registerForm, { resetFields, setFieldsValue, validate }] = useForm({
|
||||
schemas: formSchema,
|
||||
showActionButtonGroup: false,
|
||||
labelWidth: 100,
|
||||
baseRowStyle: { marginTop: '10px' },
|
||||
baseColProps: { xs: 24, sm: 12, md: 12, lg: 12, xl: 12, xxl: 12 },
|
||||
});
|
||||
//表单赋值
|
||||
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
|
||||
//加载模版
|
||||
await initTemplate();
|
||||
//重置表单
|
||||
await resetFields();
|
||||
setModalProps({ confirmLoading: false });
|
||||
@ -31,12 +51,13 @@
|
||||
await setFieldsValue({
|
||||
...data.record,
|
||||
});
|
||||
record.value = data.record;
|
||||
}
|
||||
});
|
||||
//设置标题
|
||||
const title = computed(() => (!unref(isUpdate) ? '新增' : '编辑'));
|
||||
//表单提交事件
|
||||
async function handleSubmit(v) {
|
||||
async function handleSubmit() {
|
||||
try {
|
||||
let values = await validate();
|
||||
setModalProps({ confirmLoading: true });
|
||||
@ -48,7 +69,7 @@
|
||||
values.userIds += ',';
|
||||
}
|
||||
//update-end-author:liusq---date:20230404--for: [issue#429]新增通知公告提交指定用户参数有undefined ---
|
||||
if (isUpdate.value) {
|
||||
if (isUpdate.value && record.value.sendStatus != '2') {
|
||||
values.sendStatus = '0';
|
||||
}
|
||||
await saveOrUpdate(values, isUpdate.value);
|
||||
@ -60,4 +81,36 @@
|
||||
setModalProps({ confirmLoading: false });
|
||||
}
|
||||
}
|
||||
//初始化模板
|
||||
async function initTemplate() {
|
||||
const res = await getTempList({ templateCategory: 'notice', pageSize: 100 });
|
||||
console.log('res', res);
|
||||
if (res.records && res.records.length > 0) {
|
||||
templateOption.value = res.records.map((item) => {
|
||||
return {
|
||||
label: item.templateName,
|
||||
value: item.templateCode,
|
||||
content: item.templateContent,
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 模版修改
|
||||
* @param val
|
||||
*/
|
||||
function handleChange(val) {
|
||||
const content = templateOption.value.find((item: any) => item.value === val)?.content;
|
||||
if (content) {
|
||||
setFieldsValue({
|
||||
msgContent: content,
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
.notice-cls-modal {
|
||||
top: 20px !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -34,17 +34,17 @@
|
||||
import { useModal } from '/@/components/Modal';
|
||||
import NoticeModal from './NoticeModal.vue';
|
||||
import DetailModal from './DetailModal.vue';
|
||||
import { useMethods } from '/@/hooks/system/useMethods';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import { useGlobSetting } from '/@/hooks/setting';
|
||||
import { getToken } from '/@/utils/auth';
|
||||
import { columns, searchFormSchema } from './notice.data';
|
||||
import { getList, deleteNotice, batchDeleteNotice, getExportUrl, getImportUrl, doReleaseData, doReovkeData } from './notice.api';
|
||||
import { getList, deleteNotice, batchDeleteNotice,editIzTop, getExportUrl, getImportUrl, doReleaseData, doReovkeData } from './notice.api';
|
||||
import { useListPage } from '/@/hooks/system/useListPage';
|
||||
const glob = useGlobSetting();
|
||||
const [registerModal, { openModal }] = useModal();
|
||||
const [register, { openModal: openDetail }] = useModal();
|
||||
const iframeUrl = ref('');
|
||||
|
||||
const { createMessage, createConfirm } = useMessage();
|
||||
// 列表页面公共参数、方法
|
||||
const { prefixCls, onExportXls, onImportXls, tableContext, doRequest } = useListPage({
|
||||
designScope: 'notice-template',
|
||||
@ -66,7 +66,8 @@
|
||||
});
|
||||
|
||||
const [registerTable, { reload }, { rowSelection, selectedRowKeys }] = tableContext;
|
||||
|
||||
//流程编码
|
||||
const flowCode = 'dev_sys_announcement_001';
|
||||
/**
|
||||
* 新增事件
|
||||
*/
|
||||
@ -92,6 +93,12 @@
|
||||
async function handleDelete(record) {
|
||||
await deleteNotice({ id: record.id }, reload);
|
||||
}
|
||||
/**
|
||||
* 置顶操作
|
||||
*/
|
||||
async function handleTop(record, izTop) {
|
||||
await editIzTop({ id: record.id, izTop }, reload);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除事件
|
||||
@ -118,8 +125,9 @@
|
||||
*/
|
||||
function handleDetail(record) {
|
||||
iframeUrl.value = `${glob.uploadUrl}/sys/annountCement/show/${record.id}?token=${getToken()}`;
|
||||
openDetail(true);
|
||||
openDetail(true, { record });
|
||||
}
|
||||
|
||||
/**
|
||||
* 操作列定义
|
||||
* @param record
|
||||
@ -131,6 +139,11 @@
|
||||
onClick: handleEdit.bind(null, record),
|
||||
ifShow: record.sendStatus == 0 || record.sendStatus == '2',
|
||||
},
|
||||
{
|
||||
label: '查看',
|
||||
onClick: handleDetail.bind(null, record),
|
||||
ifShow: record.sendStatus == 1,
|
||||
},
|
||||
];
|
||||
}
|
||||
/**
|
||||
@ -148,7 +161,7 @@
|
||||
},
|
||||
{
|
||||
label: '发布',
|
||||
ifShow: record.sendStatus == 0,
|
||||
ifShow: (!record?.izApproval || record.izApproval == '0') && record.sendStatus == 0,
|
||||
onClick: handleRelease.bind(null, record.id),
|
||||
},
|
||||
{
|
||||
@ -160,8 +173,22 @@
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '查看',
|
||||
onClick: handleDetail.bind(null, record),
|
||||
label: '发布',
|
||||
ifShow: record.sendStatus == '2',
|
||||
popConfirm: {
|
||||
title: '确定要再次发布吗?',
|
||||
confirm: handleRelease.bind(null, record.id),
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '置顶',
|
||||
onClick: handleTop.bind(null, record, 1),
|
||||
ifShow: record.sendStatus == 1 && record.izTop == 0,
|
||||
},
|
||||
{
|
||||
label: '取消置顶',
|
||||
onClick: handleTop.bind(null, record, 0),
|
||||
ifShow: record.sendStatus == 1 && record.izTop == 1,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
@ -5,11 +5,17 @@ enum Api {
|
||||
save = '/sys/annountCement/add',
|
||||
edit = '/sys/annountCement/edit',
|
||||
delete = '/sys/annountCement/delete',
|
||||
queryById = '/sys/annountCement/queryById',
|
||||
deleteBatch = '/sys/annountCement/deleteBatch',
|
||||
exportXls = '/sys/annountCement/exportXls',
|
||||
importExcel = '/sys/annountCement/importExcel',
|
||||
releaseData = '/sys/annountCement/doReleaseData',
|
||||
reovkeData = '/sys/annountCement/doReovkeData',
|
||||
editIzTop = '/sys/annountCement/editIzTop',
|
||||
|
||||
addVisitsNum = '/sys/annountCement/addVisitsNumber',
|
||||
|
||||
tempList = '/sys/message/sysMessageTemplate/list',
|
||||
}
|
||||
|
||||
/**
|
||||
@ -21,7 +27,7 @@ export const getExportUrl = Api.exportXls;
|
||||
*/
|
||||
export const getImportUrl = Api.importExcel;
|
||||
/**
|
||||
* 查询租户列表
|
||||
* 查询消息列表
|
||||
* @param params
|
||||
*/
|
||||
export const getList = (params) => {
|
||||
@ -33,7 +39,7 @@ export const getList = (params) => {
|
||||
* @param params
|
||||
*/
|
||||
export const saveOrUpdate = (params, isUpdate) => {
|
||||
let url = isUpdate ? Api.edit : Api.save;
|
||||
const url = isUpdate ? Api.edit : Api.save;
|
||||
return defHttp.post({ url: url, params });
|
||||
};
|
||||
|
||||
@ -46,6 +52,15 @@ export const deleteNotice = (params, handleSuccess) => {
|
||||
handleSuccess();
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 置顶编辑
|
||||
* @param params
|
||||
*/
|
||||
export const editIzTop = (params, handleSuccess) => {
|
||||
return defHttp.post({ url: Api.editIzTop, data: params }).then(() => {
|
||||
handleSuccess();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 批量消息公告
|
||||
@ -63,3 +78,26 @@ export const doReleaseData = (params) => defHttp.get({ url: Api.releaseData, par
|
||||
* @param id
|
||||
*/
|
||||
export const doReovkeData = (params) => defHttp.get({ url: Api.reovkeData, params });
|
||||
/**
|
||||
* 新增访问量
|
||||
* @param id
|
||||
*/
|
||||
export const addVisitsNum = (params) => defHttp.get({ url: Api.addVisitsNum, params }, { successMessageMode: 'none' });
|
||||
/**
|
||||
* 根据ID查询数据
|
||||
* @param id
|
||||
*/
|
||||
export const queryById = (params) => defHttp.get({ url: Api.queryById, params }, { isTransformResponse: false });
|
||||
/**
|
||||
* 发起流程
|
||||
* import { startProcess } from '/@/api/common/api';
|
||||
* @param params
|
||||
*/
|
||||
export const startProcess = (params) => defHttp.post({ url: Api.startProcess, params }, { isTransformResponse: false });
|
||||
/**
|
||||
* 查询模板列表
|
||||
* @param params
|
||||
*/
|
||||
export const getTempList = (params) => {
|
||||
return defHttp.get({ url: Api.tempList, params });
|
||||
};
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { BasicColumn, FormSchema } from '/@/components/Table';
|
||||
import { rules } from '/@/utils/helper/validator';
|
||||
import { render } from '/@/utils/common/renderUtils';
|
||||
import { h } from 'vue';
|
||||
import { Tinymce } from '@/components/Tinymce';
|
||||
|
||||
export const columns: BasicColumn[] = [
|
||||
{
|
||||
@ -87,9 +88,24 @@ export const formSchema: FormSchema[] = [
|
||||
placeholder: '请选择类型',
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'izTop',
|
||||
label: '是否置顶',
|
||||
defaultValue: '0',
|
||||
component: 'JSwitch',
|
||||
componentProps: {
|
||||
//取值 options
|
||||
options: ['1', '0'],
|
||||
//文本option
|
||||
labelOptions: ['是', '否'],
|
||||
placeholder: '是否置顶',
|
||||
checkedChildren: '是',
|
||||
unCheckedChildren: '否',
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'titile',
|
||||
label: '标题',
|
||||
label: '通告标题',
|
||||
component: 'Input',
|
||||
required: true,
|
||||
componentProps: {
|
||||
@ -114,8 +130,15 @@ export const formSchema: FormSchema[] = [
|
||||
},
|
||||
{
|
||||
field: 'msgAbstract',
|
||||
label: '摘要',
|
||||
label: '通告摘要',
|
||||
component: 'InputTextArea',
|
||||
componentProps: {
|
||||
allowClear: true,
|
||||
autoSize: {
|
||||
minRows: 2,
|
||||
maxRows: 5,
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
// {
|
||||
@ -154,9 +177,18 @@ export const formSchema: FormSchema[] = [
|
||||
},
|
||||
ifShow: ({ values }) => values.msgType == 'USER',
|
||||
},
|
||||
{
|
||||
field: 'msgClassify',
|
||||
label: '公告分类',
|
||||
component: 'JDictSelectTag',
|
||||
componentProps: {
|
||||
dictCode: 'notice_type',
|
||||
placeholder: '请选择公告分类',
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'priority',
|
||||
label: '优先级',
|
||||
label: '优先级别',
|
||||
defaultValue: 'H',
|
||||
component: 'JDictSelectTag',
|
||||
componentProps: {
|
||||
@ -166,9 +198,211 @@ export const formSchema: FormSchema[] = [
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'msgContent',
|
||||
label: '内容',
|
||||
field: 'izApproval',
|
||||
label: '是否审批',
|
||||
component: 'RadioGroup',
|
||||
defaultValue: '0',
|
||||
componentProps: {
|
||||
options: [
|
||||
{
|
||||
label: '是',
|
||||
value: '1',
|
||||
},
|
||||
{
|
||||
label: '否',
|
||||
value: '0',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'msgTemplate',
|
||||
label: '公告模版',
|
||||
component: 'Input',
|
||||
slot: 'msgTemplate',
|
||||
},
|
||||
{
|
||||
field: 'files',
|
||||
label: '通告附件',
|
||||
component: 'JUpload',
|
||||
componentProps: {
|
||||
//是否显示选择按钮
|
||||
text: '文件上传',
|
||||
//最大上传数
|
||||
maxCount: 20,
|
||||
//是否显示下载按钮
|
||||
download: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'msgContent',
|
||||
label: '通告内容',
|
||||
component: 'Input',
|
||||
colProps: { span: 24 },
|
||||
render: render.renderTinymce,
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* 流程表单调用这个方法获取formSchema
|
||||
* @param param
|
||||
*/
|
||||
export function getBpmFormSchema(_formData): FormSchema[] {
|
||||
// 默认和原始表单保持一致 如果流程中配置了权限数据,这里需要单独处理formSchema
|
||||
return [
|
||||
{
|
||||
field: 'id',
|
||||
label: 'id',
|
||||
component: 'Input',
|
||||
show: false,
|
||||
},
|
||||
{
|
||||
field: 'msgCategory',
|
||||
label: '消息类型',
|
||||
required: true,
|
||||
component: 'JDictSelectTag',
|
||||
defaultValue: '1',
|
||||
componentProps: {
|
||||
type: 'radio',
|
||||
dictCode: 'msg_category',
|
||||
placeholder: '请选择类型',
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'izTop',
|
||||
label: '是否置顶',
|
||||
defaultValue: '0',
|
||||
component: 'JSwitch',
|
||||
componentProps: {
|
||||
//取值 options
|
||||
options: ['1', '0'],
|
||||
//文本option
|
||||
labelOptions: ['是', '否'],
|
||||
placeholder: '是否置顶',
|
||||
checkedChildren: '是',
|
||||
unCheckedChildren: '否',
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'titile',
|
||||
label: '通告标题',
|
||||
component: 'Input',
|
||||
required: true,
|
||||
componentProps: {
|
||||
placeholder: '请输入标题',
|
||||
},
|
||||
// update-begin--author:liaozhiyang---date:20240701---for:【TV360X-1632】标题过长保存报错,长度校验
|
||||
dynamicRules() {
|
||||
return [
|
||||
{
|
||||
validator: (_, value) => {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
if (value.length > 100) {
|
||||
reject('最长100个字符');
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
},
|
||||
},
|
||||
];
|
||||
},
|
||||
// update-end--author:liaozhiyang---date:20240701---for:【TV360X-1632】标题过长保存报错,长度校验
|
||||
},
|
||||
{
|
||||
field: 'msgAbstract',
|
||||
label: '通告摘要',
|
||||
component: 'InputTextArea',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
field: 'msgType',
|
||||
label: '接收用户',
|
||||
defaultValue: 'ALL',
|
||||
component: 'JDictSelectTag',
|
||||
required: true,
|
||||
componentProps: {
|
||||
type: 'radio',
|
||||
dictCode: 'msg_type',
|
||||
placeholder: '请选择发布范围',
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'userIds',
|
||||
label: '指定用户',
|
||||
component: 'JSelectUserByDepartment',
|
||||
required: true,
|
||||
componentProps: {
|
||||
rowKey: 'id',
|
||||
// update-begin--author:liaozhiyang---date:20240701---for:【TV360X-1627】通知公告用户选择组件没翻译
|
||||
labelKey: 'realname',
|
||||
// update-end--author:liaozhiyang---date:20240701---for:【TV360X-1627】通知公告用户选择组件没翻译
|
||||
},
|
||||
ifShow: ({ values }) => values.msgType == 'USER',
|
||||
},
|
||||
{
|
||||
field: 'msgClassify',
|
||||
label: '公告分类',
|
||||
component: 'JDictSelectTag',
|
||||
componentProps: {
|
||||
dictCode: 'notice_type',
|
||||
placeholder: '请选择公告分类',
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'priority',
|
||||
label: '优先级别',
|
||||
defaultValue: 'H',
|
||||
component: 'JDictSelectTag',
|
||||
componentProps: {
|
||||
dictCode: 'priority',
|
||||
type: 'radio',
|
||||
placeholder: '请选择优先级',
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'msgTemplate',
|
||||
label: '公告模版',
|
||||
component: 'Input',
|
||||
slot: 'msgTemplate',
|
||||
},
|
||||
{
|
||||
field: 'files',
|
||||
label: '通告附件',
|
||||
component: 'JUpload',
|
||||
componentProps: {
|
||||
//是否显示选择按钮
|
||||
text: '文件上传',
|
||||
//最大上传数
|
||||
maxCount: 2,
|
||||
//是否显示下载按钮
|
||||
download: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'msgContent',
|
||||
label: '通告内容',
|
||||
component: 'Input',
|
||||
colProps: { span: 24 },
|
||||
ifShow: ({}) => _formData.disabled == false,
|
||||
render: ({ model, field }) => {
|
||||
return h(Tinymce, {
|
||||
showImageUpload: false,
|
||||
disabled: _formData.disabled !== false,
|
||||
height: 300,
|
||||
value: model[field],
|
||||
onChange: (value: string) => {
|
||||
model[field] = value;
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'msgContent',
|
||||
label: '通告内容',
|
||||
component: 'Input',
|
||||
colProps: { span: 24 },
|
||||
ifShow: ({}) => _formData.disabled !== false,
|
||||
slot: 'msgContent',
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
@ -184,10 +184,6 @@
|
||||
confirm: handleDelete.bind(null, record),
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '首页配置',
|
||||
onClick: handleIndexConfig.bind(null, record.roleCode),
|
||||
},
|
||||
];
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -1,6 +1,11 @@
|
||||
<template>
|
||||
<BasicModal v-bind="$attrs" @register="registerModal" :width="800" title="用户代理" @ok="handleSubmit" destroyOnClose>
|
||||
<BasicForm @register="registerForm" />
|
||||
<template #insertFooter>
|
||||
<Popconfirm title="确定删除当前配置的代理吗?" @confirm="handleDel">
|
||||
<a-button v-if="agentData.id"><Icon icon="ant-design:clear-outlined" />删除代理</a-button>
|
||||
</Popconfirm>
|
||||
</template>
|
||||
</BasicModal>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
@ -8,7 +13,8 @@
|
||||
import { BasicModal, useModalInner } from '/@/components/Modal';
|
||||
import { BasicForm, useForm } from '/@/components/Form/index';
|
||||
import { formAgentSchema } from './user.data';
|
||||
import { getUserAgent, saveOrUpdateAgent } from './user.api';
|
||||
import { deleteAgent, getUserAgent, saveOrUpdateAgent } from './user.api';
|
||||
import { Popconfirm } from 'ant-design-vue';
|
||||
// 声明Emits
|
||||
const emit = defineEmits(['success', 'register']);
|
||||
//表单配置
|
||||
@ -16,6 +22,8 @@
|
||||
schemas: formAgentSchema,
|
||||
showActionButtonGroup: false,
|
||||
});
|
||||
//表单数据
|
||||
const agentData = ref<any>({});
|
||||
//表单赋值
|
||||
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
|
||||
//重置表单
|
||||
@ -24,6 +32,8 @@
|
||||
//查询获取表单数据
|
||||
const res = await getUserAgent({ userName: data.userName });
|
||||
data = res.result ? res.result : data;
|
||||
//代理数据赋值
|
||||
agentData.value = { ...data };
|
||||
//表单赋值
|
||||
await setFieldsValue({ ...data });
|
||||
});
|
||||
@ -42,4 +52,20 @@
|
||||
setModalProps({ confirmLoading: false });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除代理
|
||||
*/
|
||||
async function handleDel() {
|
||||
const reload = async () => {
|
||||
await resetFields();
|
||||
await setFieldsValue({ userName: agentData.value.userName });
|
||||
//关闭弹窗
|
||||
closeModal();
|
||||
emit('success');
|
||||
};
|
||||
if (agentData.value.id) {
|
||||
await deleteAgent({ id: agentData.value.id }, reload);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -8,6 +8,7 @@ enum Api {
|
||||
edit = '/sys/user/edit',
|
||||
agentSave = '/sys/sysUserAgent/add',
|
||||
agentEdit = '/sys/sysUserAgent/edit',
|
||||
deleteAgent = '/sys/sysUserAgent/delete',
|
||||
getUserRole = '/sys/user/queryUserRole',
|
||||
duplicateCheck = '/sys/duplicate/check',
|
||||
deleteUser = '/sys/user/delete',
|
||||
@ -208,6 +209,15 @@ export const saveOrUpdateAgent = (params) => {
|
||||
let url = params.id ? Api.agentEdit : Api.agentSave;
|
||||
return defHttp.post({ url: url, params });
|
||||
};
|
||||
/**
|
||||
* 代理删除
|
||||
* @param params
|
||||
*/
|
||||
export const deleteAgent = (params, handleSuccess) => {
|
||||
return defHttp.delete({ url: Api.deleteAgent, params }, { joinParamsToUrl: true }).then(() => {
|
||||
handleSuccess();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 用户离职(新增代理人和用户状态变更操作)
|
||||
|
||||
Reference in New Issue
Block a user