a-table
<a-table :columns="columns" :dataSource="rows" :pagination="pagination" rowKey="id" @change="getList" :scroll="{ x: '100%' }" :loading="loading" size="middle" > <template #name="record"> {<!-- -->{ record.name }} </template> <template #action="record"> <a-dropdown> <a class="ant-dropdown-link"> More <a-icon type="down" /> </a> <template #overlay> <a-menu @click="menuHandler($event, record)"> <a-menu-item key="auth" v-if="record.isCanSetUser"> Authorize other users </a-menu-item> <a-menu-item key="detail"> details </a-menu-item> <a-menu-item key="update"> edit </a-menu-item> <a-menu-item v-if="record.id !== 1" key="delete"> delete </a-menu-item> <a-menu-item key="copy"> copy </a-menu-item> <a-menu-item key="ping" v-if="record.status === 1"> ping </a-menu-item> <a-menu-item key="connect" v-if="record.status === 1"> test connection </a-menu-item> <a-menu-item key="bindKey" v-if=" record.authType === MACHINE_AUTH_TYPE.SECRET_KEY.value " > bind key </a-menu-item> <!-- <a-menu-item key="openEnv"> <a @click="$router.push(`/machine/env/${record.id}`)" >environment variables</a > </a-menu-item> --> <a-menu-item key="openMonitor"> <a @click=" $router.push(`/machine/monitor/metrics/${record.id}`) " >Machine Monitoring</a > </a-menu-item> </a-menu> </template> </a-dropdown> </template> </a-table>
const columns = [
{
title: “Serial Number”,
key: “seq”,
width: 65,
align: “center”,
customRender: (text, record, index) => `${index + 1}`
},
{
title: “Machine Information”,
key: “name”,
ellipsis: true,
scopedSlots: { customRender: “info” }
},
{
title: “Operation”,
key: “operation”,
fixed: “right”,
align: “center”,
width: 240,
scopedSlots: { customRender: “action” }
}
];
in the action bar corresponding to the
menuHandler({ key }, record) {
const handler = moreMenuHandler[key];
handler & amp; & amp; handler. call(this, record);
},
const moreMenuHandler = {
detail(record) {
this.$refs.detailModal.open(record.id);
},
update(record) {
this.$router.push(`/machine/update/${record.id}`);
},
delete(record) {
this.$confirm({
title: “Confirm Deletion”,
content: “Do you want to delete the current machine? All data associated with the machine will be deleted!”,
okText: “Confirm”,
okType: “danger”,
cancelText: “Cancel”,
onOk: () => {
this.$api
.deleteMachine({
idList: [record.id]
})
.then(() => {
this.$message.success(“Delete successfully”);
this. getList({});
});
}
});
},
copy(record) {
this.$confirm({
title: “Confirm Copy”,
content: `Do you want to copy machine ${record.name}?`,
okText: “Copy”,
cancelText: “Cancel”,
onOk: () => {
this.$api
.copyMachine({
id: record.id
})
.then(() => {
this.$message.success(“Copy successfully”);
this. getList();
});
}
});
},
bindKey(record) {
this.$refs.keyBindModal.open(record.id, record.keyId, record.name);
}
};
Form with checkmarks
computed: {
rowSelection() {
return {
selectedRowKeys: this. selectedRowKeys,
onChange: e => {
this.selectedRowKeys = e;
},
getCheckboxProps: record => ({
props: {
disabled: record.id === 1
}
})
};
}
},
Form tree (expand/collapse)
<a-table v-if="rows. length" :columns="columns" :data-source="rows" :pagination="false" rowKey="id" :defaultExpandAllRows="defaultExpandAllRows" :key="defaultExpandAllRows ? rows.length : 0" @change="getList" :scoll="{ x: '100%' }" :loading="loading" size="middle" childrenColumnName="childs" > 1. The reason for using v-if is to initialize and assign true to defaultExpandAllRows, which does not work; 2. Dynamically click the button to expand/collapse the tree, switching defaultExpandAllRows does not work; (the document states that it only takes effect at initialization); asynchronous loading and resetting rows does not work either; 3. Solution: Change the length of the list data through the value of defaultExpandAllRows; you can expand and collapse 4. childrenColumnName customizes the sub-array identified by the tree;
a-form
Combined with es7 syntax sugar v-decorator
<template> <a-modal v-model="visible" :title="title" :width="650" :okButtonProps="{ props: { disabled: loading } }" :maskClosable="false" :destroyOnClose="true" @ok="check" @cancel="close" > <a-spin :spinning="loading"> <a-form :form="form" v-bind="layout"> <a-form-item label="upper menu" v-show="form.getFieldValue('powerType') == '1'" > <a-tree-select v-decorator="[ decorators. parentId, { initialValue: 0, rules: [ { required: form.getFieldValue('powerType') == '1' ? true : false, message: 'Please select the upper menu' } ] } ]" class="machine-input" tree-data-simple-mode style="width: 100%" :dropdown-style="{ maxHeight: '400px', overflow: 'auto' }" :tree-data="treeList" placeholder="Please select the parent menu" :replaceFields="replaceFields" allowClear @select="onSelect" /> </a-form-item> <a-form-item label="menu type"> <a-radio-group name="radioGroup" :disabled="!!this.id" v-decorator="decorators.powerType" > <a-radio value="0">Directory</a-radio> <a-radio value="1">Menu</a-radio> </a-radio-group> </a-form-item> <a-form-item :label=" form.getFieldValue('powerType') == '0' ? 'directory name' : 'menu name' " has Feedback name="name" > <a-input v-decorator="decorators.name" :placeholder=" `Please enter ${ form.getFieldValue('powerType') == '0' ? 'directory' : 'menu' }name` " showCount allowClear /> </a-form-item> <a-form-item label="Sort"> <a-input-number style="width:100%" id="inputNumber" :placeholder=" `Please specify ${ form.getFieldValue('powerType') == '0' ? 'directory' : 'menu' }location` " v-decorator="decorators.order" :max="1000" /> <!-- <p>The larger the value, the higher the display order</p> --> </a-form-item> <a-form-item :label=" form.getFieldValue('powerType') == '0' ? 'directory address' : 'menu address' " has Feedback > <a-input v-decorator="[ decorators.path, { rules: [ { required: form.getFieldValue('powerType') == '1' ? true : false, message: `Please enter ${ form.getFieldValue('powerType') == '0' ? 'directory' : 'menu' }Address` }, { max: 100, message: 'The length cannot be greater than 100 characters' } ] } ]" :placeholder=" `Please enter ${ form.getFieldValue('powerType') == '0' ? 'directory' : 'menu' }Address` " allowClear /> <p>Access routing address, such as: `/user`</p> </a-form-item> <a-form-item label="Redirect address" v-if="isTwoMenu & amp; & amp; form.getFieldValue('powerType') == '0'" > <a-input v-decorator="decorators. redirect" placeholder="Please enter redirect address" allowClear /> <p>Breadcrumb redirect routing address, such as: `/test/user`</p> </a-form-item> <a-form-item label="Component path"> <a-input v-decorator="[ decorators.component, { initialValue: form.getFieldValue('powerType') == '0' ? 'Layout' : '' } ]" placeholder="Please enter the component path" allowClear /> <p v-if="form.getFieldValue('powerType') == '1'"> The component path to access, such as: `system/user/index`, default in the `views` directory </p> </a-form-item> </a-form> </a-spin> </a-modal> </template> <script> import { pick } from "lodash"; import { md5 } from "@/lib/utils"; import { ROLE_TYPE } from "@/lib/enum"; const layout = { labelCol: { span: 5 }, wrapperCol: { span: 17 } }; function getDecorators() { return { powerType: [ "powerType", { initialValue: "0" } ], name: [ "name", { rules: [ { required: true, message: "Please enter a name" }, { max: 32, message: "The length of the user name cannot be greater than 32 characters" } ] } ], path: ["path"], order: ["order"], parentId: ["parentId"], redirect: ["redirect"], component: ["component"] }; } export default { name: "AddMenuModal", props: { treeList: { required: true, default: () => {} } }, data: function() { return { ROLE_TYPE, id: null, visible: false, title: null, loading: false, record: null, layout, decorators: getDecorators. call(this), form: this. $form. createForm(this), isRoot: false, isTwoMenu: false, replaceFields: { children: "children", title: "name", key: "id", value: "id" } }; }, watch: {}, mounted() {}, methods: { add() { this.title = "New menu"; this.initRecord({}); }, update(id) { this.title = "Modify menu"; this.$api.getMenuDetail({ id }).then(({ data }) => { this.initRecord(data); }); }, addChildren(id) { this.title = "New menu"; this.$api.getMenuDetail({ id }).then(({ data }) => { this.initRecord(data, "son"); }); }, onSelect(value, node, extray) { console.log(extray.selectedNodes[0].data.props); let extraNode = extray.selectedNodes[0].data.props; this. treeHandleSelect(extraNode); }, treeHandleSelect(node) { if (node.component == "Layout") { this.isTwoMenu = true; } else { this.isTwoMenu = false; } // if (node.id == "0" || node.id == undefined) { // this.isRoot = false; // this.isTwoMenu = false; // } else { // this.isRoot = true; // } // this. $nextTick(() => { this.form.setFieldsValue({ parentId: node.id }); }); }, async initRecord(row, val) { this.form.resetFields(); this.visible = true; this.id = row.id; await this. treeHandleSelect(row); this. record = pick( Object. assign({}, row), "powerType", "name", "order", "path", "parentId", "component", "redirect" ); if (val) { this.record = pick(Object.assign({}, row), "id"); } this. $nextTick(() => { this.form.setFieldsValue(this.record); }); }, check() { this.loading = true; this.form.validateFields((err, values) => { if (err) { this.loading = false; return; } this. submit(values); }); }, async submit(values) { let res; try { if (!this.id) { // Add to let obj = { name: values.name, powerType: values. powerType, order: values.order || "", parentId: values.powerType == "0" ? 0 : values.parentId, path: values.path || "", component: values.component || "", redirect: values.redirect || "" }; // console. log(obj); // values.password = md5(values.password); res = await this. $api. addMenu(obj); } else { // Revise res = await this. $api. updateMenu({ ...values, id: this.id }); } if (!this.id) { this.$message.success("Added successfully"); this.$emit("added", res.data); this.$root.updateFlag = true; } else { this.$message.success("Modified successfully"); this.$emit("updated", res.data); this.$root.updateFlag = true; } this. close(); } catch (e) { this.$root.updateFlag = false; // ignore } this.loading = false; }, close() { this.visible = false; this.loading = false; } } }; </script> <style scoped> p { padding: 0; margin: 0; line-height: 12px; font-size: 12px; color: #cacdd4; } </style>
-
When setting values for the form form, you cannot assign values directly, you need to combine
this.form.setFieldsValue({ username: ‘set value’ })
- When the judgment condition is false, the dom will not render (use v-show instead, and combine this.$nextTick(() => { when assigning values)
this.form.setFieldsValue({
id: node.id
});
});
//In order not to appear warning as follows
It should be noted that the domain data declared by v-decorator must be used on the form (it can not be displayed on the page when used), otherwise an error will be reported - Search bar menu binding, use: model form, using v-model will report an error
- Combined with the scene of a-radio, the corresponding form items and verification rules are different under different values; it is realized by inline
- When using an item in the form as an explicit or implicit condition; get it in the form of form.getFieldValue(‘powerType’);
- When using a-radio, an initial value is usually given; re-initialize the implementation of initialValue at the same level as the verification rule in the getDecorators() method of the form;
- The form item declared by v-decorator in the form must be used in the form (v-show=’false’); otherwise, an alarm will be generated when clicking OK
a-tree-select
v-decorator=”[
decorators. parentId,
{
initialValue: 0,
rules: [
{
required:
form.getFieldValue(‘menuType’) == ‘1’ ? true : false,
message: ‘Please select the upper menu’
}
]
}
]”
class=”machine-input”
tree-data-simple-mode
style=”width: 100%”
:dropdown-style=”{ maxHeight: ‘400px’, overflow: ‘auto’ }”
:tree-data=”treeList”
placeholder=”Please select the parent menu”
:replaceFields=”replaceFields”
allowClear
@select=”onSelect”
/>
1. replaceFields: {
children: “childs”,
title: “menuName”,
key: “id”,
value: “id”
}
Each must declare;
2. Since the id is used as the node identifier, the selected node can only get the node id
onSelect(value, node, extray) {
//Select all props of the node itself console.log(extray.selectedNodes[0].data.props);
let extraNode = extray.selectedNodes[0].data.props;
this. treeHandleSelect(extraNode);
},
Online editor for sql statement input
Plugin: vue2-ace-editor
Component Packaging
<template> <ace ref="editor" :value="value" :lang="lang" :width="width === 0 ? '100%' : width" :height="height === 0 ? '100%' : height" :theme="theme" :options="options" @init="initEditor" v-bind="config"> </ace> </template> <script> import ace from 'vue2-ace-editor' export default { name: 'Editor', components: { ace }, props: { value: { type: String, default: '' }, width: { type: Number, default: 0 }, height: { type: Number, default: 0 }, readOnly: { type: Boolean, default: false }, theme: { type: String, default: 'iplastic' }, lang: { type: String, default: 'sh' }, config: { type: Object, default: () => { return { enableLiveAutocompletion: true, fontSize: 16 } } } }, computed: { options() { return { enableBasicAutocompletion: true, enableSnippets: true, showPrintMargin: false, fontSize: this.config.fontSize, enableLiveAutocompletion: this.config.enableLiveAutocompletion, readOnly: this.readOnly } } }, methods: { initEditor(editor) { require('brace/ext/language_tools') // language setting require('brace/mode/sh') require('brace/mode/json') require('brace/mode/xml') require('brace/mode/yaml') require('brace/mode/properties') require('brace/snippets/sh') require('brace/snippets/json') require('brace/snippets/xml') require('brace/snippets/yaml') require('brace/snippets/properties') // set the theme // light iplastic sqlserver tomorrow xcode // dark dracula gruvbox idle_fingers merbivore terminal tomorrow_night_bright require('brace/theme/iplastic') // listen for changes in value editor.getSession().on('change', () => { this.$emit('change', editor.getValue()) }) }, getValue() { return this. $refs. editor. editor. getValue() }, setValue(value) { this.$refs.editor.editor.session.setValue(value) }, clear() { this.$refs.editor.editor.session.setValue('') } } } </script> <style scoped> </style>
Component Reference – Implementation Preview
<template> <a-modal v-model="visible" :width="650" :footer="null" :destroyOnClose="true" @close="close"> <!-- editor --> <Editor v-bind="editorConfig" :value="value" :height="350" :readOnly="true"/> <!-- Title --> <template #title> <span>{<!-- -->{ title }}</span> <a @click="$copy(value)" title="Copy"> <a-icon class="copy-icon-right" type="copy"/> </a> </template> </a-modal> </template> <script> import Editor from '@/components/editor/Editor' export default { name: 'EditorPreview', components: { Editor }, props: { editorConfig: { type: Object, default: () => { return {} } }, title: { type: String, default: 'Preview' } }, data() { return { visible: false, value: null } }, methods: { preview(value) { this.visible = true this.value = value }, close() { this.visible = false this. value = null } } } </script> <style scoped> </style>
When used in the form, give the initial value undefined