【模版目录】更新管理端源码

This commit is contained in:
吴昊天 2022-09-27 15:30:30 +08:00
parent 353191854f
commit 6f9dc32e8a
14 changed files with 706 additions and 94 deletions

View File

@ -4992,8 +4992,7 @@
"big.js": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
"integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==",
"dev": true
"integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ=="
},
"binary-extensions": {
"version": "2.0.0",
@ -8004,8 +8003,7 @@
"emojis-list": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
"integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==",
"dev": true
"integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q=="
},
"encodeurl": {
"version": "1.0.2",
@ -12822,7 +12820,6 @@
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz",
"integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==",
"dev": true,
"requires": {
"minimist": "^1.2.5"
}
@ -14446,9 +14443,29 @@
"integrity": "sha1-sr52n6MZQL6e7qZGnAdeNQBvo9M="
},
"monaco-editor": {
"version": "0.21.3",
"resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.21.3.tgz",
"integrity": "sha512-9N7wATLpi+googstvtm6IKg97vPQ77FDYEpkow5tLriM/VJ0DaTRyUP4UVzcoH7KlPDX+e/rE7/imcOUeGkT6g=="
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.28.1.tgz",
"integrity": "sha512-P1vPqxB4B1ZFzTeR1ScggSp9/5NoQrLCq88fnlNUsuRAP1usEBN4TIpI2lw0AYIZNVIanHk0qwjze2uJwGOHUw=="
},
"monaco-editor-webpack-plugin": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/monaco-editor-webpack-plugin/-/monaco-editor-webpack-plugin-4.2.0.tgz",
"integrity": "sha512-/P3sFiEgBl+Y50he4mbknMhbLJVop5gBUZiPS86SuHUDOOnQiQ5rL1jU5lwt1XKAwMEkhwZbUwqaHxTPkb1Utw==",
"requires": {
"loader-utils": "^2.0.0"
},
"dependencies": {
"loader-utils": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz",
"integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==",
"requires": {
"big.js": "^5.2.2",
"emojis-list": "^3.0.0",
"json5": "^2.1.2"
}
}
}
},
"move-concurrently": {
"version": "1.0.1",

View File

@ -52,7 +52,7 @@
"uglifyjs-webpack-plugin": "^2.2.0",
"v-org-tree": "^1.0.6",
"v-viewer": "^1.5.1",
"view-design": "^4.4.0",
"view-design": "^4.7.0",
"vue": "^2.5.10",
"vue-awesome-swiper": "^4.1.1",
"vue-codemirror": "^4.0.6",

View File

@ -388,3 +388,16 @@ export function importCard(data) {
params: data,
});
}
/**
* @description 商品批量设置
* @param {Number} param id {Number} 属性id
* @param {Object} param data {Object} 传值参数
*/
export function batchSetting(data) {
return request({
url: `product/batch/setting`,
method: 'POST',
data,
});
}

View File

@ -1077,4 +1077,15 @@ export function saveType(type) {
method: 'get',
params: data,
});
}
/**
* 添加语言地区表单
* @param {*} id
* @returns
*/
export function langCountryForm(id) {
return request({
url: `setting/lang_country/form/${id}`,
method: 'get',
});
}

View File

