location-manage项目代码片段
vscode 中通过快捷的代码短语快速生成常用的代码模板。
- 项目根目录下创建以下文件(完整代码见文末)
.vscode\location-manage.code-snippets
{
// Place your location-manage 工作区 snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and
// description. Add comma separated ids of the languages where the snippet is applicable in the scope field. If scope
// is left empty or omitted, the snippet gets applied to all languages. The prefix is what is
// used to trigger the snippet and the body will be expanded and inserted. Possible variables are:
// $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders.
// Placeholders with the same ids are connected.
// Example:
// "Print to console": {
// "scope": "javascript,typescript",
// "prefix": "log",
// "body": [
// "console.log('$1');",
// "$2"
// ],
// "description": "Log output to console"
// }
// Example2:
// "Print to console": {
// "scope": "javascript,typescript",
// "prefix": "log",
// "description": "location-manage 代码片段名",
// "body": [
// "console.log('$1');",
// "$2"
// ],
// }
"Print to table": {
"prefix": "table",
"description": "location-manage table",
"body": [
"<!-- table列表 -->",
"<template>",
" <Table",
" ref=\"viewersTarget\"",
" class=\"mt-20\"",
" :params=\"tableColumn\"",
" :table-data=\"tableData\"",
" :table-loading=\"tableLoading\"",
" :need-index=\"false\"",
" >",
" <template v-slot:logo=\"{ row }\">",
" <img",
" v-if=\"row.logo\"",
" :src=\"row.logo + '?imageView2/2/w/100/h/100/q/100/format/jpg'\"",
" :data-original=\"row.logo\">",
" <span v-else>-</span>",
" </template>",
" <template v-slot:operation=\"{ row }\">",
" <ElButton type=\"text\" size=\"small\" @click=\"edit(row)\">编辑</ElButton>",
" <ElButton type=\"text\" size=\"small\" @click=\"remove(row.id)\">删除</ElButton>",
" </template>",
" </Table>",
"</template>",
"",
"<script lang=\"ts\">",
"import { Component, Vue, Prop } from 'vue-property-decorator';",
"import Table from '@/common/components/Table/index.vue'; // 列表组件",
"",
"import MixinsImgViewer from '@/common/mixins/ImgViewer.vue'; // 图片预览",
"",
"@Component({",
" mixins: [MixinsImgViewer],",
" components: { Table }",
"})",
"export default class FloorTableList extends Vue {",
" /* props */",
" @Prop({",
" type: Array,",
" default: () => []",
" }) private tableData!: Array<any>",
" @Prop({",
" type: Boolean,",
" default: false",
" }) private tableLoading!: boolean",
"",
" // 是否只读:true 只读,不显示操作列",
" @Prop({",
" type: Boolean,",
" default: false",
" }) private readonly?: boolean",
"",
" /* data */",
"",
" /* computed */",
" get tableColumn() {",
" const tableColumn: any = [",
" { prop: 'floor', label: '楼层', minWidth: 80 },",
" { prop: 'name', label: '店铺名称', minWidth: 120 },",
" { prop: 'brand', label: '品牌名称', minWidth: 120 },",
" { prop: 'industries', label: '所属行业', minWidth: 120 },",
" { prop: 'shop_type', label: '店铺类型', minWidth: 120 },",
" { prop: 'last_year_amount', label: '上年月均销售量', minWidth: 140 },",
" { prop: 'area', label: '面积', minWidth: 120, suffix: 'm²' },",
" { prop: 'logo', label: '店铺logo', minWidth: 120, slotName: 'logo' }",
" ];",
" if (!this.readonly) {",
" tableColumn.push({ prop: 'operation', label: '操作', width: 120, fixed: 'right', slotName: 'operation' });",
" }",
" return tableColumn;",
" }",
"",
" /* hook */",
"",
" /* methods */",
" edit(row: any) {",
" this.\\$emit('edit', row);",
" }",
" remove(id: number) {",
" this.\\$emit('remove', id);",
" }",
"",
"",
"}",
"</script>",
"",
"<style lang=\"less\" scoped>",
"</style>",
"",
]
},
}
.vscode\location-manage.code-snippets 完整代码:
- default 基础模板
- search
- table
- page
- editor
{
// Place your location-manage 工作区 snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and
// description. Add comma separated ids of the languages where the snippet is applicable in the scope field. If scope
// is left empty or omitted, the snippet gets applied to all languages. The prefix is what is
// used to trigger the snippet and the body will be expanded and inserted. Possible variables are:
// $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders.
// Placeholders with the same ids are connected.
// Example:
// "Print to console": {
// "scope": "javascript,typescript",
// "prefix": "log",
// "body": [
// "console.log('$1');",
// "$2"
// ],
// "description": "Log output to console"
// }
// Example2:
// "Print to console": {
// "scope": "javascript,typescript",
// "prefix": "log",
// "description": "location-manage 代码片段名",
// "body": [
// "console.log('$1');",
// "$2"
// ],
// }
"Print to default": {
"prefix": "default",
"description": "location-manage 基础模板",
"body": [
"<!-- $1 -->",
"<template>",
" <div>",
" 项目编辑 {{ id }}",
" </div>",
"</template>",
"",
"<script lang=\"ts\">",
"import { Component, Vue, Prop } from 'vue-property-decorator';",
"",
"@Component",
"export default class ManageEdit extends Vue {",
" /* props */",
" @Prop({",
" type: Number,",
" default: null",
" }) private id?: number",
"",
" /* data */",
"",
" /* hook */",
" mounted() {",
" this.init();",
" }",
"",
" /* methods */",
" init() {",
" if (this.id) {",
" console.log('项目编辑');",
" } else {",
" console.log('项目新增');",
" }",
" }",
"",
"}",
"</script>",
"",
"<style lang=\"less\" scoped>",
"</style>",
"",
]
},
"Print to ts-vue": {
"prefix": "ts-vue",
"description": "生成 ts-vue 的简单模板",
"body": [
"<!-- -->",
"<template>",
" <div>",
"",
" </div>",
"</template>",
"",
"<script lang=\"ts\">",
"import Vue from 'vue';",
"",
"export default Vue.extend({",
" name: '',",
" components: {},",
" props: {},",
" data() {",
" return {",
" };",
" },",
" computed: {},",
" mounted() {",
"",
" },",
" methods: {",
"",
" }",
"});",
"</script>",
"",
"<style lang=\"less\" scoped>",
"</style>",
"",
],
},
"Print to template": {
"prefix": "template",
"description": "location-manage 生成简单说明模板",
"body": [
"<!-- -->",
"<template>",
" <div>",
"",
" </div>",
"</template>",
"",
"<script lang=\"ts\">",
"import { Component, Vue, Watch, Provide, Inject, Prop, Emit, PropSync, Model } from 'vue-property-decorator';",
"import HelloWorld from './HelloWorld.vue';",
"import { def } from '@/common/utils/ways';",
"/* vue-property-decorator依赖于Component 必须在使用装饰器语法是引入并使用Component,否则会导致无法监听到data数据变化 */",
"@Component({",
" components: {",
" HelloWorld, // 声明子组件的引用",
" },",
" filters: {",
" addWorld: (value: string) => `${value} world`,",
" },",
" directives: {",
" demoSimplify(el, binding, vnode) {",
" // do stuff",
" },",
" }",
"})",
"export default class MyComponent extends Vue {",
" /* Provide/Inject */",
" @Inject() private testData!: {[k: string]: any}",
" @Provide() private testData = (() => {",
" const testData = def(this, ['count']);",
" return testData;",
" })()",
" /* Provide/Inject end */",
"",
" /* 数据 start */",
" private msg = 'Hello';",
" private count = 0;",
" private value = 'lorry'",
" /* 数据 end */",
"",
" /* $ref定义 start */",
" public $refs!: {",
" helloworld: HelloWorld;",
" }",
" /* $ref定义 start */",
"",
"",
" /* 单项数据 start */",
" @Prop({",
" type: Number,",
" validator: (value) => {",
" return value > 100;",
" },",
" required: true",
" }) private count!: string // !表示有值, 否则 ts 会告警未初始化",
" /* 单项数据 end */",
"",
" /* 可变更的双向数据 start */",
" // 注意@PropSync 里的参数不能与定义的实例属性同名, 因为还是那个原理, props 是只读的.",
" @PropSync('count') private innerCount!: number",
" /* 可变更的双向数据 end */",
"",
" /* v-model start */",
" @Model('change', { type: [String, Number] }) private value!: string|number",
" /* v-model end */",
"",
" /* watch监听 start */",
" @Watch('person', {",
" deep: true,",
" })",
" private firstNameChange(person: any, oldPerson: any) {",
" console.log(`count change from${person.name.first}to: ${oldPerson.name}`);",
" }",
" /* watch监听 end */",
"",
" /* computed计算 start */",
" get maxConfigMix() {",
" return Object.assign({},",
" this.$attrs,",
" {",
" value: this.value[this.maxKey]",
" }",
" );",
" }",
" /* computed计算 end */",
"",
" /* 事件emit start */",
" @Emit('button-click')",
" private emitChange() {",
" this.count += 1;",
" return this.count;",
" }",
" /* 事件emit end */",
"",
" /* 生命钩子 start */",
" // ....",
" private created() {}",
" private mounted() {",
" console.log(this.$refs.helloworld);",
" }",
" // ...",
" /* 生命钩子 end */",
"",
"}",
"",
"</script>",
"",
"<style lang=\"less\" scoped>",
"</style>",
"",
]
},
"Print to search": {
"prefix": "search",
"description": "location-manage 筛选",
"body": [
"<!-- 筛选 -->",
"<template>",
" <SearchForm",
" ref=\"searchForm\"",
" :model=\"searchFormData\"",
" :label-length=\"4\"",
" @loadData=\"loadData\">",
" <FormSelect",
" v-model=\"searchFormData.floor\"",
" prop=\"floor\"",
" label=\"楼层:\"",
" :options=\"floors\"",
" option-label=\"floor\"",
" option-value=\"floor\"",
" placeholder=\"请选择楼层\"",
" />",
" <FormInput",
" v-model=\"searchFormData.name\"",
" prop=\"name\"",
" label=\"店铺:\"",
" placeholder=\"请输入店铺名称\"",
" />",
" </SearchForm>",
"</template>",
"",
"<script lang=\"ts\">",
"import { Component, Vue, Prop } from 'vue-property-decorator';",
"import SearchForm from '@/common/components/Form/SearchForm.vue'; // 搜索表单组件",
"import FormSelect from '@/common/components/Form/FormSelect.vue'; // 表单组件-选择组件",
"import FormInput from '@/common/components/Form/FormInput.vue'; // 表单组件-普通输入组件",
"",
"@Component({",
" components: { SearchForm, FormSelect, FormInput }",
"})",
"export default class FloorSearch extends Vue {",
" /* props */",
" @Prop({",
" type: Array,",
" default: () => []",
" }) private floors?: Array<any>",
" /* data */",
" // 搜索条件",
" searchFormData = {",
" floor: null, // 楼层",
" name: null, // 店铺",
" }",
"",
" /* hook */",
"",
" /* methods */",
" loadData(...rest: any[]) {",
" this.\\$emit('loadData', ...rest);",
" }",
"",
"}",
"</script>",
"",
"<style lang=\"less\" scoped>",
"</style>",
"",
]
},
"Print to table": {
"prefix": "table",
"description": "location-manage table",
"body": [
"<!-- table列表 -->",
"<template>",
" <Table",
" ref=\"viewersTarget\"",
" class=\"mt-20\"",
" :params=\"tableColumn\"",
" :table-data=\"tableData\"",
" :table-loading=\"tableLoading\"",
" :need-index=\"false\"",
" >",
" <template v-slot:logo=\"{ row }\">",
" <img",
" v-if=\"row.logo\"",
" :src=\"row.logo + '?imageView2/2/w/100/h/100/q/100/format/jpg'\"",
" :data-original=\"row.logo\">",
" <span v-else>-</span>",
" </template>",
" <template v-slot:operation=\"{ row }\">",
" <ElButton type=\"text\" size=\"small\" @click=\"edit(row)\">编辑</ElButton>",
" <ElButton type=\"text\" size=\"small\" @click=\"remove(row.id)\">删除</ElButton>",
" </template>",
" </Table>",
"</template>",
"",
"<script lang=\"ts\">",
"import { Component, Vue, Prop } from 'vue-property-decorator';",
"import Table from '@/common/components/Table/index.vue'; // 列表组件",
"",
"import MixinsImgViewer from '@/common/mixins/ImgViewer.vue'; // 图片预览",
"",
"@Component({",
" mixins: [MixinsImgViewer],",
" components: { Table }",
"})",
"export default class FloorTableList extends Vue {",
" /* props */",
" @Prop({",
" type: Array,",
" default: () => []",
" }) private tableData!: Array<any>",
" @Prop({",
" type: Boolean,",
" default: false",
" }) private tableLoading!: boolean",
"",
" // 是否只读:true 只读,不显示操作列",
" @Prop({",
" type: Boolean,",
" default: false",
" }) private readonly?: boolean",
"",
" /* data */",
"",
" /* computed */",
" get tableColumn() {",
" const tableColumn: any = [",
" { prop: 'floor', label: '楼层', minWidth: 80 },",
" { prop: 'name', label: '店铺名称', minWidth: 120 },",
" { prop: 'brand', label: '品牌名称', minWidth: 120 },",
" { prop: 'industries', label: '所属行业', minWidth: 120 },",
" { prop: 'shop_type', label: '店铺类型', minWidth: 120 },",
" { prop: 'last_year_amount', label: '上年月均销售量', minWidth: 140 },",
" { prop: 'area', label: '面积', minWidth: 120, suffix: 'm²' },",
" { prop: 'logo', label: '店铺logo', minWidth: 120, slotName: 'logo' }",
" ];",
" if (!this.readonly) {",
" tableColumn.push({ prop: 'operation', label: '操作', width: 120, fixed: 'right', slotName: 'operation' });",
" }",
" return tableColumn;",
" }",
"",
" /* hook */",
"",
" /* methods */",
" edit(row: any) {",
" this.\\$emit('edit', row);",
" }",
" remove(id: number) {",
" this.\\$emit('remove', id);",
" }",
"",
"",
"}",
"</script>",
"",
"<style lang=\"less\" scoped>",
"</style>",
"",
]
},
"Print to page": {
"prefix": "page",
"description": "location-manage 分页",
"body": [
"<Pagination",
" :current-page.sync=\"currentPage\"",
" :pagesize.sync=\"pagesize\"",
" :totalpage=\"totalpage\"",
" :total=\"total\"",
" @loadData=\"loadData\"/>",
"",
"import Pagination from '@/common/components/Pagination/index.vue'; // 分页",
"",
" // 分页data start",
" private currentPage = 1;",
" private pagesize = 20;",
" private totalpage = 0;",
" private total = 0;",
]
},
"Print to editor": {
"prefix": "editor",
"description": "location-manage 编辑表单",
"body": [
"<!-- 新增/编辑 -->",
"<template>",
" <ElDialog",
" :modal-append-to-body=\"false\"",
" :visible.sync=\"visible\"",
" :title=\"`\\${formData.id ? '编辑' : '新增'}店铺`\"",
" width=\"650px\">",
" <ElForm",
" ref=\"formData\"",
" :model=\"formData\"",
" :rules=\"rules\"",
" label-width=\"120px\">",
"",
" <FormSelect",
" v-model=\"formData.floor\"",
" prop=\"floor\"",
" label=\"楼层:\"",
" :options=\"floors\"",
" option-label=\"floor\"",
" option-value=\"floor\"",
" placeholder=\"请选择楼层\"",
" />",
" <FormInput",
" v-model=\"formData.name\"",
" prop=\"name\"",
" label=\"店铺名称\"",
" maxlength=\"20\"",
" placeholder=\"请输入店铺名称,最多20字\"",
" />",
"",
" <FormBrand",
" v-model=\"formData.brand\"",
" prop=\"brand\"",
" label=\"品牌\"",
" placeholder=\"请搜索并选择品牌\"",
" @change=\"changeBrand(formData, \\$event)\"",
" />",
"",
" <FormCascader",
" v-model=\"formData.industry_ids\"",
" prop=\"industry_ids\"",
" label=\"所属行业\"",
" :options=\"industries\"",
" :props=\"{ value: 'id', label: 'display_name', multiple: true, emitPath: false }\"",
" show-all-levels",
" filterable",
" :disabled=\"partParamDisabled\"",
" placeholder=\"请选择所属行业\"",
" />",
" <FormSelect",
" v-model=\"formData.shop_type_id\"",
" prop=\"shop_type_id\"",
" label=\"店铺类型\"",
" :options=\"shopTypes\"",
" option-label=\"name\"",
" option-value=\"id\"",
" placeholder=\"请选择店铺类型\"",
" />",
" <FormInput",
" v-model=\"formData.last_year_amount\"",
" prop=\"last_year_amount\"",
" label=\"上年月均销量\"",
" placeholder=\"请输入销售额\"",
" custom-type=\"float\"",
" maxlength=\"8\"",
" >",
" <template slot=\"append\">万元</template>",
" </FormInput>",
" <FormInput",
" v-model=\"formData.area\"",
" prop=\"area\"",
" label=\"面积\"",
" placeholder=\"请输入面积\"",
" custom-type=\"float\"",
" maxlength=\"8\"",
" >",
" <template slot=\"append\">m²</template>",
" </FormInput>",
"",
" <FormUploadEditor",
" v-model=\"formData.logo\"",
" prop=\"logo\"",
" label=\"店铺logo\"",
" :file-size=\"12\"",
" qiniu-bucket=\"linhuiba-banners\"",
" list-type=\"text\"",
" :show-file-list=\"false\"",
" show-custom-operation",
" :disabled=\"partParamDisabled\"",
" />",
"",
" <ElFormItem>",
" <ElButton :disabled=\"btnSureDisabled\" type=\"primary\" @click=\"saveFormData()\">确定</ElButton>",
" <slot name=\"close\"></slot>",
" </ElFormItem>",
" </ElForm>",
" </ElDialog>",
"</template>",
"",
"<script lang=\"ts\">",
"import { Component, Vue, Prop } from 'vue-property-decorator';",
"import { TWO_DECIMAL_NUMBER_REG } from '@/common/utils/regexp';",
"import { getIdsFromArray } from '@/common/utils/ways';",
"import FormSelect from '@/common/components/Form/FormSelect.vue'; // 筛选框",
"import FormInput from '@/common/components/Form/FormInput.vue'; // 输入框",
"import FormBrand from '@/common/components/Form/FormBrand.vue'; // 品牌",
"import FormCascader from '@/common/components/Form/FormCascader.vue'; // 级联选择器",
"import FormUploadEditor from '@/common/components/Form/FormUploadEditor.vue';",
"",
"@Component({",
" components: {",
" FormSelect,",
" FormInput,",
" FormBrand,",
" FormCascader,",
" FormUploadEditor,",
" }",
"})",
"export default class ManageEdit extends Vue {",
" /* 定义 \\$refs */",
" public \\$refs!: {",
" formData: any;",
" }",
"",
" /* props */",
" // @Prop({",
" // type: Number,",
" // default: null",
" // }) private id?: number",
" // 楼层",
" @Prop({",
" type: Array,",
" default: () => []",
" }) private floors!: Array<any>",
" // 店铺类型",
" @Prop({",
" type: Array,",
" default: () => []",
" }) private shopTypes?: Array<any>",
" // 行业",
" @Prop({",
" type: Array,",
" default: () => []",
" }) private industries?: Array<any>",
"",
" /* data */",
" private visible = false",
" private btnSureDisabled = false",
"",
" private formData: any = {}",
" private rules = {",
" 'floor': [{",
" required: true,",
" message: '请选择楼层'",
" }],",
" 'name': [{",
" required: true,",
" whitespace: true,",
" message: '请输入店铺名称'",
" }],",
" 'last_year_amount': [{",
" pattern: TWO_DECIMAL_NUMBER_REG,",
" message: '请输入两位小数点小数'",
" }],",
" 'area': [{",
" pattern: TWO_DECIMAL_NUMBER_REG,",
" message: '请输入两位小数点小数'",
" }]",
" }",
"",
" /* computed */",
" // 选择的品牌不是 其他类型 时,部分字段禁用:行业、logo",
" get partParamDisabled() {",
" return this.formData.brand && this.formData.brand.status !== 0;",
" }",
"",
" /* hook */",
"",
" /* methods */",
" init(data?: any) {",
" this.visible = true;",
" this.\\$nextTick(() => {",
" this.formData = {",
" id: null, // 店铺id",
" floor: null, // 楼层",
" name: null, // 店铺名称",
" // brand_ids: null, // 品牌名称",
" brand: null, // 品牌",
" brand_id: null, // 品牌id",
" industry_ids: [], // 所属行业",
" shop_type_id: null, // 店铺类型",
" last_year_amount: null, // 上年月均销量",
" area: null, // 面积",
" logo: [] // 店铺logo",
" };",
" // 编辑",
" if (data && data.id) {",
" const formData = JSON.parse(JSON.stringify(data));",
" formData.logo = [{ url: formData.logo }];",
" Object.assign(this.formData, formData);",
" this.\\$nextTick(function() {",
" // todo",
" // this.\\$refs.brandsSelection && this.\\$refs.brandsSelection.init();",
" });",
" }",
" });",
" }",
" // 选择品牌后获取所属行业",
" async changeBrand(shop: any, brand_id: number) {",
" let industry_ids: any = [];",
" let image = null;",
"",
" if (brand_id) {",
" shop.brand_id = brand_id;",
" await this.\\$get('/inner/m_brands/search', { ids: [brand_id] }, true).then(({ data }: {data: any}) => {",
" if (Array.isArray(data) && data.length > 0) {",
" industry_ids = getIdsFromArray(data[0].industries);",
" image = data[0].image || '';",
" }",
" });",
" } else {",
" shop.brand_id = null;",
" }",
" shop.industry_ids = industry_ids;",
" shop.logo = image ? [{ url: image }] : [];",
" }",
"",
" // 保存",
" saveFormData() {",
" this.\\$refs.formData.validate((valid: any) => {",
" if (!valid) {",
" this.\\$message.warning('信息未填写完整,请检查');",
" return false;",
" } else {",
" const {",
" id, // 店铺id",
" floor, // 楼层",
" // seq, // 楼层排序",
" name, // 店铺名称",
" // brand_ids, // 品牌名称",
" brand, // 品牌",
" brand_id, // 品牌id",
" industry_ids, // 所属行业",
" shop_type_id, // 店铺类型",
" last_year_amount, // 上年月均销量",
" area, // 面积",
" logo // 店铺logo",
" } = JSON.parse(JSON.stringify(this.formData));",
"",
" const params = {",
" community_id: this.communityId,",
" id, // 店铺id",
" floor, // 楼层",
" seq: 0, // 楼层排序",
" name, // 店铺名称",
" // brand_ids, // 品牌名称",
" brand, // 品牌",
" brand_id, // 品牌id",
" industry_ids, // 所属行业",
" shop_type_id, // 店铺类型",
" last_year_amount, // 上年月均销量",
" area, // 面积",
" logo: Array.isArray(logo) && logo.length ? logo[0].url : null // 店铺logo",
" };",
"",
" const floor_info = this.floors.find((item: { floor: any }) => item.floor === floor);",
" if (floor_info) {",
" params.seq = floor_info.seq; // 楼层排序",
" }",
"",
" this.btnSureDisabled = true;",
" this.\\$get(`/inner/communities/\\${params.community_id}/shops`, params, true).then(() => {",
" this.\\$message.success('保存成功');",
" this.visible = false;",
" this.\\$emit('complete');",
" }).finally(() => {",
" this.btnSureDisabled = false;",
" });",
" }",
" });",
" }",
"",
"}",
"</script>",
"",
"<style lang=\"less\" scoped>",
"</style>",
"",
]
},
}