对比新文件 |
| | |
| | | <template> |
| | | <div class="area-select"> |
| | | <el-button v-if="!disabled" class="mb-10" type="primary" @click="openDialog" |
| | | >选择</el-button |
| | | > |
| | | <div class="tag-list"> |
| | | <el-tag |
| | | v-for="item in value" |
| | | :key="item.city" |
| | | type="primary" |
| | | :closable="!disabled" |
| | | @close="onTagClose(item)" |
| | | >{{ item.province }}-{{ item.city }}</el-tag |
| | | > |
| | | </div> |
| | | <el-dialog |
| | | title="选择地区" |
| | | :visible.sync="dialogVisible" |
| | | append-to-body |
| | | :close-on-click-modal="false" |
| | | > |
| | | <div |
| | | v-for="item in districtList" |
| | | :key="item.code" |
| | | class="mb-10 p-10 border-dashed border-[#eee]" |
| | | > |
| | | <el-bus-checkbox |
| | | v-model="item.selected" |
| | | has-select-all |
| | | :from-dict="false" |
| | | :options="item.children" |
| | | :props="{ label: 'name', value: 'code', selectAllLabel: item.name }" |
| | | ></el-bus-checkbox> |
| | | </div> |
| | | <div slot="footer" class="flex items-center justify-between"> |
| | | <el-checkbox v-model="allChecked" @change="onCheckedChange" |
| | | >全选</el-checkbox |
| | | > |
| | | <div> |
| | | <el-button @click="dialogVisible = false">取消</el-button> |
| | | <el-button type="primary" @click="onConfirm">确定</el-button> |
| | | </div> |
| | | </div> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import cloneDeep from 'lodash.clonedeep' |
| | | export default { |
| | | props: { |
| | | value: { |
| | | type: Array, |
| | | default: () => [], |
| | | }, |
| | | disabled: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | list: [], |
| | | districtList: [], |
| | | dialogVisible: false, |
| | | allChecked: false, |
| | | } |
| | | }, |
| | | mounted() { |
| | | this.getDistrictList() |
| | | }, |
| | | methods: { |
| | | async getDistrictList() { |
| | | if (this.districtList.length === 0) { |
| | | const { code, data } = await this.$services.base.getAreaJson() |
| | | if (code === 0) { |
| | | const list = JSON.parse(data) |
| | | this.deleteRegion(list) |
| | | this.districtList = list |
| | | } |
| | | } |
| | | }, |
| | | deleteRegion(list) { |
| | | list.forEach((province) => { |
| | | if (Array.isArray(province.children)) { |
| | | province.children.forEach((city) => { |
| | | city.parentName = province.name |
| | | if ('children' in city) { |
| | | delete city.children |
| | | } |
| | | }) |
| | | } |
| | | }) |
| | | }, |
| | | getAreaStatus() { |
| | | return new Promise((resolve) => { |
| | | if (this.districtList.length > 0) { |
| | | resolve() |
| | | } else { |
| | | const timer = setInterval(() => { |
| | | if (this.districtList.length > 0) { |
| | | resolve() |
| | | clearTimeout(timer) |
| | | } |
| | | }, 100) |
| | | } |
| | | }) |
| | | }, |
| | | async openDialog() { |
| | | await this.getAreaStatus() |
| | | this.setSelectedCity() |
| | | this.dialogVisible = true |
| | | }, |
| | | onCheckedChange(e) { |
| | | if (e) { |
| | | this.districtList.forEach((province) => { |
| | | if (Array.isArray(province.children)) { |
| | | province.selected = province.children.map((i) => i.code) |
| | | } |
| | | }) |
| | | } else { |
| | | this.districtList.forEach((province) => { |
| | | province.selected = [] |
| | | }) |
| | | } |
| | | }, |
| | | // 根据当前value选中弹出框中的城市 |
| | | setSelectedCity() { |
| | | this.districtList.forEach((province) => { |
| | | const selectedCity = this.value |
| | | .filter((i) => i.province === province.code) |
| | | .map((i) => i.city) |
| | | province.selected = selectedCity |
| | | }) |
| | | this.districtList = cloneDeep(this.districtList) |
| | | }, |
| | | onConfirm() { |
| | | const value = this.districtList.reduce((total, current) => { |
| | | if (Array.isArray(current.selected) && current.selected.length > 0) { |
| | | total = total.concat( |
| | | current.selected.reduce((t, c) => { |
| | | t.push({ province: current.code, city: c }) |
| | | return t |
| | | }, []) |
| | | ) |
| | | } |
| | | return total |
| | | }, []) |
| | | this.$emit('input', value) |
| | | this.dialogVisible = false |
| | | }, |
| | | onTagClose(item) { |
| | | const value = this.value.filter( |
| | | (i) => i.province !== item.province || i.city !== item.city |
| | | ) |
| | | this.$emit('input', value) |
| | | }, |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .area-select { |
| | | width: 100%; |
| | | .tag-list { |
| | | .el-tag { |
| | | margin-right: 6px; |
| | | margin-bottom: 6px; |
| | | } |
| | | } |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <Editor |
| | | ref="editorRef" |
| | | v-model="currentValue" |
| | | :tinymce-script-src="`${baseUrl}tinymce/tinymce.min.js`" |
| | | :plugins="plugins" |
| | | :toolbar="toolbar" |
| | | :init="init" |
| | | output-format="html" |
| | | class="el-ext-editor" |
| | | /> |
| | | </template> |
| | | |
| | | <script> |
| | | // eslint-disable-next-line |
| | | import tinymce from 'tinymce/tinymce' |
| | | import Editor from '@tinymce/tinymce-vue' |
| | | import 'tinymce/icons/default/icons' |
| | | import 'tinymce/plugins/image' |
| | | import 'tinymce/plugins/table' |
| | | import 'tinymce/plugins/lists' // 列表插件 |
| | | import 'tinymce/plugins/wordcount' // 文字计数 |
| | | import 'tinymce/plugins/preview' // 预览 |
| | | import 'tinymce/plugins/emoticons' // emoji表情 |
| | | import 'tinymce/plugins/emoticons/js/emojis.js' // 必须引入这个文件才有表情图库 |
| | | import 'tinymce/plugins/code' // 编辑源码 |
| | | import 'tinymce/plugins/link' // 链接插件 |
| | | import 'tinymce/plugins/advlist' // 高级列表 |
| | | import 'tinymce/plugins/autoresize' // 自动调整编辑器大小 |
| | | import 'tinymce/plugins/searchreplace' // 查找替换 |
| | | import 'tinymce/plugins/autolink' // 自动链接 |
| | | import 'tinymce/plugins/visualblocks' // 显示元素范围 |
| | | import 'tinymce/plugins/visualchars' // 显示不可见字符 |
| | | import 'tinymce/plugins/charmap' // 特殊符号 |
| | | import 'tinymce/plugins/importcss' |
| | | import 'tinymce/plugins/nonbreaking' // 插入不间断空格 |
| | | import 'tinymce/plugins/anchor' |
| | | import 'tinymce/plugins/codesample' |
| | | import 'tinymce/plugins/fullscreen' |
| | | import 'tinymce/plugins/paste' |
| | | export default { |
| | | components: { |
| | | Editor, |
| | | }, |
| | | props: { |
| | | initOptions: { |
| | | type: Object, |
| | | default: () => ({}), |
| | | }, |
| | | value: { |
| | | type: String, |
| | | default: '', |
| | | }, |
| | | plugins: { |
| | | type: [String, Array], |
| | | default: |
| | | 'importcss autoresize searchreplace autolink code visualblocks visualchars fullscreen image link codesample table charmap nonbreaking anchor advlist lists wordcount charmap emoticons indent2em paste', |
| | | }, |
| | | toolbar: { |
| | | type: [String, Array], |
| | | default: () => [ |
| | | 'code undo redo | bold italic underline strikethrough ltr rtl | align numlist bullist | link image | table | lineheight outdent indent indent2em | charmap emoticons | anchor', |
| | | 'fontselect fontsizeselect | forecolor backcolor removeformat', |
| | | ], |
| | | }, |
| | | baseUrl: { |
| | | type: String, |
| | | default() { |
| | | return this.$config.baseUrl || '/' |
| | | }, |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | currentValue: '', |
| | | } |
| | | }, |
| | | computed: { |
| | | init() { |
| | | return { |
| | | base_url: `${this.baseUrl}tinymce/`, |
| | | width: '100%', |
| | | min_height: 400, |
| | | max_height: 700, |
| | | language: 'zh_CN', |
| | | language_url: `${this.baseUrl}tinymce/langs/zh_CN.js`, |
| | | branding: false, |
| | | promotion: false, |
| | | convert_urls: false, |
| | | paste_preprocess: (plugin, args) => { |
| | | if (args.wordContent) { |
| | | this.$message.warning( |
| | | '检测到可能是从word中复制的内容,如果存在图片请通过编辑器的图片上传功能上传' |
| | | ) |
| | | } |
| | | }, |
| | | paste_data_images: true, |
| | | font_formats: |
| | | 'Arial=arial,helvetica,sans-serif; 宋体=SimSun; 微软雅黑=Microsoft Yahei; Impact=impact,chicago;', |
| | | fontsize_formats: |
| | | '10px 11px 12px 14px 16px 18px 20px 22px 24px 36px 48px 64px 72px', |
| | | images_upload_handler: async (blobInfo, success) => { |
| | | const formData = new FormData() |
| | | formData.append('file', blobInfo.blob()) |
| | | const { code, data } = await this.$elBusHttp.request( |
| | | 'flower/api/upload/oss/file', |
| | | { |
| | | method: 'post', |
| | | data: formData, |
| | | contentType: 'multipart/form-data', |
| | | } |
| | | ) |
| | | if (code === 0) { |
| | | success(data[0]?.url) |
| | | } |
| | | }, |
| | | ...this.initOptions, |
| | | } |
| | | }, |
| | | }, |
| | | watch: { |
| | | value: { |
| | | immediate: true, |
| | | handler(value) { |
| | | this.currentValue = value || '' |
| | | }, |
| | | }, |
| | | currentValue(value) { |
| | | this.$emit('input', value) |
| | | this.$emit('change', value) |
| | | }, |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style> |
| | | .tox-tinymce-aux { |
| | | z-index: 10000 !important; |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <div class="base-image-info"> |
| | | <div class="base-image-info__list"> |
| | | <div |
| | | v-for="(item, index) in list" |
| | | :key="index" |
| | | class="base-image-info__item" |
| | | > |
| | | <el-ext-upload |
| | | v-model="item.imageUrl" |
| | | list-type="picture-card" |
| | | value-type="string" |
| | | :limit="1" |
| | | @change="onInputChange" |
| | | ></el-ext-upload> |
| | | <el-form label-width="auto" class="base-image-info__main"> |
| | | <el-form-item label="标题"> |
| | | <el-input v-model="item.title" @change="onInputChange"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="链接"> |
| | | <el-input v-model="item.link" @change="onInputChange"></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="描述"> |
| | | <el-input |
| | | v-model="item.desc" |
| | | type="textarea" |
| | | :rows="3" |
| | | @change="onInputChange" |
| | | ></el-input> |
| | | </el-form-item> |
| | | </el-form> |
| | | <div class="base-image-info__delete" @click="deleteItem(index)"> |
| | | <i class="el-icon-delete"></i> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="base-image-info__add"> |
| | | <el-button type="primary" icon="el-icon-plus" @click="add" |
| | | >添加</el-button |
| | | > |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'BaseImageInfo', |
| | | props: { |
| | | value: { |
| | | type: Array, |
| | | default: () => [], |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | list: [], |
| | | } |
| | | }, |
| | | watch: { |
| | | value: { |
| | | immediate: true, |
| | | handler(value) { |
| | | this.list = value || [] |
| | | }, |
| | | }, |
| | | }, |
| | | methods: { |
| | | add() { |
| | | this.list.push({ |
| | | imageUrl: '', |
| | | title: '', |
| | | desc: '', |
| | | link: '', |
| | | }) |
| | | this.onInputChange() |
| | | }, |
| | | deleteItem(index) { |
| | | this.list.splice(index, 1) |
| | | this.onInputChange() |
| | | }, |
| | | onInputChange() { |
| | | this.$emit('input', this.list) |
| | | this.$emit('change', this.list) |
| | | }, |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .base-image-info { |
| | | &__list { |
| | | } |
| | | &__item { |
| | | display: flex; |
| | | } |
| | | &__main { |
| | | margin-left: 15px; |
| | | flex: 1; |
| | | .el-form-item { |
| | | margin-bottom: 5px; |
| | | } |
| | | } |
| | | &__delete { |
| | | cursor: pointer; |
| | | font-size: 20px; |
| | | margin-left: 15px; |
| | | color: $tip-color; |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | &__add { |
| | | margin-top: 5px; |
| | | } |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <div class="base-link"> |
| | | <div v-for="(item, index) in linkList" :key="index" class="base-link__item"> |
| | | <el-input |
| | | v-model="item.name" |
| | | placeholder="请输入名称" |
| | | clearable |
| | | @change="onInputChange" |
| | | /> |
| | | <i class="base-link__separator">-</i> |
| | | <el-input |
| | | v-model="item.link" |
| | | placeholder="请输入链接" |
| | | clearable |
| | | @change="onInputChange" |
| | | /> |
| | | <div class="base-link__delete" @click="deletePoject(index)"> |
| | | <i class="el-icon-delete"></i> |
| | | </div> |
| | | </div> |
| | | <div class="base-link__add"> |
| | | <el-button type="primary" icon="el-icon-plus" @click="addPoject" |
| | | >继续添加</el-button |
| | | > |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: 'BaseLink', |
| | | props: { |
| | | value: { |
| | | type: Array, |
| | | default: () => [], |
| | | }, |
| | | disabled: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | codeForm: {}, |
| | | linkList: [], |
| | | } |
| | | }, |
| | | watch: { |
| | | value: { |
| | | immediate: true, |
| | | handler(value) { |
| | | this.linkList = value || [] |
| | | }, |
| | | }, |
| | | }, |
| | | methods: { |
| | | addPoject() { |
| | | this.linkList.push({ |
| | | name: '', |
| | | link: '', |
| | | }) |
| | | this.onInputChange() |
| | | }, |
| | | deletePoject(item) { |
| | | this.linkList.splice(item, 1) |
| | | this.onInputChange() |
| | | }, |
| | | onInputChange() { |
| | | this.$emit('input', this.linkList) |
| | | this.$emit('change', this.linkList) |
| | | }, |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .base-link { |
| | | height: 100%; |
| | | &__item { |
| | | position: relative; |
| | | display: flex; |
| | | align-items: center; |
| | | .el-input { |
| | | width: 45% !important; |
| | | } |
| | | &:not(:last-child) { |
| | | margin-bottom: 8px; |
| | | } |
| | | } |
| | | &__separator { |
| | | margin: 0 6px; |
| | | } |
| | | &__delete { |
| | | cursor: pointer; |
| | | font-size: 20px; |
| | | margin-left: 15px; |
| | | color: $tip-color; |
| | | } |
| | | &__add { |
| | | margin-top: 5px; |
| | | } |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <div> |
| | | <el-popover |
| | | ref="popover" |
| | | width="800" |
| | | placement="bottom-start" |
| | | trigger="click" |
| | | popper-class="mod-menu__icon-popover" |
| | | > |
| | | <el-tabs v-model="activeTab"> |
| | | <el-tab-pane |
| | | v-for="tab in tabs" |
| | | :key="tab.title" |
| | | :label="tab.title" |
| | | :name="tab.title" |
| | | > |
| | | <div class="mod-menu__icon-list"> |
| | | <el-button |
| | | v-for="(item, index) in tab.icons" |
| | | :key="index" |
| | | :class="{ 'is-active': item === currentValue }" |
| | | @click="onIconChange(item)" |
| | | > |
| | | <i :class="item" aria-hidden="true" /> |
| | | </el-button> |
| | | </div> |
| | | </el-tab-pane> |
| | | </el-tabs> |
| | | </el-popover> |
| | | <el-input |
| | | v-popover:popover |
| | | v-bind="$attrs" |
| | | :value="currentValue" |
| | | placeholder="图标" |
| | | @input="onInput" |
| | | /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import { |
| | | FILE_ICONS, |
| | | EDITOR_ICONS, |
| | | CHART_ICONS, |
| | | COMMON_ICONS, |
| | | } from '@/plugins/icons' |
| | | export default { |
| | | inheritAttrs: false, |
| | | props: { |
| | | value: { |
| | | type: String, |
| | | default: '', |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | tabs: [ |
| | | { title: '文件类图标', icons: FILE_ICONS }, |
| | | { title: '文本编辑类图标', icons: EDITOR_ICONS }, |
| | | { title: '数据类图标', icons: CHART_ICONS }, |
| | | { title: '通用类', icons: COMMON_ICONS }, |
| | | ], |
| | | activeTab: '文件类图标', |
| | | } |
| | | }, |
| | | watch: { |
| | | value: { |
| | | immediate: true, |
| | | handler(value) { |
| | | this.currentValue = value |
| | | }, |
| | | }, |
| | | }, |
| | | methods: { |
| | | onIconChange(value) { |
| | | this.$emit('input', value) |
| | | this.$emit('change', value) |
| | | }, |
| | | onInput(e) { |
| | | this.$emit('input', e) |
| | | this.$emit('change', e) |
| | | // this.onValidate() |
| | | }, |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | .mod-menu__icon-popover { |
| | | .mod-menu__icon-list { |
| | | height: 300px; |
| | | overflow: auto; |
| | | .el-button { |
| | | margin: 0 10px 10px 0; |
| | | } |
| | | } |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <div class="base-menu-item-comp"> |
| | | <el-submenu |
| | | v-if="hasChildren()" |
| | | :index="item.menuHref" |
| | | :class="`level-${level}`" |
| | | > |
| | | <template slot="title"> |
| | | <i v-if="item.menuIcon" :class="item.menuIcon"></i> |
| | | <span class="base-menu-item-comp__title">{{ item.menuName }}</span> |
| | | </template> |
| | | <base-menu-item |
| | | v-for="(data, index) in item.children" |
| | | :key="index" |
| | | :item="data" |
| | | :super-path="resolvePath(item.menuHref)" |
| | | :level="level + 1" |
| | | ></base-menu-item> |
| | | </el-submenu> |
| | | <el-menu-item v-else :index="resolvePath(item.menuHref)" @click="goRoute"> |
| | | <i v-if="item.menuIcon" :class="item.menuIcon"></i> |
| | | <span class="title">{{ item.menuName }}</span> |
| | | </el-menu-item> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import path from 'path' |
| | | |
| | | export default { |
| | | name: 'BaseMenuItem', |
| | | props: { |
| | | item: { |
| | | type: Object, |
| | | required: true, |
| | | }, |
| | | superPath: { |
| | | type: String, |
| | | default: '/', |
| | | }, |
| | | level: { |
| | | type: Number, |
| | | default: 0, |
| | | }, |
| | | }, |
| | | methods: { |
| | | hasChildren() { |
| | | if (this.item.children && this.item.children.length > 0) { |
| | | return true |
| | | } |
| | | return false |
| | | }, |
| | | goRoute() { |
| | | if (this.item.menuHref.includes('http')) { |
| | | window.open(this.item.menuHref, '_blank') |
| | | } else if (this.item.menuHref.startsWith('/')) { |
| | | this.$router.push(this.item.menuHref) |
| | | } else { |
| | | this.$router.push(this.resolvePath(this.item.menuHref)) |
| | | } |
| | | }, |
| | | resolvePath(route) { |
| | | if (route.includes('http') || route.startsWith('/')) { |
| | | return route |
| | | } |
| | | return path.join(this.superPath, route).replace(/\\/g, '/') |
| | | }, |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .base-menu-item-comp { |
| | | i { |
| | | color: #fff; |
| | | font-size: 14px; |
| | | margin-right: 16px; |
| | | } |
| | | ::v-deep .el-submenu__icon-arrow { |
| | | color: #fff; |
| | | } |
| | | .el-submenu { |
| | | @for $i from 1 through 4 { |
| | | .el-menu-item { |
| | | padding-left: 64px !important; |
| | | } |
| | | .el-submenu.level-#{$i} { |
| | | ::v-deep { |
| | | .el-submenu__title { |
| | | @if $i==0 { |
| | | padding-left: 20px !important; |
| | | } @else { |
| | | padding-left: 32px * ($i + 1) !important; |
| | | } |
| | | } |
| | | } |
| | | .el-menu-item { |
| | | @if $i==0 { |
| | | padding-left: 64px !important; |
| | | } @else { |
| | | padding-left: 32px * ($i + 1) + 10px !important; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <div class="base-nav-comp"> |
| | | <div class="base-nav-comp__toggle" @click="toggleMenu"> |
| | | <svg |
| | | :class="{ 'is-active': !menuShrink }" |
| | | class="base-nav-comp__toggle__svg" |
| | | viewBox="0 0 1024 1024" |
| | | xmlns="http://www.w3.org/2000/svg" |
| | | width="64" |
| | | height="64" |
| | | > |
| | | <path |
| | | d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z" |
| | | /> |
| | | </svg> |
| | | </div> |
| | | <!-- <div class="base-nav-comp__breadcrumb">--> |
| | | <!-- <el-ext-breadcrumb :menus="menus"></el-ext-breadcrumb>--> |
| | | <!-- </div>--> |
| | | <div class="base-nav-comp__right"> |
| | | <!-- <el-tooltip content="主题色" effect="dark" placement="bottom">--> |
| | | <!-- <div class="base-nav-comp__right__action">--> |
| | | <!-- <base-theme-picker />--> |
| | | <!-- </div>--> |
| | | <!-- </el-tooltip>--> |
| | | <el-tooltip |
| | | :content="$t('nav.layoutSize')" |
| | | effect="dark" |
| | | placement="bottom" |
| | | > |
| | | <el-dropdown trigger="click" @command="handleSize"> |
| | | <div class="base-nav-comp__right__action"> |
| | | <i class="fa fa-text-height"></i> |
| | | </div> |
| | | <el-dropdown-menu slot="dropdown"> |
| | | <el-dropdown-item |
| | | v-for="item in sizeList" |
| | | :key="item.value" |
| | | :disabled="size === item.value" |
| | | :command="item.value" |
| | | > |
| | | {{ item.label }} |
| | | </el-dropdown-item> |
| | | </el-dropdown-menu> |
| | | </el-dropdown> |
| | | </el-tooltip> |
| | | <!-- <el-tooltip--> |
| | | <!-- :content="$t('nav.language')"--> |
| | | <!-- effect="dark"--> |
| | | <!-- placement="bottom"--> |
| | | <!-- >--> |
| | | <!-- <el-dropdown trigger="click" @command="handleLanguage">--> |
| | | <!-- <div class="base-nav-comp__right__action">--> |
| | | <!-- <i class="fa fa-language"></i>--> |
| | | <!-- </div>--> |
| | | <!-- <el-dropdown-menu slot="dropdown">--> |
| | | <!-- <el-dropdown-item--> |
| | | <!-- v-for="item in languageList"--> |
| | | <!-- :key="item.value"--> |
| | | <!-- :disabled="$i18n.locale === item.value"--> |
| | | <!-- :command="item.value"--> |
| | | <!-- >--> |
| | | <!-- {{ item.label }}--> |
| | | <!-- </el-dropdown-item>--> |
| | | <!-- </el-dropdown-menu>--> |
| | | <!-- </el-dropdown>--> |
| | | <!-- </el-tooltip>--> |
| | | <el-dropdown trigger="click" @command="handleUser"> |
| | | <div class="base-nav-comp__right__user base-nav-comp__right__action"> |
| | | <img |
| | | v-if="avatar" |
| | | :src="avatar" |
| | | class="base-nav-comp__right__user__avatar" |
| | | /> |
| | | <img |
| | | src="~static/images/avatar.png" |
| | | class="base-nav-comp__right__user__avatar" |
| | | /> |
| | | <div class="base-nav-comp__right__user__nickname"> |
| | | {{ nickName || loginName }} |
| | | </div> |
| | | </div> |
| | | <el-dropdown-menu slot="dropdown"> |
| | | <el-dropdown-item command="changePassword">{{ |
| | | $t('nav.changePassword') |
| | | }}</el-dropdown-item> |
| | | <el-dropdown-item command="logout">{{ |
| | | $t('nav.logout') |
| | | }}</el-dropdown-item> |
| | | </el-dropdown-menu> |
| | | </el-dropdown> |
| | | </div> |
| | | <extra-dialog |
| | | ref="passwordDialog" |
| | | :title="$t('nav.changePassword')" |
| | | :dialog-attrs="{ appendToBody: true }" |
| | | :form-attrs="{ labelWidth: 'auto' }" |
| | | :form="passwordForm" |
| | | :at-confirm="onPasswordFormConfirm" |
| | | @formUpdate="onPasswordFormUpdate" |
| | | ></extra-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import { mapState, mapGetters } from 'vuex' |
| | | import { joinLocaleText } from 'el-business' |
| | | |
| | | export default { |
| | | name: 'BaseNav', |
| | | data() { |
| | | return { |
| | | sizeList: [ |
| | | { label: 'Medium', value: 'medium' }, |
| | | { label: 'Small', value: 'small' }, |
| | | { label: 'Mini', value: 'mini' }, |
| | | ], |
| | | languageList: [ |
| | | { label: '中文', value: 'zh-CN' }, |
| | | { label: 'English', value: 'en' }, |
| | | ], |
| | | passwordFormInfo: {}, |
| | | passwordForm: [ |
| | | { |
| | | label: this.$t('nav.newPassword'), |
| | | id: 'password', |
| | | type: 'input', |
| | | el: { type: 'password' }, |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: joinLocaleText( |
| | | this.$t('elBus.common.pleaseEnter'), |
| | | this.$t('nav.newPassword') |
| | | ), |
| | | trigger: 'blur', |
| | | }, |
| | | { |
| | | pattern: |
| | | /^(?:(?=\S*\d)(?=\S*[A-Z])(?=\S*[a-z])(?=\S*[-_!@#$%^&*? ]))\S{8,20}$/, |
| | | message: this.$t('nav.passwordPattern'), |
| | | trigger: 'blur', |
| | | }, |
| | | ], |
| | | }, |
| | | { |
| | | label: this.$t('nav.confirmPassword'), |
| | | id: 'confirmPassword', |
| | | type: 'input', |
| | | el: { type: 'password' }, |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: joinLocaleText( |
| | | this.$t('elBus.common.pleaseEnter'), |
| | | this.$t('nav.confirmPassword') |
| | | ), |
| | | trigger: 'blur', |
| | | }, |
| | | { |
| | | validator: (rule, value, callback) => { |
| | | if (value !== this.passwordFormInfo.password) { |
| | | callback(new Error(this.$t('nav.passwordInconsistent'))) |
| | | } else { |
| | | callback() |
| | | } |
| | | }, |
| | | trigger: 'blur', |
| | | }, |
| | | ], |
| | | }, |
| | | ], |
| | | } |
| | | }, |
| | | computed: { |
| | | ...mapState({ |
| | | menuShrink: (state) => state.app.menuShrink, |
| | | size: (state) => state.app.size, |
| | | }), |
| | | ...mapGetters({ |
| | | nickName: 'auth/nickName', |
| | | loginName: 'auth/loginName', |
| | | avatar: 'auth/avatar', |
| | | tel: 'auth/tel', |
| | | menus: 'permission/menus', |
| | | }), |
| | | }, |
| | | methods: { |
| | | toggleMenu() { |
| | | this.$store.commit('app/SET_MENU_SHRINK', !this.menuShrink) |
| | | }, |
| | | handleSize(size) { |
| | | this.$store.commit('app/SET_SIZE', size) |
| | | window.location.reload() |
| | | }, |
| | | handleLanguage(language) { |
| | | const url = this.switchLocalePath(language) |
| | | window.location.href = url |
| | | }, |
| | | handleUser(command) { |
| | | this[command]() |
| | | }, |
| | | logout() { |
| | | this.$store.dispatch('auth/clearLoginInfo') |
| | | this.$router.replace('/login') |
| | | }, |
| | | changePassword() { |
| | | this.$refs.passwordDialog.show() |
| | | }, |
| | | onPasswordFormUpdate(e) { |
| | | this.passwordFormInfo = { ...e } |
| | | }, |
| | | async onPasswordFormConfirm(e) { |
| | | const { code } = await this.$services.auth.changePassword(e) |
| | | if (code === 0) { |
| | | this.$message.success('密码修改成功') |
| | | return true |
| | | } |
| | | return false |
| | | }, |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .base-nav-comp { |
| | | height: 50px; |
| | | overflow: hidden; |
| | | position: relative; |
| | | background: #fff; |
| | | box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08); |
| | | display: flex; |
| | | align-items: center; |
| | | &__toggle { |
| | | padding: 0 15px; |
| | | line-height: 46px; |
| | | height: 100%; |
| | | float: left; |
| | | cursor: pointer; |
| | | transition: background 0.3s; |
| | | -webkit-tap-highlight-color: transparent; |
| | | |
| | | &:hover { |
| | | background: rgba(0, 0, 0, 0.025); |
| | | } |
| | | &__svg { |
| | | display: inline-block; |
| | | vertical-align: middle; |
| | | width: 20px; |
| | | height: 20px; |
| | | &.is-active { |
| | | transform: rotate(180deg); |
| | | } |
| | | } |
| | | } |
| | | &__breadcrumb { |
| | | margin-left: 8px; |
| | | } |
| | | &__right { |
| | | flex: 1; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: flex-end; |
| | | padding: 0 20px; |
| | | height: 100%; |
| | | .el-dropdown { |
| | | height: 100%; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | &__user { |
| | | &__avatar { |
| | | width: 30px; |
| | | height: 30px; |
| | | border-radius: 50%; |
| | | } |
| | | &__nickname { |
| | | font-size: 14px; |
| | | color: $main-title-color; |
| | | margin-left: 10px; |
| | | } |
| | | } |
| | | &__action { |
| | | padding: 0 15px; |
| | | display: flex; |
| | | align-items: center; |
| | | cursor: pointer; |
| | | height: 100%; |
| | | i { |
| | | font-size: 16px; |
| | | color: $main-title-color; |
| | | } |
| | | &:hover { |
| | | background-color: rgba(0, 0, 0, 0.025); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <el-tree |
| | | ref="tree" |
| | | :check-strictly="false" |
| | | :data="list" |
| | | :props="defaultProps" |
| | | node-key="id" |
| | | show-checkbox |
| | | @check-change="onCheckChange" |
| | | /> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | props: { |
| | | value: { |
| | | type: Array, |
| | | default: () => [], |
| | | }, |
| | | disabled: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | }, |
| | | watch: { |
| | | value: { |
| | | immediate: true, |
| | | async handler(value) { |
| | | if (this.list.length === 0) { |
| | | await this.getList() |
| | | } |
| | | this.$nextTick(() => { |
| | | if (Array.isArray(value)) { |
| | | value.forEach((i) => { |
| | | this.$refs.tree.setChecked(i, true, false) |
| | | }) |
| | | } |
| | | }) |
| | | }, |
| | | }, |
| | | disabled(value) { |
| | | this.setDisabled(this.list, value) |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | defaultProps: { |
| | | children: 'children', |
| | | label: 'menuName', |
| | | }, |
| | | list: [], |
| | | } |
| | | }, |
| | | methods: { |
| | | onCheckChange() { |
| | | const checkedNodes = this.$refs.tree.getCheckedNodes(false, true) |
| | | const checkedKeys = checkedNodes.map((i) => i.id) |
| | | this.$emit('input', checkedKeys) |
| | | this.$emit('change', checkedKeys) |
| | | }, |
| | | async getList() { |
| | | const { code, data } = await this.$elBusHttp.request( |
| | | 'flower/api/menu/list' |
| | | ) |
| | | if (code === 0) { |
| | | const list = data || [] |
| | | if (this.disabled) { |
| | | this.setDisabled(list) |
| | | } |
| | | this.list = list |
| | | } |
| | | }, |
| | | setDisabled(list, disabled = true) { |
| | | list.forEach((item) => { |
| | | item.disabled = disabled |
| | | if (Array.isArray(item.children) && item.children.length > 0) { |
| | | this.setDisabled(item.children) |
| | | } |
| | | }) |
| | | }, |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style scoped></style> |
对比新文件 |
| | |
| | | <template> |
| | | <div |
| | | class="cubebase-sidebar-comp" |
| | | :class="{ 'is-hide': menuShrink, 'is-mobile': isMobile }" |
| | | > |
| | | <nuxt-link class="cubebase-sidebar-comp__top" to="/"> |
| | | <transition name="nameFade"> |
| | | <div v-if="!menuShrink" class="cubebase-sidebar-comp__top__title"> |
| | | {{ platformName }} |
| | | </div> |
| | | </transition> |
| | | </nuxt-link> |
| | | <el-scrollbar wrap-class="scrollbar-wrapper"> |
| | | <el-bus-menu |
| | | :content="menus" |
| | | :default-active="activeRoute" |
| | | :collapse="menuShrink" |
| | | :background-color="variables.menuBg" |
| | | :text-color="variables.menuText" |
| | | :unique-opened="false" |
| | | :active-text-color="variables.menuActiveText" |
| | | :collapse-transition="false" |
| | | mode="vertical" |
| | | :props="{ index: 'fullPath' }" |
| | | @menuItemSelect="onMenuItemClick" |
| | | /> |
| | | </el-scrollbar> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import { mapState, mapGetters } from 'vuex' |
| | | import variables from '@/assets/variable.scss' |
| | | |
| | | export default { |
| | | name: 'BaseSidebar', |
| | | data() { |
| | | return { |
| | | platformName: this.$config.platformName, |
| | | } |
| | | }, |
| | | computed: { |
| | | variables() { |
| | | return variables |
| | | }, |
| | | ...mapState({ |
| | | menuShrink: (state) => state.app.menuShrink, |
| | | isMobile: (state) => state.app.isMobile, |
| | | activeRoute: (state) => state.app.activeRoute, |
| | | }), |
| | | ...mapGetters({ |
| | | menus: 'permission/menus', |
| | | leafMenus: 'permission/leafMenus', |
| | | }), |
| | | }, |
| | | watch: { |
| | | $route() { |
| | | this.setActiveRoute() |
| | | }, |
| | | }, |
| | | mounted() { |
| | | this.setActiveRoute() |
| | | }, |
| | | methods: { |
| | | setActiveRoute() { |
| | | const currentRoute = this.$route.fullPath |
| | | if (Array.isArray(this.leafMenus)) { |
| | | const matchRoute = this.leafMenus.find((item) => |
| | | currentRoute.includes(item.fullPath) |
| | | ) |
| | | if (matchRoute) { |
| | | this.$store.commit('app/SET_ACTIVE_ROUTE', matchRoute.fullPath) |
| | | } |
| | | } |
| | | }, |
| | | onMenuItemClick(item) { |
| | | if (item.fullPath.includes('http')) { |
| | | window.open(item.fullPath, '_blank') |
| | | } else { |
| | | this.$router.push(item.fullPath) |
| | | } |
| | | }, |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .nameFade-enter-active { |
| | | opacity: 0; |
| | | white-space: nowrap; |
| | | transition: all 0.28s; |
| | | } |
| | | |
| | | .cubebase-sidebar-comp { |
| | | display: flex; |
| | | flex-direction: column; |
| | | transition: width 0.28s; |
| | | width: $sideBarWidth !important; |
| | | background-color: $menuBg; |
| | | height: 100%; |
| | | position: relative; |
| | | z-index: 1001; |
| | | overflow: hidden; |
| | | &__top { |
| | | position: relative; |
| | | width: 100%; |
| | | padding: 25px 10px; |
| | | background: #2b2f3a; |
| | | text-align: center; |
| | | overflow: hidden; |
| | | display: block; |
| | | &__logo { |
| | | width: 32px; |
| | | height: 32px; |
| | | border-radius: 50%; |
| | | vertical-align: middle; |
| | | margin-bottom: 15px; |
| | | } |
| | | &__title { |
| | | margin: 0; |
| | | color: #fff; |
| | | font-weight: 600; |
| | | font-size: 14px; |
| | | overflow: hidden; |
| | | } |
| | | } |
| | | .el-scrollbar { |
| | | flex: 1; |
| | | ::v-deep .el-menu { |
| | | border: none; |
| | | height: 100%; |
| | | width: 100% !important; |
| | | .submenu-title-noDropdown, |
| | | .el-submenu__title { |
| | | &:hover { |
| | | background-color: $menuHover !important; |
| | | } |
| | | } |
| | | |
| | | .is-active > .el-submenu__title { |
| | | color: $subMenuActiveText !important; |
| | | } |
| | | |
| | | .nest-menu .el-submenu > .el-submenu__title, |
| | | .el-submenu .el-menu-item { |
| | | min-width: $sideBarWidth !important; |
| | | background-color: $subMenuBg !important; |
| | | |
| | | &:hover { |
| | | background-color: $subMenuHover !important; |
| | | } |
| | | } |
| | | } |
| | | ::v-deep { |
| | | .el-bus-menu { |
| | | i { |
| | | color: #fff; |
| | | font-size: 14px; |
| | | margin-right: 16px; |
| | | width: 14px; |
| | | } |
| | | ::v-deep .el-submenu__icon-arrow { |
| | | color: #fff; |
| | | } |
| | | .el-menu-item { |
| | | @for $i from 2 through 4 { |
| | | &.el-bus-level-#{$i} { |
| | | padding-left: 20px * $i + 24px !important; |
| | | } |
| | | } |
| | | } |
| | | .el-menu { |
| | | @for $i from 2 through 4 { |
| | | &:has(.el-submenu.el-bus-level-#{$i}) { |
| | | .el-menu-item { |
| | | &.el-bus-level-#{$i} { |
| | | padding-left: 20px * $i !important; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | ::v-deep .scrollbar-wrapper { |
| | | overflow-x: hidden !important; |
| | | } |
| | | } |
| | | &.is-hide { |
| | | width: 54px !important; |
| | | ::v-deep .el-menu { |
| | | .el-submenu { |
| | | overflow: hidden; |
| | | .el-submenu__icon-arrow { |
| | | display: none; |
| | | } |
| | | } |
| | | } |
| | | .cubebase-sidebar-comp__top { |
| | | &__logo { |
| | | margin-bottom: 0; |
| | | } |
| | | } |
| | | } |
| | | &.is-mobile { |
| | | position: fixed; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | &.is-hide { |
| | | width: 0 !important; |
| | | } |
| | | } |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <div class="cascader-filter"> |
| | | <div v-for="(item, index) in radioList" :key="index"> |
| | | <el-bus-radio |
| | | :from-dict="false" |
| | | :options="item" |
| | | :props="mProps" |
| | | :value="currentValue[index] || ''" |
| | | v-bind="$attrs" |
| | | @change="onRadioChange($event, index)" |
| | | ></el-bus-radio> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import cacheStorage from 'el-business-cache-utils' |
| | | import utils from 'el-business-utils' |
| | | import _get from 'lodash.get' |
| | | |
| | | export default { |
| | | inheritAttrs: false, |
| | | props: { |
| | | value: { |
| | | type: [Array, String, Number], |
| | | default() { |
| | | return this.emitPath ? [] : null |
| | | }, |
| | | }, |
| | | emitPath: { |
| | | type: Boolean, |
| | | default: true, |
| | | }, |
| | | props: Object, |
| | | interfaceUri: { |
| | | type: String, |
| | | default: '', |
| | | }, |
| | | otherInterfaceUri: { |
| | | type: String, |
| | | default: '', |
| | | }, |
| | | extraQuery: { |
| | | type: Object, |
| | | default: null, |
| | | }, |
| | | code: { |
| | | type: String, |
| | | }, |
| | | codeOnPath: { |
| | | type: Boolean, |
| | | default() { |
| | | return utils.isTrueEmpty(this?.$ELBUSINESS?.dictCodeOnPath) |
| | | ? false |
| | | : this?.$ELBUSINESS?.dictCodeOnPath |
| | | }, |
| | | }, |
| | | codeRequestKey: { |
| | | type: String, |
| | | default() { |
| | | return this?.$ELBUSINESS?.dictCodeRequestKey || 'type' |
| | | }, |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | options: [], |
| | | } |
| | | }, |
| | | computed: { |
| | | mProps() { |
| | | const DEFAULT_PROPS = { |
| | | label: 'label', |
| | | value: 'value', |
| | | allLabel: '不限', |
| | | allValue: '', |
| | | dataPath: '', |
| | | } |
| | | return Object.assign( |
| | | {}, |
| | | DEFAULT_PROPS, |
| | | this.$ELBUSINESS?.radioProps, |
| | | this.props |
| | | ) |
| | | }, |
| | | mInterfaceUri() { |
| | | return ( |
| | | this.interfaceUri || |
| | | this.$ELBUSINESS?.dictInterfaceUri || |
| | | 'wxkj/code/value' |
| | | ) |
| | | }, |
| | | currentValue() { |
| | | return this.emitPath ? this.value : this.getArrayValue(this.value) |
| | | }, |
| | | radioList() { |
| | | if (Array.isArray(this.options) && this.options.length > 0) { |
| | | const list = [this.options] |
| | | let mList = this.options |
| | | if (Array.isArray(this.currentValue) && this.currentValue.length > 0) { |
| | | this.currentValue.forEach((item) => { |
| | | const child = mList.find((i) => i[this.mProps.value] === item) |
| | | if ( |
| | | child && |
| | | Array.isArray(child.children) && |
| | | child.children.length > 0 |
| | | ) { |
| | | list.push(child.children) |
| | | mList = child.children |
| | | } |
| | | }) |
| | | } |
| | | return list |
| | | } |
| | | return [] |
| | | }, |
| | | }, |
| | | mounted() { |
| | | if (this.otherInterfaceUri) { |
| | | this.getOtherOptions() |
| | | } else if (this.code) { |
| | | this.getOptionList() |
| | | } |
| | | }, |
| | | methods: { |
| | | async getOptionList() { |
| | | if (this.$ELBUSINESS?.enableCache) { |
| | | const list = cacheStorage.getItem(this.code) |
| | | if (Array.isArray(list)) { |
| | | this.options = list |
| | | this.$emit('optionsChange', this.options) |
| | | return |
| | | } |
| | | } |
| | | const requestUrl = this.codeOnPath |
| | | ? utils.joinPath(this.mInterfaceUri, this.code) |
| | | : this.mInterfaceUri |
| | | const { code, data } = await this.$elBusHttp.request(requestUrl, { |
| | | params: this.codeOnPath |
| | | ? undefined |
| | | : { [this.codeRequestKey]: this.code }, |
| | | }) |
| | | if (code === 0) { |
| | | if (this.$ELBUSINESS?.enableCache) { |
| | | if (Array.isArray(data)) { |
| | | cacheStorage.setItem(this.code, data) |
| | | } |
| | | } |
| | | this.options = data || [] |
| | | this.$emit('optionsChange', this.options) |
| | | } else { |
| | | console.warn('can not get option list') |
| | | } |
| | | }, |
| | | async getOtherOptions() { |
| | | const params = Object.assign({}, this.extraQuery) |
| | | const { code, data } = await this.$elBusHttp.request( |
| | | this.otherInterfaceUri, |
| | | { |
| | | params, |
| | | } |
| | | ) |
| | | if (code === 0) { |
| | | if (this.mProps.dataPath) { |
| | | this.options = _get(data || [], this.mProps.dataPath) |
| | | } else { |
| | | this.options = data || [] |
| | | } |
| | | this.$emit('optionsChange', this.options) |
| | | } |
| | | }, |
| | | getArrayValue(value) { |
| | | const list = this.tree2List(this.options) |
| | | const deepValue = (v) => { |
| | | if (v) { |
| | | const current = list.find((i) => i[this.mProps.value] === v) |
| | | return [].concat(v, deepValue(current.parentId)) |
| | | } |
| | | return [] |
| | | } |
| | | if (Array.isArray(this.options) && this.options.length > 0) { |
| | | return deepValue(value).reverse() |
| | | } |
| | | return [] |
| | | }, |
| | | tree2List(tree) { |
| | | const toList = (arr, parentId = null) => { |
| | | if (Array.isArray(arr)) |
| | | return Array.prototype.concat.apply( |
| | | [], |
| | | arr.map((i) => toList(i)) |
| | | ) |
| | | else if (Reflect.has(arr, 'children')) |
| | | return [ |
| | | arr, |
| | | ...toList( |
| | | arr.children.map((i) => ({ |
| | | ...i, |
| | | parentId: arr[this.mProps.value], |
| | | })) |
| | | ), |
| | | ] |
| | | return [arr] |
| | | } |
| | | return toList(tree) |
| | | }, |
| | | onRadioChange(e, index) { |
| | | const value = this.currentValue.slice(0, index) |
| | | if (e !== this.mProps.allValue) { |
| | | value.push(e) |
| | | } |
| | | const emitPath = this.emitPath |
| | | if (emitPath) { |
| | | this.$emit('input', value) |
| | | this.$emit('change', value) |
| | | } else { |
| | | const emitValue = value.length > 0 ? value.pop() : '' |
| | | this.$emit('input', emitValue) |
| | | this.$emit('change', emitValue) |
| | | } |
| | | }, |
| | | }, |
| | | } |
| | | </script> |
对比新文件 |
| | |
| | | <template> |
| | | <el-card class="content-wrapper"> |
| | | <div slot="header" class="content-wrapper__header"> |
| | | <div class="content-wrapper__header__title">{{ title }}</div> |
| | | <slot name="header-right"></slot> |
| | | </div> |
| | | <slot></slot> |
| | | </el-card> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | props: { |
| | | title: { |
| | | type: String, |
| | | default: '', |
| | | }, |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .content-wrapper { |
| | | &__header { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | &__title { |
| | | font-size: $font-size-lg; |
| | | color: $main-title-color; |
| | | font-weight: 500; |
| | | line-height: 2; |
| | | } |
| | | } |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <div class="member-rule"> |
| | | <div class="mr-8">消费</div> |
| | | <el-input-number |
| | | v-model="amountValue" |
| | | v-bind="inputAttrs" |
| | | @input="onAmountChange" |
| | | ></el-input-number> |
| | | <div class="mx-8">元等于</div> |
| | | <el-input-number |
| | | v-model="growthValue" |
| | | v-bind="inputAttrs" |
| | | @input="onGrowthChange" |
| | | ></el-input-number> |
| | | <div class="ml-8">成长值</div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import { t } from 'el-business' |
| | | import utils from 'el-business-utils' |
| | | |
| | | export default { |
| | | props: { |
| | | value: { |
| | | type: Array, |
| | | default: () => [], |
| | | }, |
| | | }, |
| | | rules(item) { |
| | | const errorMsg = `${t('elBus.common.pleaseEnter')}${ |
| | | item.label ? item.label.replace(/:/g, '').replace(/:/g, '') : '' |
| | | }` |
| | | return [ |
| | | { |
| | | required: true, |
| | | message: errorMsg, |
| | | }, |
| | | { |
| | | validator: (rule, value, callback) => { |
| | | if ( |
| | | Array.isArray(value) && |
| | | value.filter((i) => !utils.isTrueEmpty(i)).length === 2 |
| | | ) { |
| | | callback() |
| | | } else { |
| | | callback(new Error(errorMsg)) |
| | | } |
| | | }, |
| | | }, |
| | | ] |
| | | }, |
| | | inputFormat(row, item) { |
| | | if ( |
| | | Array.isArray(item.commonFormatProps) && |
| | | item.commonFormatProps.length === 2 |
| | | ) { |
| | | const amount = item.commonFormatProps[0] |
| | | const growth = item.commonFormatProps[1] |
| | | if (amount in row || growth in row) { |
| | | return [row[amount], row[growth]] |
| | | } |
| | | } else { |
| | | console.warn('please set commonFormatProps') |
| | | } |
| | | }, |
| | | outputFormat(val, item) { |
| | | if ( |
| | | Array.isArray(item.commonFormatProps) && |
| | | item.commonFormatProps.length === 2 |
| | | ) { |
| | | const amount = item.commonFormatProps[0] |
| | | const growth = item.commonFormatProps[1] |
| | | return { |
| | | [amount]: !utils.isTrueEmpty(val?.[0]) ? val[0] : null, |
| | | [growth]: !utils.isTrueEmpty(val?.[1]) ? val[1] : null, |
| | | } |
| | | } else { |
| | | console.warn('please set commonFormatProps') |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | amountValue: null, |
| | | growthValue: null, |
| | | inputAttrs: { |
| | | precision: 0, |
| | | min: 1, |
| | | max: 99999999, |
| | | controls: false, |
| | | }, |
| | | } |
| | | }, |
| | | watch: { |
| | | value: { |
| | | immediate: true, |
| | | handler(value) { |
| | | value = value || [] |
| | | this.amountValue = value?.[0] || undefined |
| | | this.growthValue = value?.[1] || undefined |
| | | }, |
| | | }, |
| | | }, |
| | | methods: { |
| | | onAmountChange(e) { |
| | | const value = [e, this.growthValue] |
| | | this.emitValue(value) |
| | | }, |
| | | onGrowthChange(e) { |
| | | const value = [this.amountValue, e] |
| | | this.emitValue(value) |
| | | }, |
| | | emitValue(value) { |
| | | this.$emit('input', value) |
| | | this.$emit('change', value) |
| | | }, |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .member-rule { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <div class="select-shop-user"> |
| | | <el-button v-if="!disabled" type="primary" @click="chooseUser" |
| | | >指定用户</el-button |
| | | > |
| | | <el-table v-if="value && value.length > 0" :data="value"> |
| | | <el-table-column label="id" prop="id"></el-table-column> |
| | | <el-table-column label="店铺名称" prop="name"></el-table-column> |
| | | <el-table-column label="联系方式" prop="tel"></el-table-column> |
| | | <el-table-column v-if="!disabled" label="操作"> |
| | | <template #default="{ $index }"> |
| | | <text-button type="danger" @click="deleteUser($index)" |
| | | >删除</text-button |
| | | > |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <el-dialog |
| | | :visible.sync="dialogVisible" |
| | | title="指定用户" |
| | | append-to-body |
| | | :close-on-click-modal="false" |
| | | custom-class="shop-user-dialog" |
| | | width="80%" |
| | | > |
| | | <div class="dialog-container"> |
| | | <div class="dialog-container__list"> |
| | | <el-bus-crud v-bind="tableConfig" /> |
| | | </div> |
| | | <div class="dialog-container__selected"> |
| | | <el-bus-title title="已添加用户" size="mini" /> |
| | | <el-tag |
| | | v-for="(tag, i) in currentValue" |
| | | :key="tag.id" |
| | | closable |
| | | @close="deleteCurrentUser(i)" |
| | | >{{ tag.name }}</el-tag |
| | | > |
| | | </div> |
| | | </div> |
| | | <div slot="footer"> |
| | | <el-button @click="cancel">取消</el-button> |
| | | <el-button type="primary" @click="confirm">确定</el-button> |
| | | </div> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import cloneDeep from 'lodash.clonedeep' |
| | | export default { |
| | | props: { |
| | | value: { |
| | | type: Array, |
| | | default: () => [], |
| | | }, |
| | | disabled: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | dialogVisible: false, |
| | | currentValue: [], |
| | | tableConfig: { |
| | | url: 'flower/api/customer/page', |
| | | saveQuery: false, |
| | | hasNew: false, |
| | | hasEdit: false, |
| | | hasDelete: false, |
| | | hasView: false, |
| | | columns: [ |
| | | { label: 'id', prop: 'id' }, |
| | | { label: '店铺名称', prop: 'name' }, |
| | | { label: '联系方式', prop: 'tel' }, |
| | | ], |
| | | extraButtons: [ |
| | | { |
| | | text: '选择', |
| | | show: (row) => |
| | | !this.currentValue.find((item) => item.id === row.id), |
| | | atClick: (row) => { |
| | | this.currentValue.push({ |
| | | id: row.id, |
| | | name: row.name, |
| | | tel: row.tel, |
| | | }) |
| | | return false |
| | | }, |
| | | }, |
| | | { |
| | | text: '取消选择', |
| | | show: (row) => this.currentValue.find((item) => item.id === row.id), |
| | | atClick: (row) => { |
| | | const index = this.currentValue.findIndex( |
| | | (item) => item.id === row.id |
| | | ) |
| | | this.currentValue.splice(index, 1) |
| | | return false |
| | | }, |
| | | }, |
| | | ], |
| | | searchFormAttrs: { |
| | | labelWidth: 'auto', |
| | | }, |
| | | searchForm: [ |
| | | { |
| | | type: 'row', |
| | | span: 12, |
| | | items: [ |
| | | { label: 'id:', id: 'id', type: 'input' }, |
| | | { label: '店铺名称:', id: 'name', type: 'input' }, |
| | | { label: '联系方式:', id: 'tel', type: 'input' }, |
| | | ], |
| | | }, |
| | | ], |
| | | }, |
| | | } |
| | | }, |
| | | watch: { |
| | | value: { |
| | | immediate: true, |
| | | handler(value) { |
| | | this.currentValue = cloneDeep(value || []) |
| | | }, |
| | | }, |
| | | }, |
| | | methods: { |
| | | chooseUser() { |
| | | this.currentValue = cloneDeep(this.value || []) |
| | | this.dialogVisible = true |
| | | }, |
| | | deleteCurrentUser(i) { |
| | | this.currentValue.splice(i, 1) |
| | | }, |
| | | deleteUser(i) { |
| | | this.$elBusUtil |
| | | .confirm('确定要删除吗?') |
| | | .then(() => { |
| | | const userList = cloneDeep(this.value || []) |
| | | userList.splice(i, 1) |
| | | this.$emit('input', userList) |
| | | this.$emit('change', userList) |
| | | }) |
| | | .catch(() => {}) |
| | | }, |
| | | confirm() { |
| | | this.$emit('input', this.currentValue) |
| | | this.$emit('change', this.currentValue) |
| | | this.dialogVisible = false |
| | | }, |
| | | cancel() { |
| | | this.dialogVisible = false |
| | | }, |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .select-shop-user { |
| | | } |
| | | </style> |
| | | <style lang="scss"> |
| | | .shop-user-dialog { |
| | | .dialog-container { |
| | | display: flex; |
| | | align-items: flex-start; |
| | | &__list { |
| | | flex: 1; |
| | | border-right: 1px solid #eee; |
| | | height: 100%; |
| | | } |
| | | &__selected { |
| | | width: 40%; |
| | | height: 100%; |
| | | padding: 24px; |
| | | .el-bus-title { |
| | | margin-bottom: 15px; |
| | | } |
| | | .el-tag { |
| | | margin-right: 6px; |
| | | margin-bottom: 6px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <script> |
| | | import dayjs from 'dayjs' |
| | | import 'dayjs/locale/zh-cn' |
| | | dayjs.locale('zh-cn') |
| | | export default { |
| | | inputFormat(row, item) { |
| | | if ( |
| | | Array.isArray(item.commonFormatProps) && |
| | | item.commonFormatProps.length === 3 |
| | | ) { |
| | | const dateType = item.commonFormatProps[0] |
| | | const startDate = item.commonFormatProps[1] |
| | | const endDate = item.commonFormatProps[2] |
| | | if (dateType in row || startDate in row || endDate in row) { |
| | | const dateValue = |
| | | !row[startDate] && !row[endDate] ? [] : [row[startDate], row[endDate]] |
| | | return !row[dateType] && dateValue.length === 0 |
| | | ? [] |
| | | : [row[dateType], dateValue] |
| | | } |
| | | } |
| | | }, |
| | | outputFormat(val, item) { |
| | | if ( |
| | | Array.isArray(item.commonFormatProps) && |
| | | item.commonFormatProps.length === 3 |
| | | ) { |
| | | const dateValue = val?.[1] || [] |
| | | const radioValue = val?.[0] || '' |
| | | return { |
| | | [item.commonFormatProps[0]]: radioValue, |
| | | [item.commonFormatProps[1]]: dateValue?.[0] || '', |
| | | [item.commonFormatProps[2]]: dateValue?.[1] || '', |
| | | } |
| | | } |
| | | }, |
| | | props: { |
| | | value: { |
| | | type: Array, |
| | | default: () => [], |
| | | }, |
| | | options: { |
| | | type: Array, |
| | | default: () => [], |
| | | }, |
| | | radioAttrs: { |
| | | type: Object, |
| | | default: () => ({}), |
| | | }, |
| | | dateRangeAttrs: { |
| | | type: Object, |
| | | default: () => ({}), |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | radioValue: '', |
| | | dateRangeValue: [], |
| | | } |
| | | }, |
| | | watch: { |
| | | value: { |
| | | immediate: true, |
| | | handler(value) { |
| | | this.radioValue = value?.[0] || '' |
| | | this.dateRangeValue = value?.[1] || [] |
| | | }, |
| | | }, |
| | | }, |
| | | methods: { |
| | | onRadioChange(e) { |
| | | if (!e) { |
| | | this.emitValue([]) |
| | | } else if (e === 'custom') { |
| | | this.emitValue(['custom']) |
| | | } else if (typeof e === 'string') { |
| | | if (!e.includes(',')) { |
| | | if (e === 'yesterday') { |
| | | const yesterday = dayjs().subtract(1, 'day').format('YYYY-MM-DD') |
| | | this.emitValue([e, [yesterday, yesterday]]) |
| | | } else { |
| | | const startDate = dayjs().startOf(e).format('YYYY-MM-DD') |
| | | const endDate = dayjs().format('YYYY-MM-DD') |
| | | this.emitValue([e, [startDate, endDate]]) |
| | | } |
| | | } else { |
| | | const arr = e.split(',') |
| | | const num = arr[0] |
| | | let funcName = '' |
| | | if (e > 0) { |
| | | funcName = 'add' |
| | | } else { |
| | | funcName = 'subtract' |
| | | } |
| | | const startDate = dayjs() |
| | | [funcName](Math.abs(num), arr[1]) |
| | | .format('YYYY-MM-DD') |
| | | const endDate = dayjs().format('YYYY-MM-DD') |
| | | this.emitValue([e, [startDate, endDate]]) |
| | | } |
| | | } |
| | | }, |
| | | onDateRangeChange(e) { |
| | | this.emitValue(['custom', e]) |
| | | }, |
| | | emitValue(value) { |
| | | this.$emit('input', value) |
| | | this.$emit('change', value) |
| | | }, |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <template> |
| | | <div class="custom-date-range"> |
| | | <el-bus-radio |
| | | v-bind="{ childType: 'el-radio-button', hasAll: true, ...radioAttrs }" |
| | | v-model="radioValue" |
| | | :from-dict="false" |
| | | :options="options" |
| | | @change="onRadioChange" |
| | | /> |
| | | <el-bus-date-range |
| | | v-bind="{ canOverToday: false, ...dateRangeAttrs }" |
| | | v-model="dateRangeValue" |
| | | @change="onDateRangeChange" |
| | | /> |
| | | </div> |
| | | </template> |
| | | |
| | | <style lang="scss" scoped> |
| | | .custom-date-range { |
| | | display: flex; |
| | | align-items: center; |
| | | .el-bus-date-range { |
| | | margin-bottom: 10px; |
| | | margin-left: 15px; |
| | | } |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <el-breadcrumb class="el-ext-breadcrumb" v-bind="$attrs"> |
| | | <el-breadcrumb-item v-for="(item, index) in levelList" :key="index"> |
| | | <span v-if="index == levelList.length - 1">{{ item.title }}</span> |
| | | <a v-else @click.prevent="handleLink(item)">{{ item.title }}</a> |
| | | </el-breadcrumb-item> |
| | | </el-breadcrumb> |
| | | </template> |
| | | |
| | | <script> |
| | | const { compile } = require('path-to-regexp') |
| | | |
| | | export default { |
| | | name: 'ElExtBreadcrumb', |
| | | props: { |
| | | menus: { |
| | | type: Array, |
| | | default: () => [], |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | levelList: [], |
| | | } |
| | | }, |
| | | watch: { |
| | | $route() { |
| | | this.getBreadcrumb() |
| | | }, |
| | | }, |
| | | mounted() { |
| | | this.getBreadcrumb() |
| | | }, |
| | | methods: { |
| | | getBreadcrumb() { |
| | | const timer = setTimeout(() => { |
| | | const levelList = [] |
| | | const { params } = this.$route |
| | | this.$route.matched.forEach((route) => { |
| | | if ( |
| | | route.instances.default && |
| | | route.instances.default.$metaInfo && |
| | | route.instances.default.$metaInfo.title |
| | | ) { |
| | | const toPath = compile(route.path) |
| | | levelList.push({ |
| | | title: route.instances.default.$metaInfo.title, |
| | | path: toPath(params), |
| | | }) |
| | | } |
| | | }) |
| | | this.levelList = levelList |
| | | clearTimeout(timer) |
| | | }, 100) |
| | | }, |
| | | handleLink(item) { |
| | | const mPath = item.path |
| | | const firstChild = this.findFirstChild(mPath, this.menus) |
| | | this.$router.push(firstChild) |
| | | }, |
| | | findFirstChild(mPath, routes) { |
| | | let firstChild = mPath |
| | | if (!routes) { |
| | | return firstChild |
| | | } |
| | | for (const route of routes) { |
| | | if (route.fullPath === mPath) { |
| | | if (route.children && route.children.length > 0) { |
| | | return this.getLeafChild(route.children) |
| | | } else { |
| | | return mPath |
| | | } |
| | | } else if (route.children && route.children.length > 0) { |
| | | firstChild = this.findFirstChild(mPath, route.children) |
| | | } |
| | | } |
| | | return firstChild |
| | | }, |
| | | getLeafChild(array) { |
| | | const first = array[0] |
| | | if (first.children && first.children.length > 0) { |
| | | return this.getLeafChild(first.children) |
| | | } else { |
| | | return first.fullPath |
| | | } |
| | | }, |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style scoped lang="scss"></style> |
对比新文件 |
| | |
| | | <script> |
| | | import { Table } from 'element-ui' |
| | | export default { |
| | | extends: Table, |
| | | mounted() { |
| | | this.$nextTick(function () { |
| | | const thead = this.$el.querySelector('.el-table__header-wrapper thead') |
| | | const theadNew = thead.cloneNode(true) |
| | | this.$el |
| | | .querySelector('.el-table__body-wrapper table') |
| | | .appendChild(theadNew) |
| | | }) |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | ::v-deep { |
| | | .el-table { |
| | | &__body-wrapper thead { |
| | | display: none; |
| | | } |
| | | } |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <el-table :data="currentValue" border> |
| | | <el-table-column |
| | | label="参数名称" |
| | | prop="name" |
| | | width="120px" |
| | | ></el-table-column> |
| | | <el-table-column label="参数名称"> |
| | | <template #default="{ row }"> |
| | | <div v-if="disabled">{{ row.value }}</div> |
| | | <el-input v-else v-model="row.value" @change="onInputChange"></el-input> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | props: { |
| | | value: { |
| | | type: Array, |
| | | default: () => [], |
| | | }, |
| | | disabled: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | currentValue: [], |
| | | } |
| | | }, |
| | | watch: { |
| | | value: { |
| | | immediate: true, |
| | | handler(value) { |
| | | this.currentValue = (value || []).map((item) => { |
| | | if (!item.value) { |
| | | item.value = (item.values || []).join(',') |
| | | } |
| | | return item |
| | | }) |
| | | }, |
| | | }, |
| | | }, |
| | | methods: { |
| | | onInputChange() { |
| | | this.$emit('input', this.currentValue) |
| | | this.$emit('change', this.currentValue) |
| | | }, |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .goods-params { |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <div class="input-select"> |
| | | <el-input-number |
| | | v-model="inputValue" |
| | | v-bind="inputAttrs" |
| | | class="input-select__input" |
| | | @input="onInputChange" |
| | | /> |
| | | <el-bus-select-dict |
| | | v-model="selectValue" |
| | | v-bind="selectAttrs" |
| | | class="input-select__select" |
| | | @change="onSelectChange" |
| | | /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import { t } from 'el-business' |
| | | import utils from 'el-business-utils' |
| | | export default { |
| | | props: { |
| | | value: { |
| | | type: Array, |
| | | default: () => [], |
| | | }, |
| | | inputAttrs: { |
| | | type: Object, |
| | | default: () => ({}), |
| | | }, |
| | | selectAttrs: { |
| | | type: Object, |
| | | default: () => ({}), |
| | | }, |
| | | }, |
| | | rules(item) { |
| | | const errorMsg = `${t('elBus.common.pleaseEnter')}${ |
| | | item.label ? item.label.replace(/:/g, '').replace(/:/g, '') : '' |
| | | }` |
| | | return [ |
| | | { |
| | | required: true, |
| | | message: errorMsg, |
| | | }, |
| | | { |
| | | validator: (rule, value, callback) => { |
| | | if ( |
| | | Array.isArray(value) && |
| | | value.filter((i) => !utils.isTrueEmpty(i)).length === 2 |
| | | ) { |
| | | callback() |
| | | } else { |
| | | callback(new Error(errorMsg)) |
| | | } |
| | | }, |
| | | }, |
| | | ] |
| | | }, |
| | | inputFormat(row, item) { |
| | | if ( |
| | | Array.isArray(item.commonFormatProps) && |
| | | item.commonFormatProps.length === 2 |
| | | ) { |
| | | const input = item.commonFormatProps[0] |
| | | const select = item.commonFormatProps[1] |
| | | if (select in row || input in row) { |
| | | return [row[input], row[select]] |
| | | } |
| | | } else { |
| | | console.warn('please set commonFormatProps') |
| | | } |
| | | }, |
| | | outputFormat(val, item) { |
| | | if ( |
| | | Array.isArray(item.commonFormatProps) && |
| | | item.commonFormatProps.length === 2 |
| | | ) { |
| | | const input = item.commonFormatProps[0] |
| | | const select = item.commonFormatProps[1] |
| | | return { |
| | | [input]: !utils.isTrueEmpty(val?.[0]) ? val[0] : null, |
| | | [select]: !utils.isTrueEmpty(val?.[1]) ? val[1] : null, |
| | | } |
| | | } else { |
| | | console.warn('please set commonFormatProps') |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | inputValue: null, |
| | | selectValue: null, |
| | | } |
| | | }, |
| | | watch: { |
| | | value: { |
| | | immediate: true, |
| | | handler(value) { |
| | | value = value || [] |
| | | this.inputValue = value?.[0] || undefined |
| | | this.selectValue = value?.[1] || null |
| | | }, |
| | | }, |
| | | }, |
| | | methods: { |
| | | onInputChange(e) { |
| | | const value = [e, this.selectValue] |
| | | this.emitValue(value) |
| | | }, |
| | | onSelectChange(e) { |
| | | const value = [this.inputValue, e] |
| | | this.emitValue(value) |
| | | }, |
| | | emitValue(value) { |
| | | this.$emit('input', value) |
| | | this.$emit('change', value) |
| | | }, |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .input-select { |
| | | display: flex; |
| | | align-items: center; |
| | | &__input { |
| | | margin-right: 8px; |
| | | } |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <el-table :data="currentValue"> |
| | | <el-table-column |
| | | label="商品名称" |
| | | prop="flowerName" |
| | | min-width="100" |
| | | fixed="left" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | label="商品分类" |
| | | prop="flowerCategory" |
| | | min-width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | label="级别" |
| | | prop="flowerLevelStr" |
| | | min-width="80" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | label="颜色" |
| | | prop="flowerColor" |
| | | min-width="80" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | label="规格" |
| | | prop="flowerUnit" |
| | | min-width="100" |
| | | ></el-table-column> |
| | | <el-table-column label="数量" prop="num" min-width="100"></el-table-column> |
| | | <el-table-column |
| | | label="单价" |
| | | prop="price" |
| | | min-width="100" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | label="供应商" |
| | | prop="supplierName" |
| | | min-width="120" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | label="判断责任方" |
| | | prop="personInCharge" |
| | | min-width="120" |
| | | fixed="right" |
| | | > |
| | | <template #default="{ row }"> |
| | | <el-bus-select-dict |
| | | v-if="!disabled" |
| | | v-model="row.personInCharge" |
| | | code="CHARGE_PERSON" |
| | | clearable |
| | | @change="onFormUpdate" |
| | | ></el-bus-select-dict> |
| | | <div v-else>{{ row.personInChargeStr }}</div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="赔付金额(元)" |
| | | prop="amount" |
| | | min-width="120" |
| | | fixed="right" |
| | | > |
| | | <template #default="{ row }"> |
| | | <el-input-number |
| | | v-if="!disabled" |
| | | v-model="row.amount" |
| | | :precision="2" |
| | | :min="0" |
| | | :controls="false" |
| | | style="width: 100%" |
| | | @change="onFormUpdate" |
| | | ></el-input-number> |
| | | <div v-else>{{ row.amount }}</div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="备注" prop="remarks" min-width="250" fixed="right"> |
| | | <template #default="{ row }"> |
| | | <el-input |
| | | v-if="!disabled" |
| | | v-model="row.remarks" |
| | | @change="onFormUpdate" |
| | | ></el-input> |
| | | <div v-else>{{ row.remarks }}</div> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | props: { |
| | | value: { |
| | | type: Array, |
| | | default: () => [], |
| | | }, |
| | | disabled: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | currentValue: [], |
| | | } |
| | | }, |
| | | watch: { |
| | | value: { |
| | | immediate: true, |
| | | handler(value) { |
| | | this.currentValue = value || [] |
| | | }, |
| | | }, |
| | | }, |
| | | methods: { |
| | | onFormUpdate() { |
| | | this.$emit('input', this.currentValue) |
| | | this.$emit('change', this.currentValue) |
| | | }, |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .after-sale-items { |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <div class="after-sale-table"> |
| | | <div class="table-header"> |
| | | <div class="table-th">商品信息</div> |
| | | <div class="table-th">合计详情</div> |
| | | <div class="table-th !flex-none w-120">供应商信息</div> |
| | | <div class="table-th">收货人信息</div> |
| | | <div class="table-th !flex-none w-180">操作</div> |
| | | </div> |
| | | <div v-for="item in list" :key="item.id" class="table-item"> |
| | | <div class="table-item__title"> |
| | | <span class="font-bold">订单号:{{ item.orderNo }}</span> |
| | | <span class="font-bold">售后单号:{{ item.salesNo }}</span> |
| | | <span>申请时间:{{ item.createTime }}</span> |
| | | <span |
| | | >售后状态:<span |
| | | :class="{ 'text-primary': item.status === 'PENDING' }" |
| | | >{{ item.statusStr }}</span |
| | | ></span |
| | | > |
| | | <el-tag v-if="item.title" type="danger" size="mini" class="ml-4" |
| | | >第二次售后</el-tag |
| | | > |
| | | </div> |
| | | <div class="table-body"> |
| | | <div class="table-td"> |
| | | <div class="flex"> |
| | | <el-bus-image :src="item.flowerCover" class="w-60 h-60 mr-8" /> |
| | | <div class="leading-20"> |
| | | <div class="text-14 font-bold"> |
| | | {{ item.flowerName }} × {{ item.flowerNum }} |
| | | </div> |
| | | <div class="leading-20"> |
| | | <span>等级:{{ item.flowerLevelStr }}</span> |
| | | <span class="ml-8">颜色:{{ item.flowerColor }}</span> |
| | | </div> |
| | | <div class="leading-20"> |
| | | <span>单价:¥{{ item.price }}</span> |
| | | <span class="ml-8">订单总额:¥{{ item.total }}</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="table-td"> |
| | | <div class="leading-20">申请数量:{{ item.num }}</div> |
| | | <div class="leading-20">实际退款:{{ item.totalFee }}</div> |
| | | <div class="leading-20 flex"> |
| | | 售后类别: |
| | | <div class="flex-1 text-overflow-2 w-0 break-all"> |
| | | {{ item.salesTypeStr }} |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="table-td !flex-none w-120 flex items-center"> |
| | | {{ item.supplierName }} |
| | | </div> |
| | | <div class="table-td"> |
| | | <div class="leading-20">姓名:{{ item.customer }}</div> |
| | | <div class="leading-20">联系方式:{{ item.customerTel }}</div> |
| | | <div class="leading-20 flex"> |
| | | 用户地址: |
| | | <div class="flex-1 w-0"> |
| | | {{ item.customerProvince }}{{ item.customerCity |
| | | }}{{ item.customerRegion }}{{ item.customerAddress }} |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="table-td !flex-none w-180 flex items-center"> |
| | | <el-button type="text" @click="onDetail(item)">查看详情</el-button> |
| | | <el-button |
| | | v-if="item.status === 'PENDING'" |
| | | type="text" |
| | | @click="onHandle(item)" |
| | | >售后处理</el-button |
| | | > |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | props: { |
| | | list: { |
| | | type: Array, |
| | | default: () => [], |
| | | }, |
| | | }, |
| | | methods: { |
| | | onDetail(item) { |
| | | this.$emit('detail', item) |
| | | }, |
| | | onHandle(item) { |
| | | this.$emit('handle', item) |
| | | }, |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .after-sale-table { |
| | | .table-header { |
| | | display: flex; |
| | | align-items: center; |
| | | font-size: 14px; |
| | | color: $main-title-color; |
| | | background-color: #f4f4f5; |
| | | .table-th { |
| | | flex: 1; |
| | | height: 45px; |
| | | line-height: 45px; |
| | | padding: 0 10px; |
| | | font-weight: bold; |
| | | } |
| | | } |
| | | .table-item { |
| | | margin-top: 10px; |
| | | border-bottom: 1px solid #eee; |
| | | &__title { |
| | | height: 35px; |
| | | line-height: 35px; |
| | | background-color: #f4f4f5; |
| | | font-size: 14px; |
| | | color: $main-title-color; |
| | | padding: 0 10px; |
| | | & > span { |
| | | margin-right: 10px; |
| | | } |
| | | } |
| | | .table-body { |
| | | display: flex; |
| | | align-items: stretch; |
| | | font-size: 12px; |
| | | color: $main-title-color; |
| | | .table-td { |
| | | flex: 1; |
| | | padding: 15px 10px; |
| | | &:not(:last-child) { |
| | | border-right: 1px solid #eee; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <el-table :data="value"> |
| | | <el-table-column |
| | | label="商品名称" |
| | | prop="flowerName" |
| | | min-width="150" |
| | | fixed="left" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | label="级别" |
| | | prop="flowerLevelStr" |
| | | min-width="100" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | label="规格" |
| | | prop="flowerUnit" |
| | | min-width="120" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | label="单价(元)" |
| | | prop="price" |
| | | min-width="120" |
| | | ></el-table-column> |
| | | <el-table-column label="数量" prop="num" min-width="120"></el-table-column> |
| | | <el-table-column |
| | | label="花材底价(元)" |
| | | prop="supplierPrice" |
| | | min-width="120" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | label="补货数量" |
| | | prop="replaceNum" |
| | | min-width="120" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | label="降级数量" |
| | | prop="reduceNum" |
| | | min-width="120" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | label="降级退款(元)" |
| | | prop="reduceAmount" |
| | | min-width="120" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | label="缺货数量" |
| | | prop="lackNum" |
| | | min-width="120" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | label="缺货退款(元)" |
| | | prop="lackAmount" |
| | | min-width="120" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | label="退款总计(元)" |
| | | prop="deductAmount" |
| | | min-width="150" |
| | | fixed="right" |
| | | ></el-table-column> |
| | | </el-table> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | props: { |
| | | value: { |
| | | type: Array, |
| | | default: () => [], |
| | | }, |
| | | }, |
| | | } |
| | | </script> |
对比新文件 |
| | |
| | | <template> |
| | | <div class="after-sale-table"> |
| | | <div class="table-header"> |
| | | <div class="table-th">商品名称</div> |
| | | <div class="table-th !flex-none w-220">订单编号</div> |
| | | <div class="table-th !flex-none w-120">评价星级</div> |
| | | <div class="table-th">供应商信息</div> |
| | | <div class="table-th">评价内容</div> |
| | | <div class="table-th !flex-none w-220">买家</div> |
| | | <div class="table-th !flex-none w-220">评价时间</div> |
| | | <div class="table-th !flex-none w-180">操作</div> |
| | | </div> |
| | | <div v-for="item in list" :key="item.id" class="table-item"> |
| | | <div class="table-body"> |
| | | <div class="table-td"> |
| | | <div class="flex"> |
| | | <el-bus-image :src="item.flowerCover" class="w-60 h-60 mr-8" /> |
| | | <div class="leading-20"> |
| | | <div class="text-14 font-bold"> |
| | | {{ item.flowerName }} |
| | | </div> |
| | | <div class="leading-20"> |
| | | <span>规格:{{ item.flowerUnit }}</span> |
| | | </div> |
| | | <div class="leading-20"> |
| | | <span>等级:{{ item.flowerLevel }}</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="table-td !flex-none w-220 flex items-center"> |
| | | <div class="leading-20">{{ item.orderNo }}</div> |
| | | </div> |
| | | <div class="table-td !flex-none w-120 flex items-center"> |
| | | <div class="leading-20" style="color: #3598db">{{item.commentGrade }}星</div> |
| | | </div> |
| | | <div class="table-td"> |
| | | <div class="leading-20">{{ item.supplierName }}[ID:{{ item.supplierId }}]</div> |
| | | </div> |
| | | |
| | | <div class="table-td"> |
| | | <div class="leading-20">{{ item.comment }}</div> |
| | | </div> |
| | | |
| | | <div class="table-td !flex-none w-220 flex items-center"> |
| | | <div class="leading-20"> |
| | | <div class="leading-20"> |
| | | <span>UID: {{ item.customerId }}</span> |
| | | </div> |
| | | <div class="leading-20"> |
| | | <span>昵称: {{ item.customerName }}</span> |
| | | </div> |
| | | |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="table-td !flex-none w-220 flex items-center"> |
| | | <div class="leading-20">{{ item.createTime }}</div> |
| | | </div> |
| | | |
| | | <div class="table-td !flex-none w-180 flex items-center"> |
| | | <el-button type="text" @click="onDetail(item)">查看</el-button> |
| | | <el-button v-if="item.showFlag == '1'" type="text" @click="onShow(item)" >显示</el-button> |
| | | <el-button v-if="item.showFlag == '0'" type="text" @click="onHide(item)" >隐藏</el-button> |
| | | <el-button type="text" @click="onHandle(item)" >回复</el-button> |
| | | <el-button type="text" @click="onDelete(item)" >删除</el-button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | props: { |
| | | list: { |
| | | type: Array, |
| | | default: () => [], |
| | | }, |
| | | }, |
| | | methods: { |
| | | onDetail(item) { |
| | | this.$emit('detail', item) |
| | | }, |
| | | onHandle(item) { |
| | | this.$emit('handle', item) |
| | | }, |
| | | onDelete(item) { |
| | | this.$emit('delete', item) |
| | | }, |
| | | onShow(item) { |
| | | this.$emit('show', item) |
| | | }, |
| | | onHide(item) { |
| | | this.$emit('hide', item) |
| | | }, |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .after-sale-table { |
| | | .table-header { |
| | | display: flex; |
| | | align-items: center; |
| | | font-size: 14px; |
| | | color: $main-title-color; |
| | | background-color: #f4f4f5; |
| | | .table-th { |
| | | flex: 1; |
| | | height: 45px; |
| | | line-height: 45px; |
| | | padding: 0 10px; |
| | | font-weight: bold; |
| | | } |
| | | } |
| | | .table-item { |
| | | margin-top: 10px; |
| | | border-bottom: 1px solid #eee; |
| | | &__title { |
| | | height: 35px; |
| | | line-height: 35px; |
| | | background-color: #f4f4f5; |
| | | font-size: 14px; |
| | | color: $main-title-color; |
| | | padding: 0 10px; |
| | | & > span { |
| | | margin-right: 10px; |
| | | } |
| | | } |
| | | .table-body { |
| | | display: flex; |
| | | align-items: stretch; |
| | | font-size: 12px; |
| | | color: $main-title-color; |
| | | .table-td { |
| | | flex: 1; |
| | | padding: 15px 10px; |
| | | &:not(:last-child) { |
| | | border-right: 1px solid #eee; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <div class="goods-table-item-list"> |
| | | <div v-for="(item, index) in showItems" :key="index">{{ item.str }}</div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | props: { |
| | | items: { |
| | | type: Array, |
| | | default: () => [], |
| | | }, |
| | | }, |
| | | computed: { |
| | | showItems() { |
| | | const list = this.items || [] |
| | | return list.map((item) => { |
| | | const str = [ |
| | | `${item.flowerName} · ${item.flowerColor}`, |
| | | item.flowerLevelStr, |
| | | item.flowerCategory, |
| | | item.flowerUnit, |
| | | item.supplierName, |
| | | `¥${item.price} × ${item.num}扎`, |
| | | ] |
| | | .filter((i) => !!i) |
| | | .join('|') |
| | | return { |
| | | str, |
| | | } |
| | | }) |
| | | }, |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .goods-table-item-list { |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <el-table :data="list"> |
| | | <el-table-column label="商品名称" prop="flowerName"></el-table-column> |
| | | <el-table-column label="商品等级" prop="flowerLevelStr"></el-table-column> |
| | | <el-table-column label="商品数量" prop="num"></el-table-column> |
| | | <el-table-column label="单价" prop="price"></el-table-column> |
| | | <el-table-column label="供应商名称" prop="supplierName"></el-table-column> |
| | | <el-table-column label="质检备注" prop="checkRemarks"></el-table-column> |
| | | </el-table> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | props: { |
| | | orderId: { |
| | | type: String, |
| | | default: null, |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | list: [], |
| | | } |
| | | }, |
| | | watch: { |
| | | orderId(value) { |
| | | if (value) { |
| | | this.getOrderItemList(value) |
| | | } |
| | | }, |
| | | }, |
| | | methods: { |
| | | async getOrderItemList(id) { |
| | | const { code, data } = await this.$elBusHttp.request( |
| | | 'flower/api/order/item/list', |
| | | { params: { id } } |
| | | ) |
| | | if (code === 0) { |
| | | this.list = (data || []).filter((i) => i.status === 'reduce') |
| | | } |
| | | }, |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .level-down-list { |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <div class="print-list"> |
| | | <div v-for="(item, i) in orderList" :key="i" class="break-page"> |
| | | <div ref="orderTable" class="print-item"> |
| | | <el-row :gutter="10" class="mb-15"> |
| | | <el-col :span="24"> |
| | | <div class="area-text"> |
| | | {{ item.warehouseName || '' }}/{{ |
| | | item.warehouseLocationCode || '' |
| | | }} |
| | | </div> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <div class="desc-info"> |
| | | <div>姓名:</div> |
| | | <div class="desc-info__value">{{ item.customer }}</div> |
| | | </div> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <div class="desc-info"> |
| | | <div>电话:</div> |
| | | <div class="desc-info__value">{{ item.customerTel }}</div> |
| | | </div> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <div class="desc-info"> |
| | | <div>收货地址:</div> |
| | | <div class="desc-info__value"> |
| | | {{ item.customerProvince }}{{ item.customerCity |
| | | }}{{ item.customerRegion }}{{ item.customerAddress }} |
| | | </div> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | <el-table-print |
| | | :data="item.items" |
| | | :summary-method="getSummaries.bind(this, item.totalAmount)" |
| | | show-summary |
| | | border |
| | | style="width: 100%" |
| | | > |
| | | <el-table-column label="序号" type="index"></el-table-column> |
| | | <el-table-column |
| | | prop="orderNo" |
| | | label="订单号" |
| | | align="center" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | label="下单品种" |
| | | :formatter=" |
| | | (row) => `${row.flowerName || ''} · ${row.flowerColor || ''}` |
| | | " |
| | | align="center" |
| | | > |
| | | </el-table-column> |
| | | <el-table-column prop="flowerLevelStr" label="等级" align="center"> |
| | | </el-table-column> |
| | | <el-table-column prop="num" label="数量" align="center"> |
| | | </el-table-column> |
| | | <el-table-column prop="flowerUnit" label="规格" align="center"> |
| | | </el-table-column> |
| | | <el-table-column |
| | | prop="supplierName" |
| | | label="供应商名称" |
| | | align="center" |
| | | > |
| | | </el-table-column> |
| | | <el-table-column prop="stationName" label="所属集货站" align="center"> |
| | | </el-table-column> |
| | | </el-table-print> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | // import groupBy from 'lodash.groupby' |
| | | export default { |
| | | props: { |
| | | orderList: { |
| | | type: Array, |
| | | default: () => [], |
| | | }, |
| | | }, |
| | | computed: { |
| | | // groupList() { |
| | | // const sanhuList = this.orderList.filter((i) => !i.partnerId) |
| | | // const partnerList = this.orderList.filter((i) => !!i.partnerId) |
| | | // const sList = groupBy(sanhuList, (i) => i.createBy) |
| | | // const pList = groupBy(partnerList, (i) => i.partnerId) |
| | | // return [...Object.values(pList), ...Object.values(sList)] |
| | | // }, |
| | | }, |
| | | methods: { |
| | | objectSpanMethod(len, { rowIndex, columnIndex }) { |
| | | if (columnIndex === 0) { |
| | | if (rowIndex === 0) { |
| | | return { |
| | | rowspan: len, |
| | | colspan: 1, |
| | | } |
| | | } else { |
| | | return { |
| | | rowspan: 0, |
| | | colspan: 0, |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | getSummaries(totalAmount, param) { |
| | | const { columns, data } = param |
| | | const sums = [] |
| | | columns.forEach((column, index) => { |
| | | if (index === 0) { |
| | | sums[index] = `总扎数合计:${data.reduce((total, current) => { |
| | | total += current.num |
| | | return total |
| | | }, 0)} 总金额:¥${totalAmount}` |
| | | } else { |
| | | sums[index] = '' |
| | | } |
| | | // if (index === 1) { |
| | | // sums[index] = '总扎数合计' |
| | | // } else if (index === 2) { |
| | | // sums[index] = data.reduce((total, current) => { |
| | | // total += current.num |
| | | // return total |
| | | // }, 0) |
| | | // } else { |
| | | // sums[index] = '' |
| | | // } |
| | | }) |
| | | return sums |
| | | }, |
| | | }, |
| | | } |
| | | </script> |
对比新文件 |
| | |
| | | <template> |
| | | <div class="video-list"> |
| | | <video |
| | | v-for="(item, index) in value" |
| | | :key="index" |
| | | controls |
| | | width="300px" |
| | | height="200" |
| | | class="mr-20 mb-15" |
| | | > |
| | | <source :src="item" /> |
| | | </video> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | props: { |
| | | value: { |
| | | type: Array, |
| | | default: () => [], |
| | | }, |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .video-list { |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <div class="simple-text" :class="{ 'is-primary': type === 'primary' }"> |
| | | {{ text || value }} |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | props: { |
| | | value: { |
| | | type: [String, Number], |
| | | default: null, |
| | | }, |
| | | type: { |
| | | type: String, |
| | | default: '', |
| | | }, |
| | | text: { |
| | | type: [String, Number], |
| | | default: null, |
| | | }, |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .simple-text { |
| | | display: inline-block; |
| | | &.is-primary { |
| | | color: $primary-color; |
| | | } |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <div class="copy-textarea"> |
| | | <div> |
| | | <span style="color:red;">手动输入最多支持100个号码,大批量号码建议通过文件导入形式提交</span> |
| | | <el-button type="text" @click="clearVal">点击清空</el-button></div> |
| | | <el-input type="textarea" :rows="5" v-model="currentValue" |
| | | placeholder="提示:一行输入一个号码,多个手机号请换行隔开。" |
| | | width="80%" |
| | | @change="handlerInputChange" |
| | | ></el-input> |
| | | <div> |
| | | <span style="color:gray;">提示:一行输入一个号码,多个手机号请换行隔开。</span> |
| | | </div> |
| | | |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import cloneDeep from 'lodash.clonedeep' |
| | | export default { |
| | | props: { |
| | | value: { |
| | | type: String, |
| | | default:'', |
| | | }, |
| | | disabled: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | dialogVisible: false, |
| | | currentValue: '', |
| | | } |
| | | }, |
| | | watch: { |
| | | value: { |
| | | immediate: true, |
| | | handler(value) { |
| | | this.currentValue = value |
| | | }, |
| | | }, |
| | | }, |
| | | methods: { |
| | | clearVal(){ |
| | | this.$elBusUtil |
| | | .confirm('确定要清空吗?') |
| | | .then(() => { |
| | | this.currentValue = '' |
| | | this.$emit('input', '') |
| | | this.$emit('change', '') |
| | | }) |
| | | .catch(() => {}) |
| | | }, |
| | | handlerInputChange(){ |
| | | this.$emit('input', this.currentValue) |
| | | this.$emit('change', this.currentValue) |
| | | } |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .copy-textarea { |
| | | } |
| | | </style> |
| | | <style lang="scss"> |
| | | .shop-user-dialog { |
| | | .dialog-container { |
| | | display: flex; |
| | | align-items: flex-start; |
| | | &__list { |
| | | flex: 1; |
| | | border-right: 1px solid #eee; |
| | | height: 100%; |
| | | } |
| | | &__selected { |
| | | width: 40%; |
| | | height: 100%; |
| | | padding: 24px; |
| | | .el-bus-title { |
| | | margin-bottom: 15px; |
| | | } |
| | | .el-tag { |
| | | margin-right: 6px; |
| | | margin-bottom: 6px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <div class="select-shop-user"> |
| | | <el-button v-if="!disabled" type="primary" @click="chooseUser">选择用户列表</el-button> |
| | | <el-table v-if="value && value.length > 0" :data="value"> |
| | | <el-table-column label="id" prop="id"></el-table-column> |
| | | <el-table-column label="名称" prop="loginName"></el-table-column> |
| | | <el-table-column label="注册手机号方式" prop="tel"></el-table-column> |
| | | <el-table-column v-if="!disabled" label="操作"> |
| | | <template #default="{ $index }"> |
| | | <text-button type="danger" @click="deleteUser($index)">删除</text-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <el-dialog :visible.sync="dialogVisible" title="选择用户列表" append-to-body :close-on-click-modal="false" |
| | | custom-class="shop-user-dialog" width="80%"> |
| | | <div class="dialog-container"> |
| | | <div class="dialog-container__list"> |
| | | <el-bus-crud v-bind="tableConfig" /> |
| | | </div> |
| | | <div class="dialog-container__selected"> |
| | | <el-bus-title title="已添加用户" size="mini" /> |
| | | <el-tag v-for="(tag, i) in currentValue" :key="tag.id" closable @close="deleteCurrentUser(i)">{{ tag.loginName |
| | | }}</el-tag> |
| | | </div> |
| | | </div> |
| | | <div slot="footer"> |
| | | <el-button @click="cancel">取消</el-button> |
| | | <el-button type="primary" @click="confirm">确定</el-button> |
| | | </div> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import cloneDeep from 'lodash.clonedeep' |
| | | export default { |
| | | props: { |
| | | value: { |
| | | type: Array, |
| | | default: () => [], |
| | | }, |
| | | disabled: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | dialogVisible: false, |
| | | currentValue: [], |
| | | tableConfig: { |
| | | url: 'flower/api/user/user/list', |
| | | saveQuery: false, |
| | | hasNew: false, |
| | | hasEdit: false, |
| | | hasDelete: false, |
| | | hasView: false, |
| | | columns: [ |
| | | { type: 'selection' }, |
| | | { label: 'id', prop: 'id' }, |
| | | { label: '名称', prop: 'loginName' }, |
| | | { label: '注册手机号', prop: 'tel' }, |
| | | ], |
| | | extraButtons: [ |
| | | { |
| | | text: '选择', |
| | | show: (row) => |
| | | !this.currentValue.find((item) => item.id === row.id), |
| | | atClick: (row) => { |
| | | this.currentValue.push({ |
| | | id: row.id, |
| | | userId: row.userId, |
| | | loginName: row.loginName, |
| | | tel: row.tel, |
| | | }) |
| | | return false |
| | | }, |
| | | }, |
| | | { |
| | | text: '取消选择', |
| | | show: (row) => this.currentValue.find((item) => item.id === row.id), |
| | | atClick: (row) => { |
| | | const index = this.currentValue.findIndex( |
| | | (item) => item.id === row.id |
| | | ) |
| | | this.currentValue.splice(index, 1) |
| | | return false |
| | | }, |
| | | }, |
| | | ], |
| | | headerButtons: [ |
| | | { |
| | | text: '批量选择', |
| | | type: 'primary', |
| | | disabled: (selected) => selected.length === 0, |
| | | atClick: (selected) => { |
| | | console.log(selected) |
| | | selected.forEach(item => { |
| | | // 检查 selected 数组的每个元素是否已在 currentValue 中 |
| | | if (!this.currentValue.some(currentItem => currentItem.id === item.id)) { |
| | | this.currentValue.push({ |
| | | id: item.id, |
| | | userId: item.userId, |
| | | loginName: item.loginName, |
| | | tel: item.tel, |
| | | }) |
| | | } |
| | | }); |
| | | return true |
| | | }, |
| | | }, |
| | | { |
| | | text: '批量取消', |
| | | type: 'primary', |
| | | disabled: (selected) => selected.length === 0, |
| | | atClick: (selected) => { |
| | | selected.forEach(item => { |
| | | // 检查 selected 数组的每个元素是否存在于 currentValue 中 |
| | | const index = this.currentValue.findIndex(currentItem => currentItem.id === item.id); |
| | | if (index !== -1) { |
| | | this.currentValue.splice(index, 1); // 如果存在,则移除 |
| | | } |
| | | }); |
| | | return true |
| | | }, |
| | | }, |
| | | ], |
| | | |
| | | searchFormAttrs: { |
| | | labelWidth: 'auto', |
| | | }, |
| | | searchForm: [ |
| | | { |
| | | type: 'row', |
| | | span: 12, |
| | | items: [ |
| | | { |
| | | label: '列表类型:', |
| | | id: 'userType', |
| | | type: 'bus-select-dict', |
| | | el: { |
| | | code: 'USER_TYPE', |
| | | multiple: false, |
| | | style: 'width:100%', |
| | | }, |
| | | default: 'customer', |
| | | searchImmediately: true, |
| | | on: { |
| | | change: (e, updateForm, obj) => { |
| | | console.log(e[0]) |
| | | // if (e[0] === 'supplier') { |
| | | // this.tableConfig.url = 'flower/api/supplier/page' |
| | | // } else if (e[0] === 'partner') { |
| | | // this.tableConfig.url = 'flower/api/partner/page' |
| | | // }else if(e[0]==='customer'){ |
| | | // this.tableConfig.url = 'flower/api/customer/page' |
| | | // } |
| | | }, |
| | | }, |
| | | |
| | | }, |
| | | |
| | | { label: 'id:', id: 'id', type: 'input' }, |
| | | { label: '名称:', id: 'loginName', type: 'input' }, |
| | | { label: '注册手机号:', id: 'tel', type: 'input' }, |
| | | ], |
| | | }, |
| | | ], |
| | | }, |
| | | } |
| | | }, |
| | | watch: { |
| | | value: { |
| | | immediate: true, |
| | | handler(value) { |
| | | this.currentValue = cloneDeep(value || []) |
| | | }, |
| | | }, |
| | | }, |
| | | methods: { |
| | | handleSelectionChange(rows) { |
| | | console.log(rows) |
| | | alert("全选") |
| | | }, |
| | | chooseUser() { |
| | | this.currentValue = cloneDeep(this.value || []) |
| | | this.dialogVisible = true |
| | | }, |
| | | deleteCurrentUser(i) { |
| | | this.currentValue.splice(i, 1) |
| | | }, |
| | | deleteUser(i) { |
| | | this.$elBusUtil |
| | | .confirm('确定要删除吗?') |
| | | .then(() => { |
| | | const userList = cloneDeep(this.value || []) |
| | | userList.splice(i, 1) |
| | | this.$emit('input', userList) |
| | | this.$emit('change', userList) |
| | | }) |
| | | .catch(() => { }) |
| | | }, |
| | | confirm() { |
| | | this.$emit('input', this.currentValue) |
| | | this.$emit('change', this.currentValue) |
| | | this.dialogVisible = false |
| | | }, |
| | | cancel() { |
| | | this.dialogVisible = false |
| | | }, |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .select-shop-user {} |
| | | </style> |
| | | <style lang="scss"> |
| | | .shop-user-dialog { |
| | | .dialog-container { |
| | | display: flex; |
| | | align-items: flex-start; |
| | | |
| | | &__list { |
| | | flex: 1; |
| | | border-right: 1px solid #eee; |
| | | height: 100%; |
| | | } |
| | | |
| | | &__selected { |
| | | width: 40%; |
| | | height: 100%; |
| | | padding: 24px; |
| | | |
| | | .el-bus-title { |
| | | margin-bottom: 15px; |
| | | } |
| | | |
| | | .el-tag { |
| | | margin-right: 6px; |
| | | margin-bottom: 6px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <div class="copy-textarea"> |
| | | <div> |
| | | <el-link href="https://hmy-flower.oss-cn-shanghai.aliyuncs.com/ea/ea5ed90664d345768245f20682e9564bsample.xlsx" download="template_phone.xlsx"> |
| | | <span style="color:#5FA7EE;">点击下载模板</span> |
| | | </el-link> |
| | | |
| | | <!-- <el-link @click="downloadTemplate">点击下载模板a</el-link> --> |
| | | </div> |
| | | |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import cloneDeep from 'lodash.clonedeep' |
| | | export default { |
| | | props: { |
| | | value: { |
| | | type: String, |
| | | default:'', |
| | | }, |
| | | disabled: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | dialogVisible: false, |
| | | currentValue: '', |
| | | } |
| | | }, |
| | | watch: { |
| | | value: { |
| | | immediate: true, |
| | | handler(value) { |
| | | this.currentValue = value |
| | | }, |
| | | }, |
| | | }, |
| | | methods: { |
| | | downloadTemplate() { |
| | | const link = document.createElement('a'); |
| | | link.href = 'https://hmy-flower.oss-cn-shanghai.aliyuncs.com/a5/a57ec65b165148e5a669e7766743e489template_phone.xlsx'; |
| | | link.download = 'template_phone.xlsx'; |
| | | link.click(); |
| | | } |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .copy-textarea { |
| | | } |
| | | </style> |
| | | <style lang="scss"> |
| | | .shop-user-dialog { |
| | | .dialog-container { |
| | | display: flex; |
| | | align-items: flex-start; |
| | | &__list { |
| | | flex: 1; |
| | | border-right: 1px solid #eee; |
| | | height: 100%; |
| | | } |
| | | &__selected { |
| | | width: 40%; |
| | | height: 100%; |
| | | padding: 24px; |
| | | .el-bus-title { |
| | | margin-bottom: 15px; |
| | | } |
| | | .el-tag { |
| | | margin-right: 6px; |
| | | margin-bottom: 6px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <div id="tags-view-container" class="tags-view-container"> |
| | | <scroll-pane |
| | | ref="scrollPane" |
| | | class="tags-view-wrapper" |
| | | @scroll="handleScroll" |
| | | > |
| | | <tag-item |
| | | v-for="tag in visitedViews" |
| | | ref="tag" |
| | | :key="tag.path" |
| | | :class="isActive(tag) ? 'active' : ''" |
| | | :to="{ |
| | | ...tag, |
| | | }" |
| | | tag="span" |
| | | class="tags-view-item" |
| | | @click.native.prevent="toCurrentTag(tag)" |
| | | @click.middle.native="closeSelectedTag(tag)" |
| | | @contextmenu.prevent.native="openMenu(tag, $event)" |
| | | > |
| | | {{ tag.title }} |
| | | <span |
| | | v-if="!isOnlyOne" |
| | | class="el-icon-close" |
| | | @click.prevent.stop="closeSelectedTag(tag)" |
| | | /> |
| | | </tag-item> |
| | | </scroll-pane> |
| | | <ul |
| | | v-show="visible" |
| | | :style="{ left: left + 'px', top: top + 'px' }" |
| | | class="contextmenu" |
| | | > |
| | | <li |
| | | :class="{ 'is-disabled': isOnlyOne }" |
| | | @click="closeSelectedTag(selectedTag)" |
| | | > |
| | | 关闭 |
| | | </li> |
| | | <li :class="{ 'is-disabled': isOnlyOne }" @click="closeOthersTags"> |
| | | 关闭其他标签页 |
| | | </li> |
| | | <li |
| | | :class="{ 'is-disabled': isLastView }" |
| | | @click="closeRight(selectedTag)" |
| | | > |
| | | 关闭右侧标签页 |
| | | </li> |
| | | </ul> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import { mapState } from 'vuex' |
| | | import ScrollPane from './scroll-pane' |
| | | import TagItem from './tag-item' |
| | | |
| | | export default { |
| | | components: { ScrollPane, TagItem }, |
| | | data() { |
| | | return { |
| | | visible: false, |
| | | top: 0, |
| | | left: 0, |
| | | selectedTag: {}, |
| | | } |
| | | }, |
| | | computed: { |
| | | ...mapState({ |
| | | visitedViews: (state) => state.tagsView.visitedViews, |
| | | }), |
| | | isLastView() { |
| | | const latestView = this.visitedViews.slice(-1)[0] |
| | | if (latestView?.name && latestView.name === this.selectedTag.name) { |
| | | return true |
| | | } |
| | | return false |
| | | }, |
| | | isOnlyOne() { |
| | | return this.visitedViews.length <= 1 |
| | | }, |
| | | }, |
| | | watch: { |
| | | $route() { |
| | | const timer = setTimeout(() => { |
| | | this.addTags() |
| | | this.moveToCurrentTag() |
| | | clearTimeout(timer) |
| | | }, 500) |
| | | }, |
| | | visible(value) { |
| | | if (value) { |
| | | document.body.addEventListener('click', this.closeMenu) |
| | | } else { |
| | | document.body.removeEventListener('click', this.closeMenu) |
| | | } |
| | | }, |
| | | }, |
| | | mounted() { |
| | | this.addTags() |
| | | }, |
| | | methods: { |
| | | isActive(route) { |
| | | return route.name === this.$route.name |
| | | }, |
| | | toCurrentTag(tag) { |
| | | if (!this.isActive(tag)) { |
| | | this.$router.push(tag.fullPath) |
| | | } |
| | | }, |
| | | addTags() { |
| | | const { name } = this.$route |
| | | if (name) { |
| | | this.$store.dispatch('tagsView/addVisitedView', this.$route) |
| | | } |
| | | return false |
| | | }, |
| | | moveToCurrentTag() { |
| | | const tags = this.$refs.tag |
| | | if (tags) { |
| | | this.$nextTick(() => { |
| | | for (const tag of tags) { |
| | | if (tag.to.name === this.$route.name) { |
| | | this.$refs.scrollPane.moveToTarget(tag, this.visitedViews) |
| | | break |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | }, |
| | | closeSelectedTag(view) { |
| | | if (!this.isOnlyOne) { |
| | | this.$store |
| | | .dispatch('tagsView/delVisitedView', view) |
| | | .then((visitedViews) => { |
| | | if (this.isActive(view)) { |
| | | this.toLastView(visitedViews) |
| | | // this.moveToCurrentTag() |
| | | } |
| | | }) |
| | | } |
| | | }, |
| | | closeOthersTags() { |
| | | if (!this.isOnlyOne) { |
| | | this.$router.push(this.selectedTag) |
| | | this.$store |
| | | .dispatch('tagsView/delOthersVisitedViews', this.selectedTag) |
| | | .then(() => { |
| | | // this.moveToCurrentTag() |
| | | }) |
| | | } |
| | | }, |
| | | closeRight() { |
| | | if (!this.isLastView) { |
| | | this.$store |
| | | .dispatch('tagsView/delRightVisitedViews', this.selectedTag) |
| | | .then((visitedViews) => { |
| | | if (!visitedViews.find((item) => item.name === this.$route.name)) { |
| | | if ( |
| | | this.$route.matched.slice(-1)[0]?.instances?.default?.$metaInfo |
| | | ?.title |
| | | ) { |
| | | this.toLastView(visitedViews) |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | }, |
| | | toLastView(visitedViews) { |
| | | const latestView = visitedViews.slice(-1)[0] |
| | | if (latestView) { |
| | | this.$router.push(latestView.fullPath) |
| | | } |
| | | }, |
| | | openMenu(tag, e) { |
| | | const menuMinWidth = 105 |
| | | const offsetLeft = this.$el.getBoundingClientRect().left // container margin left |
| | | const offsetWidth = this.$el.offsetWidth // container width |
| | | const maxLeft = offsetWidth - menuMinWidth // left boundary |
| | | const left = e.clientX - offsetLeft + 15 // 15: margin right |
| | | |
| | | if (left > maxLeft) { |
| | | this.left = maxLeft |
| | | } else { |
| | | this.left = left |
| | | } |
| | | |
| | | this.top = e.clientY |
| | | this.visible = true |
| | | this.selectedTag = tag |
| | | }, |
| | | closeMenu() { |
| | | this.visible = false |
| | | }, |
| | | handleScroll() { |
| | | this.closeMenu() |
| | | }, |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .tags-view-container { |
| | | height: 34px; |
| | | width: 100%; |
| | | background: #fff; |
| | | border-bottom: 1px solid #d8dce5; |
| | | box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 3px 0 rgba(0, 0, 0, 0.04); |
| | | .tags-view-wrapper { |
| | | .tags-view-item { |
| | | display: inline-block; |
| | | position: relative; |
| | | cursor: pointer; |
| | | height: 26px; |
| | | line-height: 26px; |
| | | border: 1px solid #d8dce5; |
| | | color: #495060; |
| | | background: #fff; |
| | | padding: 0 8px; |
| | | font-size: 12px; |
| | | margin-left: 5px; |
| | | margin-top: 4px; |
| | | &:first-of-type { |
| | | margin-left: 15px; |
| | | } |
| | | &:last-of-type { |
| | | margin-right: 15px; |
| | | } |
| | | &.active { |
| | | background-color: #42b983; |
| | | color: #fff; |
| | | border-color: #42b983; |
| | | &::before { |
| | | content: ''; |
| | | background: #fff; |
| | | display: inline-block; |
| | | width: 8px; |
| | | height: 8px; |
| | | border-radius: 50%; |
| | | position: relative; |
| | | margin-right: 2px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | .contextmenu { |
| | | margin: 0; |
| | | background: #fff; |
| | | z-index: 3000; |
| | | position: absolute; |
| | | list-style-type: none; |
| | | padding: 5px 0; |
| | | border-radius: 4px; |
| | | font-size: 12px; |
| | | font-weight: 400; |
| | | color: #333; |
| | | box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, 0.3); |
| | | li { |
| | | margin: 0; |
| | | padding: 7px 16px; |
| | | cursor: pointer; |
| | | &.is-disabled { |
| | | color: #999; |
| | | cursor: not-allowed; |
| | | } |
| | | &:not(.is-disabled):hover { |
| | | background: #eee; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |
| | | |
| | | <style lang="scss"> |
| | | //reset element css of el-icon-close |
| | | .tags-view-wrapper { |
| | | .tags-view-item { |
| | | .el-icon-close { |
| | | width: 16px; |
| | | height: 16px; |
| | | vertical-align: 2px; |
| | | border-radius: 50%; |
| | | text-align: center; |
| | | transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1); |
| | | transform-origin: 100% 50%; |
| | | &:before { |
| | | transform: scale(0.6); |
| | | display: inline-block; |
| | | vertical-align: -3px; |
| | | } |
| | | &:hover { |
| | | background-color: #b4bccc; |
| | | color: #fff; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <el-scrollbar |
| | | ref="scrollContainer" |
| | | :vertical="false" |
| | | class="scroll-container" |
| | | @wheel.native.prevent="handleScroll" |
| | | > |
| | | <slot /> |
| | | </el-scrollbar> |
| | | </template> |
| | | |
| | | <script> |
| | | const tagAndTagSpacing = 4 // tagAndTagSpacing |
| | | |
| | | export default { |
| | | name: 'ScrollPane', |
| | | data() { |
| | | return { |
| | | left: 0, |
| | | } |
| | | }, |
| | | computed: { |
| | | scrollWrapper() { |
| | | return this.$refs.scrollContainer.$refs.wrap |
| | | }, |
| | | }, |
| | | mounted() { |
| | | this.scrollWrapper.addEventListener('scroll', this.emitScroll, true) |
| | | }, |
| | | beforeDestroy() { |
| | | this.scrollWrapper.removeEventListener('scroll', this.emitScroll) |
| | | }, |
| | | methods: { |
| | | handleScroll(e) { |
| | | const eventDelta = e.wheelDelta || -e.deltaY * 40 |
| | | const $scrollWrapper = this.scrollWrapper |
| | | $scrollWrapper.scrollLeft = $scrollWrapper.scrollLeft + eventDelta / 4 |
| | | }, |
| | | emitScroll() { |
| | | this.$emit('scroll') |
| | | }, |
| | | moveToTarget(currentTag, visitedViews) { |
| | | const $container = this.$refs.scrollContainer.$el |
| | | const $containerWidth = $container.offsetWidth |
| | | const $scrollWrapper = this.scrollWrapper |
| | | // 这边的tagList的顺序不能保证和实际源数组的顺序保持一致 |
| | | // 比如源数组中在某个位置删除一项,然后在相同位置加入一项,那么加入的这一项是在tagList末尾 |
| | | // 所以这边不能直接根据顺序去取第一项和最后一项 |
| | | const tagList = this.$parent.$refs.tag |
| | | |
| | | let firstTag = null |
| | | let lastTag = null |
| | | |
| | | // find first tag and last tag |
| | | if (tagList.length > 0) { |
| | | firstTag = tagList.find( |
| | | (item) => item?.to?.name === visitedViews[0].name |
| | | ) |
| | | lastTag = tagList.find( |
| | | (item) => |
| | | item?.to?.name === visitedViews[visitedViews.length - 1].name |
| | | ) |
| | | } |
| | | |
| | | if (firstTag === currentTag) { |
| | | $scrollWrapper.scrollLeft = 0 |
| | | } else if (lastTag === currentTag) { |
| | | $scrollWrapper.scrollLeft = $scrollWrapper.scrollWidth - $containerWidth |
| | | } else { |
| | | // find preTag and nextTag |
| | | const currentIndex = visitedViews.findIndex( |
| | | (item) => item.name === currentTag?.to?.name |
| | | ) |
| | | const prevTag = tagList.find( |
| | | (item) => item?.to?.name === visitedViews[currentIndex - 1].name |
| | | ) |
| | | const nextTag = tagList.find( |
| | | (item) => item?.to?.name === visitedViews[currentIndex + 1].name |
| | | ) |
| | | |
| | | // the tag's offsetLeft after of nextTag |
| | | const afterNextTagOffsetLeft = |
| | | nextTag.$el.offsetLeft + nextTag.$el.offsetWidth + tagAndTagSpacing |
| | | |
| | | // the tag's offsetLeft before of prevTag |
| | | const beforePrevTagOffsetLeft = |
| | | prevTag.$el.offsetLeft - tagAndTagSpacing |
| | | |
| | | if ( |
| | | afterNextTagOffsetLeft > |
| | | $scrollWrapper.scrollLeft + $containerWidth |
| | | ) { |
| | | $scrollWrapper.scrollLeft = afterNextTagOffsetLeft - $containerWidth |
| | | } else if (beforePrevTagOffsetLeft < $scrollWrapper.scrollLeft) { |
| | | $scrollWrapper.scrollLeft = beforePrevTagOffsetLeft |
| | | } |
| | | } |
| | | }, |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .scroll-container { |
| | | white-space: nowrap; |
| | | position: relative; |
| | | overflow: hidden; |
| | | width: 100%; |
| | | ::v-deep { |
| | | .el-scrollbar__bar { |
| | | bottom: 0px; |
| | | } |
| | | .el-scrollbar__wrap { |
| | | height: 49px; |
| | | overflow-x: auto !important; |
| | | } |
| | | } |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <span><slot></slot></span> |
| | | </template> |
| | | |
| | | <script> |
| | | // 原来用router-link跳转时有问题,为了较少改动增加一个没有实际意义的组件 |
| | | export default { |
| | | name: 'TagItem', |
| | | props: { |
| | | to: Object, |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style scoped></style> |
对比新文件 |
| | |
| | | <template> |
| | | <el-card class="location-item"> |
| | | <div class="location-item__main"> |
| | | <div class="location-item__title text-overflow-1"> |
| | | <div>{{ info.code }}</div> |
| | | <div |
| | | v-if="info.used && info.orderDTO && info.orderDTO.length > 0" |
| | | class="h-130 py-10" |
| | | > |
| | | <div class="flex items-center"> |
| | | <div class="text-12 text-primary flex-1 text-overflow-1"> |
| | | {{ info.orderDTO[0].orderNo }} |
| | | </div> |
| | | <el-popover placement="bottom" trigger="hover"> |
| | | <el-table :data="info.orderDTO"> |
| | | <el-table-column |
| | | prop="orderNo" |
| | | label="订单号" |
| | | min-width="150" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | label="订单金额(元)" |
| | | prop="totalAmount" |
| | | min-width="120" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | label="下单时间" |
| | | prop="createTime" |
| | | min-width="180" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | label="合伙人" |
| | | prop="partnerName" |
| | | min-width="120" |
| | | ></el-table-column> |
| | | </el-table> |
| | | <el-button slot="reference" type="text" class="p-0 ml-4" |
| | | >查看更多</el-button |
| | | > |
| | | </el-popover> |
| | | </div> |
| | | <div |
| | | v-if="info.goodsItems && info.goodsItems.length > 0" |
| | | class="flex items-center mt-10" |
| | | > |
| | | <div class="text-subTitle text-12 flex-1 text-overflow-1"> |
| | | {{ info.goodsItems[0].flowerName |
| | | }}<span class="ml-8">{{ info.goodsItems[0].flowerLevelStr }}</span |
| | | ><span class="ml-8">{{ info.goodsItems[0].flowerColor }}</span |
| | | ><span class="ml-8">{{ info.goodsItems[0].flowerUnit }}</span |
| | | >×{{ info.goodsItems[0].num }} |
| | | </div> |
| | | <el-popover placement="bottom" trigger="hover"> |
| | | <el-table :data="info.goodsItems"> |
| | | <el-table-column |
| | | prop="flowerName" |
| | | label="商品名称" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="flowerLevelStr" |
| | | label="级别" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | prop="flowerColor" |
| | | label="颜色" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | property="flowerUnit" |
| | | label="规格" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | property="supplierName" |
| | | label="供应商名称" |
| | | ></el-table-column> |
| | | <el-table-column |
| | | property="orderNo" |
| | | label="订单号" |
| | | min-width="150" |
| | | ></el-table-column> |
| | | </el-table> |
| | | <el-button slot="reference" type="text" class="p-0 ml-4" |
| | | >查看更多</el-button |
| | | > |
| | | </el-popover> |
| | | </div> |
| | | <div class="text-subTitle text-12 mt-10 text-overflow-1"> |
| | | {{ info.orderDTO[0].customer |
| | | }}<span class="ml-8">{{ info.orderDTO[0].customerTel }}</span> |
| | | </div> |
| | | <el-tooltip |
| | | v-if="info.orderDTO[0].customerAddress" |
| | | class="item" |
| | | effect="dark" |
| | | :content="`${info.orderDTO[0].customerProvince || ''}${ |
| | | info.orderDTO[0].customerCity || '' |
| | | }${info.orderDTO[0].customerRegion || ''}${ |
| | | info.orderDTO[0].customerAddress || '' |
| | | }`" |
| | | placement="top-start" |
| | | > |
| | | <div class="text-subTitle text-12 mt-10 text-overflow-1"> |
| | | {{ info.orderDTO[0].customerProvince |
| | | }}{{ info.orderDTO[0].customerCity |
| | | }}{{ info.orderDTO[0].customerRegion |
| | | }}{{ info.orderDTO[0].customerAddress }} |
| | | </div> |
| | | </el-tooltip> |
| | | </div> |
| | | <div |
| | | v-else |
| | | class="h-130 flex items-center justify-center text-primary cursor-pointer" |
| | | @click="onAddOrder" |
| | | > |
| | | <i class="el-icon-circle-plus-outline mr-6"></i> |
| | | 添加订单 |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="location-item__bottom"> |
| | | <div class="location-item__area"> |
| | | {{ info.warehouseName }} |
| | | </div> |
| | | <div> |
| | | <el-tooltip class="item" effect="dark" content="编辑"> |
| | | <i class="el-icon-edit" @click="editItem"></i> |
| | | </el-tooltip> |
| | | <el-tooltip class="item" effect="dark" content="删除"> |
| | | <i class="el-icon-delete is-delete" @click="deleteItem"></i> |
| | | </el-tooltip> |
| | | </div> |
| | | </div> |
| | | </el-card> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | props: { |
| | | info: { |
| | | type: Object, |
| | | default: () => ({}), |
| | | }, |
| | | }, |
| | | methods: { |
| | | editItem() { |
| | | this.$emit('edit') |
| | | }, |
| | | deleteItem() { |
| | | this.$emit('delete') |
| | | }, |
| | | onAddOrder() { |
| | | this.$emit('addOrder') |
| | | }, |
| | | }, |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .location-item { |
| | | position: relative; |
| | | margin-bottom: 20px; |
| | | &__main { |
| | | padding-top: 20px; |
| | | } |
| | | &__title { |
| | | font-size: 16px; |
| | | color: $main-title-color; |
| | | font-weight: bold; |
| | | } |
| | | &__bottom { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | border-top: 1px solid #eee; |
| | | height: 50px; |
| | | i { |
| | | font-size: 18px; |
| | | font-weight: normal; |
| | | padding: 0 6px; |
| | | cursor: pointer; |
| | | margin-left: 8px; |
| | | &.is-delete { |
| | | color: $danger-color; |
| | | } |
| | | } |
| | | } |
| | | &__area { |
| | | font-size: 14px; |
| | | color: $main-title-color; |
| | | } |
| | | } |
| | | ::v-deep { |
| | | .el-card { |
| | | &__body { |
| | | padding-top: 0; |
| | | padding-bottom: 0; |
| | | } |
| | | } |
| | | } |
| | | </style> |
对比新文件 |
| | |
| | | <template> |
| | | <el-bus-crud ref="crud" v-bind="tableConfig"></el-bus-crud> |
| | | </template> |
| | | |
| | | <script> |
| | | import { getPartnerListConfig } from '@/utils/form-item-config' |
| | | export default { |
| | | props: { |
| | | value: { |
| | | type: String, |
| | | default: null, |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | tableConfig: { |
| | | url: 'flower/api/warehouse/location/list/orders', |
| | | hasNew: false, |
| | | hasEdit: false, |
| | | hasDelete: false, |
| | | hasView: false, |
| | | saveQuery: false, |
| | | columns: [ |
| | | { |
| | | label: '序号', |
| | | type: 'index', |
| | | }, |
| | | { label: '订单号', prop: 'orderNo' }, |
| | | { label: '下单人姓名', prop: 'customer' }, |
| | | { label: '下单人联系电话', prop: 'customerTel' }, |
| | | { |
| | | label: '下单人地址', |
| | | formatter: (row) => |
| | | `${row.customerProvince || ''}${row.customerCity || ''}${ |
| | | row.customerRegion || '' |
| | | }${row.customerAddress || ''}`, |
| | | }, |
| | | { label: '所属合伙人', prop: 'partnerName' }, |
| | | ], |
| | | searchForm: [ |
| | | { |
| | | type: 'row', |
| | | items: [ |
| | | { label: '订单号', id: 'orderNo', type: 'input' }, |
| | | { ...getPartnerListConfig() }, |
| | | ], |
| | | }, |
| | | ], |
| | | extraButtons: [ |
| | | { |
| | | text: '选择', |
| | | show: (row) => this.value !== row.id, |
| | | atClick: (row) => { |
| | | this.$emit('input', row.id) |
| | | return false |
| | | }, |
| | | }, |
| | | { |
| | | text: '已选择', |
| | | disabled: () => true, |
| | | show: (row) => this.value === row.id, |
| | | }, |
| | | ], |
| | | }, |
| | | } |
| | | }, |
| | | } |
| | | </script> |
| | |
| | | { |
| | | httpBaseUri: 'http://localhost:8080', |
| | | httpBaseUri: 'http://192.168.1.213:8080', |
| | | } |
| | |
| | | { |
| | | //httpBaseUri: 'http://localhost:8080', |
| | | httpBaseUri: 'http://14.103.144.28', |
| | | httpBaseUri: 'http://192.168.1.213:8080', |
| | | // httpBaseUri: 'http://14.103.144.28', |
| | | baseUrl: '/platform/' |
| | | } |
| | | |
| | |
| | | data() { |
| | | return { |
| | | tableConfig: { |
| | | url: 'flower/api/filmset/page', |
| | | url: 'flower/api/filmWorks/list', |
| | | newUrl: 'flower/api/filmWorks/new', |
| | | editUrl: 'flower/api/filmWorks/edit', |
| | | deleteUrl: 'flower/api/filmWorks/delete', |
| | | dialogNeedRequest: true, |
| | | persistSelection: true, |
| | | columns: [ |
| | | { type: 'selection' }, |
| | | { label: '标题', prop: 'title' }, |
| | | { label: '发布日期', prop: 'publishDate' }, |
| | | { label: '编辑日期', prop: 'updateTime' }, |
| | | { label: '状态', prop: 'statusStr' }, |
| | | { label: '中文名称', prop: 'nameCn', minWidth: 120 }, |
| | | { label: '英文名称', prop: 'nameEn', minWidth: 120 }, |
| | | { label: '作品类型', prop: 'typeStr' , minWidth: 150 }, |
| | | { label: '上映年份', prop: 'releaseYear' }, |
| | | { label: '导演', prop: 'director', minWidth: 150 }, |
| | | { label: '制片方', prop: 'producer', minWidth: 150 }, |
| | | { label: '主要演员', prop: 'actors', minWidth: 300 }, |
| | | { label: '剧情关键词', prop: 'keywords' }, |
| | | { label: '剧情简介', prop: 'synopsis' , minWidth: 400 }, |
| | | { label: '封面图片' ,formatter: this.formatterImage, minWidth: 200 }, |
| | | { label: '封面图片描述', prop: 'coverAlt', minWidth: 120 }, |
| | | { label: '用户类型', prop: 'userTypeStr' }, |
| | | { label: '置顶权重', prop: 'stickyWeight' , minWidth: 80 }, |
| | | { label: '状态', prop: 'statusStr' , minWidth: 80 }, |
| | | { label: '收藏量', prop: 'collectCount' , minWidth: 80 }, |
| | | { label: '点赞量', prop: 'likeCount', minWidth: 80 }, |
| | | { label: '评论量', prop: 'commentCount', minWidth: 80 }, |
| | | { label: '分享量', prop: 'shareCount', minWidth: 80 }, |
| | | { label: '创建日期', prop: 'createDate', minWidth: 80 }, |
| | | ], |
| | | searchForm: [ |
| | | { |
| | | type: 'row', |
| | | items: [ |
| | | { label: '标题', id: 'title', type: 'input' }, |
| | | { label: '中文名称', id: 'nameCn', type: 'input' }, |
| | | { label: '英文名称', id: 'nameEn', type: 'input' }, |
| | | { label: '作品类型', id: 'type', type: 'input' }, |
| | | { label: '上映年份', id: 'releaseYear', type: 'input' }, |
| | | { |
| | | label: '创建日期', |
| | | id: 'createDateBeginStr', |
| | |
| | | ], |
| | | form: [ |
| | | { |
| | | label: '标题:', |
| | | id: 'title', |
| | | label: '中文名称:', |
| | | id: 'nameCn', |
| | | type: 'input', |
| | | rules: { |
| | | required: true, |
| | |
| | | }, |
| | | }, |
| | | { |
| | | label: '片场内容类型:', |
| | | label: '英文名称:', |
| | | id: 'nameEn', |
| | | type: 'input', |
| | | rules: { |
| | | required: true, |
| | | message: '请输入标题', |
| | | trigger: 'blur', |
| | | }, |
| | | }, |
| | | { |
| | | label: '作品类型:', |
| | | id: 'type', |
| | | type: 'bus-select-dict', |
| | | el: { |
| | |
| | | }, |
| | | rules: { |
| | | required: true, |
| | | message: '请选择片场内容类型', |
| | | message: '请选择影视作品类型', |
| | | }, |
| | | }, |
| | | { |
| | | label: '内容:', |
| | | id: 'content', |
| | | label: '上映年份:', |
| | | id: 'releaseYear', |
| | | type: 'input', |
| | | rules: { |
| | | required: true, |
| | | message: '请输入上映年份', |
| | | trigger: 'blur', |
| | | }, |
| | | }, |
| | | { |
| | | label: '导演:', |
| | | id: 'director', |
| | | type: 'input', |
| | | rules: { |
| | | required: true, |
| | | message: '请输入导演,多个导演,分割', |
| | | trigger: 'blur', |
| | | }, |
| | | }, |
| | | { |
| | | label: '制片方:', |
| | | id: 'producer', |
| | | type: 'input', |
| | | rules: { |
| | | required: true, |
| | | message: '请输入制片方,多个制片方,分割', |
| | | trigger: 'blur', |
| | | }, |
| | | }, |
| | | { |
| | | label: '主要演员:', |
| | | id: 'actors', |
| | | type: 'input', |
| | | rules: { |
| | | required: true, |
| | | message: '请输入主要演员,多个主要演员,分割', |
| | | trigger: 'blur', |
| | | }, |
| | | }, |
| | | { |
| | | label: '剧情关键词:', |
| | | id: 'keywords', |
| | | type: 'input', |
| | | rules: { |
| | | required: true, |
| | | message: '请输入剧情关键词', |
| | | trigger: 'blur', |
| | | }, |
| | | }, |
| | | { |
| | | label: '剧情简介:', |
| | | id: 'synopsis', |
| | | component: 'base-editor', |
| | | richText: true, |
| | | rules: { required: true, message: '请输入内容', trigger: 'blur' }, |
| | | rules: { required: true, message: '请输入剧情简介', trigger: 'blur' }, |
| | | }, |
| | | // { |
| | | // label: '封面:', |
| | | // id: 'cover', |
| | | // type: 'bus-upload', |
| | | // el: { |
| | | // listType: 'picture-card', |
| | | // limitSize: 2, |
| | | // limit: 1, |
| | | // tipText: '大小不超过2M', |
| | | // valueType: 'string', |
| | | // }, |
| | | // forceDisabled: true, |
| | | // }, |
| | | { |
| | | label: '封面图片:', |
| | | id: 'coverUrl', |
| | | type: 'bus-upload', |
| | | el: { |
| | | listType: 'picture-card', |
| | | limitSize: 2, |
| | | limit: 1, |
| | | tipText: '大小不超过2M', |
| | | valueType: 'string', |
| | | }, |
| | | forceDisabled: true, |
| | | }, |
| | | { |
| | | label: '封面图片描述:', |
| | | id: 'coverAlt', |
| | | type: 'input', |
| | | rules: { |
| | | required: true, |
| | | message: '请输入封面图片描述', |
| | | trigger: 'blur', |
| | | }, |
| | | }, |
| | | { |
| | | label: '用户类型:', |
| | | id: 'userType', |
| | | type: 'bus-select-dict', |
| | | el: { |
| | | code: 'FILMSET_CREATE_TYPE', |
| | | style: 'width:100%', |
| | | clearable: true, |
| | | }, |
| | | rules: { |
| | | required: true, |
| | | message: '请选择用户类型', |
| | | }, |
| | | }, |
| | | { |
| | | label: '置顶权重:', |
| | | id: 'stickyWeight', |
| | | type: 'input', |
| | | rules: { |
| | | required: true, |
| | | message: '请输入置顶权重描述', |
| | | trigger: 'blur', |
| | | }, |
| | | }, |
| | | { |
| | | label: '收藏量:', |
| | | id: 'collectCount', |
| | | type: 'input', |
| | | rules: { |
| | | required: true, |
| | | message: '请输入收藏量', |
| | | trigger: 'blur', |
| | | }, |
| | | }, |
| | | { |
| | | label: '点赞量:', |
| | | id: 'likeCount', |
| | | type: 'input', |
| | | rules: { |
| | | required: true, |
| | | message: '请输入点赞量', |
| | | trigger: 'blur', |
| | | }, |
| | | }, |
| | | { |
| | | label: '评论量:', |
| | | id: 'commentCount', |
| | | type: 'input', |
| | | rules: { |
| | | required: true, |
| | | message: '请输入评论量', |
| | | trigger: 'blur', |
| | | }, |
| | | }, |
| | | { |
| | | label: '分享量:', |
| | | id: 'shareCount', |
| | | type: 'input', |
| | | rules: { |
| | | required: true, |
| | | message: '请输入分享量', |
| | | trigger: 'blur', |
| | | }, |
| | | }, |
| | | ], |
| | | extraButtons: [ |
| | | { |
| | |
| | | try { |
| | | await this.$elBusUtil.confirm(`确定要${action}吗?`) |
| | | const { code } = await this.$elBusHttp.request( |
| | | 'flower/api/filmset/page/changeStatus', |
| | | 'flower/api/filmWorks/changeStatus', |
| | | { params: { id: row.id } } |
| | | ) |
| | | if (code === 0) { |
| | |
| | | `确定要批量发布这${selectedNotice.length}个片场内容吗?` |
| | | ) |
| | | const { code } = await this.$elBusHttp.request( |
| | | 'flower/api/filmset/page/publish/batch', |
| | | 'flower/api/filmWorks/publish/batch', |
| | | { |
| | | method: 'post', |
| | | data: { |
| | |
| | | `确定要批量删除这${selected.length}个片场内容吗?` |
| | | ) |
| | | const { code } = await this.$elBusHttp.request( |
| | | 'flower/api/filmset/page/delete/batch', |
| | | 'flower/api/filmWorks/delete/batch', |
| | | { |
| | | method: 'post', |
| | | data: { |
| | |
| | | }, |
| | | head() { |
| | | return { |
| | | title: '片场内容管理', |
| | | title: '影视作品内容管理', |
| | | } |
| | | }, |
| | | methods: { |
| | | formatterImage(row) { |
| | | if (row.coverUrl) { |
| | | // 使用第三方镜像服务(示例) |
| | | const proxyUrl = `https://images.weserv.nl/?url=${encodeURIComponent(row.coverUrl)}`; |
| | | return <el-bus-image src={proxyUrl} preview-src-list={[proxyUrl]} style="width:150px" /> |
| | | } |
| | | return '无封面'; |
| | | } |
| | | }, |
| | | } |