@ -310,6 +310,17 @@ export function updtaeAdmin(data) {
data,
});
}
/**
* @description 文件管理 --- 设置密码
* data 请求参数
*/
export function setFilePassword(data) {
return request({
url: `setting/set_file_password`,
method: 'PUT',
data,
});
}
/**
* @description 个人中心 --- 设置会员等级

View File

@ -11,6 +11,7 @@
<!--消息中心<Badge style="margin-left: 10px" :count="messageUnreadCount"></Badge>-->
<!--</DropdownItem>-->
<DropdownItem name="userCenter"><Icon type="ios-contact-outline" class="iconImg" />个人中心</DropdownItem>
<DropdownItem v-show = "info.level === 0" name="fileEdit"><Icon type="ios-document-outline" class="iconImg" />文件管理</DropdownItem>
<DropdownItem name="logout"><Icon type="ios-log-out" class="iconImg" />退出登录</DropdownItem>
</DropdownMenu>
</Dropdown>
@ -75,6 +76,9 @@ export default {
userCenter() {
this.$router.push('/admin/system/user');
},
fileEdit(){
this.$router.push('/admin/system/files');
},
message() {
this.$router.push({
name: 'message_page',
@ -91,6 +95,9 @@ export default {
case 'message':
this.message();
break;
case 'fileEdit':
this.fileEdit();
break;
}
},
},

View File

@ -45,6 +45,20 @@
><Button type="primary" class="bnt mr15" icon="md-add">添加商品</Button></router-link
>
<Button v-auth="['product-crawl-save']" type="success" class="bnt mr15" @click="onCopy">商品采集</Button>
<Dropdown class="bnt mr15" @on-click="batchSelect">
<Button type="info">
批量操作
<Icon type="ios-arrow-down"></Icon>
</Button>
<DropdownMenu slot="list">
<DropdownItem :name="1">分类设置</DropdownItem>
<DropdownItem :name="2">物流设置</DropdownItem>
<DropdownItem :name="3">赠送积分</DropdownItem>
<DropdownItem :name="4">赠送优惠券</DropdownItem>
<DropdownItem :name="5">用户标签</DropdownItem>
<DropdownItem :name="6">商品推荐</DropdownItem>
</DropdownMenu>
</Dropdown>
<Button
v-auth="['product-product-product_show']"
class="bnt mr15"
@ -133,11 +147,125 @@
>
<tao-bao ref="taobaos" v-if="modals" @on-close="onClose"></tao-bao>
</Modal>
<Modal
v-model="batchModal"
class="batch-box"
scrollable
closable
title="批量设置"
:mask-closable="false"
width="1000"
@on-ok="batchSub"
@on-visible-change="clearBatchData"
>
<Form
class="batchFormData"
ref="batchFormData"
:rules="ruleBatch"
:model="batchFormData"
:label-width="120"
label-position="right"
@submit.native.prevent
>
<Row :gutter="24" type="flex">
<Col span="24" v-if="batchType == 1">
<Divider orientation="left">基础设置</Divider>
<FormItem label="商品分类:" prop="cate_id">
<Select v-model="batchFormData.cate_id" placeholder="请选择商品分类" multiple class="perW20">
<Option v-for="item in treeSelect" :disabled="item.pid === 0" :value="item.id" :key="item.id">{{
item.html + item.cate_name
}}</Option>
</Select>
</FormItem>
</Col>
<Col span="24" v-if="batchType == 2">
<Divider orientation="left">物流设置</Divider>
<FormItem label="物流方式:" prop="logistics">
<CheckboxGroup v-model="batchFormData.logistics" @on-change="logisticsBtn">
<Checkbox label="1">快递</Checkbox>
<Checkbox label="2">到店核销</Checkbox>
</CheckboxGroup>
</FormItem>
<FormItem label="运费设置:">
<RadioGroup v-model="batchFormData.freight">
<!-- <Radio :label="1">包邮</Radio> -->
<Radio :label="2">固定邮费</Radio>
<Radio :label="3">运费模板</Radio>
</RadioGroup>
</FormItem>
<FormItem label="" v-if="batchFormData.freight == 2">
<div class="acea-row">
<InputNumber :min="0" v-model="batchFormData.postage" placeholder="请输入金额" class="perW20 maxW" />
</div>
</FormItem>
<FormItem label="" v-if="batchFormData.freight == 3" prop="temp_id">
<div class="acea-row">
<Select v-model="batchFormData.temp_id" clearable placeholder="请选择运费模板" class="perW20 maxW">
<Option v-for="(item, index) in templateList" :value="item.id" :key="index">{{ item.name }}</Option>
</Select>
</div>
</FormItem>
</Col>
<Col span="24" v-if="[3, 4, 5, 6].includes(batchType)">
<Divider orientation="left" v-if="[3, 4, 5, 6].includes(batchType)">营销设置</Divider>
<FormItem label="赠送积分:" prop="give_integral" v-if="batchType == 3">
<InputNumber v-model="batchFormData.give_integral" :min="0" :max="999999" placeholder="请输入积分" />
</FormItem>
<FormItem label="赠送优惠券:" v-if="batchType == 4">
<div v-if="couponName.length" class="mb20">
<Tag closable v-for="(item, index) in couponName" :key="index" @on-close="handleClose(item)">{{
item.title
}}</Tag>
</div>
<Button type="primary" @click="addCoupon">添加优惠券</Button>
</FormItem>
<FormItem label="关联用户标签:" prop="label_id" v-if="batchType == 5">
<div style="display: flex">
<div class="labelInput acea-row row-between-wrapper" @click="openLabel">
<div style="width: 90%">
<div v-if="dataLabel.length">
<Tag closable v-for="(item, index) in dataLabel" @on-close="closeLabel(item)" :key="index">{{
item.label_name
}}</Tag>
</div>
<span class="span" v-else>选择用户关联标签</span>
</div>
<div class="iconfont iconxiayi"></div>
</div>
</div>
</FormItem>
<FormItem label="商品推荐:" v-if="batchType == 6">
<CheckboxGroup v-model="batchFormData.recommend">
<Checkbox label="is_hot">热卖单品</Checkbox>
<Checkbox label="is_benefit">促销单品</Checkbox>
<Checkbox label="is_best">精品推荐</Checkbox>
<Checkbox label="is_new">首发新品</Checkbox>
<Checkbox label="is_good">优品推荐</Checkbox>
</CheckboxGroup>
</FormItem>
</Col>
</Row>
</Form>
</Modal>
<!-- 用户标签 -->
<Modal
v-model="labelShow"
scrollable
title="请选择用户标签"
:closable="false"
width="500"
:footer-hide="true"
:mask-closable="false"
>
<userLabel ref="userLabel" @activeData="activeData" @close="labelClose"></userLabel>
</Modal>
<!-- 商品弹窗 -->
<div v-if="isProductBox">
<div class="bg" @click="isProductBox = false"></div>
<goodsDetail :goodsId="goodsId"></goodsDetail>
</div>
<coupon-list ref="couponTemplates" @nameId="nameId" :couponids="batchFormData.coupon_ids"></coupon-list>
</div>
</template>
@ -148,19 +276,23 @@ import toExcel from '../../../utils/Excel.js';
import { mapState } from 'vuex';
import taoBao from './taoBao';
import goodsDetail from './components/goodsDetail.vue';
import couponList from '@/components/couponList';
import {
getGoodHeade,
getGoods,
PostgoodsIsShow,
treeListApi,
treeListApi, // 分类列表
productShowApi,
productUnshowApi,
storeProductApi,
batchSetting,
} from '@/api/product';
import userLabel from '@/components/labelList';
export default {
name: 'product_productList',
components: { expandRow, attribute, taoBao, goodsDetail },
components: { expandRow, attribute, taoBao, goodsDetail, userLabel, couponList },
computed: {
...mapState('userLevel', ['categoryId']),
},
@ -168,6 +300,24 @@ export default {
return {
template: false,
modals: false,
batchModal: false,
labelShow: false,
batchType: 1, // 批量设置类型
batchFormData: {
cate_id: [],
logistics: [],
freight: 2,
postage: 0,
temp_id: null,
give_integral: 0,
label_id: [],
coupon_ids: [],
recommend: [],
},
ruleBatch: {},
couponName: [], // 优惠券
dataLabel: [], // 标签
templateList: [], // 运费模版
grid: {
xl: 6,
lg: 8,
@ -278,6 +428,7 @@ export default {
ids: [],
goodsId: '',
isProductBox: false,
treeSelect: [],
};
},
watch: {
@ -298,10 +449,104 @@ export default {
}
},
methods: {
batchSub() {
console.log(this.selectedIds, this.ids);
let data = this.batchFormData;
data.ids = this.ids;
data.type = this.batchType;
let activeIds = [];
this.dataLabel.forEach((item) => {
activeIds.push(item.id);
});
data.label_id = activeIds;
batchSetting(data)
.then((res) => {
this.$Message.success(res.msg);
this.getDataList();
this.clearBatchData();
})
.catch((err) => {
this.$Message.error(err.msg);
});
},
clearBatchData(status) {
if (!status) {
this.batchFormData = {
cate_id: [],
logistics: [],
freight: 0,
postage: null,
temp_id: null,
give_integral: null,
label_id: [],
coupon_ids: [],
recommend: [],
};
this.ids = [];
this.dataLabel = [];
this.clearAll(false);
}
},
// 批量设置商品
batchSelect(type) {
if (this.ids.length === 0) {
this.$Message.warning('请选择要设置的商品');
} else {
this.batchType = type;
this.batchModal = true;
this.productGetTemplate();
}
},
activeData(dataLabel) {
this.labelShow = false;
this.dataLabel = dataLabel;
},
nameId(id, names) {
this.batchFormData.coupon_ids = id;
this.couponName = this.unique(names);
},
handleClose(name) {
let index = this.couponName.indexOf(name);
this.couponName.splice(index, 1);
this.formValidate.coupon_ids.splice(index, 1);
},
//对象数组去重;
unique(arr) {
const res = new Map();
return arr.filter((arr) => !res.has(arr.id) && res.set(arr.id, 1));
},
// 获取运费模板;
productGetTemplate() {
productGetTemplateApi().then((res) => {
this.templateList = res.data;
});
},
// 标签弹窗关闭
labelClose() {
this.labelShow = false;
},
look(row) {
this.goodsId = row.id;
this.isProductBox = true;
},
// 物流方式
logisticsBtn(e) {
this.batchFormData.logistics = e;
},
// 关联用户标签
openLabel(row) {
this.labelShow = true;
this.$refs.userLabel.userLabel(JSON.parse(JSON.stringify(this.dataLabel)));
},
closeLabel(label) {
let index = this.dataLabel.indexOf(this.dataLabel.filter((d) => d.id == label.id)[0]);
this.dataLabel.splice(index, 1);
},
// 添加优惠券
addCoupon() {
this.$refs.couponTemplates.isTemplate = true;
this.$refs.couponTemplates.tableList();
},
getPath() {
this.columns2 = [...this.columns];
if (name !== '1' && name !== '2') {
@ -376,6 +621,7 @@ export default {
});
}
},
// 全选
// onSelectTab (selection) {
// let data = []
@ -412,6 +658,9 @@ export default {
this.setChecked();
});
},
clearAll(status) {
this.$refs.table.selectAll(status);
},
// 取消某一行
handleCancelRow(selection, row) {
this.selectedIds.delete(row.id);
@ -605,7 +854,13 @@ export default {
overflow: auto;
}
}
.batch-box{
>>> .ivu-modal-body {
overflow: auto;
min-height: 350px;
}
}
.tabBox_img {
width: 36px;
height: 36px;
@ -655,4 +910,21 @@ export default {
border: 1px solid #eee;
}
}
.labelInput {
border: 1px solid #dcdee2;
width: 20%;
padding: 0 5px;
border-radius: 5px;
min-height: 30px;
cursor: pointer;
.span {
color: #c5c8ce;
}
.iconxiayi {
font-size: 12px;
}
}
</style>

View File

@ -34,6 +34,11 @@
</Form>
</Card>
<Card :bordered="false" dis-hover>
<Row type="flex">
<Col v-bind="grid">
<Button type="primary" icon="md-add" @click="add">添加语言地区</Button>
</Col>
</Row>
<Table
ref="table"
:columns="columns"
@ -46,7 +51,7 @@
<template slot-scope="{ row, index }" slot="action">
<a @click="edit(row)">编辑</a>
<Divider type="vertical" />
<a @click="del(row, '删除语言', index)">删除</a>
<a @click="del(row, '删除地区语言', index)">删除</a>
</template>
</Table>
<div class="acea-row row-right page">
@ -64,10 +69,17 @@
</template>
<script>
import { mapState } from 'vuex';
import { langCountryList } from '@/api/setting';
import { langCountryList, langCountryForm } from '@/api/setting';
export default {
data() {
return {
grid: {
xl: 7,
lg: 7,
md: 12,
sm: 24,
xs: 24,
},
formValidate: {
keyword: '',
page: 1,
@ -115,6 +127,32 @@ export default {
this.getList();
},
methods: {
// 添加
add() {
this.$modalForm(langCountryForm(0)).then(() => this.getList());
},
edit(row) {
this.$modalForm(langCountryForm(row.id)).then(() => this.getList());
},
// 删除
del(row, tit, num) {
let delfromData = {
title: tit,
num: num,
url: `setting/lang_country/del/${row.id}`,
method: 'DELETE',
ids: '',
};
this.$modalSure(delfromData)
.then((res) => {
this.$Message.success(res.msg);
this.tabList.splice(num, 1);
// this.getList();
})
.catch((res) => {
this.$Message.error(res.msg);
});
},
selChange() {
this.formValidate.page = 1;
this.getList();

View File

@ -102,7 +102,7 @@
<Radio :label="item.value" v-for="(item, index) in langType.isAdmin" :key="index">{{ item.title }}</Radio>
</RadioGroup>
</FormItem>
<Input v-model="langFormData.edit" type="hidden"></Input>
<Input v-model="langFormData.edit" v-show="false"></Input>
<FormItem label="语言说明:" prop="remarks" class="mb20">
<Input v-model="langFormData.remarks" placeholder="请输入语言说明" style="width: 330px"></Input>
</FormItem>

View File

@ -22,12 +22,6 @@
<FormItem label="确认新密码" prop="conf_pwd">
<Input type="password" v-model="formValidate.conf_pwd" class="input"></Input>
</FormItem>
<FormItem label="文件管理新密码" prop="file_pwd">
<Input type="password" v-model="formValidate.file_pwd" class="input"></Input>
</FormItem>
<FormItem label="文件管理确认新密码" prop="conf_file_pwd">
<Input type="password" v-model="formValidate.conf_file_pwd" class="input"></Input>
</FormItem>
<FormItem>
<Button type="primary" @click="handleSubmit('formValidate')">提交</Button>
</FormItem>
@ -59,16 +53,12 @@ export default {
pwd: '',
new_pwd: '',
conf_pwd: '',
file_pwd: '',
conf_file_pwd: '',
},
ruleValidate: {
real_name: [{ required: true, message: '您的姓名不能为空', trigger: 'blur' }],
pwd: [{ required: true, message: '请输入您的原始密码', trigger: 'blur' }],
new_pwd: [{ required: true, message: '请输入您的新密码', trigger: 'blur' }],
conf_pwd: [{ required: true, message: '请确认您的新密码', trigger: 'blur' }],
file_pwd: [{ required: true, message: '请输入您的文件管理新密码', trigger: 'blur' }],
conf_file_pwd: [{ required: true, message: '请确认您的文件管理新密码', trigger: 'blur' }],
},
};
},

View File

@ -0,0 +1,80 @@
<template>
<div>
<div class="i-layout-page-header">
<div class="i-layout-page-header">
<span class="ivu-page-header-title">{{ $route.meta.title }}</span>
</div>
</div>
<Card :bordered="false" dis-hover class="ivu-mt">
<Form ref="formValidate" :model="formValidate" :rules="ruleValidate" :label-width="160" label-position="right">
<FormItem label="账号" prop="">
<Input type="text" v-model="account" :disabled="true" class="input"></Input>
</FormItem>
<FormItem label="文件管理新密码" prop="file_pwd">
<Input type="password" v-model="formValidate.file_pwd" class="input"></Input>
</FormItem>
<FormItem label="文件管理确认新密码" prop="conf_file_pwd">
<Input type="password" v-model="formValidate.conf_file_pwd" class="input"></Input>
</FormItem>
<FormItem>
<Button type="primary" @click="handleSubmit('formValidate')">提交</Button>
</FormItem>
</Form>
</Card>
</div>
</template>
<script>
import { setFilePassword } from '@/api/user';
import { mapState } from 'vuex';
export default {
name: 'setting_files',
computed: {
...mapState('media', ['isMobile']),
...mapState('userLevel', ['categoryId']),
labelWidth() {
return this.isMobile ? undefined : 75;
},
labelPosition() {
return this.isMobile ? 'top' : 'left';
},
},
data() {
return {
account: '',
formValidate: {
file_pwd: '',
conf_file_pwd: '',
},
ruleValidate: {
file_pwd: [{ required: true, message: '请输入您的文件管理新密码', trigger: 'blur' }],
conf_file_pwd: [{ required: true, message: '请确认您的文件管理新密码', trigger: 'blur' }],
},
};
},
mounted() {
this.account = this.$store.state.userInfo.userInfo.account;
},
methods: {
handleSubmit(name) {
this.$refs[name].validate((valid) => {
if (valid) {
setFilePassword(this.formValidate)
.then((res) => {
this.$Message.success(res.msg);
})
.catch((res) => {
this.$Message.error(res.msg);
});
}
});
},
},
};
</script>
<style scoped>
.input {
width: 400px;
}
</style>

View File

@ -27,13 +27,13 @@
</template>
</Table>
</Card>
<Modal :class-name="className" v-model="modals" scrollable footer-hide closable :mask-closable="false" width="80%">
<Modal :class-name="className" v-model="modals" scrollable footer-hide closable :mask-closable="false" width="80%" :before-close = 'editModalChange'>
<p slot="header" class="diy-header" ref="diyHeader">
<span>{{title}}</span>
<Icon @click="winChanges" class="diy-header-icon" :type="className ? 'ios-contract' : 'ios-qr-scanner'" size = "20"/>
</p>
<div style="height: 100%;">
<Button type="primary" id="savefile" class="diy-button" @click="savefile">保存</Button>
<Button type="primary" id="savefile" class="diy-button" @click="savefile(indexEditor)">保存</Button>
<Button id="refresh" class="diy-button" @click="refreshfile">刷新</Button>
<div class="file-box">
@ -48,7 +48,7 @@
</div>
<div class="file-left">
<Tree class="diy-tree-render" :data="navList" :render="renderContent" :load-data="loadData" @on-contextmenu="handleContextMenu" expand-node>
<template class="diy-menu" slot="contextMenu">
<template transfer slot="contextMenu">
<DropdownItem v-if="contextData && contextData.isDir" @click.native="handleContextCreateFolder()">新建文件夹</DropdownItem>
<DropdownItem v-if="contextData && contextData.isDir" @click.native="handleContextCreateFile()">新建文件</DropdownItem>
<DropdownItem @click.native="handleContextRename()">重命名</DropdownItem>
@ -58,7 +58,11 @@
</div>
<div class="file-fix"></div>
<div class="file-content">
<div id="container" style="height:100%;min-height: 600px;"></div>
<Tabs type="card" v-model="indexEditor" style="height: 100%;" @on-click="toggleEditor" :animated="false" closable @on-tab-remove="handleTabRemove">
<TabPane v-for="(value) in editorIndex" :key="value.index" :name="value.index.toString()" :label="value.title" :icon="value.icon" v-if="value.tab">
<div ref="container" :id="'container_'+value.index" style="height:100%;min-height: 560px;"></div>
</TabPane>
</Tabs>
</div>
<Spin size="large" fix v-if="spinShow"></Spin>
</div>
@ -105,17 +109,38 @@
getCookies,
removeCookies
} from '@/libs/util';
import Fullscreen from '@/components/main/components/fullscreen';
// import Fullscreen from '@/components/main/components/fullscreen';
import * as monaco from 'monaco-editor'
export default {
name: 'opendir',
data() {
return {
editor: '',
modals: false, //编辑器开关
editor: '', //当前编辑器对象
editorIndex:[ //选项卡数组
{
tab:true,
index:'0',
title:'',
icon:'',
}
],
editorList:[], //编辑器数组
indexEditor:0, //当前编辑器索引
code: '', //当前文件打开时的内容
navList: [], //左侧导航数据
navItem:{}, //左侧导航点击是选中的数据
contextData:null, //左侧导航右键点击是产生的数据对象
fileType:'', // 文件操作类型 createFolder|创建文件夹 createFile|创建文件 delFolder|删除文件夹或者文件
className:"", //全屏 class名
// fullscreen:false, // 是否全屏
isSave:true, //当前文件是否保存
isShowLogn: false, // 登录
isShowList: false, // 登录之后列表
code: '',
modals: false,
spinShow: false,
loading: false,
tabList: [],
@ -151,17 +176,17 @@
minWidth: 150,
},
],
formItem: {
formItem: { //记录当前路径信息,获取文件列表时使用
dir: '',
superior: 0,
filedir: '',
},
rows: {},
pathname: '',
title: '',
navList: [], //左侧导航数据
navItem:{}, //左侧导航点击是选中的数据
contextData:null, //左侧导航右键点击是产生的数据对象
dir:'', //当前完整文件路径
// rows: {}, //
pathname: '', // 当前文件路径
title: '', //当前文件标题
formFile: { //重命名表单
filename: '',
},
@ -170,17 +195,13 @@
{ required: true, message: '请输入文件或文件夹的名字', trigger: 'blur' }
]
},
formShow:false,
// 文件操作类型 createFolder|创建文件夹 createFile|创建文件 delFolder|删除文件夹或者文件
fileType:'',
formTitle:'测试',
className:"",
fullscreen:false, // 是否全屏
formShow:false, //表单开关
formTitle:'', //表单标题
};
},
components: {
loginFrom,
Fullscreen
},
mounted() {
this.initEditor();
@ -261,7 +282,7 @@
},
// 打开
open(row) {
this.rows = row;
// this.rows = row;
this.formItem = {
dir: row.path,
superior: 0,
@ -275,28 +296,48 @@
this.spinShow = true;
this.pathname = row.pathname;
this.title = row.filename;
this.editorIndex[0].title = row.filename;
this.navList = this.navListForTab;
this.openfile(row.pathname,true);
this.dir = row.path;
// 创建代码容器
if(this.editorList.length <= 0)
{
this.initEditor();
}
this.openfile(row.pathname,false);
},
// 保存
savefile() {
/**
* 保存
* @param {Object} index // 当前索引
* @param {Object} type // true 不更新当前本地数据,false或者为空 更新当前数据
*/
savefile(index,type) {
let code = this.editorList[index].editor.getValue();
let data = {
comment: this.editor.getValue(),
filepath: this.pathname,
comment: code,
filepath: this.editorList[index].path,
};
let that = this;
savefileApi(data)
.then(async (res) => {
this.$Message.success(res.msg);
// this.modals = false;
if(!type)
{
that.code = code;
that.isSave = true;
that.editorIndex[index].icon = '';
that.editorList[index].isSave = true;
}
that.$Message.success(res.msg);
that.$Modal.remove();
})
.catch((res) => {
this.catchFun(res);
that.catchFun(res);
});
},
// 刷新
refreshfile() {
// 刷新编辑器
if(!this.navItem.isDir) this.openfile(this.navItem.pathname,false);
if(this.editorList[this.indexEditor]) this.openfile(this.editorList[this.indexEditor].path,true);
},
// 登录跳转
onLogin(data) {
@ -381,11 +422,20 @@
* @param {Object} data
*/
clickDir(data,root,node){
this.navItem = data;
this.pathname = data.pathname;
let that = this;
that.navItem = data;
that.pathname = data.pathname;
if(!data.isDir)
{
this.openfile(data.pathname,false);
let index = that.editorIndex.length
// 创建tabs
that.editorIndex.push({tab:true,index:index.toString(),title:data.title,icon:''});
that.indexEditor = index.toString();
// 创建代码容器
that.initEditor();
that.openfile(data.pathname,true);
}
},
//侧边栏右键点击事件
@ -394,7 +444,7 @@
this.contextData = data;
},
// 文件操作类型 createFolder|创建文件夹 createFile|创建文件 delFolder|删除文件夹或者文件
// 文件操作类型 createFolder|创建文件夹 createFile|创建文件 delFolder|删除文件夹或者文件 renameFile|文件重命名
//创建文件夹
handleContextCreateFolder () {
this.formFile.filename = '';
@ -443,21 +493,24 @@
},
//打开文件
openfile(path,is_edit){
let that = this;
openfileApi(path)
.then(async (res) => {
let data = res.data;
this.code = data.content;
// this.editor.setValue(this.code);
that.code = data.content;
// 保存相对信息
that.editorList[that.indexEditor].path = path;
that.editorList[that.indexEditor].oldCode = that.code;
//改变属性
this.changeModel(data.mode,this.code);
if(is_edit)
that.changeModel(data.mode,that.code);
if(!is_edit)
{
this.modals = true;
this.spinShow = false;
that.modals = true;
that.spinShow = false;
}
})
.catch((res) => {
this.catchFun(res);
that.catchFun(res);
});
},
/**
@ -465,38 +518,45 @@
*/
initEditor(){
let that = this;
// 初始化编辑器,确保dom已经渲染
that.editor = monaco.editor.create(document.getElementById('container'), {
value:that.code,//编辑器初始显示文字
language:'sql',//语言支持自行查阅demo
automaticLayout: true,//自动布局
theme:'vs-dark' ,//官方自带三种主题vs, hc-black, or vs-dark
foldingStrategy: 'indentation', // 代码可分小段折叠
overviewRulerBorder: false, // 不要滚动条的边框
scrollbar: { // 滚动条设置
verticalScrollbarSize: 4, // 竖滚动条
horizontalScrollbarSize: 10, // 横滚动条
},
autoIndent: true, // 自动布局
tabSize: 4, // tab缩进长度
autoClosingOvertype:'always',
that.$nextTick(() => {
// 初始化编辑器,确保dom已经渲染
that.editor = monaco.editor.create(document.getElementById('container_'+that.indexEditor), {
value:that.code,//编辑器初始显示文字
language:'sql',//语言支持自行查阅demo
automaticLayout: true,//自动布局
theme:'vs-dark' ,//官方自带三种主题vs, hc-black, or vs-dark
foldingStrategy: 'indentation', // 代码可分小段折叠
overviewRulerBorder: false, // 不要滚动条的边框
scrollbar: { // 滚动条设置
verticalScrollbarSize: 4, // 竖滚动条
horizontalScrollbarSize: 10, // 横滚动条
},
autoIndent: true, // 自动布局
tabSize: 4, // tab缩进长度
autoClosingOvertype:'always',
});
//添加按键监听
that.editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KEY_S, function () {
  that.savefile(that.indexEditor);
});
that.editor.onKeyUp(() => {
// 当键盘按下,判断当前编辑器文本与已保存的编辑器文本是否一致
if(that.editor.getValue() != that.code){
that.isSave = false;
that.editorIndex[that.indexEditor].icon = 'md-warning';
that.editorList[that.indexEditor].isSave = false;
}
});
that.editorList.push({'editor':that.editor,'oldCode':that.code,'path':'','isSave':true,'index':that.indexEditor});
});
//添加按键监听
that.editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KEY_S, function () {
  that.savefile();
});
},
getValue(){
this.editor.getValue(); //获取编辑器中的文本
},
/**
* 切换语言
* @param {Object} mode
*/
changeModel(mode,value){
var oldModel = this.editor.getModel();//获取旧模型
var oldModel = this.editorList[this.indexEditor].editor.getModel();//获取旧模型
// var value = this.editor.getValue();//获取旧的文本
//创建新模型,value为旧文本,id为modeId,即语言(language.id)
//modesIds即为支持语言
@ -510,7 +570,7 @@
oldModel.dispose();
}
//设置新模型
this.editor.setModel(newModel);
this.editorList[this.indexEditor].editor.setModel(newModel);
},
// 文件操作类型 createFolder|创建文件夹 createFile|创建文件 delFolder|删除文件夹或者文件
handleSubmit(name) {
@ -616,6 +676,9 @@
}
})
},
/**
* 窗口最大化
*/
winChanges(){
if(this.className)
{
@ -623,6 +686,76 @@
}else{
this.className = "diy-fullscreen";
}
},
/**
* 切换选项卡
* @param {Object} index
*/
toggleEditor(index){
index = Number(index);
this.code = this.editorList[index].oldCode; //设置文件打开时的代码
this.editor = this.editorList[index].editor; //设置编辑器实例
},
handleTabRemove (index) {
let that = this;
// 关闭选项卡
that.editorIndex[index].tab = false; // 关闭选项卡
// 判断当前文件有没有保存
if(!that.editorList[index].isSave)
{
that.$Modal.confirm({
title: '文件未保存',
content: '您是否需要保存当前文件',
loading: true,
onOk: () => {
// 保存文件
that.savefile(index);
},
onCancel: () => {
that.$Message.info('取消保存');
},
});
}
},
//编辑器状态变化
editModalChange()
{
let that = this;
that.editorList.forEach(function(value,index){
if(value.isSave === false)
{
if(confirm(`${that.editorIndex[index].title}文件未保存,是否要保存该文件`))
{
// 保存当前文件
that.savefile(index,true);
}else{
that.$Message.info(`已取消${that.editorIndex[index].title}文件保存`);
}
}
// 销毁当前编辑器
that.editorList[index].editor.dispose();
that.editorList[index].editor = null;
});
// 初始话数据
that.modals = false; //编辑器开关
that.editor = ''; //当前编辑器对象
that.editorIndex = [ //选项卡数组
{
tab:true,
index:'0',
title:'',
icon:'',
}
];
that.editorList = []; //编辑器数组
that.indexEditor = '0'; //当前编辑器索引
that.code = ''; //当前文件打开时的内容
that.navList = []; //左侧导航数据
that.navItem = {}; //左侧导航点击是选中的数据
that.contextData = null; //左侧导航右键点击是产生的数据对象
}
},
};
@ -764,7 +897,7 @@
white-space:nowrap;/* 不换行 */
overflow:hidden;
text-overflow:ellipsis;
padding: 5px 5px;
padding: 7px 5px;
body >>>.ivu-select-dropdown{
background: #fff;
}
@ -815,9 +948,39 @@ body >>>.ivu-select-dropdown{
height: 100%;
.ivu-modal-body
height: 100%;
.ivu-tabs
.ivu-tabs-content-animated
height: 92%;
background-color:#2f2f2f !important;
.ivu-tabs-content
height: 100%
.ivu-tabs
.ivu-tabs-tabpane
height: 92%
>>>.ivu-modal
.ivu-modal-content
.ivu-modal-body
height: 632px;
overflow: hidden;
.ivu-tabs
.ivu-tabs-content-animated
height: 560px;
margin-top: -1px;
.ivu-tabs-tabpane
height: 560px;
margin-top: -1px;
.ivu-tabs-nav .ivu-tabs-tab .ivu-icon
color: #f00;
>>>body .ivu-select-dropdown .ivu-dropdown-transfer
background:red !important;
// 导航栏右键样式 无效
.ivu-select-dropdown.ivu-dropdown-transfer{
background:#fff !important;
}
.ivu-select-dropdown.ivu-dropdown-transfer .ivu-dropdown-menu .ivu-dropdown-item:hover{
background-color: #e5e5e5 !important;
}
// 选项卡头部
>>>.ivu-tabs.ivu-tabs-card > .ivu-tabs-bar .ivu-tabs-nav-container
background-color: #333;
</style>

View File

@ -57,6 +57,15 @@ const frameIn = [
},
component: () => import('@/pages/setting/user/index'),
},
{
path: '/admin/system/files',
name: `systemFiles`,
meta: {
auth: ['admin-setting-files'],
title: '文件管理',
},
component: () => import('@/pages/setting/userFile/index'),
},
// 刷新页面 必须保留
{
path: 'refresh',

View File

@ -677,3 +677,4 @@ body {
.paddingBox {
padding: 0 10px 10px;
}