From a35f4b4d0c555493cc464bfd36d037230547f1aa Mon Sep 17 00:00:00 2001 From: tj <1378534974@qq.com> Date: 星期四, 20 三月 2025 09:44:44 +0800 Subject: [PATCH] 1.高级安全防护 --- src/views/system/modules/SysDictItemModal.vue | 267 +++++++++ src/views/system/modules/SecurityModal.vue | 173 ++++++ package.json | 8 src/views/system/SecurityList.vue | 219 +++++-- src/views/system/modules/CloudContentModal.vue | 154 +++++ src/views/system/modules/SysDictModal.vue | 146 +++++ src/components/Editor.vue | 119 ++++ src/views/system/SysDictList.vue | 227 ++++++++ src/views/system/CloudContent.vue | 234 ++++++++ README.md | 80 ++ 10 files changed, 1,564 insertions(+), 63 deletions(-) diff --git a/README.md b/README.md index 5c5dadb..08acd7c 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,80 @@ -## jspERP-web -node -v v16.20.2 +jshERP-web Vue + +#### 前端技术 + +- 基础框架:[ant-design-vue](https://github.com/vueComponent/ant-design-vue) - Ant Design Of Vue 实现 +- JavaScript框架:Vue +- Jeecg-boot 的前段UI框架 +- Webpack +- node +- yarn +- eslint +- @vue/cli 3.2.1 +- [vue-cropper](https://github.com/xyxiao001/vue-cropper) - 头像裁剪组件 +- [@antv/g2](https://antv.alipay.com/zh-cn/index.html) - Alipay AntV 数据可视化图表 +- [Viser-vue](https://viserjs.github.io/docs.html#/viser/guide/installation) - antv/g2 封装实现 + + + +项目运行 +---- + +- 安装nodeJS +``` +建议安装node-v20.17.0-x64版本 教程参考 https://blog.csdn.net/Coin_Collecter/article/details/136484312 +``` + +- 安装yarn +``` +npm install -g yarn +``` + +- 配镜像源(速度快) +``` +yarn config set registry https://registry.npmmirror.com +``` + +- 安装依赖 +``` +yarn install +``` + +- 开发模式运行 +``` +yarn serve +``` + +- 编译发布项目 +``` +yarn build +``` + + +其他说明 +---- + +- 项目使用的 [vue-cli3](https://cli.vuejs.org/guide/), 请更新您的 cli + +- 关闭 Eslint (不推荐) 移除 `package.json` 中 `eslintConfig` 整个节点代码 + +- 修改 Ant Design 配色,在文件 `vue.config.js` 中,其他 less 变量覆盖参考 [ant design](https://ant.design/docs/react/customize-theme-cn) 官方说明 +```ecmascript 6 + css: { + loaderOptions: { + less: { + modifyVars: { + /* less 变量覆盖,用于自定义 ant design 主题 */ + + 'primary-color': '#F5222D', + 'link-color': '#F5222D', + 'border-radius-base': '4px', + }, + javascriptEnabled: true, + } + } + } +``` + + diff --git a/package.json b/package.json index c8d1e65..01a13a4 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,9 @@ "lodash.pick": "^4.4.0", "md5": "^2.2.1", "nprogress": "^0.2.0", + "quill": "^2.0.3", + "quill-image-drop-module": "^1.0.3", + "quill-image-resize-module": "^3.0.0", "viser-vue": "^2.4.4", "vue": "^2.6.10", "vue-area-linkage": "^5.1.0", @@ -33,12 +36,15 @@ "vue-ls": "^3.2.0", "vue-photo-preview": "^1.1.3", "vue-print-nb-jeecg": "^1.0.9", + "vue-quill-editor": "^3.0.6", "vue-router": "^3.0.1", "vue-splitpane": "^1.0.4", "vuedraggable": "^2.20.0", - "vuex": "^3.1.0" + "vuex": "^3.1.0", + "wangeditor": "^4.7.15" }, "devDependencies": { + "@babel/plugin-proposal-class-properties": "^7.18.6", "@babel/polyfill": "^7.2.5", "@vue/cli-plugin-babel": "^3.3.0", "@vue/cli-plugin-eslint": "^3.3.0", diff --git a/src/components/Editor.vue b/src/components/Editor.vue new file mode 100644 index 0000000..1bf2afb --- /dev/null +++ b/src/components/Editor.vue @@ -0,0 +1,119 @@ +<template> + <div class="editor-container" :style="{ width: width }"> + <div ref="editor"></div> + </div> +</template> + +<script> +import E from 'wangeditor' + +export default { + name: 'Editor', + props: { + value: { + type: String, + default: '' + }, + width: { + type: String, + default: '100%' + }, + height: { + type: Number, + default: 300 + } + }, + data() { + return { + editor: null, + content: '' + } + }, + watch: { + value: { + handler(val) { + if (val !== this.content && this.editor) { + this.content = val || '' + this.editor.txt.html(this.content) + } + }, + immediate: true + } + }, + mounted() { + this.initEditor() + }, + beforeDestroy() { + if (this.editor) { + this.editor.destroy() + this.editor = null + } + }, + methods: { + initEditor() { + this.editor = new E(this.$refs.editor) + + // 配置菜单栏 + this.editor.config.menus = [ + 'head', + 'bold', + 'fontSize', + 'fontName', + 'italic', + 'underline', + 'strikeThrough', + 'foreColor', + 'backColor', + 'link', + 'list', + 'justify', + 'quote', + 'emoticon', + 'image', + 'table', + 'code', + 'undo', + 'redo' + ] + + // 配置编辑器高度 + this.editor.config.height = this.height + + // 配置图片上传 + this.editor.config.uploadImgServer = '/jshERP-boot/common/upload' + this.editor.config.uploadFileName = 'file' + this.editor.config.uploadImgHooks = { + customInsert: (insertImgFn, result) => { + if (result.code === 200) { + insertImgFn(result.data.url) + } else { + this.$message.error('图片上传失败') + } + } + } + + // 配置 onchange 回调函数 + this.editor.config.onchange = (html) => { + this.content = html + this.$emit('input', html) + this.$emit('change', html) + } + + // 创建编辑器 + this.editor.create() + + // 设置初始内容 + if (this.value) { + this.editor.setHtml(this.value) + } + } + } +} +</script> + +<style scoped> +.editor-container { + border: 1px solid #ccc; + z-index: 100; +} +</style> \ No newline at end of file diff --git a/src/views/system/CloudContent.vue b/src/views/system/CloudContent.vue new file mode 100644 index 0000000..6c6622e --- /dev/null +++ b/src/views/system/CloudContent.vue @@ -0,0 +1,234 @@ +<template> + <a-row :gutter="24"> + <a-col :md="24"> + <a-card :style="cardStyle" :bordered="false"> + <!-- 查询区域 --> + <div class="table-page-search-wrapper"> + <a-form layout="inline" @keyup.enter.native="searchQuery"> + <a-row :gutter="24"> + <a-col :md="6" :sm="24"> + <a-form-item label="标题" :labelCol="labelCol" :wrapperCol="wrapperCol"> + <a-input placeholder="请输入标题查询" v-model="queryParam.title"></a-input> + </a-form-item> + </a-col> + <a-col :md="6" :sm="24"> + <a-form-item label="内容类型" :labelCol="labelCol" :wrapperCol="wrapperCol"> + <a-select placeholder="请选择内容类型" v-model="queryParam.type" allowClear> + <a-select-option value="privacy_policy">隐私政策</a-select-option> + <a-select-option value="user_guide">用户指南</a-select-option> + </a-select> + </a-form-item> + </a-col> + <a-col :md="6" :sm="24"> + <a-form-item label="状态" :labelCol="labelCol" :wrapperCol="wrapperCol"> + <a-select placeholder="请选择状态" v-model="queryParam.status" allowClear> + <a-select-option :value="0">草稿</a-select-option> + <a-select-option :value="1">已发布</a-select-option> + </a-select> + </a-form-item> + </a-col> + <span style="float: left;overflow: hidden;" class="table-page-search-submitButtons"> + <a-col :md="6" :sm="24"> + <a-button type="primary" @click="searchQuery">查询</a-button> + <a-button style="margin-left: 8px" @click="searchReset">重置</a-button> + </a-col> + </span> + </a-row> + </a-form> + </div> + <!-- 操作按钮区域 --> + <div class="table-operator" style="margin-top: 5px"> + <a-button type="primary" icon="plus" @click="handleAdd">新增</a-button> + <a-button type="primary" icon="delete" @click="batchDel">删除</a-button> + </div> + <!-- table区域-begin --> + <div> + <a-table + ref="table" + size="middle" + bordered + rowKey="id" + :columns="columns" + :dataSource="dataSource" + :pagination="ipagination" + :loading="loading" + :rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}" + @change="handleTableChange"> + <span slot="action" slot-scope="text, record"> + <a @click="handleEdit(record)">编辑</a> + <a-divider type="vertical" /> + <a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)"> + <a>删除</a> + </a-popconfirm> + </span> + <template slot="statusSlot" slot-scope="text"> + <a-tag :color="text === 1 ? 'green' : 'orange'"> + {{ text === 1 ? '已发布' : '草稿' }} + </a-tag> + </template> + <template slot="typeSlot" slot-scope="text"> + {{ text === 'privacy_policy' ? '隐私政策' : '用户指南' }} + </template> + </a-table> + </div> + <!-- table区域-end --> + + <!-- 表单区域 --> + <cloud-content-modal ref="modalForm" @ok="modalFormOk"></cloud-content-modal> + </a-card> + </a-col> + </a-row> +</template> + +<script> +import { JeecgListMixin } from '@/mixins/JeecgListMixin' +import CloudContentModal from './modules/CloudContentModal' +import { deleteAction, getAction } from '@/api/manage' + +export default { + name: "CloudContentList", + mixins:[JeecgListMixin], + components: { + CloudContentModal + }, + data () { + return { + description: '云内容管理页面', + labelCol: { + xs: { span: 24 }, + sm: { span: 5 }, + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 16 }, + }, + // 查询条件 + queryParam: { + title: '', + type: '', + status: undefined + }, + // 表头 + columns: [ + { + title: '#', + dataIndex: '', + key:'rowIndex', + width:60, + align:"center", + customRender:function (t,r,index) { + return parseInt(index)+1; + } + }, + { + title: '操作', + dataIndex: 'action', + width:120, + align:"center", + scopedSlots: { customRender: 'action' } + }, + { + title: '标题', + align:"left", + dataIndex: 'title' + }, + { + title: '内容类型', + align:"center", + dataIndex: 'type', + scopedSlots: { customRender: 'typeSlot' } + }, + { + title: '版本号', + align:"center", + dataIndex: 'version' + }, + { + title: '状态', + align:"center", + dataIndex: 'status', + scopedSlots: { customRender: 'statusSlot' } + }, + { + title: '创建时间', + align:"center", + dataIndex: 'createTime', + width: 180 + } + ], + url: { + list: "/cloudContent/list", + delete: "/cloudContent/delete", + deleteBatch: "/cloudContent/deleteBatch", + exportXlsUrl: "/cloudContent/exportXls", + importExcelUrl: "/cloudContent/importExcel", + }, + btnEnableList: [], + cardStyle: { + height: '100%' + } + } + }, + computed: { + importExcelUrl: function(){ + return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`; + } + }, + methods: { + searchReset() { + this.queryParam = { + title: '', + type: '', + status: undefined + } + this.loadData(1); + }, + handleEdit: function (record) { + this.$refs.modalForm.edit(record); + this.$refs.modalForm.title = "编辑"; + this.$refs.modalForm.disableSubmit = false; + if(this.btnEnableList.indexOf(1)===-1) { + this.$refs.modalForm.isReadOnly = true + } + }, + handleAdd: function () { + this.$refs.modalForm.add(); + this.$refs.modalForm.title = "新增"; + this.$refs.modalForm.disableSubmit = false; + }, + handleDelete(id) { + deleteAction(this.url.delete, {id: id}).then((res) => { + if (res.success) { + this.$message.success(res.message); + this.loadData(); + } else { + this.$message.warning(res.message); + } + }); + }, + batchDel() { + if (this.selectedRowKeys.length <= 0) { + this.$message.warning('请选择一条记录!'); + return; + } + let ids = ""; + this.selectedRowKeys.forEach(function(val) { + ids+=val+","; + }); + ids = ids.substring(0,ids.length-1); + deleteAction(this.url.deleteBatch, {ids: ids}).then((res) => { + if (res.success) { + this.$message.success(res.message); + this.loadData(); + this.selectedRowKeys = []; + } else { + this.$message.warning(res.message); + } + }); + } + } +} +</script> +<style scoped> +@import '~@assets/less/common.less' +</style> \ No newline at end of file diff --git a/src/views/system/SecurityList.vue b/src/views/system/SecurityList.vue index 24a044c..912acb2 100644 --- a/src/views/system/SecurityList.vue +++ b/src/views/system/SecurityList.vue @@ -9,13 +9,22 @@ <a-row :gutter="24"> <a-col :md="6" :sm="24"> <a-form-item label="关键词" :labelCol="labelCol" :wrapperCol="wrapperCol"> - <a-input placeholder="请输入关键词查询" v-model="queryParam.name"></a-input> + <a-input placeholder="请输入关键词查询" v-model="queryParam.keyword"></a-input> </a-form-item> </a-col> <a-col :md="6" :sm="24"> - <a-form-item label="备注" :labelCol="labelCol" :wrapperCol="wrapperCol"> - <a-input placeholder="请输入备注查询" v-model="queryParam.description"></a-input> - </a-form-item> + <a-form-item label="防护类型" :labelCol="labelCol" :wrapperCol="wrapperCol"> + <a-select + optionFilterProp="children" + :dropdownMatchSelectWidth="false" + showSearch allow-clear style="width: 100%" + placeholder="请选择防护类型" + v-model="queryParam.type"> + <a-select-option v-for="(type,index) in typeList" :value="type.itemValue" :key="index"> + {{ type.itemText }} + </a-select-option> + </a-select> + </a-form-item> </a-col> <span style="float: left;overflow: hidden;" class="table-page-search-submitButtons"> <a-col :md="6" :sm="24"> @@ -28,10 +37,10 @@ </div> <!-- 操作按钮区域 --> <div class="table-operator" style="margin-top: 5px"> - <a-button v-if="btnEnableList.indexOf(1)>-1" @click="handleAdd" type="primary" icon="plus">新增</a-button> - <a-button v-if="btnEnableList.indexOf(1)>-1" @click="batchDel" icon="delete">删除</a-button> - <a-button v-if="btnEnableList.indexOf(1)>-1" @click="batchSetStatus(true)" icon="check-square">启用</a-button> - <a-button v-if="btnEnableList.indexOf(1)>-1" @click="batchSetStatus(false)" icon="close-square">禁用</a-button> + <a-button @click="handleAdd" type="primary" icon="plus">新增</a-button> + <a-button @click="batchDel" icon="delete">删除</a-button> + <a-button @click="batchSetStatus(true)" icon="check-square">启用</a-button> + <a-button @click="batchSetStatus(false)" icon="close-square">禁用</a-button> </div> <!-- table区域-begin --> <div> @@ -48,27 +57,26 @@ :rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}" @change="handleTableChange"> <span slot="action" slot-scope="text, record"> - <a @click="handleSetFunction(record)">分配功能</a> - <a-divider type="vertical" /> - <a @click="handleSetPushBtn(record.id, record.name)">分配按钮</a> - <a-divider type="vertical" /> <a @click="handleEdit(record)">编辑</a> - <a-divider v-if="btnEnableList.indexOf(1)>-1" type="vertical" /> - <a-popconfirm v-if="btnEnableList.indexOf(1)>-1" title="确定删除吗?" @confirm="() => handleDelete(record.id)"> + <a-divider type="vertical" /> + <a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)"> <a>删除</a> </a-popconfirm> - <a-modal v-model="roleModalVisible" title="操作提示" @ok="handleRoleTip(record)"> - <p>保存角色已经操作成功!现在继续<b>分配功能</b>吗?</p> - </a-modal> + </span> - <span slot="typeTitle"> + <!-- <span slot="typeTitle"> 防护类型 - <a-tooltip title="1、全部数据-该角色对应的用户可以看到全部单据;2、本机构数据-该角色对应的用户可以看到自己所在机构的全部单据; - 3、个人数据-该角色对应的用户只可以看到自己的单据。单据是指采购入库、销售出库等"> + <a-tooltip title=""> <a-icon type="question-circle" /> </a-tooltip> - </span> + </span> --> <!-- 状态渲染模板 --> + + + <template slot="type" slot-scope="type"> + <a-tag color="green">{{ getDictItemLabel(typeList,type) }}</a-tag> + </template> + <template slot="customRenderFlag" slot-scope="enabled"> <a-tag v-if="enabled" color="green">启用</a-tag> <a-tag v-if="!enabled" color="orange">禁用</a-tag> @@ -77,36 +85,34 @@ </div> <!-- table区域-end --> <!-- 表单区域 --> - <role-modal ref="modalForm" @ok="roleModalFormOk"></role-modal> + <security-modal ref="modalForm" @ok="roleModalFormOk"></security-modal> <role-function-modal ref="roleFunctionModal" @ok="roleFunctionModalFormOk"></role-function-modal> <role-push-btn-modal ref="rolePushBtnModal" @ok="modalFormOk"></role-push-btn-modal> - <a-modal v-model="roleFunctionModalVisible" title="操作提示" @ok="handleRoleFunctionTip"> - <p>分配功能已经操作成功!现在继续<b>分配按钮</b>吗?</p> - </a-modal> + </a-card> </a-col> </a-row> </template> <!-- f r o m 7 5 2 7 1 8 9 2 0 --> <script> - import RoleModal from './modules/RoleModal' + import SecurityModal from './modules/SecurityModal' import RoleFunctionModal from './modules/RoleFunctionModal' import RolePushBtnModal from './modules/RolePushBtnModal' import { JeecgListMixin } from '@/mixins/JeecgListMixin' import JDate from '@/components/jeecg/JDate' + import {getAction,deleteAction,postAction } from '@/api/manage' export default { - name: "RoleList", + name: "SecurityList", mixins:[JeecgListMixin], components: { - RoleModal, + SecurityModal, RoleFunctionModal, RolePushBtnModal, JDate }, data () { return { - description: '角色管理页面', - roleModalVisible: false, + description: '高级安全防护管理页面', roleFunctionModalVisible: false, currentRoleId: '', labelCol: { @@ -118,8 +124,8 @@ }, // 查询条件 queryParam: { - name: '', - description: '', + keyword: '', + type: '', }, // 表头 columns: [ @@ -144,8 +150,9 @@ title: '关键词', align:"left", dataIndex: 'keyword', width: 120 }, { - align:"left", dataIndex: 'type', width: 100, - slots: { title: 'typeTitle' } + title:' 防护类型',align:"left", dataIndex: 'type', width: 100, + slots: { title: 'typeTitle' }, + scopedSlots: { customRender: 'type' } }, { title: '状态',dataIndex: 'status',width:60,align:"center", scopedSlots: { customRender: 'customRenderFlag' } @@ -157,6 +164,7 @@ deleteBatch: "/config-security/deleteBatch", batchSetStatusUrl: "/config-security/batchSetStatus" }, + typeList:[], } }, computed: { @@ -164,11 +172,56 @@ return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`; } }, + + mounted(){ + this.loadDictData(); + }, methods: { - handleSetFunction(record) { - this.$refs.roleFunctionModal.edit(record); - this.$refs.roleFunctionModal.title = "分配功能给:" + record.name + "【分配之后请继续分配按钮】" - this.$refs.roleFunctionModal.disableSubmit = false; + + searchQuery() { + this.ipagination.current = 1; + this.loadData(); + }, + + loadData(arg) { + //加载数据 若传入参数1则加载第一页的内容 + // this.ipagination.current = 1; + + let params = this.queryParam + params.currentPage = this.ipagination.current; + params.pageSize = this.ipagination.pageSize; + + this.loading = true; + getAction(this.url.list, params).then((res) => { + if (res.code===200) { + this.dataSource = res.data.rows; + this.ipagination.total = res.data.total; + this.tableAddTotalRow(this.columns, this.dataSource) + this.realityPriceTotal = res.data.realityPriceTotal + } else if(res.code===510){ + this.$message.warning(res.data) + } else { + this.$message.warning(res.data.message) + } + this.loading = false; + }) + }, + + loadDictData() { + // 安全防护类型 + var dictCode='securityType' + getAction(`/sysDict/items/dict-code/${dictCode}`).then((res)=>{ + if(res.code === 200){ + this.typeList = res.data; + }else{ + this.$message.info(res.data); + } + }) + }, + + getDictItemLabel(list, value) { + const item = list.find(item => item.itemValue === value); + return item ? item.itemText : null; }, handleSetPushBtn(roleId, roleName) { this.$refs.rolePushBtnModal.edit(roleId); @@ -178,7 +231,6 @@ roleModalFormOk() { //重载列表 this.loadData() - this.roleModalVisible = true }, roleFunctionModalFormOk(id) { //重载列表 @@ -186,37 +238,84 @@ this.roleFunctionModalVisible = true this.currentRoleId = id }, - handleRoleTip(record) { - if(record) { - this.roleModalVisible = false - this.handleSetFunction(record) - } - }, - handleRoleFunctionTip() { - if(this.currentRoleId) { - this.roleFunctionModalVisible = false - let roleName = '' - for (let i = 0; i < this.dataSource.length; i++) { - if(this.dataSource[i].id == this.currentRoleId) { - roleName = this.dataSource[i].name - } - } - this.handleSetPushBtn(this.currentRoleId, roleName) - } - }, + handleAdd: function () { this.$refs.modalForm.add(); - this.$refs.modalForm.title = "新增【保存之后请继续分配功能】"; + this.$refs.modalForm.title = "新增"; this.$refs.modalForm.disableSubmit = false; }, handleEdit: function (record) { + console.log("edit", record); this.$refs.modalForm.edit(record); - this.$refs.modalForm.title = "编辑【保存之后请继续分配功能】"; + this.$refs.modalForm.title = "编辑"; this.$refs.modalForm.disableSubmit = false; if(this.btnEnableList.indexOf(1)===-1) { this.$refs.modalForm.isReadOnly = true } - } + }, + handleDelete(id) { + deleteAction(this.url.delete+`/${id}`, {id: id}).then((res) => { + if (res.code === 200) { + this.loadData(); + this.$message.success(res.message); + } else { + this.$message.warning(res.message); + } + }); + }, + batchDel() { + if (this.selectedRowKeys.length <= 0) { + this.$message.warning('请选择一条记录!'); + return; + } + let ids = ""; + this.selectedRowKeys.forEach(function(val) { + ids+=val+","; + }); + ids = ids.substring(0,ids.length-1); + deleteAction(this.url.deleteBatch, {ids: ids}).then((res) => { + if(res.code === 200){ + this.$message.success(res.msg); + this.loadData(); + this.selectedRowKeys = []; + } else { + this.$message.warning(res.msg); + } + }); + }, + batchSetStatus: function (status) { + if(!this.url.batchSetStatusUrl){ + this.$message.error("请设置url.batchSetStatusUrl属性!") + return + } + if (this.selectedRowKeys.length <= 0) { + this.$message.warning('请选择一条记录!'); + return; + } else { + var ids = ""; + for (var a = 0; a < this.selectedRowKeys.length; a++) { + ids += this.selectedRowKeys[a] + ","; + } + var that = this; + this.$confirm({ + title: "确认操作", + content: "是否操作选中数据?", + onOk: function () { + that.loading = true; + postAction(that.url.batchSetStatusUrl, {status: status, ids: ids}).then((res) => { + if(res.code === 200){ + that.loadData() + } else { + that.$message.warning(res.data.message); + } + }).finally(() => { + that.loading = false; + }); + } + }); + } + }, + } } </script> diff --git a/src/views/system/SysDictList.vue b/src/views/system/SysDictList.vue new file mode 100644 index 0000000..8c2518e --- /dev/null +++ b/src/views/system/SysDictList.vue @@ -0,0 +1,227 @@ +<template> + <a-row :gutter="24"> + <a-col :md="24"> + <a-card :style="cardStyle" :bordered="false"> + <!-- 查询区域 --> + <div class="table-page-search-wrapper"> + <a-form layout="inline" @keyup.enter.native="searchQuery"> + <a-row :gutter="24"> + <a-col :md="6" :sm="24"> + <a-form-item label="字典编码" :labelCol="labelCol" :wrapperCol="wrapperCol"> + <a-input placeholder="请输入字典编码" v-model="queryParam.dictCode"></a-input> + </a-form-item> + </a-col> + <a-col :md="6" :sm="24"> + <a-form-item label="字典名称" :labelCol="labelCol" :wrapperCol="wrapperCol"> + <a-input placeholder="请输入字典名称" v-model="queryParam.dictName"></a-input> + </a-form-item> + </a-col> + <a-col :md="6" :sm="24"> + <a-form-item label="状态" :labelCol="labelCol" :wrapperCol="wrapperCol"> + <a-select placeholder="请选择状态" v-model="queryParam.status" allowClear> + <a-select-option :value="0">停用</a-select-option> + <a-select-option :value="1">启用</a-select-option> + </a-select> + </a-form-item> + </a-col> + <span style="float: left;overflow: hidden;" class="table-page-search-submitButtons"> + <a-col :md="6" :sm="24"> + <a-button type="primary" @click="searchQuery">查询</a-button> + <a-button style="margin-left: 8px" @click="searchReset">重置</a-button> + </a-col> + </span> + </a-row> + </a-form> + </div> + <!-- 操作按钮区域 --> + <div class="table-operator" style="margin-top: 5px"> + <a-button type="primary" icon="plus" @click="handleAdd">新增</a-button> + <a-button type="primary" icon="delete" @click="batchDel">删除</a-button> + </div> + <!-- table区域-begin --> + <div> + <a-table + ref="table" + size="middle" + bordered + rowKey="id" + :columns="columns" + :dataSource="dataSource" + :pagination="ipagination" + :loading="loading" + :rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}" + @change="handleTableChange"> + <span slot="action" slot-scope="text, record"> + <a @click="handleEdit(record)">编辑</a> + <a-divider type="vertical" /> + <a @click="handleItems(record)">字典项</a> + <a-divider type="vertical" /> + <a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)"> + <a>删除</a> + </a-popconfirm> + </span> + <template slot="statusSlot" slot-scope="text"> + <a-tag :color="text === 1 ? 'green' : 'orange'"> + {{ text === 1 ? '启用' : '停用' }} + </a-tag> + </template> + </a-table> + </div> + <!-- table区域-end --> + + <!-- 表单区域 --> + <sys-dict-modal ref="modalForm" @ok="modalFormOk"></sys-dict-modal> + <sys-dict-item-modal ref="itemModalForm" @ok="modalFormOk"></sys-dict-item-modal> + </a-card> + </a-col> + </a-row> +</template> + +<script> + import { JeecgListMixin } from '@/mixins/JeecgListMixin' + import SysDictModal from './modules/SysDictModal' + import SysDictItemModal from './modules/SysDictItemModal' + import { deleteAction } from '@/api/manage' + + export default { + name: "SysDictList", + mixins:[JeecgListMixin], + components: { + SysDictModal, + SysDictItemModal + }, + data () { + return { + description: '字典管理页面', + labelCol: { + xs: { span: 24 }, + sm: { span: 5 }, + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 16 }, + }, + // 查询条件 + queryParam: { + dictCode: '', + dictName: '', + status: undefined + }, + // 表头 + columns: [ + { + title: '#', + dataIndex: '', + key:'rowIndex', + width:60, + align:"center", + customRender:function (t,r,index) { + return parseInt(index)+1; + } + }, + { + title: '操作', + dataIndex: 'action', + width:150, + align:"center", + scopedSlots: { customRender: 'action' } + }, + { + title: '字典编码', + align:"left", + dataIndex: 'dictCode' + }, + { + title: '字典名称', + align:"left", + dataIndex: 'dictName' + }, + { + title: '描述', + align:"left", + dataIndex: 'description' + }, + { + title: '状态', + align:"center", + dataIndex: 'status', + scopedSlots: { customRender: 'statusSlot' } + }, + { + title: '创建时间', + align:"center", + dataIndex: 'createTime', + width: 180 + } + ], + url: { + list: "/sysDict/list", + delete: "/sysDict/delete", + deleteBatch: "/sysDict/deleteBatch" + }, + btnEnableList: [], + cardStyle: { + height: '100%' + } + } + }, + methods: { + searchReset() { + this.queryParam = { + dictCode: '', + dictName: '', + status: undefined + } + this.loadData(1); + }, + handleEdit: function (record) { + this.$refs.modalForm.edit(record); + this.$refs.modalForm.title = "编辑"; + this.$refs.modalForm.disableSubmit = false; + }, + handleAdd: function () { + this.$refs.modalForm.add(); + this.$refs.modalForm.title = "新增"; + this.$refs.modalForm.disableSubmit = false; + }, + handleItems: function (record) { + this.$refs.itemModalForm.show(record); + this.$refs.itemModalForm.title = "字典项管理"; + this.$refs.itemModalForm.disableSubmit = false; + }, + handleDelete(id) { + deleteAction(this.url.delete, {id: id}).then((res) => { + if (res.success) { + this.$message.success(res.message); + this.loadData(); + } else { + this.$message.warning(res.message); + } + }); + }, + batchDel() { + if (this.selectedRowKeys.length <= 0) { + this.$message.warning('请选择一条记录!'); + return; + } + let ids = ""; + this.selectedRowKeys.forEach(function(val) { + ids+=val+","; + }); + ids = ids.substring(0,ids.length-1); + deleteAction(this.url.deleteBatch, {ids: ids}).then((res) => { + if (res.success) { + this.$message.success(res.message); + this.loadData(); + this.selectedRowKeys = []; + } else { + this.$message.warning(res.message); + } + }); + } + } + } +</script> +<style scoped> + @import '~@assets/less/common.less' +</style> \ No newline at end of file diff --git a/src/views/system/modules/CloudContentModal.vue b/src/views/system/modules/CloudContentModal.vue new file mode 100644 index 0000000..4d8f42b --- /dev/null +++ b/src/views/system/modules/CloudContentModal.vue @@ -0,0 +1,154 @@ +<template> + <div ref="container"> + <a-modal + :title="title" + :width="1200" + :visible="visible" + :confirmLoading="confirmLoading" + :getContainer="() => $refs.container" + :maskStyle="{'top':'93px','left':'154px'}" + :wrapClassName="wrapClassNameInfo()" + :mask="isDesktop()" + :maskClosable="false" + @ok="handleOk" + @cancel="handleCancel" + cancelText="取消" + okText="保存" + style="top:10%;height: 80%;"> + <a-spin :spinning="confirmLoading"> + <a-form :form="form" id="cloudContentModal"> + <a-row class="form-row" :gutter="24"> + <a-col :span="12"> + <a-form-item label="标题" :labelCol="labelCol" :wrapperCol="wrapperCol"> + <a-input placeholder="请输入标题" v-decorator="['title', validatorRules.title]" /> + </a-form-item> + </a-col> + <a-col :span="12"> + <a-form-item label="内容类型" :labelCol="labelCol" :wrapperCol="wrapperCol"> + <a-select placeholder="请选择内容类型" v-decorator="['type', validatorRules.type]"> + <a-select-option value="privacy_policy">隐私政策</a-select-option> + <a-select-option value="user_guide">用户指南</a-select-option> + </a-select> + </a-form-item> + </a-col> + <a-col :span="12"> + <a-form-item label="版本号" :labelCol="labelCol" :wrapperCol="wrapperCol"> + <a-input placeholder="请输入版本号" v-decorator="['version', validatorRules.version]" /> + </a-form-item> + </a-col> + <a-col :span="12"> + <a-form-item label="状态" :labelCol="labelCol" :wrapperCol="wrapperCol"> + <a-radio-group v-decorator="['status', {initialValue: 0}]"> + <a-radio :value="0">草稿</a-radio> + <a-radio :value="1">发布</a-radio> + </a-radio-group> + </a-form-item> + </a-col> + <a-col :span="24"> + <a-form-item label="内容" :labelCol="{span: 2}" :wrapperCol="{span: 22}"> + <editor v-decorator="['content', validatorRules.content]" :height="400" /> + </a-form-item> + </a-col> + </a-row> + </a-form> + </a-spin> + </a-modal> + </div> +</template> + +<script> +import { mixinDevice } from '@/utils/mixin' +import Editor from '@/components/Editor' +import pick from 'lodash.pick' + +export default { + name: "CloudContentModal", + mixins: [mixinDevice], + components: { + Editor + }, + data () { + return { + title: "操作", + visible: false, + model: {}, + labelCol: { + xs: { span: 24 }, + sm: { span: 5 }, + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 16 }, + }, + confirmLoading: false, + form: this.$form.createForm(this), + validatorRules: { + title: { + rules: [{ required: true, message: '请输入标题!' }] + }, + type: { + rules: [{ required: true, message: '请选择内容类型!' }] + }, + version: { + rules: [{ required: true, message: '请输入版本号!' }] + }, + content: { + rules: [{ required: true, message: '请输入内容!' }] + } + } + } + }, + methods: { + add () { + this.edit({}) + }, + edit (record) { + this.form.resetFields() + this.model = Object.assign({}, record) + this.visible = true + this.$nextTick(() => { + this.form.setFieldsValue(pick(this.model,'title', 'type', 'version', 'content', 'status')) + }) + }, + close () { + this.$emit('close') + this.visible = false + }, + handleOk () { + const that = this + this.form.validateFields((err, values) => { + if (!err) { + that.confirmLoading = true + let formData = Object.assign(this.model, values) + let obj + if(!this.model.id){ + obj = this.$http.post('/cloudContent', formData) + }else{ + obj = this.$http.put('/cloudContent', formData) + } + obj.then((res)=>{ + if(res.code === 200){ + that.$message.success(res.msg) + that.$emit('ok') + }else{ + that.$message.warning(res.msg) + } + }).finally(() => { + that.confirmLoading = false + that.close() + }) + } + }) + }, + handleCancel () { + this.close() + } + } +} +</script> + +<style lang="less" scoped> +.form-row { + padding: 0 24px; +} +</style> \ No newline at end of file diff --git a/src/views/system/modules/SecurityModal.vue b/src/views/system/modules/SecurityModal.vue new file mode 100644 index 0000000..e49166b --- /dev/null +++ b/src/views/system/modules/SecurityModal.vue @@ -0,0 +1,173 @@ +<template> + <div ref="container"> + <a-modal + :title="title" + :width="800" + :visible="visible" + :confirmLoading="confirmLoading" + :getContainer="() => $refs.container" + :maskStyle="{'top':'93px','left':'154px'}" + :wrapClassName="wrapClassNameInfo()" + :mask="isDesktop()" + :maskClosable="false" + @ok="handleOk" + @cancel="handleCancel" + cancelText="取消" + okText="保存"> + <a-spin :spinning="confirmLoading"> + <a-form :form="form"> + <a-row class="form-row" :gutter="24"> + <a-col :span="24"> + <a-form-item label="关键词" :labelCol="labelCol" :wrapperCol="wrapperCol"> + <a-input placeholder="请输入关键词" v-decorator="['keyword', validatorRules.keyword]" /> + </a-form-item> + </a-col> + <a-col :span="24"> + <a-form-item label="防护类型" :labelCol="labelCol" :wrapperCol="wrapperCol"> + <!-- <a-input placeholder="请输入防护类型" v-decorator="['type', validatorRules.type]" /> --> + <a-select + optionFilterProp="children" + :dropdownMatchSelectWidth="false" + showSearch allow-clear style="width: 100%" + placeholder="请选择防护类型" + v-decorator="['type', validatorRules.type]" + > + <a-select-option v-for="(type,index) in typeList" :value="type.itemValue" :key="index"> + {{ type.itemText }} + </a-select-option> + </a-select> + </a-form-item> + </a-col> + <a-col :span="24"> + <a-form-item label="状态" :labelCol="labelCol" :wrapperCol="wrapperCol"> + <a-radio-group v-decorator="['status', {initialValue: 1}]"> + <a-radio :value="1">启用</a-radio> + <a-radio :value="0">禁用</a-radio> + </a-radio-group> + </a-form-item> + </a-col> + </a-row> + </a-form> + </a-spin> + </a-modal> + </div> +</template> + +<script> + import { mixinDevice } from '@/utils/mixin' + import { postAction, putAction,getAction } from '@/api/manage' + import pick from 'lodash.pick' + + export default { + name: "SysDictModal", + mixins: [mixinDevice], + data () { + return { + title:"操作", + visible: false, + model: {}, + labelCol: { + xs: { span: 24 }, + sm: { span: 5 }, + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 16 }, + }, + confirmLoading: false, + form: this.$form.createForm(this), + validatorRules:{ + keyword: { + rules: [{ + required: true, + message: '请输入关键词!' + }, + { + max: 50, + message: '关键词长度不能超过50个字符!' + } + ] + }, + type: { + rules: [{ + required: true, + message: '请输入防护类型!' + }] + } + }, + url: { + add: "/config-security", + edit: "/config-security" + }, + typeList:[], + } + }, + mounted(){ + this.loadDictData(); + }, + methods: { + loadDictData() { + // 安全防护类型 + var dictCode='securityType' + getAction(`/sysDict/items/dict-code/${dictCode}`).then((res)=>{ + if(res.code === 200){ + this.typeList = res.data; + }else{ + this.$message.info(res.data); + } + }) + }, + add () { + this.edit({}) + }, + edit (record) { + debugger; + this.form.resetFields() + this.model = Object.assign({}, record) + this.visible = true + this.$nextTick(() => { + this.form.setFieldsValue(pick(this.model,'keyword','type','status')) + }) + }, + close () { + this.$emit('close') + this.visible = false + }, + handleOk () { + const that = this + this.form.validateFields((err, values) => { + if (!err) { + that.confirmLoading = true + let formData = Object.assign(this.model, values) + let obj + if(!this.model.id){ + obj = postAction(this.url.add, formData) + }else{ + obj = putAction(this.url.edit, formData) + } + obj.then((res)=>{ + if(res.code === 200){ + that.$message.success(res.msg) + that.$emit('ok') + }else{ + that.$message.warning(res.msg) + } + }).finally(() => { + that.confirmLoading = false + that.close() + }) + } + }) + }, + handleCancel () { + this.close() + } + } + } +</script> + +<style lang="less" scoped> + .form-row { + padding: 0 24px; + } +</style> \ No newline at end of file diff --git a/src/views/system/modules/SysDictItemModal.vue b/src/views/system/modules/SysDictItemModal.vue new file mode 100644 index 0000000..8fa48f2 --- /dev/null +++ b/src/views/system/modules/SysDictItemModal.vue @@ -0,0 +1,267 @@ +<template> + <div ref="container"> + <a-modal + :title="title" + :width="1000" + :visible="visible" + :confirmLoading="confirmLoading" + :getContainer="() => $refs.container" + :maskStyle="{'top':'93px','left':'154px'}" + :wrapClassName="wrapClassNameInfo()" + :mask="isDesktop()" + :maskClosable="false" + @ok="handleOk" + @cancel="handleCancel" + cancelText="关闭"> + <template slot="footer"> + <a-button key="back" @click="handleCancel">关闭</a-button> + </template> + <a-card :bordered="false"> + <!-- 操作按钮区域 --> + <div class="table-operator"> + <a-button type="primary" icon="plus" @click="handleAdd">新增</a-button> + </div> + <!-- table区域-begin --> + <div> + <a-table + ref="table" + size="middle" + bordered + rowKey="id" + :columns="columns" + :dataSource="dataSource" + :pagination="false" + :loading="loading"> + <span slot="action" slot-scope="text, record"> + <a @click="handleEdit(record)">编辑</a> + <a-divider type="vertical" /> + <a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)"> + <a>删除</a> + </a-popconfirm> + </span> + <template slot="statusSlot" slot-scope="text"> + <a-tag :color="text === 1 ? 'green' : 'orange'"> + {{ text === 1 ? '启用' : '停用' }} + </a-tag> + </template> + </a-table> + </div> + <!-- table区域-end --> + </a-card> + + <a-modal + :title="itemTitle" + :width="600" + :visible="itemVisible" + :confirmLoading="itemConfirmLoading" + @ok="handleItemOk" + @cancel="handleItemCancel" + cancelText="取消" + okText="保存"> + <a-form :form="itemForm"> + <a-form-item label="字典项文本" :labelCol="labelCol" :wrapperCol="wrapperCol"> + <a-input placeholder="请输入字典项文本" v-decorator="['itemText', validatorRules.itemText]" /> + </a-form-item> + <a-form-item label="字典项值" :labelCol="labelCol" :wrapperCol="wrapperCol"> + <a-input placeholder="请输入字典项值" v-decorator="['itemValue', validatorRules.itemValue]" /> + </a-form-item> + <a-form-item label="描述" :labelCol="labelCol" :wrapperCol="wrapperCol"> + <a-textarea placeholder="请输入描述" v-decorator="['description']" :rows="2" /> + </a-form-item> + <a-form-item label="排序" :labelCol="labelCol" :wrapperCol="wrapperCol"> + <a-input-number placeholder="请输入排序" v-decorator="['sortOrder', {initialValue: 0}]" :min="0" style="width: 100%" /> + </a-form-item> + <a-form-item label="状态" :labelCol="labelCol" :wrapperCol="wrapperCol"> + <a-radio-group v-decorator="['status', {initialValue: 1}]"> + <a-radio :value="1">启用</a-radio> + <a-radio :value="0">停用</a-radio> + </a-radio-group> + </a-form-item> + </a-form> + </a-modal> + </a-modal> + </div> +</template> + +<script> + import { mixinDevice } from '@/utils/mixin' + import { getAction, postAction, putAction, deleteAction } from '@/api/manage' + import pick from 'lodash.pick' + + export default { + name: "SysDictItemModal", + mixins: [mixinDevice], + data () { + return { + title:"字典项管理", + visible: false, + model: {}, + labelCol: { + xs: { span: 24 }, + sm: { span: 5 }, + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 16 }, + }, + confirmLoading: false, + loading: false, + dataSource: [], + + // 字典项表单相关 + itemTitle: "", + itemVisible: false, + itemConfirmLoading: false, + itemModel: {}, + itemForm: this.$form.createForm(this), + validatorRules: { + itemText: { + rules: [{ + required: true, + message: '请输入字典项文本!' + }] + }, + itemValue: { + rules: [{ + required: true, + message: '请输入字典项值!' + }] + } + }, + + // 表头 + columns: [ + { + title: '#', + dataIndex: '', + key:'rowIndex', + width:60, + align:"center", + customRender:function (t,r,index) { + return parseInt(index)+1; + } + }, + { + title: '操作', + dataIndex: 'action', + width:120, + align:"center", + scopedSlots: { customRender: 'action' } + }, + { + title: '文本', + align:"left", + dataIndex: 'itemText' + }, + { + title: '值', + align:"left", + dataIndex: 'itemValue' + }, + { + title: '描述', + align:"left", + dataIndex: 'description' + }, + { + title: '排序', + align:"center", + dataIndex: 'sortOrder', + width: 80 + }, + { + title: '状态', + align:"center", + dataIndex: 'status', + width: 80, + scopedSlots: { customRender: 'statusSlot' } + } + ] + } + }, + methods: { + show (record) { + this.model = Object.assign({}, record) + this.visible = true + this.loadData() + }, + loadData () { + this.loading = true + getAction(`/sysDict/items/${this.model.id}`).then((res) => { + if (res.code === 200) { + this.dataSource = res.data + } + this.loading = false + }) + }, + handleAdd () { + this.itemTitle = "新增字典项" + this.itemForm.resetFields() + this.itemModel = {} + this.itemVisible = true + }, + handleEdit (record) { + this.itemTitle = "编辑字典项" + this.itemForm.resetFields() + this.itemModel = Object.assign({}, record) + this.itemVisible = true + this.$nextTick(() => { + this.itemForm.setFieldsValue(pick(this.itemModel,'itemText','itemValue','description','sortOrder','status')) + }) + }, + handleDelete (id) { + deleteAction(`/sysDict/item/${id}`).then((res) => { + if (res.code === 200) { + this.$message.success(res.msg) + this.loadData() + } else { + this.$message.warning(res.msg) + } + }) + }, + handleItemOk () { + const that = this + this.itemForm.validateFields((err, values) => { + if (!err) { + that.itemConfirmLoading = true + let formData = Object.assign(this.itemModel, values) + formData.dictId = this.model.id + let obj + if(!this.itemModel.id){ + obj = postAction('/sysDict/item', formData) + }else{ + obj = putAction('/sysDict/item', formData) + } + obj.then((res)=>{ + if(res.code === 200){ + that.$message.success(res.msg) + that.loadData() + that.itemVisible = false + }else{ + that.$message.warning(res.msg) + } + }).finally(() => { + that.itemConfirmLoading = false + }) + } + }) + }, + handleItemCancel () { + this.itemVisible = false + }, + handleCancel () { + this.close() + }, + close () { + this.$emit('close') + this.visible = false + } + } + } +</script> + +<style lang="less" scoped> + .table-operator { + margin-bottom: 18px; + } +</style> \ No newline at end of file diff --git a/src/views/system/modules/SysDictModal.vue b/src/views/system/modules/SysDictModal.vue new file mode 100644 index 0000000..944e3ed --- /dev/null +++ b/src/views/system/modules/SysDictModal.vue @@ -0,0 +1,146 @@ +<template> + <div ref="container"> + <a-modal + :title="title" + :width="800" + :visible="visible" + :confirmLoading="confirmLoading" + :getContainer="() => $refs.container" + :maskStyle="{'top':'93px','left':'154px'}" + :wrapClassName="wrapClassNameInfo()" + :mask="isDesktop()" + :maskClosable="false" + @ok="handleOk" + @cancel="handleCancel" + cancelText="取消" + okText="保存"> + <a-spin :spinning="confirmLoading"> + <a-form :form="form"> + <a-row class="form-row" :gutter="24"> + <a-col :span="12"> + <a-form-item label="字典编码" :labelCol="labelCol" :wrapperCol="wrapperCol"> + <a-input placeholder="请输入字典编码" v-decorator="['dictCode', validatorRules.dictCode]" /> + </a-form-item> + </a-col> + <a-col :span="12"> + <a-form-item label="字典名称" :labelCol="labelCol" :wrapperCol="wrapperCol"> + <a-input placeholder="请输入字典名称" v-decorator="['dictName', validatorRules.dictName]" /> + </a-form-item> + </a-col> + <a-col :span="24"> + <a-form-item label="描述" :labelCol="labelCol" :wrapperCol="wrapperCol"> + <a-textarea placeholder="请输入描述" v-decorator="['description']" :rows="2" /> + </a-form-item> + </a-col> + <a-col :span="12"> + <a-form-item label="状态" :labelCol="labelCol" :wrapperCol="wrapperCol"> + <a-radio-group v-decorator="['status', {initialValue: 1}]"> + <a-radio :value="1">启用</a-radio> + <a-radio :value="0">停用</a-radio> + </a-radio-group> + </a-form-item> + </a-col> + </a-row> + </a-form> + </a-spin> + </a-modal> + </div> +</template> + +<script> + import { mixinDevice } from '@/utils/mixin' + import { postAction, putAction } from '@/api/manage' + import pick from 'lodash.pick' + + export default { + name: "SysDictModal", + mixins: [mixinDevice], + data () { + return { + title:"操作", + visible: false, + model: {}, + labelCol: { + xs: { span: 24 }, + sm: { span: 5 }, + }, + wrapperCol: { + xs: { span: 24 }, + sm: { span: 16 }, + }, + confirmLoading: false, + form: this.$form.createForm(this), + validatorRules:{ + dictCode: { + rules: [{ + required: true, + message: '请输入字典编码!' + }] + }, + dictName: { + rules: [{ + required: true, + message: '请输入字典名称!' + }] + } + }, + url: { + add: "/sysDict", + edit: "/sysDict" + } + } + }, + methods: { + add () { + this.edit({}) + }, + edit (record) { + this.form.resetFields() + this.model = Object.assign({}, record) + this.visible = true + this.$nextTick(() => { + this.form.setFieldsValue(pick(this.model,'dictCode','dictName','description','status')) + }) + }, + close () { + this.$emit('close') + this.visible = false + }, + handleOk () { + const that = this + this.form.validateFields((err, values) => { + if (!err) { + that.confirmLoading = true + let formData = Object.assign(this.model, values) + let obj + if(!this.model.id){ + obj = postAction(this.url.add, formData) + }else{ + obj = putAction(this.url.edit, formData) + } + obj.then((res)=>{ + if(res.code === 200){ + that.$message.success(res.msg) + that.$emit('ok') + }else{ + that.$message.warning(res.msg) + } + }).finally(() => { + that.confirmLoading = false + that.close() + }) + } + }) + }, + handleCancel () { + this.close() + } + } + } +</script> + +<style lang="less" scoped> + .form-row { + padding: 0 24px; + } +</style> \ No newline at end of file -- Gitblit v1.9.3