Browse Source

增加低代码表格

v1
超级管理员 2 years ago
parent
commit
8915ff1235
  1. 10
      package.json
  2. 4
      src/api/DesignForm/flow.ts
  3. 19
      src/api/DesignForm/form.ts
  4. 73
      src/api/DesignForm/index.ts
  5. 22
      src/api/DesignForm/system.ts
  6. 87
      src/api/DesignForm/types.ts
  7. 108
      src/api/DesignForm/utils.ts
  8. 12
      src/api/displayboardapi/indexapi.ts
  9. 52
      src/api/displayboardapi/types.ts
  10. 14
      src/api/hr/people/index.ts
  11. 24
      src/api/hr/people/type.ts
  12. 33
      src/api/matrixapi/index.ts
  13. 21
      src/api/matrixapi/type.ts
  14. 139
      src/assets/data.json
  15. 539
      src/assets/iconfont/demo.css
  16. 1959
      src/assets/iconfont/demo_index.html
  17. 323
      src/assets/iconfont/iconfont.css
  18. 1
      src/assets/iconfont/iconfont.js
  19. 548
      src/assets/iconfont/iconfont.json
  20. BIN
      src/assets/iconfont/iconfont.ttf
  21. BIN
      src/assets/iconfont/iconfont.woff
  22. BIN
      src/assets/iconfont/iconfont.woff2
  23. 1
      src/assets/icons/select1.svg
  24. 1
      src/assets/icons/select3.svg
  25. BIN
      src/assets/image/icon_file.png
  26. BIN
      src/assets/image/icon_people.png
  27. BIN
      src/assets/image/next_level.png
  28. BIN
      src/assets/image/next_level_active.png
  29. BIN
      src/assets/img/data.png
  30. BIN
      src/assets/img/echarts.png
  31. BIN
      src/assets/img/flow.png
  32. BIN
      src/assets/img/form-list.png
  33. BIN
      src/assets/img/form.png
  34. BIN
      src/assets/img/ruler.png
  35. 9
      src/assets/scss/element-var.scss
  36. 125
      src/assets/scss/flow.scss
  37. 296
      src/assets/scss/form.scss
  38. 1
      src/assets/scss/index.scss
  39. 120
      src/assets/scss/layout.scss
  40. 111
      src/assets/scss/screen.scss
  41. 322
      src/components/DesignForm/assembly/index.ts
  42. 166
      src/components/DesignForm/dragControl.vue
  43. 14
      src/components/DesignForm/public/form/childTable.vue
  44. 14
      src/components/DesignForm/public/form/flexBox.vue
  45. 483
      src/components/DesignForm/public/form/form.vue
  46. 436
      src/components/DesignForm/public/form/formGroup.vue
  47. 14
      src/components/DesignForm/public/form/formItem.vue
  48. 68
      src/components/DesignForm/public/headTools.vue
  49. 49
      src/components/DesignForm/template.vue
  50. 19
      src/components/DesignForm/tooltip.vue
  51. 7
      src/main.ts
  52. 22
      src/store/DesignForm/designForm.ts
  53. 42
      src/store/DesignForm/layout.ts
  54. 87
      src/utils/DesignForm/form.ts
  55. 16
      src/utils/DesignForm/formChangeValue.ts
  56. 34
      src/utils/DesignForm/formatResult.ts
  57. 18
      src/utils/DesignForm/formatScreen.ts
  58. 95
      src/utils/DesignForm/index.ts
  59. 35
      src/utils/DesignForm/request.ts
  60. 7
      src/views/matrix/index.vue
  61. 21
      src/views/matrix/matrixcont/setupmatrixfield.vue
  62. 183
      src/views/matrix/matrixcont/setupmatrixuser.vue
  63. 182
      src/views/matrix/matrixcont/setupmatrixuser_black.vue
  64. 613
      src/views/matrix/orgoruser/pickorg.vue
  65. 256
      src/views/matrix/orgoruser/pickuser.vue
  66. 244
      src/views/sysworkflow/codepage/index.vue

10
package.json

@ -40,6 +40,7 @@
]
},
"dependencies": {
"@element-plus/icons-vue": "^2.1.0",
"@vitejs/plugin-vue": "^4.2.3",
"@vueuse/core": "^10.1.2",
"@wangeditor/editor": "^5.1.23",
@ -48,19 +49,26 @@
"axios": "^1.4.0",
"echarts": "^5.2.2",
"element-plus": "^2.3.4",
"js-beautify": "^1.14.8",
"js-md5": "^0.7.3",
"md5": "^2.3.0",
"nprogress": "^0.2.0",
"path-browserify": "^1.0.1",
"path-to-regexp": "^6.2.0",
"pinia": "^2.0.33",
"screenfull": "^6.0.0",
"ts-md5": "^1.3.1",
"vue": "^3.3.1",
"vue-i18n": "9.2.2",
"vue-router": "^4.2.0"
"vue-router": "^4.2.0",
"vuedraggable": "^4.1.0",
"vuedraggable-es": "^4.1.1"
},
"devDependencies": {
"@commitlint/cli": "^17.6.3",
"@commitlint/config-conventional": "^17.6.3",
"@iconify-json/ep": "^1.1.10",
"@types/md5": "^2.3.2",
"@types/nprogress": "^0.2.0",
"@types/path-browserify": "^1.0.0",
"@typescript-eslint/eslint-plugin": "^5.59.6",

4
src/api/DesignForm/flow.ts

@ -0,0 +1,4 @@
export default {
flowSave: 'flow/save',
flowList: 'flow/list'
}

19
src/api/DesignForm/form.ts

@ -0,0 +1,19 @@
export default {
designSave: 'design/save', // 保存设计的表单
designEdit: 'design/edit', // 保存设计的表单
designList: 'design/list', // 获取所有已设计的表单
designChange: 'design/change', // 改变设计表单部分设置内容
designDelete: 'design/delete', // 根据id删除已设计
designById: 'design/id', // 根据id获取已设计的表单
sourceList: 'dataSource/list', // 获取数据源列表
sourceDelete: 'dataSource/delete',
sourceCreat: 'dataSource/creat', // 创建数据源
sourceEdit: 'dataSource/edit', // 编辑数据源
sourceById: 'dataSource/id', // 根据id获取数据源
saveFormContent: 'content/save', // 往已设计好的表单里添加内容
editFormContent: 'content/edit', // 往已设计好的表单里添加内容
getContentList: 'content/list', // 获取表单内容列表
delFormContent: 'content/delete', // 删除表单内容
getFormContent: 'content/id', // 获取表单内容
upload: 'upload/single' // 默认el-upload上传url,也可单独在设计时填写上传地址
}

73
src/api/DesignForm/index.ts

@ -0,0 +1,73 @@
import request from '@/utils/DesignForm/request'
import form from './form'
import system from './system'
import flow from './flow'
const allApi: any = Object.assign(form, system, flow)
export const getRequest = (apiKey: string, data?: any, options: any = {}) => {
let url = allApi[apiKey] || apiKey
// 解决动态url 如/api/delete/id(id为动态时)
// url设置为:/api/delete/$id
// options参数设置:options:{apikey:$id:xx}
if (Object.keys(options.apiKey || {}).length) {
for (const key in options.apiKey) {
url = url.replace(key, options.apiKey[key])
}
}
let obj: any = Object.assign(
{
url: '/api/' + url, // 添加个前缀
method: 'POST',
data
},
options
)
// github演示时使用下面地址
if (window.location.host.indexOf('github') !== -1) {
let id = ''
if (url.indexOf('/id') !== -1 && data.id) {
id = data.id + ''
}
if (url.indexOf('/id') !== -1 && data.formId) {
id += data.formId
}
if (url.indexOf('design/list') !== -1 && data.type) {
id = data.type
}
if (url.indexOf('content/list') !== -1 && data.formId) {
id = data.formId
}
if (
url.includes('/save') ||
url.includes('/edit') ||
url.includes('/delete') ||
url.includes('/creat') ||
url.includes('/change') ||
url.includes('/single')
) {
url = 'ok'
}
if (options.method) {
delete options.method
}
obj = Object.assign(
{
url: `./mock/${url}${id}.json`,
method: 'GET',
params: data
},
options
)
}
return request(obj)
}
export const uploadUrl = '/api/' + allApi.upload
/*export function uploadFiledTinymce(data, url) {
return request({
url: url || '/upload/single',
method: 'post',
data,
headers: {
'Content-Type': 'multipart/form-data'
}
})
}*/

22
src/api/DesignForm/system.ts

@ -0,0 +1,22 @@
export default {
dictSave: 'system/dict/save',
dictList: 'system/dict/list',
dictDelete: 'system/dict/delete',
dictEdit: 'system/dict/edit',
deptSave: 'system/dept/save',
deptEdit: 'system/dept/edit',
deptList: 'system/dept/list',
deptDelete: 'system/dept/delete',
menuSave: 'system/menu/save',
menuEdit: 'system/menu/edit',
menuList: 'system/menu/list',
menuDelete: 'system/menu/delete',
roleSave: 'system/role/save',
roleEdit: 'system/role/edit',
roleList: 'system/role/list',
roleDelete: 'system/role/delete',
userSave: 'system/user/save',
userEdit: 'system/user/edit',
userList: 'system/user/list',
userDelete: 'system/user/delete'
}

87
src/api/DesignForm/types.ts

@ -0,0 +1,87 @@
export interface FormList {
name: string
type: string
control: any // 当前type表单控件所有props
item?: FormItem // formItem组件所有props
config: any // 其他配置信息
customRules?: any // 自定义检验规则,这个规则会合并进item.rules
columns?: any // 布局字段
tableData?: any // 子表时
options?: Options[] // radio,checkbox,select选项
}
export interface Options {
label: string
value: string
disabled?: boolean
}
export interface FormItem {
label?: string
labelWidth?: string
required?: boolean
rules?: any
error?: string
showMessage?: boolean
inlineMessage?: boolean
size?: string
showLabel?: boolean
}
export interface FormData {
list: FormList[]
form: any // form所有props
config?: {
style?: string // 表单css样式,相当于scope
hideField?: string[] // 使用v-if隐藏的字段,用于交互
requestUrl?: string // 表单数据请求url
addUrl?: string // 提交表单
editUrl?: string // 编辑保存
addLoad?: boolean
expand?: boolean // 用于设置筛选条件默认展开/收起状态
}
events?: {
beforeRequest?: Function
afterResponse?: Function | string
beforeSubmit?: Function
afterSubmit?: Function
change?: Function
}
}
export interface TableData {
tableProps?: any
columns: any
controlBtn?: any
events?: any
treeData?: {
show: boolean
beforeRequest?: Function
afterResponse?: Function | string
method: string
requestUrl: string
name: string
}
operateBtn?: any
config?: any
}
export interface OpenDrawer {
//visible: boolean
title?: string
direction?: string
content?: any
codeType?: string
callback?: Function | string
type?: string
}
//文件
export interface FileAttribute{
imgPath:any;
title:any;
formData:any;
}
export interface FileAttributeAll{
visible:boolean;
list:FileAttribute[];
}

108
src/api/DesignForm/utils.ts

@ -0,0 +1,108 @@
import { EDITTYPE } from '@/utils/DesignForm/form'
export const aceEdit = (data: any, id?: string, type?: string | undefined) => {
id = id || 'editJson'
type = type || EDITTYPE
// @ts-ignore
const editor = ace.edit(id)
editor.setOptions({
enableBasicAutocompletion: true,
enableSnippets: true,
enableLiveAutocompletion: true
})
editor.setFontSize(14)
editor.setShowPrintMargin(false)
editor.session.setMode('ace/mode/' + type)
editor.setTheme('ace/theme/tomorrow_night')
editor.setValue(data)
return editor
}
// 将字符类数字转为数值类
export const formatNumber = (val: any) => {
// 将字符类数字转为数值类
if (typeof val === 'string' && /^\d+(\.\d+)?$/.test(val.toString())) {
// 为数字
return Number(val)
} else {
return val
}
}
// 转所有值转为字符串类型
export const formatToString = (val: any) => {
if (val !== undefined) {
return val.toString()
} else {
return val
}
}
// 将{key:value}转[{label:'key',value:'value'}]
export const objectToArray = (obj: any) => {
if (Object.prototype.toString.call(obj) === '[object Object]') {
const temp: any = []
for (const key in obj) {
temp.push({
label: obj[key],
value: key
})
}
return temp
}
return obj
}
/****
* css
* @param id id
* @param cssContent css内容
* @param append true插入false移除
*/
export const appendOrRemoveStyle = (
id: string,
cssContent: string,
append?: boolean
) => {
const styleId: any = document.getElementById(id)
if (styleId && append) {
// 存在时直接修改,不用多次插入
styleId.innerText = cssContent
return
}
if (cssContent && append) {
const styleEl = document.createElement('style')
styleEl.id = id
styleEl.type = 'text/css'
styleEl.appendChild(document.createTextNode(cssContent))
document.head.appendChild(styleEl)
}
if (!append || !cssContent) {
// 移除
styleId && styleId.parentNode.removeChild(styleId)
}
}
// 定义两个空方法,用于在编辑事件时作为默认值
export const beforeRequest =
'opt=(data, route) => {\n' +
' // data经过处理后返回\n' +
" console.log('beforeRequest',data)\n" +
' return data\n' +
'}'
export const afterResponse =
'opt=(res) => {\n' +
' // res返回数据\n' +
" console.log('afterResponse',res)\n" +
' return res\n' +
'}'
export const onChange =
'opt=(key,model) => {\n' +
' // name当前改变组件的值,model表单的值\n' +
" console.log('onChange',key)\n" +
' return model\n' +
'}'
// provide 方法定义的key
const prefix = 'AK'
export const constControlChange = prefix + 'ControlChange' // 表单组件改变事件
export const constSetFormOptions = prefix + 'SetFormOptions' // 使用setOptions设置下拉值
export const constGetControlByName = prefix + 'GetControlByName' // 根据name从formData.list查找数据
export const constFormBtnEvent = prefix + 'FormBtnEvent' // 按钮组件事件
export const constFormProps = prefix + 'FormProps' // 按钮组件事件

12
src/api/displayboardapi/indexapi.ts

@ -1,6 +1,6 @@
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { dimissionRateQuery,publicId,eduStruCont,sendOrgCont } from './types';
import { dimissionRateQuery,publicId,eduStruCont,sendOrgCont,outputOrgAndUser } from './types';
/**
*
*/
@ -51,3 +51,13 @@ import { dimissionRateQuery,publicId,eduStruCont,sendOrgCont } from './types';
data: data
});
}
/**
*
*/
export function getBasisOrgChiled(data?: publicId): AxiosPromise<outputOrgAndUser>{
return request({
url: '/hrapi/org/basis_org_obtain_sonorg_and_man',
method: 'post',
data: data
});
}

52
src/api/displayboardapi/types.ts

@ -1,5 +1,5 @@
export interface publicId{
id?:number;
id?:number|string;
}
/**
*
@ -34,14 +34,17 @@ export interface orgInfo{
schoole: number;
kingdeeid: string;
ispower: number;
sort: number
sort: number;
ischild: boolean;
isActiveItem: boolean;
}
/**
*
*/
export interface sendOrgCont{
current:number;
list:orgInfo[]
list:orgInfo[];
tabval:any;
}
/**
*
@ -50,3 +53,46 @@ export interface eduStruCont{
education:string;
percentage:number;
}
/**
*
*/
export interface breadCrumbs{
departmentId:string // "309",
id:string // "309",
departmentKey:string // "GK00",
departmentName:string // "山东恒信高科能源有限公司",
parentId:string // "313",
departmentNames:string // "山东恒信高科能源有限公司"
}
/**
*
*/
export interface outputOrgAndUser{
childDepartments:childDepartmentsCont[];
employees:employeesCont[];
titleDepartments:breadCrumbs[];
}
export interface employeesCont{
id:string //"95196156539179008",
employeeName:string //"胡齐帅",
isLeave:string //"0",
open:boolean //"false",
icon:string //"",
iconToBase64:string //"",
wechat:string //"",
departmentid:number //102,
departmentname:string //"企管部",
postid:number //798,
postname:string //"岗监员",
tema:number //0,
temaname:string //""
ispick:boolean //
}
export interface childDepartmentsCont{
id:string; //"103",
departmentKey:string; //"GK0302",
departmentName:string; //"IT",
parentId:string; //"102",
departmentNames:string; //"IT"
isActiveItem:boolean; //
}

14
src/api/hr/people/index.ts

@ -20,7 +20,9 @@ import {
groupInnerWorkCont,
editUserIcon,
editUserAboutOrg,
teamClassQueay
teamClassQueay,
searchPeoleCont,
queryPeopleCont
} from './type';
/**
*
@ -344,3 +346,13 @@ import {
data: data
});
}
/**
*
*/
export function searchUserCont(data: searchPeoleCont): AxiosPromise<PageResult<queryPeopleCont[]>>{
return request({
url: '/kpiapi/powerpc/search_people',
method: 'post',
data: data
});
}

24
src/api/hr/people/type.ts

@ -542,3 +542,27 @@ export interface teamClassCont{
rule:teamRule[];
list:teamList[];
}
/**
*
*/
export interface searchPeoleCont extends PageQuery{
name?:number|string; //关键字
}
/**
*
*/
export interface queryPeopleCont{
id:string // "15993815826844528",
employeeName:string // "秦东",
isLeave:string // "0",
open:boolean // "false",
icon:string // "https://wework.qpic.cn/wwhead/duc2TvpEgSTPk74IwG7BswsATgrfz6BGVPpX5QU5uvaCiaxk3ReIlRhdUwIeiaBBazzCLiaHI8VuA4/0",
iconToBase64:string //
wechat:string // "KaiXinGuo",
departmentid:number // 102,
departmentname:string // "企管部",
postid:number // 794,
postname:string // "主管",
tema:number // 1,
temaname:string // "长白班"
}

33
src/api/matrixapi/index.ts

@ -1,6 +1,6 @@
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { searchMatrix,matrixCont,editMatrixCont,editMatrixInfo,editStatus,chineseInitialFirstWord,sendMatrixField,getMatrixWord } from './type';
import { searchMatrix,matrixCont,editMatrixCont,editMatrixInfo,editStatus,chineseInitialFirstWord,sendMatrixField,getMatrixWord,orgAndUserMatrixCont } from './type';
/**
*
@ -72,3 +72,34 @@ export function editMatrixCont(queryParams: editMatrixInfo){
data: queryParams
});
}
/**
*
*/
export function getNumber(queryParams: getMatrixWord){
return request({
url: '/systemapi/public/send_number',
method: 'post',
data: queryParams
});
}
/**
*
*/
export function submitMatrixData(queryParams: any){
return request({
url: '/systemapi/matrix/submit_matrix_data',
method: 'post',
data: queryParams
});
}
/**
*
*/
export function haveMatrixCont(queryParams: getMatrixWord){
return request({
url: '/systemapi/matrix/gain_matrix_data',
// url: 'http://localhost:9999/src/assets/data.json',
method: 'post',
data: queryParams
});
}

21
src/api/matrixapi/type.ts

@ -81,6 +81,7 @@ export interface matrixTable{
id:number;
label:string;
prop:string
types:number;
}
/**
*
@ -88,3 +89,23 @@ export interface matrixTable{
export interface objectStruct{
[idx: string]: any
}
/**
* 穿
*/
export interface shuttleFramePickData{
id:number|string;
name:string;
icon:string;
}
/**
* 使
*/
export interface orgAndUserMatrixCont{
id:number|string;
number:string;
userlist:shuttleFramePickData[];
types:number;
mcid:number;
mhid:number;
}

139
src/assets/data.json

@ -0,0 +1,139 @@
{
"code": 0,
"msg": "成功",
"data": {
"childDepartments": [
{
"id": "103",
"departmentKey": "GK0302",
"departmentName": "IT",
"parentId": "102",
"departmentNames": "IT"
},
{
"id": "272",
"departmentKey": "GK0301",
"departmentName": "企管",
"parentId": "102",
"departmentNames": "企管"
},
{
"id": "273",
"departmentKey": "GK0303",
"departmentName": "岗监",
"parentId": "102",
"departmentNames": "岗监"
}
],
"employees": [
{
"id": "10638305678856192",
"employeeName": "庞富镇",
"isLeave": "0",
"open": "false",
"icon": "",
"iconToBase64": "data:image/jpeg;base64,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",
"wechat": "PangFuZhen",
"departmentid": 102,
"departmentname": "企管部",
"postid": 1949,
"postname": "开发专员",
"tema": 0,
"temaname": ""
},
{
"id": "20833135155482624",
"employeeName": "薛中国",
"isLeave": "0",
"open": "false",
"icon": "",
"iconToBase64": "data:image/jpeg;base64,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",
"wechat": "XueZhongGuo",
"departmentid": 102,
"departmentname": "企管部",
"postid": 797,
"postname": "IT",
"tema": 0,
"temaname": ""
},
{
"id": "95196156539179008",
"employeeName": "胡齐帅",
"isLeave": "0",
"open": "false",
"icon": "",
"iconToBase64": "",
"wechat": "",
"departmentid": 102,
"departmentname": "企管部",
"postid": 798,
"postname": "岗监员",
"tema": 0,
"temaname": ""
},
{
"id": "95196160066588672",
"employeeName": "高宇",
"isLeave": "0",
"open": "false",
"icon": "",
"iconToBase64": "data:image/jpeg;base64,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",
"wechat": "",
"departmentid": 102,
"departmentname": "企管部",
"postid": 798,
"postname": "岗监员",
"tema": 0,
"temaname": ""
},
{
"id": "112229905093103616",
"employeeName": "孙殿泉",
"isLeave": "0",
"open": "false",
"icon": "",
"iconToBase64": "data:image/jpeg;base64,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",
"wechat": "",
"departmentid": 102,
"departmentname": "企管部",
"postid": 1120,
"postname": "新员工",
"tema": 0,
"temaname": ""
},
{
"id": "134825671351341056",
"employeeName": "李文轩",
"isLeave": "0",
"open": "false",
"icon": "",
"iconToBase64": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAgAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0a\r\nHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIy\r\nMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAB4AGQDASIA\r\nAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQA\r\nAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3\r\nODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWm\r\np6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEA\r\nAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSEx\r\nBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElK\r\nU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3\r\nuLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD2M0ma\r\nU1GTUgOzRmoy1YfiDxTY+HYPMu5Bk8hR1NIZ0G6kJrze6+MvhyG3keFbqaRfux7Au4/UnpXMJ8dr\r\ngzvnRYzCfugT8j6nHP5U7Ae37qN1eOW/xzt9xFzpTckY8uUfj1rsvDvxG0HxC8cMc/2e6ccQzHBJ\r\n9AehoA7HdSZpAcj2NFADgaTOKSikAuaKKKBDyaiY09jioHbFAyC/u0s7Ka4c/LGhY/hXy34n1q41\r\nnWLiaSeRo952AngD0GK+hvGdw8XhDVXj+8tuxr5hs7a71O58mAdPvN6CmmtwtfREJ2luV4Hc0rtH\r\ngAsBXUR+DHdPmuHye9MbwK2f+PhvxFT7WHc09jPscqx3kBMGnxyNEyFWYMOcqeQa6xfAmSD55+mK\r\nbe+CPLhLQSN5gHfpR7WAexn2PRvhj8Rp9QC6VqkhlkRAIpT1IHY+p6V68DmvkTRL250HXonkUJLG\r\n3O7IGPw/nX1fp1wLrT7ecEESRqwI6ciqZmXc0DmkBzTlpCFxRS0UWGMeqkzVac1TnoAxtctP7R0a\r\n9syM+dC6D6kcfrXivg6xS2sruecKmJCpJ7Y617lO20E4zgZrzRLW2e3uJPJAhmmaby8Zxk5xWVR6\r\nWN6EW5XKlvqukzSCP7Rt9ypArdh06JowwkWTPcVhSajaQmKM2MxDnAIRfl+vORWxZSo0aGE4SQZA\r\nxj9K55JdDupu+jHz21tbJullWMDqScVkPq2kmfyhdKT06Vq38kUMZkmwVHBzzWTHqmlXKtGbN1Ab\r\nYzNEMZoik0E3Z2Ry/jDR999aTW6585hGCvcnpX0Pp0H2PTra2znyYljznOcDFeXpa2azadLcKxt7\r\nW4WbaoyTtDEfrj8q9TgkEsSSLkK6hhketdVKXu2OCvFqVy2pqRTUCmpVNaGJLRQOlFAELmqk3SrL\r\nmq0vIpAZ83WuOuoY7a6kiUcBiQPTPP8AWuxnFcrrkey8Eg/iXn6j/IrGotDow7tKxnvFEVLMOBUV\r\nvMrTFlwQvAA7U2SXdGwJ7VlC+nhmVUEawom0rjlj65/piudK56N0jbeWKS4aKQDB7GpktYowcKMf\r\nSsKC4uJ5XEuzBYMhAwVH1zz+lbQuMRgHJNFrBo1cs2NiuoX8UBXMe7Lj/Zwa9AQAAAcCuT8LRbri\r\n4mP8KhR+PP8ASusTpXTSVkebiJXlbsSipFqNakWtjAlB4opo6UUAQsahenu1Qs1ICtOvBrmtdiL2\r\n/mDqh/Q/5FdLMw2msS/eNYpDIwCYOcniokrqxcHZpnC3Tt5bKhwx9aoP56jLyRAHtsOKumRWJD8H\r\n9DTHWNwd2OOxrlR6Ka3K4+1smVeIjt8ladtKXjUH7w61WVkVQAOPapYLiNbiM7fkDAscds0A5JbH\r\nomg2ptdPQMMPJ87fj0/SttKzreZXRXRgynkEHg1djfIrrjoebJtu7LIqRaiVqlU1ZJIOlFA6UUAZ\r\nzyY71VluAookJPU1CF5yKzuOww75m5+UVR1/TjcaBN5K5kjYSnHUgdf0OfwrTAxzU8b4ak9Slo7n\r\nlPlh/SgQuBhG6diMiuq1zwnL5jXWkgMrHLW+cYP+z/h+XpXPfPCxS4jeKQdVkUg/rXM4tHbCakVv\r\nIZ/9YScdh0pTGAuKkeXryKs6dpd7q0gFvEfLz80rcKPx7/Skk2U2ludB4Mic2d4WJ8sONns2Dn+l\r\ndKHaNsHmo9O09NNslt48kLyzHue5p0i5Oa6YqyOGbu7lyOXcKso1Y6u8ZyDVuC5DEBuDVpkNGkG4\r\noqJW460VYjMIUnmk2Y56inMv74/Wk6EisyhcDFGcHimE0ZoAnWUZ+bg+op0iwzptkVJF9GGf51Wz\r\nRuoGPXTNPVty2VqD6iNasbkUADoOgFVd1KGosGpM8m7joBUZwabk0c0xWEKAnpTSNoz6VKvWknXE\r\nDH2oAlSV0UAcj3opoICjPpRQAvG7P51EeWJoooAjPWm7ec5oopAPFKBRRQAYooopjFzS55oooEOF\r\nPYbrdh3FFFCEVpXCsAT2FFFFBR//2Q==",
"wechat": "",
"departmentid": 102,
"departmentname": "企管部",
"postid": 1120,
"postname": "新员工",
"tema": 0,
"temaname": ""
}
],
"titleDepartments": [
{
"departmentId": "309",
"id": "309",
"departmentKey": "GK00",
"departmentName": "山东恒信高科能源有限公司",
"parentId": "313",
"departmentNames": "山东恒信高科能源有限公司"
},
{
"departmentId": "102",
"id": "102",
"departmentKey": "GK03",
"departmentName": "企管部",
"parentId": "309",
"departmentNames": "企管部"
}
]
}
}

539
src/assets/iconfont/demo.css

@ -0,0 +1,539 @@
/* Logo 字体 */
@font-face {
font-family: "iconfont logo";
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');
}
.logo {
font-family: "iconfont logo";
font-size: 160px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* tabs */
.nav-tabs {
position: relative;
}
.nav-tabs .nav-more {
position: absolute;
right: 0;
bottom: 0;
height: 42px;
line-height: 42px;
color: #666;
}
#tabs {
border-bottom: 1px solid #eee;
}
#tabs li {
cursor: pointer;
width: 100px;
height: 40px;
line-height: 40px;
text-align: center;
font-size: 16px;
border-bottom: 2px solid transparent;
position: relative;
z-index: 1;
margin-bottom: -1px;
color: #666;
}
#tabs .active {
border-bottom-color: #f00;
color: #222;
}
.tab-container .content {
display: none;
}
/* 页面布局 */
.main {
padding: 30px 100px;
width: 960px;
margin: 0 auto;
}
.main .logo {
color: #333;
text-align: left;
margin-bottom: 30px;
line-height: 1;
height: 110px;
margin-top: -50px;
overflow: hidden;
*zoom: 1;
}
.main .logo a {
font-size: 160px;
color: #333;
}
.helps {
margin-top: 40px;
}
.helps pre {
padding: 20px;
margin: 10px 0;
border: solid 1px #e7e1cd;
background-color: #fffdef;
overflow: auto;
}
.icon_lists {
width: 100% !important;
overflow: hidden;
*zoom: 1;
}
.icon_lists li {
width: 100px;
margin-bottom: 10px;
margin-right: 20px;
text-align: center;
list-style: none !important;
cursor: default;
}
.icon_lists li .code-name {
line-height: 1.2;
}
.icon_lists .icon {
display: block;
height: 100px;
line-height: 100px;
font-size: 42px;
margin: 10px auto;
color: #333;
-webkit-transition: font-size 0.25s linear, width 0.25s linear;
-moz-transition: font-size 0.25s linear, width 0.25s linear;
transition: font-size 0.25s linear, width 0.25s linear;
}
.icon_lists .icon:hover {
font-size: 100px;
}
.icon_lists .svg-icon {
/* 通过设置 font-size 来改变图标大小 */
width: 1em;
/* 图标和文字相邻时,垂直对齐 */
vertical-align: -0.15em;
/* 通过设置 color 来改变 SVG 的颜色/fill */
fill: currentColor;
/* path stroke 溢出 viewBox 部分在 IE 下会显示
normalize.css 中也包含这行 */
overflow: hidden;
}
.icon_lists li .name,
.icon_lists li .code-name {
color: #666;
}
/* markdown 样式 */
.markdown {
color: #666;
font-size: 14px;
line-height: 1.8;
}
.highlight {
line-height: 1.5;
}
.markdown img {
vertical-align: middle;
max-width: 100%;
}
.markdown h1 {
color: #404040;
font-weight: 500;
line-height: 40px;
margin-bottom: 24px;
}
.markdown h2,
.markdown h3,
.markdown h4,
.markdown h5,
.markdown h6 {
color: #404040;
margin: 1.6em 0 0.6em 0;
font-weight: 500;
clear: both;
}
.markdown h1 {
font-size: 28px;
}
.markdown h2 {
font-size: 22px;
}
.markdown h3 {
font-size: 16px;
}
.markdown h4 {
font-size: 14px;
}
.markdown h5 {
font-size: 12px;
}
.markdown h6 {
font-size: 12px;
}
.markdown hr {
height: 1px;
border: 0;
background: #e9e9e9;
margin: 16px 0;
clear: both;
}
.markdown p {
margin: 1em 0;
}
.markdown>p,
.markdown>blockquote,
.markdown>.highlight,
.markdown>ol,
.markdown>ul {
width: 80%;
}
.markdown ul>li {
list-style: circle;
}
.markdown>ul li,
.markdown blockquote ul>li {
margin-left: 20px;
padding-left: 4px;
}
.markdown>ul li p,
.markdown>ol li p {
margin: 0.6em 0;
}
.markdown ol>li {
list-style: decimal;
}
.markdown>ol li,
.markdown blockquote ol>li {
margin-left: 20px;
padding-left: 4px;
}
.markdown code {
margin: 0 3px;
padding: 0 5px;
background: #eee;
border-radius: 3px;
}
.markdown strong,
.markdown b {
font-weight: 600;
}
.markdown>table {
border-collapse: collapse;
border-spacing: 0px;
empty-cells: show;
border: 1px solid #e9e9e9;
width: 95%;
margin-bottom: 24px;
}
.markdown>table th {
white-space: nowrap;
color: #333;
font-weight: 600;
}
.markdown>table th,
.markdown>table td {
border: 1px solid #e9e9e9;
padding: 8px 16px;
text-align: left;
}
.markdown>table th {
background: #F7F7F7;
}
.markdown blockquote {
font-size: 90%;
color: #999;
border-left: 4px solid #e9e9e9;
padding-left: 0.8em;
margin: 1em 0;
}
.markdown blockquote p {
margin: 0;
}
.markdown .anchor {
opacity: 0;
transition: opacity 0.3s ease;
margin-left: 8px;
}
.markdown .waiting {
color: #ccc;
}
.markdown h1:hover .anchor,
.markdown h2:hover .anchor,
.markdown h3:hover .anchor,
.markdown h4:hover .anchor,
.markdown h5:hover .anchor,
.markdown h6:hover .anchor {
opacity: 1;
display: inline-block;
}
.markdown>br,
.markdown>p>br {
clear: both;
}
.hljs {
display: block;
background: white;
padding: 0.5em;
color: #333333;
overflow-x: auto;
}
.hljs-comment,
.hljs-meta {
color: #969896;
}
.hljs-string,
.hljs-variable,
.hljs-template-variable,
.hljs-strong,
.hljs-emphasis,
.hljs-quote {
color: #df5000;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-type {
color: #a71d5d;
}
.hljs-literal,
.hljs-symbol,
.hljs-bullet,
.hljs-attribute {
color: #0086b3;
}
.hljs-section,
.hljs-name {
color: #63a35c;
}
.hljs-tag {
color: #333333;
}
.hljs-title,
.hljs-attr,
.hljs-selector-id,
.hljs-selector-class,
.hljs-selector-attr,
.hljs-selector-pseudo {
color: #795da3;
}
.hljs-addition {
color: #55a532;
background-color: #eaffea;
}
.hljs-deletion {
color: #bd2c00;
background-color: #ffecec;
}
.hljs-link {
text-decoration: underline;
}
/* 代码高亮 */
/* PrismJS 1.15.0
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
/**
* prism.js default theme for JavaScript, CSS and HTML
* Based on dabblet (http://dabblet.com)
* @author Lea Verou
*/
code[class*="language-"],
pre[class*="language-"] {
color: black;
background: none;
text-shadow: 0 1px white;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"]::-moz-selection,
pre[class*="language-"] ::-moz-selection,
code[class*="language-"]::-moz-selection,
code[class*="language-"] ::-moz-selection {
text-shadow: none;
background: #b3d4fc;
}
pre[class*="language-"]::selection,
pre[class*="language-"] ::selection,
code[class*="language-"]::selection,
code[class*="language-"] ::selection {
text-shadow: none;
background: #b3d4fc;
}
@media print {
code[class*="language-"],
pre[class*="language-"] {
text-shadow: none;
}
}
/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
}
:not(pre)>code[class*="language-"],
pre[class*="language-"] {
background: #f5f2f0;
}
/* Inline code */
:not(pre)>code[class*="language-"] {
padding: .1em;
border-radius: .3em;
white-space: normal;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: slategray;
}
.token.punctuation {
color: #999;
}
.namespace {
opacity: .7;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #905;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #690;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #9a6e3a;
background: hsla(0, 0%, 100%, .5);
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #07a;
}
.token.function,
.token.class-name {
color: #DD4A68;
}
.token.regex,
.token.important,
.token.variable {
color: #e90;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}

1959
src/assets/iconfont/demo_index.html

File diff suppressed because it is too large

323
src/assets/iconfont/iconfont.css

@ -0,0 +1,323 @@
@font-face {
font-family: "iconfont"; /* Project id 2578019 */
src: url('iconfont.woff2?t=1683511822799') format('woff2'),
url('iconfont.woff?t=1683511822799') format('woff'),
url('iconfont.ttf?t=1683511822799') format('truetype');
}
.iconfont,[class*="icon-"] {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-mouse:before {
content: "\e60b";
}
.icon-hand:before {
content: "\e6cf";
}
.icon-lock-open:before {
content: "\e9d6";
}
.icon-lock:before {
content: "\e669";
}
.icon-eye-close:before {
content: "\ebcd";
}
.icon-border:before {
content: "\e673";
}
.icon-text2:before {
content: "\e607";
}
.icon-stext:before {
content: "\e801";
}
.icon-apply:before {
content: "\e606";
}
.icon-work:before {
content: "\e68c";
}
.icon-todo:before {
content: "\ebb1";
}
.icon-applyed:before {
content: "\e633";
}
.icon-done:before {
content: "\e60d";
}
.icon-button:before {
content: "\e690";
}
.icon-design:before {
content: "\e62c";
}
.icon-data-source:before {
content: "\e617";
}
.icon-sp:before {
content: "\e626";
}
.icon-cs:before {
content: "\e605";
}
.icon-branch:before {
content: "\e993";
}
.icon-doc:before {
content: "\e7d0";
}
.icon-sys:before {
content: "\e634";
}
.icon-creat:before {
content: "\e661";
}
.icon-data:before {
content: "\e602";
}
.icon-menu:before {
content: "\e62f";
}
.icon-user:before {
content: "\e66b";
}
.icon-form:before {
content: "\e625";
}
.icon-list:before {
content: "\ec6b";
}
.icon-log:before {
content: "\e604";
}
.icon-dict:before {
content: "\e668";
}
.icon-post:before {
content: "\e658";
}
.icon-role:before {
content: "\e618";
}
.icon-log2:before {
content: "\ea45";
}
.icon-tool:before {
content: "\e628";
}
.icon-bar:before {
content: "\e6ce";
}
.icon-pie:before {
content: "\e902";
}
.icon-line:before {
content: "\ec66";
}
.icon-tree2:before {
content: "\e892";
}
.icon-flex:before {
content: "\e608";
}
.icon-div:before {
content: "\e60f";
}
.icon-tree:before {
content: "\ebb3";
}
.icon-time:before {
content: "\e600";
}
.icon-tinymce:before {
content: "\e66f";
}
.icon-rate:before {
content: "\e69d";
}
.icon-slider:before {
content: "\e627";
}
.icon-divider:before {
content: "\e638";
}
.icon-color:before {
content: "\ee22";
}
.icon-import:before {
content: "\e616";
}
.icon-image:before {
content: "\e63e";
}
.icon-card:before {
content: "\e622";
}
.icon-help:before {
content: "\e61c";
}
.icon-table:before {
content: "\e6a9";
}
.icon-component:before {
content: "\e620";
}
.icon-link:before {
content: "\e623";
}
.icon-cascader:before {
content: "\e624";
}
.icon-number:before {
content: "\e647";
}
.icon-title:before {
content: "\e61d";
}
.icon-tabs:before {
content: "\e6d4";
}
.icon-close:before {
content: "\e615";
}
.icon-plus:before {
content: "\e603";
}
.icon-arrow:before {
content: "\e61b";
}
.icon-check:before {
content: "\e6c1";
}
.icon-vue:before {
content: "\e69a";
}
.icon-switch:before {
content: "\e646";
}
.icon-save:before {
content: "\e61f";
}
.icon-move:before {
content: "\e696";
}
.icon-clone:before {
content: "\e692";
}
.icon-del:before {
content: "\e67d";
}
.icon-eye:before {
content: "\e601";
}
.icon-json:before {
content: "\e60e";
}
.icon-grid:before {
content: "\e652";
}
.icon-text:before {
content: "\e621";
}
.icon-date:before {
content: "\e64c";
}
.icon-input:before {
content: "\e629";
}
.icon-checkbox:before {
content: "\e61e";
}
.icon-textarea:before {
content: "\e60a";
}
.icon-radio:before {
content: "\e6b1";
}
.icon-select:before {
content: "\e64d";
}

1
src/assets/iconfont/iconfont.js

File diff suppressed because one or more lines are too long

548
src/assets/iconfont/iconfont.json

@ -0,0 +1,548 @@
{
"id": "2578019",
"name": "formDemo",
"font_family": "iconfont",
"css_prefix_text": "icon-",
"description": "",
"glyphs": [
{
"icon_id": "13644674",
"name": "箭头",
"font_class": "mouse",
"unicode": "e60b",
"unicode_decimal": 58891
},
{
"icon_id": "18372381",
"name": "手,手势",
"font_class": "hand",
"unicode": "e6cf",
"unicode_decimal": 59087
},
{
"icon_id": "7577422",
"name": "24gl-unlock4",
"font_class": "lock-open",
"unicode": "e9d6",
"unicode_decimal": 59862
},
{
"icon_id": "658044",
"name": "解锁",
"font_class": "lock",
"unicode": "e669",
"unicode_decimal": 58985
},
{
"icon_id": "5388071",
"name": "眼睛_隐藏_o",
"font_class": "eye-close",
"unicode": "ebcd",
"unicode_decimal": 60365
},
{
"icon_id": "3294800",
"name": "设置边框",
"font_class": "border",
"unicode": "e673",
"unicode_decimal": 58995
},
{
"icon_id": "11179879",
"name": "文字边框",
"font_class": "text2",
"unicode": "e607",
"unicode_decimal": 58887
},
{
"icon_id": "21529713",
"name": "m-滚动文字",
"font_class": "stext",
"unicode": "e801",
"unicode_decimal": 59393
},
{
"icon_id": "33172809",
"name": "发起的",
"font_class": "apply",
"unicode": "e606",
"unicode_decimal": 58886
},
{
"icon_id": "1206679",
"name": "工作台",
"font_class": "work",
"unicode": "e68c",
"unicode_decimal": 59020
},
{
"icon_id": "5388003",
"name": "待办任务_o",
"font_class": "todo",
"unicode": "ebb1",
"unicode_decimal": 60337
},
{
"icon_id": "7158013",
"name": "我发起的",
"font_class": "applyed",
"unicode": "e633",
"unicode_decimal": 58931
},
{
"icon_id": "20438918",
"name": "我的已办",
"font_class": "done",
"unicode": "e60d",
"unicode_decimal": 58893
},
{
"icon_id": "1766470",
"name": "符号-按钮",
"font_class": "button",
"unicode": "e690",
"unicode_decimal": 59024
},
{
"icon_id": "1150901",
"name": "设计",
"font_class": "design",
"unicode": "e62c",
"unicode_decimal": 58924
},
{
"icon_id": "12771491",
"name": "数据源管理",
"font_class": "data-source",
"unicode": "e617",
"unicode_decimal": 58903
},
{
"icon_id": "6321263",
"name": "审批",
"font_class": "sp",
"unicode": "e626",
"unicode_decimal": 58918
},
{
"icon_id": "12911863",
"name": "抄送",
"font_class": "cs",
"unicode": "e605",
"unicode_decimal": 58885
},
{
"icon_id": "18170243",
"name": "代码,分支,分流,分叉",
"font_class": "branch",
"unicode": "e993",
"unicode_decimal": 59795
},
{
"icon_id": "5371107",
"name": "文档",
"font_class": "doc",
"unicode": "e7d0",
"unicode_decimal": 59344
},
{
"icon_id": "12959365",
"name": "系统管理",
"font_class": "sys",
"unicode": "e634",
"unicode_decimal": 58932
},
{
"icon_id": "24007617",
"name": "创建图表",
"font_class": "creat",
"unicode": "e661",
"unicode_decimal": 58977
},
{
"icon_id": "24069228",
"name": "可视化",
"font_class": "data",
"unicode": "e602",
"unicode_decimal": 58882
},
{
"icon_id": "339044",
"name": "菜单",
"font_class": "menu",
"unicode": "e62f",
"unicode_decimal": 58927
},
{
"icon_id": "397442",
"name": "icon-user",
"font_class": "user",
"unicode": "e66b",
"unicode_decimal": 58987
},
{
"icon_id": "4329375",
"name": "表单管理",
"font_class": "form",
"unicode": "e625",
"unicode_decimal": 58917
},
{
"icon_id": "5961366",
"name": "列表",
"font_class": "list",
"unicode": "ec6b",
"unicode_decimal": 60523
},
{
"icon_id": "7474663",
"name": "操作日志",
"font_class": "log",
"unicode": "e604",
"unicode_decimal": 58884
},
{
"icon_id": "8605754",
"name": "字典管理",
"font_class": "dict",
"unicode": "e668",
"unicode_decimal": 58984
},
{
"icon_id": "8949009",
"name": "岗位",
"font_class": "post",
"unicode": "e658",
"unicode_decimal": 58968
},
{
"icon_id": "10213489",
"name": "角色管理",
"font_class": "role",
"unicode": "e618",
"unicode_decimal": 58904
},
{
"icon_id": "26876046",
"name": "管理登录日志",
"font_class": "log2",
"unicode": "ea45",
"unicode_decimal": 59973
},
{
"icon_id": "34047671",
"name": "系统工具",
"font_class": "tool",
"unicode": "e628",
"unicode_decimal": 58920
},
{
"icon_id": "1057386",
"name": "柱状图",
"font_class": "bar",
"unicode": "e6ce",
"unicode_decimal": 59086
},
{
"icon_id": "1727592",
"name": "407饼图",
"font_class": "pie",
"unicode": "e902",
"unicode_decimal": 59650
},
{
"icon_id": "5961328",
"name": "折线图",
"font_class": "line",
"unicode": "ec66",
"unicode_decimal": 60518
},
{
"icon_id": "11307823",
"name": "Directory tree",
"font_class": "tree2",
"unicode": "e892",
"unicode_decimal": 59538
},
{
"icon_id": "20360961",
"name": "流式布局",
"font_class": "flex",
"unicode": "e608",
"unicode_decimal": 58888
},
{
"icon_id": "12225038",
"name": "divide",
"font_class": "div",
"unicode": "e60f",
"unicode_decimal": 58895
},
{
"icon_id": "5388006",
"name": "树状图_o",
"font_class": "tree",
"unicode": "ebb3",
"unicode_decimal": 60339
},
{
"icon_id": "77110",
"name": "时间",
"font_class": "time",
"unicode": "e600",
"unicode_decimal": 58880
},
{
"icon_id": "2471358",
"name": "富文本框",
"font_class": "tinymce",
"unicode": "e66f",
"unicode_decimal": 58991
},
{
"icon_id": "8687733",
"name": "评分",
"font_class": "rate",
"unicode": "e69d",
"unicode_decimal": 59037
},
{
"icon_id": "11121364",
"name": "滑块",
"font_class": "slider",
"unicode": "e627",
"unicode_decimal": 58919
},
{
"icon_id": "11121454",
"name": "分割线",
"font_class": "divider",
"unicode": "e638",
"unicode_decimal": 58936
},
{
"icon_id": "22385724",
"name": "颜色库",
"font_class": "color",
"unicode": "ee22",
"unicode_decimal": 60962
},
{
"icon_id": "6244963",
"name": "导入",
"font_class": "import",
"unicode": "e616",
"unicode_decimal": 58902
},
{
"icon_id": "145454",
"name": "图片",
"font_class": "image",
"unicode": "e63e",
"unicode_decimal": 58942
},
{
"icon_id": "646357",
"name": "卡片",
"font_class": "card",
"unicode": "e622",
"unicode_decimal": 58914
},
{
"icon_id": "737945",
"name": "help",
"font_class": "help",
"unicode": "e61c",
"unicode_decimal": 58908
},
{
"icon_id": "1467412",
"name": "table",
"font_class": "table",
"unicode": "e6a9",
"unicode_decimal": 59049
},
{
"icon_id": "13253956",
"name": "component",
"font_class": "component",
"unicode": "e620",
"unicode_decimal": 58912
},
{
"icon_id": "15196938",
"name": "11.符号-级联选择",
"font_class": "link",
"unicode": "e623",
"unicode_decimal": 58915
},
{
"icon_id": "16880964",
"name": "cascader",
"font_class": "cascader",
"unicode": "e624",
"unicode_decimal": 58916
},
{
"icon_id": "17374561",
"name": "计数器",
"font_class": "number",
"unicode": "e647",
"unicode_decimal": 58951
},
{
"icon_id": "19657932",
"name": "标题",
"font_class": "title",
"unicode": "e61d",
"unicode_decimal": 58909
},
{
"icon_id": "8017649",
"name": "bootstrap_tabs",
"font_class": "tabs",
"unicode": "e6d4",
"unicode_decimal": 59092
},
{
"icon_id": "7826085",
"name": "close",
"font_class": "close",
"unicode": "e615",
"unicode_decimal": 58901
},
{
"icon_id": "6756281",
"name": "加号",
"font_class": "plus",
"unicode": "e603",
"unicode_decimal": 58883
},
{
"icon_id": "902007",
"name": "arrow on",
"font_class": "arrow",
"unicode": "e61b",
"unicode_decimal": 58907
},
{
"icon_id": "1176866",
"name": "check",
"font_class": "check",
"unicode": "e6c1",
"unicode_decimal": 59073
},
{
"icon_id": "13744032",
"name": "vue",
"font_class": "vue",
"unicode": "e69a",
"unicode_decimal": 59034
},
{
"icon_id": "20905073",
"name": "开关",
"font_class": "switch",
"unicode": "e646",
"unicode_decimal": 58950
},
{
"icon_id": "11493812",
"name": "保存",
"font_class": "save",
"unicode": "e61f",
"unicode_decimal": 58911
},
{
"icon_id": "384286",
"name": "move",
"font_class": "move",
"unicode": "e696",
"unicode_decimal": 59030
},
{
"icon_id": "836441",
"name": "clone",
"font_class": "clone",
"unicode": "e692",
"unicode_decimal": 59026
},
{
"icon_id": "18367976",
"name": "删 除 (1)",
"font_class": "del",
"unicode": "e67d",
"unicode_decimal": 59005
},
{
"icon_id": "925051",
"name": "eye",
"font_class": "eye",
"unicode": "e601",
"unicode_decimal": 58881
},
{
"icon_id": "15214524",
"name": "json",
"font_class": "json",
"unicode": "e60e",
"unicode_decimal": 58894
},
{
"icon_id": "350628",
"name": "GRID",
"font_class": "grid",
"unicode": "e652",
"unicode_decimal": 58962
},
{
"icon_id": "4521248",
"name": "文字",
"font_class": "text",
"unicode": "e621",
"unicode_decimal": 58913
},
{
"icon_id": "15167569",
"name": "date",
"font_class": "date",
"unicode": "e64c",
"unicode_decimal": 58956
},
{
"icon_id": "16880988",
"name": "input",
"font_class": "input",
"unicode": "e629",
"unicode_decimal": 58921
},
{
"icon_id": "18536117",
"name": "check_box-24px",
"font_class": "checkbox",
"unicode": "e61e",
"unicode_decimal": 58910
},
{
"icon_id": "18727247",
"name": "textarea",
"font_class": "textarea",
"unicode": "e60a",
"unicode_decimal": 58890
},
{
"icon_id": "19457233",
"name": "radio",
"font_class": "radio",
"unicode": "e6b1",
"unicode_decimal": 59057
},
{
"icon_id": "20962223",
"name": "下拉选择",
"font_class": "select",
"unicode": "e64d",
"unicode_decimal": 58957
}
]
}

BIN
src/assets/iconfont/iconfont.ttf

Binary file not shown.

BIN
src/assets/iconfont/iconfont.woff

Binary file not shown.

BIN
src/assets/iconfont/iconfont.woff2

Binary file not shown.

1
src/assets/icons/select1.svg

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1688711543101" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4759" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M818.655 971.545h-613.312c-84.303 0-152.886-66.343-152.886-147.89v-623.306c0-81.549 68.585-147.89 152.886-147.89h613.312c84.303 0 152.886 66.342 152.886 147.89v623.306c0 81.548-68.585 147.89-152.886 147.89zM205.345 123.155c-45.318 0-82.19 34.628-82.19 77.191v623.306c0 42.564 36.869 77.191 82.19 77.191h613.312c45.318 0 82.19-34.627 82.19-77.191v-623.306c0-42.563-36.869-77.191-82.19-77.191h-613.312z" fill="" p-id="4760"></path></svg>

After

Width:  |  Height:  |  Size: 768 B

1
src/assets/icons/select3.svg

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1688711511324" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3445" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M815.5 962.3h-605c-81.6 0-148-66.4-148-148v-605c0-81.6 66.4-148 148-148h605c81.6 0 148 66.4 148 148v605c0 81.6-66.4 148-148 148z m-605-845c-50.7 0-92 41.3-92 92v605c0 50.7 41.3 92 92 92h605c50.7 0 92-41.3 92-92v-605c0-50.7-41.3-92-92-92h-605z" fill="#2c2c2c" p-id="3446"></path><path d="M465.3 665.4h-2.6c-22.1-0.7-43-10.7-57.5-27.3l-98-107.8c-10.4-11.4-9.6-29.2 1.9-39.6 11.4-10.4 29.2-9.6 39.6 1.9L447 600.9l0.2 0.3c4.4 5.1 10.5 8 17.3 8.2 6.7 0.2 13-2.3 17.8-7.1l0.1-0.1 234.9-235.9c10.9-11 28.6-11 39.6-0.1s11 28.6 0.1 39.6L522.1 641.7c-15 15.1-35.6 23.7-56.8 23.7z" fill="#2c2c2c" p-id="3447"></path></svg>

After

Width:  |  Height:  |  Size: 944 B

BIN
src/assets/image/icon_file.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 B

BIN
src/assets/image/icon_people.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
src/assets/image/next_level.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 245 B

BIN
src/assets/image/next_level_active.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 B

BIN
src/assets/img/data.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

BIN
src/assets/img/echarts.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

BIN
src/assets/img/flow.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

BIN
src/assets/img/form-list.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

BIN
src/assets/img/form.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

BIN
src/assets/img/ruler.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

9
src/assets/scss/element-var.scss

@ -0,0 +1,9 @@
@charset "UTF-8";
:root {
/*--el-border-base: 1px solid red*/
--el-menu-item-height:44px;
--el-menu-base-level-padding:10px;
.el-header{
--el-header-height:40px
}
}

125
src/assets/scss/flow.scss

@ -0,0 +1,125 @@
.flow-container {
$background: #fff;
$borderColor: #eee;
overflow-x: auto;
.flow-main { min-width: min-content;display: flex;flex-direction: column;align-items: center;}
.flow-group {position: relative;background: $background;min-width: min-content}
.flow-item {border: 1px solid $borderColor;box-shadow: 0 0 6px rgba(102, 102, 102, 0.1);height: 80px;border-radius: 5px;overflow: hidden;display: flex;flex-direction: column;transition: all .3s;position: relative;z-index: 2;background: $background;width: 180px;
&:hover {border-color: rgb(85, 197, 192);
.title .close {visibility: visible;opacity: 1}
}
.title {background: rgb(85, 197, 192);color: #fff;display: flex;align-items: center;padding: 3px 10px;justify-content: space-between;
span {flex: 2}
.close {transform: scale(.8);visibility: hidden;transition: all .3s;opacity: 0;cursor: pointer}
i {font-size: 14px;margin-right: 3px}
&.bg-2 {background: rgb(255, 148, 62)}
&.bg-5 {background: none;color: #666}
&.bg-3 {background: rgb(50, 150, 250)}
}
.text {flex: 1;display: flex;align-items: center;padding: 5px 15px;cursor: pointer;
div {display: block;max-height: 38px;overflow: hidden;color: #666;text-overflow: ellipsis;display: -webkit-box;-webkit-box-orient: vertical;-webkit-line-clamp: 2;}
}
}
.flow-add {padding: 8px 0;position: relative;font-size: 12px;
i {width: 30px;height: 30px;border-radius: 50%;border: 1px solid #eee;box-shadow: 0 0 6px rgba(102, 102, 102, 0.1);display: flex;align-items: center;justify-content: center;margin: 0 auto;background: $background;position: relative;z-index: 2;cursor: pointer;transform: scale(.7);
}
&:before {content: '';display: block;width: 1px;left: 50%;background: #eee;position: absolute;top: 0;bottom: 0}
}
.flow-col {flex: 1;margin: 0 5px;display: flex;flex-direction: column;align-items: center;position: relative;
&:before {content: '';display: block;width: 1px;top: 0; bottom: 0;left: 50%;background: #eee;position: absolute}
}
.flow-row {display: flex;position: relative}
.flow-branch-btn {display: none}
.flow-branch {padding: 40px 0 1px;display: flex;flex-direction: column;
.flow-branch-btn {display: block;position: absolute;left: 50%;top: 0;transform: translateX(-50%);z-index: 2}
&:before {content: '';display: block;left: 0;right: 0;bottom: 46px;top: 12px;border: 1px solid #eee;position: absolute}
.flow-col { // 中线
&:before {top: -28px}
&:after {content: '';display: none;width: 50%;top: 0;background: $borderColor;}
}
.mask-left, .mask-right {position: absolute;background: $background;top: -28px;display: block;bottom: -1px;width: calc(50% + 9px)}
.mask-left {left: -10px}
.mask-right {right: -10px}
}
.flow-end {
box-shadow: 0 2px 10px 0 rgb(145 145 153 / 50%);margin: 0 auto 30px;border-radius: 50%;position: relative;background: #bcbcc5;width: 50px;height: 50px;color: #fff;display: flex;align-items: center;justify-content: center;
}
&.type-show {
// 展示模式
.flow-branch {padding-top: 28px}
.flow-item {margin-bottom: 20px}
.flow-branch:before {bottom: 0;top: 0}
.flow-end {position: relative;margin-top: 20px;
&:before {content: '';width: 1px;background: $borderColor;position: absolute;left: 50%;top: -20px;height: 20px;}
}
}
.tools {text-align: right}
}
.flow-node-down {
h3 {font-size: 14px;margin-bottom: 10px}
div {display: flex}
i {font-size: 14px;margin-right: 5px}
}
.flow-container.horizontal {
$borderColor: #eee;
.flow-main {flex-direction: row;justify-content: center}
.flow-group:first-child {overflow: hidden;}
.flow-col {flex-direction: row;margin: 8px 0;
&:before {width: auto; right: 0;height: 1px;left: -29px;top: 50%}
}
.flow-add {padding: 0 8px;
&:before {left: 0;top: 50%;height: 1px;width: 100%}
}
.flow-row {flex-direction: column}
.flow-branch {flex-direction: row;align-items: center;padding: 0;
.flow-branch-btn {position: static;transform: translateX(0);margin-right: 8px;
button {width: 50px;white-space: normal;padding: 15px 10px;overflow: hidden;line-height: 14px}
}
&:before {bottom: 0;top: 0;left: 30px;right: 45px}
.mask-left, .mask-right {left: -29px;right: -1px;width: auto; height: calc(50% + 8px)}
.mask-left {top: -8px;}
.mask-right {bottom: -9px;top: auto}
.flow-col {
}
}
.flow-end {margin: 0}
&.type-show {
.flow-branch {margin-left: 20px}
.flow-item {margin-right: 20px;margin-bottom: 0}
.flow-branch .flow-col:before {left: -20px}
.flow-branch:before {left: -20px;right: -1px}
.flow-end {position: relative;margin-left: 20px;
&:before {content: '';height: 1px;background: $borderColor;position: absolute;top: 50%;left: -20px;width: 20px;}
}
}
}
// 侧栏drawer
.flow-modal-class {
$borderColor: #eee;
.el-drawer__header {border-bottom: 1px solid $borderColor;margin-bottom: 0;padding-bottom: 20px}
}
.flow-drawer {
.tip {margin-bottom: 20px;color: #999;line-height: 22px}
}
// 设计主页
.design-flow-container {position: relative;
.tools {position: absolute;right: 20px;top: 13px;z-index: 2}
.tabs-info {display: flex;justify-content: center;
form {width: 680px;}
}
}
//工作台
.task-apply {
.item {margin-bottom: 20px;
h3 {font-size: 14px;margin-bottom: 10px}
}
.list {display: flex;margin: 0 -8px;
> div {border: 1px solid #dcdfe6;padding: 16px;border-radius: 8px;height: 100px;margin: 0 8px;width: 24%;display: flex;align-items: center;font-weight: 700;transition: all .3s;cursor: pointer;box-shadow: 0 0 2px #ddd;
&:hover {border-color: #409eff}
}
.icon {font-size: 36px;width: 50px;height: 50px;display: flex;align-items: center;justify-content: center;border-radius: 4px;overflow: hidden;color: #fff;margin-right: 10px;
&:before {font-weight: 400}
}
}
}

296
src/assets/scss/form.scss

@ -0,0 +1,296 @@
@charset "UTF-8";
// 左侧栏
$mainColor: #66b1ff;
.design-container {margin: 10px !important;display: flex; background-color: #FFFFFF;}
.components-list {width: 250px;padding: 8px 0;overflow-y: auto;height: calc(100vh - 104px);position: relative;overflow-x: hidden;
.title {padding: 8px 12px;position: relative;
.template {position: absolute;right: 12px;top: 0;padding: 8px;cursor: pointer}
}
ul { position: relative;overflow: hidden;padding: 0 10px 10px;margin: 0;
li {font-size: 13px;display: flex;width: 48%;line-height: 28px;position: relative;float: left;left: 0;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;margin: 0 1% 5px;color: #333;padding: 0 10px;border: 1px solid transparent;background: #f4f6fc;user-select: none;align-items: center;
i {margin-right: 5px}
&:hover {
color: $mainColor;border: 1px dashed $mainColor;cursor: move;
}
&.title {padding: 0 10px}
}
}
.content {margin-left: 12px}
}
.use-template {position: absolute;left: -100%;top: 0;width: 100%;bottom: 0;background: #fff;opacity: 0;
&.active {animation: templateAni .5s forwards;}
.close {position: absolute;right: 5px;top: 5px;font-size: 14px;cursor: pointer}
.list {padding: 30px 10px;overflow-y: auto;
.item {box-shadow: 0 0 4px rgba(0, 21, 41, 0.1);padding: 10px;text-align: center;transition: all .5s;cursor: pointer;margin-bottom: 10px;
img {display: block;width: 100%;margin: 0 auto 10px}
&:hover {box-shadow: 0 0 4px rgba(0, 21, 41, 0.25);}
}
}
.no-date {text-align: center;padding-top: 20px;color: #999}
}
@keyframes templateAni {
100% {opacity: 1;left: 0}
}
// 框架
.main-body {flex: 2; border-left: 1px solid #e0e0e0;border-right: 1px solid #e0e0e0;margin: 0;overflow: hidden;
.empty-tips {text-align: center;width: 100%;font-size: 20px;color: #ccc;position: absolute;left: 0;top: 100px;
}
.main-form { background: #fff;border: 1px dashed #999;margin: 10px;height: calc(100vh - 165px);overflow-y: auto;overflow-x: hidden;position: relative}
}
// 中间按钮工具
.main-tools {line-height: 26px;border-bottom: 2px solid #e4e7ed;margin-right: 10px;padding: 8px 0;display: flex;align-items: center;justify-content: flex-end;
button {color: $mainColor;
i {padding-right: 5px}
}
}
.add-form {padding: 0px;box-sizing: border-box;
// 格珊
.form-row {
.form-col {
&.active-col {border: 3px solid $mainColor;position: relative;
> .drag-control {display: block;}
> .tooltip {display: block;}
}
}
}
.title {border-bottom: 1px solid #ddd;font-weight: 700;font-size: 14px;height: 30px;padding: 0 5px;margin-bottom: 22px}
.form-tabs {
.drag {min-height: 80px;}
}
.group-card {
.el-collapse {border: 0}
.el-collapse-item__header {font-weight: 700;border-bottom: 1px solid #ddd;margin-bottom: 20px}
.el-collapse-item__wrap {border: 0}
}
.group-inputSlot {display: none}
.form-table {margin-bottom: 22px;
.drag {border: 0;display: flex;overflow-x: auto;white-space: nowrap;padding: 0;flex-wrap: nowrap;
> div {min-width: 150px;width: auto}
}
.el-form-item {display: block}
}
.table-btn {padding-top: 10px}
.el-collapse-item__content {padding-bottom: 5px }
.form-table-add {
.el-form-item__label {display: none}
.el-form-item {margin: 0}
.el-table .cell {overflow: inherit;
.el-form-item__error {padding-top: 0}
}
}
.gray {color: #999}
> .drag {border: 0 !important;}
.group-flex {
.flex-group {display: flex;justify-content: space-between;
button {margin-left: 10px}
}
.flex-item {flex: 2;}
}
.group-txt {margin-bottom: 18px}
.div-layout {
/*&.inline {
.drag {display: inline-flex}
.group {width: auto;margin-right: 10px}
}*/
&.right {
.drag {text-align: right;justify-content: flex-end}
}
&.center {
.drag {text-align: center;justify-content: center}
}
&.left {
}
}
// 设置默认下input和select一样宽
.el-select {width: 100%;}
.el-select {
.el-input__wrapper .el-input__suffix {position: absolute;right: 10px}
}
.group {width: 100%}
.drag {display: flex;flex-wrap: wrap}
&.form-row-2 {
.group {width: 50%}
}
&.form-row-3 {
.group {width: 33%}
}
&.form-row-4 {
.group {width: 25%}
}
}
.sidebar-tools {width: 300px;right: 0;top: 0;overflow-y: auto;box-sizing: border-box;padding-bottom: 10px;bottom: 0; height: calc(100vh - 60px);
.form {
.el-form-item {margin-bottom: 10px;}
}
.h3 {font-size: 14px;margin-bottom: 10px;display: flex;align-items: center;
h3 {font-size: 14px}
}
.el-tabs__nav-wrap {padding: 0 10px}
.el-tabs__content {padding: 0 10px}
.icon-del {cursor: pointer}
.option-radio {
> label {margin-right: 8px}
}
.event-btn {
button {margin: 0 12px 5px 0}
}
}
#editJson, #editJsonCopy {width: 100%;height: calc(100vh - 65px)}
#editJsonCopy {height: calc(100vh - 350px)}
.ace-dialog {background: #1e1e1e;
.el-drawer__body {padding: 0}
.el-drawer__header {margin: 0;color: #e9e9e9;font-size: 12px;padding: 3px 10px}
.dialog-footer {text-align: center;padding-top: 5px;}
}
.export-dialog {
.el-dialog__body {padding: 0 20px}
}
.design-form {min-height: calc(100vh - 170px);
> div {height: 100%}
> .drag {min-height: calc(100vh - 170px) !important;}
.ghost {
background: #F56C6C;
border: 2px solid #F56C6C;
outline-width: 0;
height: 3px;
box-sizing: border-box;
font-size: 0;
content: '';
overflow: hidden;
padding: 0;
width: 100%;
}
.group {border: 1px dashed #ddd;margin: 2px 2px 10px 2px;padding: 5px;position: relative;min-height: 50px;
&.active {border: 3px solid $mainColor;position: relative;
> .drag-control {display: block}
> .tooltip {display: block;}
}
&:hover {border-color: $mainColor;background: #ecf5ff}
> div {margin-bottom: 0}
&:after{content: '';position: absolute;left: 0;top:0;right: 0;bottom: 0;opacity: 0;z-index: 1;display: block;}
&.group-grid,&.group-tabs,&.group-card,&.group-flex,&.group-div,&.group-table{
&:after{display: none}
}
}
.group-inputSlot {border-color: #eebe77;display: inline-block;
&:hover, &.active {border-color: #eebe77 !important;}
}
.tooltip {display: none;position: absolute;font-size: 12px;top: 0;right: 0;z-index: 5}
.drag-control {display: none;
.item-control {position: absolute;right: 0;bottom: 0;z-index: 2; display: flex;align-items: center;height: 24px;background: $mainColor;
i {width: 24px;height: 24px;color: #fff;display: flex;align-items: center;justify-content: center;cursor: pointer}
}
.drag-move {position: absolute;left: 0;top: 0;z-index: 2;width: 24px;height: 24px;background: $mainColor;color: #fff;text-align: center;line-height: 24px;cursor: move}
}
.drag {height: 100%;border: 1px dashed #ddd;min-height: 40px;margin: 0 2px;padding: 5px;align-content: flex-start;}
&.form-row-2 {
.group {width: 48%}
}
&.form-row-3 {
.group {width: 32%}
}
&.form-row-4 {
.group {width: 23%}
}
}
/*表格设计*/
.design-table {
.main-body {border-left: 0}
.header {position: relative;
.field {position: absolute;left: 10px;top: 7px;display: flex;
}
}
.components-list {
.content {padding: 0 12px;
> div {display: flex;flex-wrap: wrap;justify-content: flex-start;
label {margin: 0 10px 8px 0 !important;}
}
}
}
.main-table {padding: 10px 20px;
.add-form {min-height: auto;display: flex;
> .drag {height: auto;min-height: auto !important;}
}
.el-divider {margin: 8px 0 0}
.table-tip {color: #999;padding: 30px 0;line-height: 22px}
.search-box {position: relative;
&:after {content: '';width: 100%;height: 100%;position: absolute;left: 0;right: 0;bottom: 0;top: 0;z-index: 2;cursor: pointer;}
.group {width: auto;margin-right: 10px}
}
.control-btn {padding: 10px 0;
margin-bottom: 10px;display: flex;justify-content: space-between;align-items: center
}
.tip {border: 1px dotted #ddd;padding: 3px 5px;border-radius: 5px;color: #999;text-align: center;cursor: pointer}
.el-table__header {
th {
.cell {position: relative;}
.icon-close {display: none;font-size: 12px;margin-left: 12px;cursor: pointer;position: absolute;}
&:hover {
.icon-close {display: inline-block}
}
}
}
}
.table-tag {
.el-form-item__content {display: flex;
> div {flex: 2;margin-right: 5px;}
}
}
}
.table-field-list {
h3 {font-size: 14px}
.item {margin-bottom: 20px}
.list {display: flex;justify-content: flex-start;flex-wrap: wrap;
label {width: 25%;margin: 0}
}
}
.table-list-comm {display: flex;justify-content: space-between;
.tree-sidebar {width: 180px;border-right: 1px solid #ddd;padding-right: 10px;margin-right: 10px;flex-shrink: 0;
.el-input {margin-bottom: 10px}
}
.table-list {display: block;width: 100%}
.table-main {margin-bottom: 20px;
&.hide-vertical-scroll { // 固定了横向滚动条时禁用表格固定头部的滚动
.el-scrollbar__wrap {overflow: hidden;}
.is-vertical {display: none !important;}
}
.table-operate-btn {display: flex;align-items: center}
}
.table-search {position: relative;
form {display: flex;flex-wrap: wrap;padding-bottom: 0;border-bottom: 1px solid #dcdfe6;margin-bottom: 10px;}
.drag {display: flex;flex-wrap: wrap;
> div {margin-right: 10px}
}
.group {width: auto}
.search-icon {margin-left: 10px;height: 30px;cursor: pointer;position: absolute;right: 0;top: 0}
.autoHeight-enter-active,
.autoHeight-leave-active {
max-height: 200px;
transition: all .6s;
overflow: hidden;
}
.autoHeight-enter-from,
.autoHeight-leave-to {
max-height: 0;
}
}
.control-btn {margin-bottom: 10px;display: flex;justify-content: space-between;align-items: center}
}
/*图片文件上传*/
.upload-style {
.limit {
.el-upload {display: none}
// 超出limit时不显示上传按钮
}
.el-upload-list__item-preview {display: none !important;}
// 不显示点击放大按钮
.el-upload--picture {
.icon-plus {font-size: 28px;display: flex;align-items: center;justify-content: center;color: #8c939d;width: 148px;height: 148px;border: 1px dashed #d9d9d9;border-radius: 6px;cursor: pointer;overflow: hidden;background: #fbfdff}
}
}
/*分页*/
.table-page {padding-top: 10px;display: flex;justify-content: flex-end}
//.el-scrollbar__wrap{overflow: hidden!important;}
//.el-scrollbar__bar.is-vertical{display: none}

1
src/assets/scss/index.scss

@ -0,0 +1 @@
@import "layout","form","flow","screen";

120
src/assets/scss/layout.scss

@ -0,0 +1,120 @@
html, body, div, span, ul, li, i, h3, p {margin: 0;padding: 0;}
ul, li {list-style: none}
body {font-size: 14px; font-family: "Microsoft YaHei UI"}
* {box-sizing: border-box}
a{color: #409eff;text-decoration: none}
::-webkit-scrollbar {
width: 8px;
height: 8px;
position: relative;
z-index: 100;
}
::-webkit-scrollbar-thumb {
background-color: #babdc2;
background-clip: padding-box;
min-height: 28px;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
}
::-webkit-scrollbar-corner {
background: #babdc2;
}
/*&::-webkit-scrollbar:$colorGray2; //滚动条整体部分
::-webkit-scrollbar-button:''; //滚动条两端的按钮
::-webkit-scrollbar-track:''; //外层轨道
::-webkit-scrollbar-track-piece:''; //内层滚动槽
::-webkit-scrollbar-thumb:$colorGray3; //滚动的滑块
::-webkit-scrollbar-corner:''; //边角
::-webkit-resizer //定义右下角拖动块的样式*/
.common-layout {
.common-sidebar {
transition: all 0.3s;
box-shadow: 2px 0 6px rgb(0 21 41 / 35%);
color: #fff;
background-color: rgb(48 65 86);
height: 100vh;
overflow-x: hidden;
.logo {
display: flex;
align-items: center;
font-size: 14px;
height: 40px;
justify-content: center;
cursor: pointer;
font-weight: 700;
img {
width: 14px;
height: 14px;
}
}
.el-menu {
border-right: 0;
.icon{margin-right: 5px;font-size: 15px;opacity: .8}
}
.el-sub-menu .el-menu-item{min-width: 180px}
}
.common-header {
box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
display: flex;
align-items: center;
justify-content: space-between;
.collapse-icon {
cursor: pointer;
font-size: 18px;
margin-right: 15px;
}
.breadcrumb {flex: 2;}
.comm-header-tool {margin: 0 10px;display: flex;
i {margin: 0 5px;cursor: pointer}
}
}
// 使用整个右侧滚动没必要固定那个头部浪费空间
.overflow-scroll{overflow-y: auto;display: block;height: 100vh}
.common-main {
background: #f0f2f5;
padding: 10px;
overflow: hidden;
> div:first-child {border-radius: 5px;padding: 10px 15px;background: #fff;overflow-x: auto; // 横向滚动条放在这里
&.bg-none{background: none;}
}
}
.tag-tabs {display: flex;justify-content: space-between;align-items: center;
padding: 0 20px;
box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
.el-tabs__content {
display: none;
}
.el-tabs__nav-wrap::after {
display: none;
}
.el-tabs__item {
padding: 0 10px !important;
}
.el-tabs__header {
margin: 0;
}
.tabs-label {
i {margin-left: 3px}
}
.clear-tag {cursor: pointer}
}
.quit-full {position: fixed;right: 10px;top: 10px;cursor: pointer;z-index: 101}
}
// 设置el-tooltip最大宽度
.el-popper {
max-width: 400px;
}
.fade-transform-leave-active,
.fade-transform-enter-active {
transition: all .3s;
}
.fade-transform-enter-from{opacity: .3;transform: translateX(-30px)}
.fade-transform-enter-active {
}
.fade-transform-enter-to{transform: translateX(0);opacity: 1}
.fade-transform-leave-active {
opacity: 0;
transform: translateX(30px);
}

111
src/assets/scss/screen.scss

@ -0,0 +1,111 @@
.bg-black { /*background: rgb(48, 65, 86) !important;margin: -10px;border-radius: 0 !important;color: #fff*/
}
.container-screen {display: flex;justify-content: space-between;padding: 0 !important;
.tabs {
.el-tabs__nav {display: flex;justify-content: space-between;width: 100%}
.el-tabs__item {flex: 2;padding: 0;text-align: center}
}
.main-left {width: 180px;transition: all .3s;
.scroll {height: calc(100vh - 114px)}
.components-list {width: 100%;
ul {
li {padding: 0 5px;
i {font-size: 13px;margin-right: 3px}
}
}
}
.layer-list {font-size: 14px;overflow-y: auto;
ul {height: 100%}
li {line-height: 36px;padding: 0 8px;background: #f4f6fc;transition: all .3s;display: flex;justify-content: space-between;align-items: center;border: 1px solid transparent;border-bottom-color: #fff;
span {flex: 2;cursor: move;}
i {margin: 0 3px}
.icon {font-size: 20px;cursor: pointer}
&:hover {color: #66b1ff}
&.active { color: #fff;background: #66b1ff}
&.lock { color: #eebe77;
span {cursor: not-allowed}
}
&.display {opacity: .5}
&.isGroup{padding-left: 20px}
}
}
}
.main-box {flex: 2;border-left: 1px solid #e0e0e0;border-right: 1px solid #e0e0e0;height: calc(100vh - 66px);display: flex;flex-direction: column;color: #fff;width: 100%;position: relative;overflow: hidden;
.main-tools {line-height: 20px;
.control-tools {flex: 2;color: #999;margin-left: 20px;
i {margin-right: 5px;cursor: pointer}
.active {color: #409eff}
}
}
.design-box {background: rgb(48, 65, 86);flex: 2;padding: 0 0 0 20px;position: relative;overflow: auto;}
.draw-react {border: 1px solid #409eff;position: absolute;z-index: 999}
.design-canvas {height: 100%;position: absolute;cursor: pointer;top: 20px;left: 20px;transform-origin: left top;
.drag {height: 100%}
.resize-box {
position: absolute;left: 0;top: 0;width: 100%;height: 100%;border: 1px dotted #409eff;z-index: 5;
span {width: 8px;height: 8px;display: block;border-radius: 50%;background: #409eff;position: absolute;border: 1px solid rgba(255, 255, 255, .8);
}
.rs1 {left: -4px;top: -4px;cursor: se-resize;}
.rs2 {left: 50%;top: -4px;margin-left: -4px;cursor: s-resize}
.rs3 {right: -4px;top: -4px;cursor: sw-resize}
.rs4 {left: -4px;top: 50%;margin-top: -4px;cursor: e-resize}
.rs5 {right: -4px;top: 50%;margin-top: -4px;cursor: e-resize}
.rs6 {left: -4px;bottom: -4px;cursor: sw-resize}
.rs7 {left: 50%;bottom: -4px;margin-left: -4px;cursor: s-resize}
.rs8 {right: -4px;bottom: -4px;cursor: se-resize;}
&:hover {background: rgba(64, 158, 255, .5);cursor: move}
.position {font-size: 12px;position: absolute;left: 0;top: -20px}
}
&.preview {position: fixed;left: 0;top: 0;z-index: 50;
transform: scale(1) translate(0px, 0px) !important;transition: all .3s;
.resize-box {display: none}
}
}
.design-footer {background: rgb(48, 65, 86);display: flex;justify-content: space-between;padding: 0 5px;align-items: center;
.center {flex: 2;display: flex;justify-content: center}
.item {display: flex;align-items: center;margin: 0 10px;
.label {margin-right: 5px;display: block;white-space: nowrap}
}
.slider {
.label {margin-right: 10px}
.el-slider {width: 150px}
}
.icon {cursor: pointer}
//.offset{width: 120px;text-align: center;color: red}
}
.el-slider__marks-stop {background: red}
.no-date {color: #ccc;position: absolute;left: 50%;top: 30%;transform: translateX(-50%);font-size: 20px}
}
.main-right {width: 220px;transition: all .3s;position: relative;
form {padding: 0 10px}
.el-form-item {margin-bottom: 8px}
.color-picker {
.el-color-picker__trigger, .el-color-picker {width: 100%}
}
.upload-image {
.el-form-item__content {display: flex}
.el-input {flex: 2}
.el-upload-list {display: none}
}
&.lock {
&:after {position: absolute;left: 0;top: 0;bottom: 0;right: 0;content: '';background: rgba(255, 255, 255, .3)}
.lock {z-index: 2}
}
}
.close-preview {position: fixed;right: 10px;top: 10px;z-index: 51;color: #999;cursor: pointer}
.screen-right-menu {position: absolute;z-index: 100;background: #fff;width: 160px;transform: translateY(-50%);
li {padding: 5px 15px;cursor: pointer;
&:hover {background: #409eff;color: #fff}
&.display{cursor: not-allowed;opacity: .5;
&:hover{background: #fff;color: #333}}
}
}
}
.design-canvas {
.group {
position: absolute;
}
.default-img, .default-bg {display: block;width: 100%;height: 100%}
}

322
src/components/DesignForm/assembly/index.ts

@ -0,0 +1,322 @@
const selectOption: any = [
/*{
label: '标签1',
value: 'value1'
},
{
label: '标签2',
value: 'value2'
},
{
label: '标签3',
value: 'value3'
}*/
]
const config: { optionsType: number } = {
optionsType: 0 // 0固定 1数据源 2 接口字典
}
export default [
{
title: '基础字段',
children: [
{
type: 'input',
label: '单行文本',
icon: 'input',
control: {
// 组件所有属性
modelValue: ''
},
config: {} // 其他配置信息
},
{
type: 'textarea',
label: '多行文本',
icon: 'textarea',
control: {
modelValue: ''
},
config: {}
},
{
type: 'radio',
label: '单选框组',
icon: 'radio',
control: {
modelValue: ''
},
options: selectOption, // 下拉选项数据集合
config: config
},
{
type: 'checkbox',
label: '多选框组',
icon: 'checkbox',
control: {
modelValue: []
},
options: selectOption,
config: config
},
{
type: 'select',
label: '下拉选择框',
icon: 'select',
control: {
modelValue: '',
appendToBody: true
},
options: selectOption,
config: config
},
{
type: 'datePicker',
label: '日期选择器',
icon: 'date',
control: {
modelValue: '',
type: 'date'
},
config: {}
},
{
type: 'timePicker',
label: '时间选择器',
icon: 'time',
control: {
modelValue: ''
},
config: {}
},
{
type: 'colorPicker',
label: '取色器',
icon: 'color',
control: {
modelValue: ''
},
config: {}
},
{
type: 'switch',
label: '开关',
icon: 'switch',
control: {
modelValue: false
},
config: {}
},
{
type: 'inputNumber',
label: '计数器',
icon: 'number',
control: {
modelValue: 0
},
config: {}
},
{
type: 'cascader',
label: '级联选择器',
icon: 'cascader',
control: {
modelValue: []
},
options: [],
config: config
},
{
type: 'rate',
label: '评分',
icon: 'rate',
control: {
modelValue: 0
},
config: {}
},
{
type: 'slider',
label: '滑块',
icon: 'slider',
control: {
modelValue: 0
},
config: {}
},
{
type: 'treeSelect',
label: '树形控件',
icon: 'tree2',
control: {
modelValue: '',
data: [],
renderAfterExpand: false
},
config: {
optionsType: 0
}
},
{
type: 'txt',
label: '文字',
icon: 'text',
control: {
modelValue: ''
},
config: {}
},
{
type: 'title',
label: '标题',
icon: 'title',
control: {
modelValue: '标题'
},
config: {}
},
{
type: 'button',
label: '按钮',
icon: 'button',
control: {
label: '保存'
},
config: {}
}
]
},
{
title: '高级字段',
children: [
{
type: 'table',
label: '子表',
icon: 'table',
list: [],
tableData: [], // 子表表格列表数据集合
control: {
border: true
},
config: {
addBtnText: '添加一行'
}
},
{
type: 'component',
label: '自定义组件',
icon: 'component',
control: {
modelValue: ''
},
config: {}
/*template: '', //
component: '' // 根据template注入的组件*/
},
{
type: 'upload',
label: '图片/文件',
icon: 'image',
control: {
modelValue: '' // 也可以是[{name:'',url:''}]形式
},
config: {}
},
{
type: 'tinymce',
label: 'tinymce富文本',
icon: 'tinymce',
control: {
modelValue: ''
},
config: {}
}
]
},
{
title: '布局字段',
children: [
{
type: 'grid',
label: '格栅布局',
icon: 'grid',
columns: [
// 格栅列数据
{
attr: { span: 12 },
list: []
},
{
attr: { span: 12 },
list: []
}
],
control: {},
config: {}
},
{
type: 'tabs',
label: '标签页',
icon: 'tabs',
columns: [
{
label: 'Tab1',
list: []
}
],
control: {},
config: {}
},
{
type: 'card',
label: '卡片布局',
icon: 'card',
list: [],
control: {},
config: {},
item: {} // label标题相关
},
{
type: 'flex',
label: '弹性布局',
icon: 'flex',
list: [],
tableData: [], // 值集合
control: {},
config: {
addBtnText: '添加一行'
}
},
{
type: 'divider',
label: '分割线',
icon: 'divider',
control: {},
config: {}
},
{
type: 'div',
label: 'div容器',
icon: 'div',
control: {},
config: {},
list: []
}
]
},
{
title: '扩展组件',
children: [
{
type: 'expand-user',
label: '选择用户',
icon: 'user',
control: {
// 组件所有属性
modelValue: ''
},
config: {} // 其他配置信息
}
]
}
]

166
src/components/DesignForm/dragControl.vue

@ -0,0 +1,166 @@
<!--
@ 作者: 秦东
@ 时间: 2023-07-12 10:58:26
@ 备注: 快速选择表单字段
-->
<script lang='ts' setup>
import { FormData,FormList } from '@/api/DesignForm/types'
import { stringToObj } from '@/utils/DesignForm/form'
import { jsonParseStringify } from '@/utils/DesignForm'
import controlListData from '@/components/DesignForm/assembly'
import { getRequest } from '@/api/DesignForm'
import Draggable from 'vuedraggable-es'
import UseTemplate from './template.vue'
const props = withDefaults(
defineProps<{
formId?: number | string
}>(),
{}
)
//
const searchField = [
'input',
'radio',
'checkbox',
'select',
'datePicker',
'timePicker',
'inputNumber',
'cascader',
'component',
'button'
]
const designType = inject('formDesignType') as string
const formDataList = ref<any[]>([])
const isSearch = computed(() => {
return designType === 'search'
})
const emits = defineEmits(["clickCheck","click"]);
//
const selectChange = (val: any,obj: FormList) => {
if (val) {
//
const newObj = jsonParseStringify(obj)
delete newObj.rules
delete newObj.customRules
emits('clickCheck', newObj)
}
}
const controlList = computed(() => {
if (designType === 'search') {
//
const temp: any = []
controlListData.forEach((item: any) => {
if (item.children) {
const filter = item.children.filter((ch: any) => {
return searchField.includes(ch.type)
})
if (filter && filter.length) {
temp.push({ title: item.title, children: filter })
}
}
})
return temp
} else {
return controlListData
}
})
//使
const useTemplateEl = ref()
const useTemplateClick = () => {
useTemplateEl.value.open()
}
const useTemplateSelect = (data: FormData) => {
emits('click', data)
}
const clone = (origin: any) => {
return jsonParseStringify(origin)
}
//
watch(
() => props.formId,
(val: any) => {
if (val && isSearch.value) {
getFormField(val)
}
}
)
//
const getFormField = (formId: number) => {
getRequest('designById', { id: formId }).then((res: any) => {
const data = stringToObj(res.data.data)
if (data && data.list) {
forEachGetData(data.list)
}
})
}
const forEachGetData = (data: FormList[]) => {
data.forEach((item: any) => {
if (item.type === 'grid' || item.type === 'tabs') {
item.columns.forEach((col: any) => {
forEachGetData(col.list)
})
} else if (item.type === 'card') {
forEachGetData(item.list)
} else if (searchField.includes(item.type) && item.type !== 'button') {
formDataList.value.push(item)
}
})
}
</script>
<template>
<div class="components-list">
<div v-if="isSearch && formDataList?.length">
<div class="title">快速选择表单字段</div>
<div class="content">
<el-checkbox
v-for="item in formDataList"
:key="item.name"
@change="selectChange($event,item)"
>
{{ item.item?.label }}
</el-checkbox>
</div>
</div>
<!--组件主体-->
<div v-for="(list, index) in controlList" :key="index">
<div class="title">
{{ list.title }}
<div
class="template"
v-if="index === 0 && !isSearch"
@click="useTemplateClick"
>
使用模板
</div>
</div>
<draggable
itemKey="key123"
tag="ul"
v-model="list.children"
:group="{ name: 'form', pull: 'clone', put: false }"
ghost-class="ghost"
:sort="false"
:clone="clone"
>
<template #item="{ element }">
<li :class="[element.type]">
<i :class="`icon-${element.icon}`"></i>
<span :title="element.label">{{ element.label }}</span>
</li>
</template>
</draggable>
</div>
<use-template
ref="useTemplateEl"
@click="useTemplateSelect"
v-if="!isSearch"
/>
</div>
</template>
<style lang='scss' scoped>
</style>

14
src/components/DesignForm/public/form/childTable.vue

@ -0,0 +1,14 @@
<!--
@ 作者: 秦东
@ 时间: 2023-07-14 08:51:25
@ 备注: 表单子表
-->
<script lang='ts' setup>
</script>
<template>
<div></div>
</template>
<style lang='scss' scoped>
</style>

14
src/components/DesignForm/public/form/flexBox.vue

@ -0,0 +1,14 @@
<!--
@ 作者: 秦东
@ 时间: 2023-07-14 11:17:43
@ 备注:
-->
<script lang='ts' setup>
</script>
<template>
<div></div>
</template>
<style lang='scss' scoped>
</style>

483
src/components/DesignForm/public/form/form.vue

@ -0,0 +1,483 @@
<!--
@ 作者: 秦东
@ 时间: 2023-07-12 15:08:07
@ 备注: 表单画布
-->
<script lang='ts' setup>
import FormGroup from './formGroup.vue'
import { FormData,FormList } from '@/api/DesignForm/types'
import { getRequest } from '@/api/DesignForm'
import { useRoute, useRouter } from 'vue-router'
import {
constGetControlByName,
constSetFormOptions,
constFormBtnEvent,
constControlChange,
constFormProps,
appendOrRemoveStyle
} from '@/api/DesignForm/utils'
import formatResult from '@/utils/DesignForm/formatResult'
import formChangeValue from '@/utils/DesignForm/formChangeValue'
import { jsonParseStringify } from '@/utils/DesignForm'
const props = withDefaults(
defineProps<{
formData: FormData
type?: number // 123 4 5
disabled?: boolean //
requestUrl?: string // url
beforeRequest?: Function //
afterResponse?: Function | string //
addUrl?: string // url
editUrl?: string // url
beforeSubmit?: Function | string //
afterSubmit?: Function // return false
value?: { [key: string]: any } // setValue
options?: { [key: string]: any } // setOptions
dict?: object //
isSearch?: boolean // 使
}>(),
{
type: 1, // 123 4 5
formData: () => {
return {
list: [],
form: {},
config: {}
}
},
dict: () => {
return {}
},
isSearch: false
}
)
const emits = defineEmits<{
(e: 'btnClick', type: string): void
(e: 'change', val: any): void //
}>()
const route = useRoute()
const router = useRouter()
const loading = ref(false)
let timer = 0
let eventName = ''
let getValueEvent = ''
// window
const setWindowEvent = (bool?: boolean) => {
if (props.formData.list.length > 0) {
const formName = props.formData.form?.name
if (!formName) {
// .vuename
return
}
eventName = `get${formName}ControlByName`
getValueEvent = `get${formName}ValueByName`
if (formName && (!window[eventName as any] || !bool)) {
// name
// @ts-ignore
window[eventName] = (name: string) => {
return getNameForEach(props.formData.list, name)
}
// name
// @ts-ignore
window[getValueEvent] = (name: string) => {
return model.value[name]
}
}
}
}
watch(
() => props.formData.config,
() => {
if (timer < 2) {
setWindowEvent() //
}
timer++
appendRemoveStyle(true) //
},
{ deep: true }
)
setWindowEvent()
//
const resultDict = ref({})
//
const model = ref<any>({})
// model
const getInitModel = () => {
const obj = {}
forEachGetFormModel(props.formData.list, obj)
model.value = obj
}
watch(
() => props.formData.list,
() => {
// formData
getInitModel()
}
)
// model
const forEachGetFormModel = (list: FormList[], obj: any) => {
list.forEach((item: any) => {
if (['table', 'flex'].includes(item.type)) {
obj[item.name] = jsonParseStringify(item.tableData)
} else if (['grid', 'tabs'].includes(item.type)) {
item.columns.forEach((col: any) => {
forEachGetFormModel(col.list, obj)
})
} else if (['card', 'div'].includes(item.type)) {
forEachGetFormModel(item.list, obj)
} else {
const excludeType = ['title', 'divider', 'txt', 'button']
if (excludeType.indexOf(item.type) === -1) {
obj[item.name] = jsonParseStringify(item.control.modelValue)
}
}
})
}
// tProp
provide(constControlChange, ({ key, value, data, tProp }: any) => {
if (key) {
if (!tProp) {
// change
model.value[key] = value
}
// 线AB
if (props.formData.events?.change) {
model.value = props.formData.events.change(key, model.value)
}
const onFormChange = props.formData.events?.change
if (onFormChange) {
if (typeof onFormChange === 'function') {
model.value = onFormChange(key, model.value)
} else {
model.value = formChangeValue(key, model.value, onFormChange)
}
}
// tProps
emits('change', { key, value, model: model.value, data, tProp })
}
})
const dictForm = computed(() => {
const storage = window.localStorage.getItem('akFormDict')
let storageDict = {}
if (storage) {
storageDict = JSON.parse(storage)
}
//
return Object.assign({}, storageDict, props.dict, resultDict.value)
})
//
const formProps = computed(() => {
return {
model: model.value,
type: props.type,
hideField: props.formData.config?.hideField as [],
showColon: props.formData.form.showColon,
dict: dictForm.value
}
})
provide(constFormProps, formProps)
// nameformData.list
const getNameForEach = (data: any, name: string) => {
let temp = {}
for (const key in data) {
const dataKey = data[key]
if (dataKey.name === name) {
return dataKey
}
if (['grid', 'tabs'].includes(dataKey.type)) {
dataKey.columns.forEach((co: any) => {
temp = getNameForEach(co.list, name)
})
}
if (['card', 'div'].includes(dataKey.type)) {
temp = getNameForEach(dataKey.list, name)
}
}
return temp
}
const getControlByName = (name: string) => {
return getNameForEach(props.formData.list, name)
}
provide(constGetControlByName, getControlByName)
//
const ruleForm = ref()
const validate = (callback: any) => {
ruleForm.value.validate((valid: boolean, fields: any) => {
let fieldValue = fields
if (valid) {
//
fieldValue = getValue()
}
callback(valid, fieldValue)
})
}
//
const getValue = (filter?: boolean) => {
if (filter) {
const obj: any = {}
for (const key in model.value) {
// eslint-disable-next-line no-prototype-builtins
if (model.value.hasOwnProperty(key)) {
const val = (model.value as any)[key]
if (!/^\s*$/.test(val)) {
obj[key] = val
}
}
}
return obj
} else {
return model.value
}
}
//
const setValue = (obj: { [key: string]: any }, filter?: boolean) => {
// falseobjmodelobjmodel
// true
if (filter) {
for (const key in obj) {
if (model.value[key] !== undefined) {
model.value[key] = obj[key]
}
}
} else {
model.value = Object.assign({}, model.value, jsonParseStringify(obj)) // 使set
}
}
//
const setFormOptions = ref({})
provide(constSetFormOptions, setFormOptions)
const setOptions = (obj: { [key: string]: string[] }) => {
setFormOptions.value = obj
}
// style
const appendRemoveStyle = (type?: boolean) => {
try {
const {
config: { style }
} = props.formData
appendOrRemoveStyle('formStyle', style || '', type)
} catch (e) {
/* empty */
}
}
//
provide(constFormBtnEvent, (obj: any) => {
emits('btnClick', obj.key)
if ([3, 4, 5].includes(props.type)) {
return ElMessage.error('当前模式不能提交表单')
}
switch (obj.key) {
case 'submit':
submit() //
break
case 'reset':
resetFields() //
break
case 'cancel': //
router.go(-1) //
break
}
})
//
const getData = (params = {}) => {
const requestUrl = props.formData.config?.requestUrl || props.requestUrl
if (props.type === 5 || !requestUrl || props.isSearch) {
console.error('执行了获取数据方法,但配置有误!')
return
}
loading.value = true
const newParams: any = params
// 使propsevents使使
let newParams2
const beforeRequest = props.formData.events?.beforeRequest
if (typeof beforeRequest === 'function') {
newParams2 = beforeRequest(newParams, route)
}
if (typeof props.beforeRequest === 'function') {
newParams2 = props.beforeRequest(newParams, route)
}
if (newParams2 === false) {
//
return
}
getRequest(requestUrl, newParams2 ?? newParams)
.then(res => {
// console.log(res)
loading.value = false
const result = res.data
if (result) {
let formatRes: any = result
//
const afterResponse = props.formData.events?.afterResponse
if (typeof afterResponse === 'string' && afterResponse) {
formatRes = formatResult(result, afterResponse)
} else if (typeof afterResponse === 'function') {
formatRes = afterResponse(result) ?? result
}
// vue
if (typeof props.afterResponse === 'string' && props.afterResponse) {
formatRes = formatResult(result, props.afterResponse)
} else if (typeof props.afterResponse === 'function') {
formatRes = props.afterResponse(result) ?? result
}
if (formatRes === false) {
return
}
setValue(formatRes.result || formatRes)
nextTick(() => {
// dictoptions
if (formatRes.dict && Object.keys(formatRes.dict).length) {
resultDict.value = formatRes.dict
}
})
}
})
.catch((res: any) => {
loading.value = false
return ElMessage.error(res.message)
})
}
const submit = (params = {}) => {
const addUrl = props.formData.config?.addUrl || props.addUrl
const editUrl = props.formData.config?.editUrl || props.editUrl
const apiUrl = props.type === 1 ? addUrl : editUrl
if (props.isSearch || !apiUrl || loading.value) {
if (!props.isSearch && !apiUrl) {
console.error(
new Error('请在表单设计处配置接口事件url或选择数据源或设置props')
)
}
//
return
}
validate((valid: boolean, fields: any) => {
if (valid) {
const formatParams = Object.assign({}, fields, params)
let submitParams
const beforeSubmit = props.formData.events?.beforeSubmit
if (beforeSubmit) {
if (typeof beforeSubmit === 'function') {
submitParams = beforeSubmit(formatParams, route)
} else {
submitParams = formatResult(formatParams, beforeSubmit)
}
}
if (props.beforeSubmit && typeof props.beforeSubmit === 'string') {
submitParams = formatResult(formatParams, props.beforeSubmit)
} else if (typeof props.beforeSubmit === 'function') {
submitParams = props.beforeSubmit(formatParams, route)
}
if (submitParams === false) {
return
}
loading.value = true
//
getRequest(apiUrl, submitParams ?? formatParams)
.then((res: any) => {
afterSubmit('success', res)
})
.catch(res => {
afterSubmit('fail', res)
})
} else {
//
afterSubmit('validate', fields)
}
})
}
//
const afterSubmit = (type: string, res: any) => {
const afterSubmit = props.formData.events?.afterSubmit
let notReturn
if (typeof afterSubmit === 'function') {
notReturn = afterSubmit(type, res)
} else if (typeof props.afterSubmit === 'function') {
notReturn = props.afterSubmit(type, res)
}
loading.value = false
//
// resetFields()
if (notReturn === false) {
// false
return
}
if (type === 'success') {
ElMessage.success(res.message || '保存成功!')
} else if (type === 'fail') {
ElMessage.error(res.message || '保存失败!')
}
}
//
watch(
() => props.value,
(v: any) => {
v && setValue(v)
},
{
immediate: true
}
)
// options
watch(
() => props.options,
(v: any) => {
v && setOptions(v)
}
)
// ------------------------------------------------
//
const resetFields = () => {
ruleForm.value.resetFields()
// setValue(Object.assign(model.value, obj || {})) //
}
onMounted(() => {
getInitModel()
nextTick(() => {
appendRemoveStyle(true)
})
})
onUnmounted(() => {
if (eventName) {
// @ts-ignore
window[eventName] = ''
}
appendRemoveStyle()
})
defineExpose({
setOptions,
setValue,
getValue,
validate,
resetFields,
getData,
submit
})
</script>
<template>
<div v-loading="loading">
<el-form
v-bind="formData.form"
ref="ruleForm"
:model="model as any"
:disabled="disabled || type === 3"
class="add-form"
:class="{
'design-form': type === 5,
'detail-form': type === 3 || type === 4
}"
>
<FormGroup :data="formData.list" />
<slot></slot>
</el-form>
</div>
</template>
<style lang='scss' scoped>
</style>

436
src/components/DesignForm/public/form/formGroup.vue

@ -0,0 +1,436 @@
<!--
@ 作者: 秦东
@ 时间: 2023-07-14 08:46:51
@ 备注: 表单组
-->
<script lang='ts' setup>
import { computed, watch, inject, onUnmounted } from 'vue'
import Draggable from 'vuedraggable-es'
import FormItem from './formItem.vue'
import ChildTable from './childTable.vue'
import Tooltips from '@/components/DesignForm/tooltip.vue'
import FlexBox from './flexBox.vue'
import { useDesignFormStore } from '@/store/DesignForm/designForm'
import { FormList } from '@/api/DesignForm/types'
import {
constFormBtnEvent,
constFormProps
} from '@/api/DesignForm/utils'
import { Md5 } from 'ts-md5';
import { jsonParseStringify } from '@/utils/DesignForm'
const props = withDefaults(
defineProps<{
data: FormList[]
}>(),
{
data: () => {
return []
}
}
)
const store = useDesignFormStore() as any
const formProps = inject(constFormProps, {}) as any
const type = computed(() => {
return formProps.value.type
})
const state = reactive({
clone: true, // clone
gridAdd: false
})
const dataList = ref<any>(props.data)
watch(
() => props.data,
(v: FormList[]) => {
dataList.value = v
}
)
const activeKey = computed(() => {
return store.activeKey
})
//
const notNested = (type: string) => {
const controlType = ['grid', 'table', 'tabs', 'div', 'flex', 'card']
return controlType.includes(type)
}
//
const click = (action: string, index: number, item?: any) => {
if (type.value !== 5) {
return //
}
if (action === 'clone') {
const key = item.type + new Date().getTime().toString()
const newItem = jsonParseStringify(item)
dataList.value.splice(index, 0, Object.assign(newItem, { name: key }))
} else if (action === 'del') {
dataList.value.splice(index, 1)
//
store.setActiveKey('')
store.setControlAttr({})
} else if (action === 'gridAdd') {
item.columns.push({
list: [],
attr: { span: 12 }
})
} else if (action === 'delGridChild') {
item.splice(index, 1)
}
}
const draggableAdd = (evt: any) => {
if (type.value !== 5) {
return //
}
const newIndex = evt.newIndex
const key = new Date().getTime().toString()
const obj: any = dataList.value[newIndex]
const isNested = evt.target && evt.target.getAttribute('data-type') //
if (isNested === 'not-nested' && notNested(obj.type)) {
dataList.value.splice(newIndex, 1)
return
}
if (!obj) {
return
}
const label = obj.label || obj.item.label
delete obj.label
delete obj.icon
let objectItem = {}
// item
const notNeedItem = [
'txt',
'title',
'button',
'table',
'grid',
'tabs',
'flex',
'div'
]
if (!notNeedItem.includes(obj.type)) {
objectItem = {
item: {
label: label
}
}
}
// name
let nameObj = {}
const notNeedName = [
'txt',
'title',
'button',
'grid',
'tabs',
'divider',
'div',
'card'
]
if (!notNeedName.includes(obj.type) && !obj.name) {
nameObj = {
name: obj.type + key
}
}
Object.assign(obj, nameObj, objectItem)
groupClick(obj)
}
const getGroupName = (item: any) => {
if (item.name) {
return item.name
} else {
let md5Object:any = new Md5()
md5Object.appendAsciiStr(JSON.stringify(item))
let md5Str = md5Object.end()
return md5Str
}
}
//
const groupClick = (item: any, ele?: string) => {
//
if (type.value !== 5) {
return
}
if (ele) {
item.type = ele
}
store.setActiveKey(getGroupName(item))
store.setControlAttr(item)
// grid
state.gridAdd = item.type === 'grid'
state.clone = !notNested(item.type)
}
//
const getFormItemStyle = (ele: FormList) => {
if (ele.config?.span === 0) {
return { width: 'auto', margin: '0 5px' }
}
if (ele.config && ele.config.span) {
return { width: (ele.config.span / 24) * 100 + '%' }
}
}
//
const linksShow = (el: FormList, index: number) => {
//
if (!el.config) {
return true
}
const key = el.config.linkKey
const value = el.config.linkValue
const linkResult = el.config.linkResult
if (key && value && type.value !== 5) {
const Fn = new Function('$', `return (${value})`)
const pass = Fn(formProps.value.model)
if (linkResult === 'disabled') {
// disabled
dataList.value[index].control.disabled = pass
return true
} else {
return pass
}
}
return true
}
//
const linksIf = (obj: FormList) => {
const { type } = formProps.value
const { config: { disabledAdd, disabledEdit, disabledDetail } = {} } = obj
if (type === 1) {
if (disabledAdd) {
// ||
return false //
}
} else if (type === 2) {
//
if (disabledEdit) {
return false
}
} else if (type === 4 || type === 3) {
//
if (disabledDetail) {
return false
}
}
// namevIf
const vIf: string | string[] = formProps.value.hideField
if (vIf?.length > 0 && obj.name) {
return vIf.indexOf(obj.name) === -1 // false
}
return true
}
//
const injectBtnEvent = inject(constFormBtnEvent)
const clickBtn = (control: any) => {
// 0: '',
// 1: '',
// 2: '',
// 3: '()'
if (type.value !== 5) {
//
injectBtnEvent && injectBtnEvent(control)
}
}
onUnmounted(() => {
// console.log('formGroup onUnmounted')
dataList.value = {}
store.setActiveKey('')
store.setControlAttr({})
})
</script>
<template>
<draggable
itemKey="id"
:list="dataList"
name="fade"
class="drag"
v-bind="{
group: 'form',
ghostClass: 'ghost',
animation: 200,
handle: '.drag-move',
disabled: type !== 5
}"
@add="draggableAdd"
>
<template #item="{ element, index }">
<div
class="group"
:class="{
['group-' + element.type]: true,
active: activeKey === getGroupName(element)
}"
:style="getFormItemStyle(element)"
@click.stop="groupClick(element)"
v-show="linksShow(element, index)"
v-if="linksIf(element)"
>
<template v-if="element.type === 'tabs'">
<div class="form-tabs">
<el-tabs
v-bind="element.control"
:class="[element.config?.className]"
>
<el-tab-pane
v-for="(item, tIndex) in element.columns"
:label="item.label"
:key="tIndex"
>
<form-group :data="item.list" data-type="not-nested" />
</el-tab-pane>
</el-tabs>
</div>
</template>
<template v-else-if="element.type === 'title'">
<div
class="title"
:class="[element.config.className]"
v-bind="element.control"
>
<span v-html="element.control.modelValue"></span>
<Tooltips
:content="element.config.help"
v-if="element.config.help"
/>
</div>
</template>
<template v-else-if="element.type === 'txt'">
<div
v-bind="element.control"
:class="[element.config.className]"
v-html="element.control.modelValue"
></div>
</template>
<template v-else-if="element.type === 'table'">
<div class="form-table" v-if="type === 5">
<form-group :data="element.list" data-type="not-nested" />
</div>
<child-table v-else :data="element" />
</template>
<template v-else-if="element.type === 'grid'">
<el-row class="form-row" :class="[element.className]">
<el-col
class="form-col"
:class="{
'active-col': activeKey === getGroupName(col),
[col.className]: col.className
}"
v-bind="col.attr"
v-for="(col, i) in element.columns"
:key="i"
@click.stop="groupClick(col, 'gridChild')"
>
<form-group :data="col.list" data-type="not-nested" />
<div class="drag-control" v-if="type === 5">
<div class="item-control">
<i
class="icon-del"
@click.stop="
click('delGridChild', i as number, element.columns)
"
></i>
</div>
</div>
</el-col>
</el-row>
</template>
<template v-else-if="element.type === 'card'">
<el-collapse model-value="1">
<el-collapse-item :title="element.item.label" name="1">
<template #title v-if="element.help">
{{ element.item.label }}
<Tooltips :content="element.help" />
</template>
<form-group :data="element.list" data-type="not-nested" />
</el-collapse-item>
</el-collapse>
</template>
<template v-else-if="element.type === 'divider'">
<el-divider v-bind="element.control"
>{{ element.item && element.item.label }}
</el-divider>
</template>
<template v-else-if="element.type === 'div'">
<div
class="div-layout"
v-bind="element.control"
:class="{
[element.className]: element.className,
inline: element.config?.inline,
[element.config?.textAlign]: element.config?.textAlign
}"
>
<form-group :data="element.list" data-type="not-nested" />
</div>
</template>
<template v-else-if="element.type === 'flex'">
<form-group
:data="element.list"
data-type="not-nested"
v-if="type === 5"
/>
<flex-box :data="element" v-else />
<el-button
style="position: relative; top: -28px; left: 10px"
v-if="element.config.addBtnText && type === 5"
size="small"
>{{ element.config.addBtnText }}</el-button
>
</template>
<template v-else-if="element.type === 'button'">
<div
:class="[element.config?.className]"
:style="{ 'text-align': element.config?.textAlign }"
>
<el-button
v-bind="element.control"
@click="clickBtn(element.control)"
>{{ element.control?.label }}</el-button
>
</div>
</template>
<template v-else-if="element.type === 'inputSlot' && type !== 5">
<!-- 除设计外其他无需处理-->
</template>
<form-item v-else :data="element" />
<template v-if="type === 5">
<div class="drag-control">
<div class="item-control">
<i
class="icon-plus"
@click.stop="click('gridAdd', index, element)"
v-if="state.gridAdd"
title="添加列"
></i>
<i
class="icon-clone"
@click.stop="click('clone', index, element)"
v-if="state.clone"
title="克隆"
></i>
<i class="icon-del" @click.stop="click('del', index)"></i>
</div>
<div class="drag-move icon-move"></div>
</div>
<div class="tooltip">{{ element.name }}</div>
</template>
</div>
</template>
</draggable>
</template>
<style lang='scss' scoped>
</style>

14
src/components/DesignForm/public/form/formItem.vue

@ -0,0 +1,14 @@
<!--
@ 作者: 秦东
@ 时间: 2023-07-14 08:50:36
@ 备注: 表单项目
-->
<script lang='ts' setup>
</script>
<template>
<div></div>
</template>
<style lang='scss' scoped>
</style>

68
src/components/DesignForm/public/headTools.vue

@ -0,0 +1,68 @@
<!--
@ 作者: 秦东
@ 时间: 2023-07-12 14:41:18
@ 备注: 主体画板顶部
-->
<script lang='ts' setup>
import { computed } from 'vue'
const props = withDefaults(
defineProps<{
showKey?: string[] // showKey,hideKeyshowKey
hideKey?: string[] // showKeyhideKey
}>(),
{
showKey: () => {
return []
},
hideKey: () => {
return []
}
}
)
const emits = defineEmits<{(e: 'click', value: string): void}>();
const btnClick = (type: string) => {
emits('click', type)
}
const btnList = computed(() => {
const list = [
{ icon: 'del', label: '清空', key: 1 },
{ icon: 'eye', label: '预览', key: 2 },
{ icon: 'json', label: '生成脚本预览', key: 3 },
{ icon: 'vue', label: '导出vue文件', key: 4 },
{ icon: 'save', label: '保存', key: 5 }
]
if (props.showKey?.length) {
// key
return list.filter((item: any) => {
return props.showKey.includes(item.key)
})
} else if (props.hideKey?.length) {
// key
return list.filter((item: any) => {
return !props.hideKey.includes(item.key)
})
} else {
return list //
}
})
</script>
<template>
<div class="main-tools">
<slot></slot>
<el-button
link
type="primary"
@click="btnClick(item.icon)"
v-for="item in btnList"
:key="item.icon"
>
<i :class="['icon-' + item.icon]"></i>{{ item.label }}
</el-button>
</div>
</template>
<style lang='scss' scoped>
</style>

49
src/components/DesignForm/template.vue

@ -0,0 +1,49 @@
<!--
@ 作者: 秦东
@ 时间: 2023-07-14 08:27:12
@ 备注:
-->
<script lang='ts' setup>
import { FormData,FileAttributeAll } from '@/api/DesignForm/types'
const emits = defineEmits<{
(e: 'click', value: FormData): void
}>()
// const state = reactive({
// visible: false,
// list: []
// })
const state = reactive<FileAttributeAll>({
visible: false,
list: []
})
const open = () => {
state.visible = true
init()
}
const init = () => {
const template = import.meta.globEager('./template/*.ts')
console.log(template)
state.list = []
Object.keys(template).forEach((key: string) => {
const file: any = template[key]
state.list.push({
imgPath: file.imgPath,
title: file.title,
formData: file.formData
})
})
}
const selectClick = (item: any) => {
emits('click', item.formData)
state.visible = false
}
defineExpose({
open
})
</script>
<template>
<div></div>
</template>
<style lang='scss' scoped>
</style>

19
src/components/DesignForm/tooltip.vue

@ -0,0 +1,19 @@
<!--
@ 作者: 秦东
@ 时间: 2023-07-14 11:15:54
@ 备注:
-->
<script lang='ts' setup>
withDefaults(defineProps<{ content: string }>(), {})
</script>
<template>
<el-tooltip placement="top">
<template #content>
<span v-html="content"></span>
</template>
<i class="icon-help"></i>
</el-tooltip>
</template>
<style lang='scss' scoped>
</style>

7
src/main.ts

@ -24,5 +24,12 @@ const app = createApp(App);
setupDirective(app);
// 全局注册 状态管理(store)
setupStore(app);
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component)
}
app.use(router).use(i18n).mount('#app');

22
src/store/DesignForm/designForm.ts

@ -0,0 +1,22 @@
import { defineStore } from 'pinia'
export const useDesignFormStore = defineStore('designForm', {
state: () => {
return {
controlAttr: {},
activeKey: ''
//type: 1, //当前表单状态 1新增;2查看(表单模式) ;3查看; 4设计
//isEdit: false, //编辑状态,type=1新增模式下有编辑状态,主要用于控制编辑模式下某些字段的禁用状态,即可新增但不能修改
//model: {}, // 给form-group提供联动条件设置
//hideField: [], // 设置了使用v-if隐藏的字段
}
},
actions: {
setControlAttr(data: any) {
this.controlAttr = data
},
setActiveKey(key: string) {
this.activeKey = key
}
}
})

42
src/store/DesignForm/layout.ts

@ -0,0 +1,42 @@
import { defineStore } from 'pinia'
import { nextTick } from 'vue'
/*interface Breadcrumb {
label: string
to?: string
}*/
interface TabsViews {
title: string
path: string
name: string // 路由名称name
}
const getSession = window.sessionStorage.getItem('tagViews')
let tabs: any = []
if (getSession) {
tabs = JSON.parse(getSession)
}
export const useLayoutStore = defineStore('layout', {
state: () => {
return {
breadcrumb: [],
tabs: tabs,
reloadFlag: true // 用于刷新路由
}
},
// 也可以定义为
// state: () => ({ count: 0 })
actions: {
changeBreadcrumb(data: any) {
this.breadcrumb = data
},
setTabsViews(obj: TabsViews[]) {
this.tabs = obj
window.sessionStorage.setItem('tagViews', JSON.stringify(obj))
},
setReloadRouter() {
this.reloadFlag = false
nextTick(() => {
this.reloadFlag = true
})
}
}
})

87
src/utils/DesignForm/form.ts

@ -0,0 +1,87 @@
// @ts-ignore
import jsBeautify from 'js-beautify'
export const EDITTYPE = 'javascript' // 弹出编辑器可输入类型 json/javascript
export function evil(fn: any) {
const Fn = Function // 一个变量指向Function,防止有些前端编译工具报错
return new Fn('return ' + fn)()
}
export function obj2string(o: any) {
let r: any = []
if (o === null) {
// 这里有个问题 因typeOf null=object,下面判断会报错
return null
}
if (typeof o === 'string') {
return (
'"' +
o
.replace(/([\\'\\"\\])/g, '\\$1')
.replace(/(\n)/g, '\\n')
.replace(/(\r)/g, '\\r')
.replace(/(\t)/g, '\\t') +
'"'
)
}
if (typeof o === 'object') {
if (!o.sort) {
for (const i in o) {
if (o.hasOwnProperty(i)) {
let iii = i
if (i.indexOf('-') !== -1) {
iii = `"${i}"`
}
r.push(iii + ':' + obj2string(o[i]))
}
}
if (
!!document.all &&
!/^\n?function\s*toString\(\)\s*\{\n?\s*\[native code\]\n?\s*\}\n?\s*$/.test(
o.toString
)
) {
r.push('toString:' + o.toString.toString())
}
r = '{' + r.join() + '}'
} else {
for (let i = 0; i < o.length; i++) {
r.push(obj2string(o[i]))
}
r = '[' + r.join() + ']'
}
return r
}
return o && o.toString()
}
export function objToStringify(obj: any, isBeautify?: boolean) {
if (EDITTYPE === 'javascript') {
if (isBeautify) {
return jsBeautify('opt=' + obj2string(obj), {
indent_size: 2,
brace_style: 'expand'
})
} else {
return obj2string(obj)
}
} else {
return isBeautify ? JSON.stringify(obj, null, 2) : JSON.stringify(obj)
}
}
export function stringToObj(string: string) {
if (EDITTYPE === 'javascript') {
return evil(string)
} else {
return JSON.parse(string)
}
}
export function string2json(string: string) {
return JSON.parse(string || '{}')
}
export function json2string(obj: any, isBeautify?: boolean) {
return isBeautify ? JSON.stringify(obj, null, 2) : JSON.stringify(obj)
}

16
src/utils/DesignForm/formChangeValue.ts

@ -0,0 +1,16 @@
// 用于在线模式表单值改变事件,此方法可实际如A组件改变时,自动对B组件设值或修改
// 必须要return
/*
@params name name值
@params model当前表单的值
@params key
*/
const formChangeValue = (
name: string,
model: { [key: string]: any },
key: string
) => {
console.log(key, model, name)
return model
}
export default formChangeValue

34
src/utils/DesignForm/formatResult.ts

@ -0,0 +1,34 @@
// 处理返回结果,当数据比较复杂时,使用在线编辑器如afterResponse方法不太适合,key即为afterResponse的字符串值
// 必须要return
const formatResult = (res: any, key: string) => {
// console.log('formatResult', res, key)
switch (key) {
case 'transformDataToChild':
return transformDataToChild(res.list || res)
}
return res
}
// 根据id及parentId扁平数据转为children嵌套格式
const transformDataToChild = (res: any) => {
const temp: any = []
transformDataList(res, 0, temp)
return temp
}
const transformDataList = (data: any, parentId: number, temp: any) => {
data.forEach((item: any) => {
item.value = item.id // tree组件只能修改label取值,不能指定value,这里添加一个
item.label = item.name
if (item.parentId === parentId) {
const childrenList = data.filter((ch: any) => {
return ch.parentId === item.id
})
if (childrenList?.length) {
item.children = []
transformDataList(data, item.id, item.children)
}
temp.push(item)
}
})
}
// 部门侧栏树列表数据处理结束
export default formatResult

18
src/utils/DesignForm/formatScreen.ts

@ -0,0 +1,18 @@
// 用于在线模式表单值改变事件,此方法可实际如A组件改变时,自动对B组件设值或修改
// 必须要return
/*
@params key
@params result api接口返回结果
@params options options数据
@params global
*/
const formatScreen = (
key: string,
result: any,
options?: any,
global?: any
) => {
console.log(key, result, options, global)
return options
}
export default formatScreen

95
src/utils/DesignForm/index.ts

@ -0,0 +1,95 @@
export function debounce<T extends (...args: any[]) => void>(func: T, delay = 500, immediate?: boolean): T {
let timerId: any
return function (this: any, ...args: any[]) {
if (timerId) {
clearTimeout(timerId)
}
if (immediate) {
const callNow = !timerId
timerId = setTimeout(() => {
timerId = null
}, delay)
if (callNow) {
func.apply(this, args)
}
} else {
timerId = setTimeout(() => {
func.apply(this, args)
}, delay)
}
} as T
}
// 时间格式化
export const dateFormatting = (time: any, cFormat?: string) => {
const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
// 字符串数字形式的时间戳要转换下
let newTime = time
if (/^\d+?$/.test(time)) {
newTime = parseInt(time)
}
const date = typeof time === 'object' ? time : new Date(newTime)
const formatObj: any = {
y: date.getFullYear(),
m: date.getMonth() + 1,
d: date.getDate(),
h: date.getHours(),
i: date.getMinutes(),
s: date.getSeconds(),
w: date.getDay()
}
return format.replace(/{(y|m|d|h|i|s|w)+}/g, (result, key) => {
let value = formatObj[key]
if (key === 'w') {
return ['日', '一', '二', '三', '四', '五', '六'][value]
}
if (result.length > 0 && value < 10) {
value = '0' + value
}
return value || 0
})
}
// 动态远程加载script脚本
export function loadScript(src: string) {
return new Promise((resolve, reject) => {
const script = document.createElement('script')
script.type = 'text/javascript'
script.onload = resolve
script.onerror = reject
script.src = src
document.head.appendChild(script)
})
}
// 随机数字符串
export const randomString = (len: number) => {
len = len || 32
const str = 'ABCDEFGHIJKMNOPQSTWXYZabcdefghijklmnopqrstwxyz1234567890'
let n = ''
for (let i = 0; i < len; i++) {
n += str.charAt(Math.floor(Math.random() * str.length))
}
return n
}
export const jsonParseStringify = (val: any) => {
if (typeof val === 'object') {
return JSON.parse(JSON.stringify(val))
} else {
return val
}
}
/**
* local session storage
* @param key
* @param data setget
* @param type local/session默认
*/
export const getSetStorage = (key: string, data?: string, type = 'session') => {
//console.log(key, data)
const winType = type === 'session' ? 'sessionStorage' : 'localStorage'
if (data) {
window[winType].setItem(key, data)
} else {
return window[winType].getItem(key)
}
}

35
src/utils/DesignForm/request.ts

@ -0,0 +1,35 @@
import axios from 'axios'
// 全局设置
/* axios.defaults.baseURL = window.APP_CONFIG.BASE_URL
axios.defaults.headers.common['Authorization'] = getToken() */
const service = axios.create({
baseURL: import.meta.env.VITE_APP_URL, // api的base_url
//baseURL: 'http://localhost:3001/api', // api的base_url
timeout: 3000, // request timeout
headers: {}
})
service.interceptors.request.use(
(config) => {
return config
},
(error) => {
Promise.reject(error)
}
)
service.interceptors.response.use(
(response) => {
if (response.data.code === 1) {
return response.data
} else {
// 这里面需增加统一拦截
return Promise.reject(response.data)
}
},
(error) => {
return Promise.reject(error)
}
)
export default service

7
src/views/matrix/index.vue

@ -8,7 +8,7 @@ import { orgInfo } from '@/api/hr/org/type'
import { getOrgTreeList } from '@/api/hr/org/index'
import { searchMatrix,matrixCont } from '@/api/matrixapi/type'
import { getMatrixList,editMatrixStatus } from '@/api/matrixapi/index'
import { getOrgChiled } from '@/api/displayboardapi/indexapi'
/**
* 引入页面
*/
@ -17,6 +17,7 @@ import MatrixContEdit from '@/views/matrix/matrixcont/matrixcontedit.vue'
import SetupMatrixField from '@/views/matrix/matrixcont/setupmatrixfield.vue'
import SetupMatrixUser from '@/views/matrix/matrixcont/setupmatrixuser.vue'
const ids = ref<number[]>([]); //ID
const queryFormRef = ref(ElForm); //
const orgTreeLoading = ref(false); //
@ -144,10 +145,12 @@ function openEditMatriexDialog(cont:matrixCont){
editCont.value = cont
matrixEditBox.value = true;
}
//
onMounted(() => {
haveOrgTreeInfo();
searchMatrixList();
});
</script>
<template>
@ -271,7 +274,7 @@ onMounted(() => {
<!--设置矩阵字段-->
<SetupMatrixField v-model:fieldShow="matrixSetFieldBox" :matrixcont="editCont" />
<!--设置字段使用人-->
<SetupMatrixUser v-model:userShow="matrixSetUserBox" :matrixcont="editCont" />
<SetupMatrixUser v-model:userShow="matrixSetUserBox" :matrixcont="editCont"/>
</el-main>
</el-container>
</template>

21
src/views/matrix/matrixcont/setupmatrixfield.vue

@ -65,6 +65,12 @@ function handleCloseBox(){
* 初始化数据
*/
function initData(){
// if(tjAndZhi.factor && tjAndZhi.factor.length > 0){
// tjAndZhi.factor.splice(0,tjAndZhi.factor.length);
// }
// if(tjAndZhi.outcome && tjAndZhi.outcome.length > 0){
// tjAndZhi.outcome.splice(0,tjAndZhi.outcome.length);
// }
tjAndZhi.factor.splice(0,tjAndZhi.factor.length);
tjAndZhi.outcome.splice(0,tjAndZhi.outcome.length);
addMatrixField(1);
@ -116,10 +122,17 @@ watch(() => props.fieldShow,() => {
getMatrixField({id:props.matrixcont.id})
.then(({data})=>{
console.log("监听数据---->",data)
tjAndZhi.factor.splice(0,tjAndZhi.factor.length);
tjAndZhi.outcome.splice(0,tjAndZhi.outcome.length);
tjAndZhi.factor = data.factor
tjAndZhi.outcome = data.outcome
if(data.factor && data.factor.length > 0){
tjAndZhi.factor.splice(0,tjAndZhi.factor.length);
tjAndZhi.factor = data.factor
console.log("监听数据--1-->",data)
}
if(data.outcome && data.outcome.length > 0){
tjAndZhi.outcome.splice(0,tjAndZhi.outcome.length);
tjAndZhi.outcome = data.outcome
console.log("监听数据--2-->",data)
}
});
}
});

183
src/views/matrix/matrixcont/setupmatrixuser.vue

@ -4,8 +4,15 @@
@ 备注: 设置字段值
-->
<script lang='ts' setup>
import { matrixTable,objectStruct } from '@/api/matrixapi/type'
import { getMatrixField } from '@/api/matrixapi';
import { matrixTable,objectStruct,orgAndUserMatrixCont } from '@/api/matrixapi/type'
import { getMatrixField,getNumber,submitMatrixData,haveMatrixCont } from '@/api/matrixapi';
import { Search } from '@element-plus/icons-vue'
/**
* 引入页面
*/
import PickOrg from '@/views/matrix/orgoruser/pickorg.vue'
import PickUser from '@/views/matrix/orgoruser/pickuser.vue'
import { th } from 'element-plus/es/locale';
const props = defineProps({
userShow:{
@ -24,6 +31,17 @@ const addFieldLoading = ref(false)
const tabelColumn = reactive<matrixTable[]>([])
const tableList = reactive<any[]>([])
const loading = ref(false)
const orgOrUserBox = ref(false); //
const judgePage = ref(false);
const orguseInfo = reactive<orgAndUserMatrixCont[]>([])
const systemMenuTreeProps = {
children: "child",
label: "name",
value:"id"
}
const orgOptionsList = ref<any>(); //
const tableValue = ref<any>(); //
const ids = ref<number[]>([]); //ID
/**
* 弹窗显示控制
*/
@ -44,6 +62,9 @@ const field_is_Show = computed({
* 初始化数据
*/
function initData(){
orgOptionsList.value?.splice(0,orgOptionsList.value.length);
// console.log("tableList-------->",tableList.length)
tableList.splice(0, tableList.length);
}
/**
* 监听数据
@ -53,61 +74,193 @@ function initData(){
getMatrixField({id:props.matrixcont.id})
.then(({data})=>{
console.log("监听数据---->",data)
tabelColumn.splice(0,tabelColumn.length)
data.factor.forEach(item=>{
tabelColumn.push({
id:item.id,
label:item.name,
prop:item.pinyin
prop:item.pinyin,
types:item.types
})
})
data.outcome.forEach(item=>{
tabelColumn.push({
id:item.id,
label:item.name,
prop:item.pinyin
prop:item.pinyin,
types:item.types
})
})
})
.finally(()=>{
var jks:objectStruct = {}
tabelColumn.forEach(item=>{
jks[item.prop]=1
})
console.log("监听数据-->",jks)
tableList.splice(0,tableList.length)
haveMatrixCont({id:props.matrixcont.id})
.then((data)=>{
if(data.data&&data.data.length>0){
data.data.forEach((item:any)=>{
tableList.push(item)
})
}
})
.finally(()=>{
if(tableList.length<1){
addTableHang();
}
})
})
}
});
/**
* 添加行
*/
function addTableHang(){
//
getNumber({id:8})
.then((data)=>{
var jks:objectStruct = {}
tabelColumn.forEach(item=>{
jks[item.prop]={
id:item.id,
types:item.types,
number:data.data.uuidstring,
userlist:[],
orgid:0,
namelist:[],
isedit:false,
pinyin:item.prop
}
})
tableList.push(jks)
})
// console.log("-1111->",props.orglist,props.orgtree)
}
/**
* 提交使用人
*/
function submitAddMatrixUser(){
if(orguseInfo&&orguseInfo.length>0){
orguseInfo.splice(0,orguseInfo.length)
}
console.log("提交数据-->",tableList)
if(tableList&&tableList.length > 0){
tableList.forEach((item)=>{
console.log("提交数据-4->",item,item.bm)
// if(item&&item.length>=0){
// item.forEach((items: any)=>{
// console.log("-2->",items)
// })
// }
const entries = Object.entries(item);
entries.map((val:any)=>{
console.log("提交数据-2->",val,val[val.length-1].number)
let typeClass = 1
if(val[val.length-1].types == 1){
typeClass = 2
}
orguseInfo.push({
id:0,
number:val[val.length-1].number,
userlist:val[val.length-1].userlist,
types:typeClass,
mcid:props.matrixcont.id,
mhid:val[val.length-1].id,
})
})
})
}
submitMatrixData(orguseInfo)
.then((data)=>{
console.log("提交数据-66666->",data)
handleCloseBox();
})
console.log("提交数据-1->",orguseInfo)
}
function sdfdsf(cont:any){
console.log("单击单元格-2222222->",cont)
if(cont.types<1){
judgePage.value = true
}else{
judgePage.value = false
}
cont.isedit=true
orgOrUserBox.value = true
tableValue.value = cont
}
/**
* 删除行
*/
function delTableHang(id:any){
console.log("删除行",id)
tableList.splice(id,1)
if(tableList.length<1){
addTableHang();
}
}
</script>
<template>
<el-dialog v-model="field_is_Show" custom-class="dialog_box" title="矩阵数据维护" :before-close="handleCloseBox" width="80%">
<el-dialog v-model="field_is_Show" custom-class="dialog_box" title="矩阵数据维护" :before-close="handleCloseBox" width="80%" draggable>
<PickOrg v-model:orgBoxShow="orgOrUserBox" :ismultiselect="false" :tabledata="tableValue" />
<el-table
v-loading="loading"
highlight-current-row
:data="tableList"
border
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column v-for="(item,index) in tabelColumn" :key="index" align="center">
<!-- 自定义表头 -->
<template #header>
{{item.label}}
</template>
<!-- 自定义表项/单元格内容 -->
<template #default="scope">
<div v-if="!scope.row[item.prop].isedit" class="edit_table_row" @dblclick="sdfdsf(scope.row[item.prop])" >
<el-tag v-for="(itemtext,ti) in scope.row[item.prop].userlist" :key="ti" class="ml-2" size="small">{{ itemtext.name }}</el-tag>&nbsp;
</div>
<div v-else>
<el-input
v-model="scope.row[item.prop].namelist"
placeholder="请选择"
:suffix-icon="Search"
/>
</div>
</template>
</el-table-column>
<el-table-column label="操作" width="80" align="center">
<template #default="scope">
<el-button type="danger" link @click="delTableHang(scope.$index)">删除</el-button>
</template>
</el-table-column>
</el-table>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" :loading="addFieldLoading" @click="submitAddMatrixUser" > </el-button>
<el-button @click="handleCloseBox"> </el-button>
<div class="dialog-footer left_right">
<div>
<el-button type="warning" @click="addTableHang">添加数据</el-button>
</div>
<div>
<el-button type="primary" :loading="addFieldLoading" @click="submitAddMatrixUser" > </el-button>
<el-button @click="handleCloseBox"> </el-button>
</div>
</div>
</template>
</el-dialog>
</template>
<style lang='scss' scoped>
.edit_table_row{
display: block;
width: 100%;
height: 100%;
}
.left_right{
display: flex;
justify-content: space-between;
align-items: center;
}
</style>

182
src/views/matrix/matrixcont/setupmatrixuser_black.vue

@ -0,0 +1,182 @@
<!--
@ 作者: 秦东
@ 时间: 2023-07-05 15:03:42
@ 备注: 设置字段值
-->
<script lang='ts' setup>
import { matrixTable,objectStruct } from '@/api/matrixapi/type'
import { getMatrixField } from '@/api/matrixapi';
const props = defineProps({
userShow:{
type:Boolean,
default:false
},
matrixcont:{
type:Object,
default(){
return {}
}
},
orglist:{
type:Object,
default(){
return {}
}
},
orgtree:{
type:Object,
default(){
return {}
}
}
});
const emits = defineEmits(["update:userShow"]); //
const addFieldLoading = ref(false)
const tabelColumn = reactive<matrixTable[]>([])
const tableList = reactive<any[]>([])
const loading = ref(false)
const systemMenuTreeProps = {
children: "child",
label: "name",
value:"id"
}
const orgOptionsList = ref<any>(); //
/**
* 弹窗显示控制
*/
const field_is_Show = computed({
get: () => props.userShow,
set: (val) => {
emits("update:userShow", val);
},
});
/**
* 关闭弹窗
*/
function handleCloseBox(){
emits("update:userShow", false);
initData()
}
/**
* 初始化数据
*/
function initData(){
orgOptionsList.value?.splice(orgOptionsList.value.length);
}
/**
* 监听数据
*/
watch(() => props.userShow,() => {
if(props.userShow){
getMatrixField({id:props.matrixcont.id})
.then(({data})=>{
console.log("监听数据---->",data)
data.factor.forEach(item=>{
tabelColumn.push({
id:item.id,
label:item.name,
prop:item.pinyin,
types:item.types
})
})
data.outcome.forEach(item=>{
tabelColumn.push({
id:item.id,
label:item.name,
prop:item.pinyin,
types:item.types
})
})
})
.finally(()=>{
tableList.splice(0,tableList.length)
addTableHang();
})
}
});
/**
* 添加行
*/
function addTableHang(){
var jks:objectStruct = {}
tabelColumn.forEach(item=>{
jks[item.prop]={
id:item.id,
types:item.types,
number:1,
userlist:[309],
orgid:309,
namelist:["山东恒信高科能源有限公司"],
isedit:false
}
})
tableList.push(jks)
// console.log("-1111->",props.orglist,props.orgtree)
}
/**
* 提交使用人
*/
function submitAddMatrixUser(){
}
</script>
<template>
<el-dialog v-model="field_is_Show" custom-class="dialog_box" title="矩阵数据维护" :before-close="handleCloseBox" width="80%">
<el-table
v-loading="loading"
highlight-current-row
:data="tableList"
border
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column v-for="(item,index) in tabelColumn" :key="index" align="center">
<!-- 自定义表头 -->
<template #header>
{{item.label}}
</template>
<!-- 自定义表项/单元格内容 -->
<template #default="scope">
{{scope.row[item.prop].types}}---->{{scope.row[item.prop].isedit}}
<div v-if="!scope.row[item.prop].isedit" @dblclick="scope.row[item.prop].isedit = true">
<el-text v-for="(itemtext,ti) in scope.row[item.prop].namelist" :key="ti" class="mx-1">{{ itemtext }}</el-text>
</div>
<div v-else>
<el-select v-if="scope.row[item.prop].types==3" v-model="scope.row[item.prop].orgid" clearable placeholder="请选择行政组织">
<el-option
v-for="item in props.orglist.list"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
<el-tree-select
v-if="scope.row[item.prop].types==2"
ref="orgTreePostRef"
v-model="scope.row[item.prop].orgid"
placeholder="选择归属行政组织"
:data="props.orgtree"
node-key="id"
check-strictly
:props="systemMenuTreeProps"
:render-after-expand="false"
class="orgTree"
/>
</div>
</template>
</el-table-column>
</el-table>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" :loading="addFieldLoading" @click="submitAddMatrixUser" > </el-button>
<el-button @click="handleCloseBox"> </el-button>
</div>
</template>
</el-dialog>
</template>
<style lang='scss' scoped>
</style>

613
src/views/matrix/orgoruser/pickorg.vue

@ -0,0 +1,613 @@
<!--
@ 作者: 秦东
@ 时间: 2023-07-07 09:11:55
@ 备注: 选择行政组织
-->
<script lang='ts' setup>
import { Search } from '@element-plus/icons-vue' //
import { ElDivider } from 'element-plus'
import { orgInfo,breadCrumbs,employeesCont,childDepartmentsCont } from '@/api/displayboardapi/types'
import { getOrgChiled,getBasisOrgChiled } from '@/api/displayboardapi/indexapi'
import { shuttleFramePickData } from '@/api/matrixapi/type'
import { queryPeopleCont } from '@/api/hr/people/type'
import { searchUserCont } from '@/api/hr/people/index'
const spacer = h(ElDivider, { direction: 'vertical' })
const props = defineProps({
orgBoxShow:{
type:Boolean,
default:false
},
ismultiselect:{
type:Boolean,
default:false
},
tabledata:{
type:Object,
default(){
return {}
}
}
});
const emits = defineEmits(["update:orgBoxShow"]); //
const dialogTitle = ref<string>()
const addOrgUserLoading = ref(false);
const searchKeywords = ref<string>()
const keywordsTitle = ref<string>()
const orgInfoList = ref<orgInfo[]>()
const orgBreadCrumbs = ref<breadCrumbs[]>()
const employees = ref<employeesCont[]>()
const childDepartments = ref<childDepartmentsCont[]>()
const isCheckBox = ref(false); //
const pickDataList = ref<any>()
const duoxuanVal = reactive<shuttleFramePickData[]>([])
// const danxuanVal = ref<shuttleFramePickData>()
const countPick=ref(0)
/**
* 弹窗显示控制
*/
const pickorg_is_Show = computed({
get: () => props.orgBoxShow,
set: (val) => {
emits("update:orgBoxShow", val);
},
});
/**
* 关闭弹窗
*/
function closeBox(){
// eslint-disable-next-line vue/no-mutating-props
props.tabledata.isedit = false;
pickDataList.value =[]
orgInfoList.value = []
duoxuanVal.slice(0,duoxuanVal.length)
let emptyOrg = new Array
duoxuanVal.length = 0
searchKeywords.value=""
// //console.log("",duoxuanVal)
// eslint-disable-next-line vue/no-mutating-props
// props.tabledata.namelist=["",""]
emits("update:orgBoxShow", false);
}
/**
* 获取行政组织
*/
function getOrgList(orgId:number){
getOrgChiled({id:orgId})
.then(({data})=>{
// //console.log("",data)
orgInfoList.value = data.list
orgBreadCrumbs.value = data.tabval
})
.finally(()=>{
isPick()
})
}
/**
* 判断是否选中
*/
function isPick(id?:number|string){
// //console.log("orgInfoList->",orgInfoList)
// //console.log("pickDataList->",pickDataList)
if(pickDataList.value && pickDataList.value.length > 0){
orgInfoList.value?.forEach(item=>{
if(id == item.id){
item.isActiveItem = false
}
pickDataList.value.forEach((items: any)=>{
if(item.id == items.id){
item.isActiveItem = true
}
})
})
employees.value?.forEach(item=>{
if(id == item.id){
item.ispick = false
}
pickDataList.value.forEach((items: any)=>{
if(item.id == items.id){
item.ispick = true
}
})
})
}else{
orgInfoList.value?.forEach(item=>{
if(id == item.id){
item.isActiveItem = false
}
})
employees.value?.forEach(items=>{
if(id == items.id){
items.ispick = false
}
})
}
}
/**
* 监听数据
*/
watch(() => props.orgBoxShow,() => {
duoxuanVal.slice(0,duoxuanVal.length)
if(props.orgBoxShow){
isCheckBox.value = props.ismultiselect
pickDataList.value = props.tabledata.userlist
// //console.log("-----sd3------>",isCheckBox.value)
switch(props.tabledata.types){
case 2:
dialogTitle.value = "选择行政组织"
keywordsTitle.value = "请输入关键字"
break;
case 3:
dialogTitle.value = "选择分部"
keywordsTitle.value = "请输入关键字"
break;
default:
dialogTitle.value = "选择成员"
keywordsTitle.value = "请输入姓名或工号"
}
if(props.tabledata.types > 1){
getOrgList(313)
}else{
getOrgAndPeople(313)
}
}
})
/**
* 选定值
*/
function pickval(cont:any){
// //console.log("----",duoxuanVal)
if(isCheckBox.value){
cont.isActiveItem = true
let xieRu = true;
duoxuanVal.forEach(item =>{
if(item.id == cont.id){
xieRu=false;
}
})
if(xieRu){
duoxuanVal.push({
id:cont.id.toString(),
name:cont.name,
icon:""
})
pickDataList.value = duoxuanVal
}
}else{
pickDataList.value =[
{
id:cont.id.toString(),
name:cont.name,
icon:""
}
]
orgInfoList.value?.forEach(item=>{
if(cont.id == item.id){
item.isActiveItem = true
}else{
item.isActiveItem = false
}
})
}
countPick.value = pickDataList.value.length
}
/**
* 选定人员
*/
function pickuserval(cont:any){
if(cont.ispick){
cont.ispick = false
let dxval = new Array
pickDataList.value.forEach((item: any)=>{
if(item.id != cont.id){
dxval.push(item);
}
})
duoxuanVal.splice(0,duoxuanVal.length)
dxval.forEach(items=>{
duoxuanVal.push(items)
})
pickDataList.value = dxval
}else{
cont.ispick = true
let iconVal = cont.icon
if(iconVal == "" || iconVal == null) iconVal = cont.iconToBase64
duoxuanVal.push({
id:cont.id.toString(),
name:cont.employeeName,
icon:iconVal
})
pickDataList.value = duoxuanVal
//console.log("--1->",cont)
//console.log("--2->",pickDataList)
//console.log("--3->",duoxuanVal)
//console.log("--4->",iconVal)
}
countPick.value = pickDataList.value.length
}
/**
* 删除已经选择
*/
function delPickData(cont:any,index:number){
pickDataList.value.splice(index, 1);
isPick(cont.id)
}
function delPickUserData(cont:any,index:number){
pickDataList.value.splice(index, 1);
isPick(cont.id)
}
/**
* 提交数据
*/
function submitPickOrgOrUser(){
// eslint-disable-next-line vue/no-mutating-props
props.tabledata.isedit = false;
// eslint-disable-next-line vue/no-mutating-props
// props.tabledata.namelist=["",""]
if(pickDataList.value && pickDataList.value.length > 0){
let nameAry = new Array
let userAry = new Array
pickDataList.value.forEach((item: any)=>{
nameAry.push(item.name)
userAry.push({
id:item.id.toString(),
name:item.name,
icon:item.icon
})
})
// eslint-disable-next-line vue/no-mutating-props
props.tabledata.namelist = nameAry
// eslint-disable-next-line vue/no-mutating-props
props.tabledata.userlist = userAry
}else{
// eslint-disable-next-line vue/no-mutating-props
props.tabledata.namelist = []
// eslint-disable-next-line vue/no-mutating-props
props.tabledata.userlist = []
}
closeBox();
}
/**
* 清空
*/
function emptyPickList(){
pickDataList.value =[]
duoxuanVal.slice(0,duoxuanVal.length)
let emptyOrg = new Array
duoxuanVal.length = 0
orgInfoList.value?.forEach(item=>{
item.isActiveItem = false
})
}
/** =========================================分割线。以下是行政组织人员相关内容=============================================================== */
/**
* 清空已选择的人员
*/
function emptyPickuserList(){
pickDataList.value =[]
duoxuanVal.slice(0,duoxuanVal.length)
let emptyOrg = new Array
duoxuanVal.length = 0
employees.value?.forEach(item=>{
item.ispick = false
})
}
/**
* 获取行政组织和人员
*/
function getOrgAndPeople(orgid:number){
getBasisOrgChiled({id:orgid.toString()})
.then(({data})=>{
//console.log("",data)
orgBreadCrumbs.value = data.titleDepartments
employees.value = data.employees
childDepartments.value = data.childDepartments
})
.finally(()=>{
isPick()
})
}
/**
* 搜索人员
*/
function searchPeople(){
if(searchKeywords.value != ""){
childDepartments.value = new Array
searchUserCont({page:1,pagesize:20,name:searchKeywords.value})
.then(({data})=>{
//console.log("",data)
let usAry = new Array
data.list.forEach(item=>{
let pickVal = false
if(pickDataList.value && pickDataList.value.length > 0){
pickDataList.value.forEach((items: any)=>{
if(item.id == items.id){
pickVal = true
}
})
}
usAry.push({
"id":item.id, //string //"95196156539179008",
"employeeName":item.employeeName, //string //"",
"isLeave":item.isLeave, //string //"0",
"open":item.open, //boolean //"false",
"icon":item.icon, //string //"",
"iconToBase64":item.iconToBase64, //string //"",
"wechat":item.wechat, //string //"",
"departmentid":item.departmentid, //number //102,
"departmentname":item.departmentname, //string //"",
"postid":item.postid, //number //798,
"postname":item.postname, //string //"",
"tema":item.tema, //number //0,
"temaname":item.temaname, //string //""
"ispick":pickVal, //boolean //
})
})
employees.value = usAry
})
}else{
getOrgAndPeople(313)
}
}
</script>
<template>
<el-dialog
v-model="pickorg_is_Show"
width="600px"
:title="dialogTitle"
append-to-body
draggable
:before-close="closeBox"
>
<el-row v-if="props.tabledata.types > 1" class="biankuang_all">
<el-col :span="12" class="col_body ">
<div class="input_box">
<el-input
v-model="searchKeywords"
:placeholder="keywordsTitle"
:prefix-icon="Search"
size="large"
class="inputDeep"
/>
</div>
<el-space :size="-2" :spacer="spacer" class="mianbaoxue">
<el-text class="allSearch" @click="getOrgList(313)">所有</el-text>
<el-text v-for="(it,ind) in orgBreadCrumbs" :key="ind" @click="getOrgList(parseInt(it.id))">{{ it.departmentName }}</el-text>
</el-space>
<ul class="select-box">
<li v-for="(item,index) in orgInfoList" :key="index" :class="{active: item.isActiveItem}">
<div class="orgboxdiv">
<el-tooltip
class="box-item"
effect="dark"
:content="item.name"
placement="left"
>
<el-text truncated @click="pickval(item)">
<img src="@/assets/image/icon_file.png">{{ item.name }}
</el-text>
</el-tooltip>
<i v-if="item.ischild&&props.tabledata.types!=3" @click="getOrgList(item.id)">下级</i>
</div>
</li>
</ul>
</el-col>
<el-col :span="12" class="col_body biankuang_left">
<div class="pick_head input_box">
<span>已选择{{ countPick }}</span>
<span class="emptyPick" @click="emptyPickList">清空</span>
</div>
<ul class="pick_select_box">
<li v-for="(item,index) in pickDataList" :key="index">
<el-tooltip
class="box-item"
effect="dark"
:content="item.name"
placement="right"
>
<el-text truncated>
<img src="@/assets/image/icon_file.png">{{ item.name }}
</el-text>
</el-tooltip>
<svg-icon icon-class="cc_k" class="right_5" @click="delPickData(item,index)" />
</li>
</ul>
</el-col>
</el-row>
<!--选择人员-->
<el-row v-if="props.tabledata.types < 2" class="biankuang_all">
<el-col :span="12" class="col_body ">
<div class="input_box">
<el-input
v-model="searchKeywords"
:placeholder="keywordsTitle"
:prefix-icon="Search"
size="large"
class="inputDeep"
@input="searchPeople"
/>
</div>
<el-space :size="-2" :spacer="spacer" class="mianbaoxue">
<el-text class="allSearch" @click="getOrgAndPeople(313)">所有</el-text>
<el-text v-for="(it,ind) in orgBreadCrumbs" :key="ind" @click="getOrgAndPeople(parseInt(it.id))">{{ it.departmentName }}</el-text>
</el-space>
<ul class="select-box">
<li v-for="(item,index) in childDepartments" :key="index" :class="{active: item.isActiveItem}">
<div class="orgboxdiv">
<el-tooltip
class="box-item"
effect="dark"
:content="item.departmentName"
placement="left"
>
<el-text truncated>
<img src="@/assets/image/icon_file.png">{{ item.departmentName }}
</el-text>
</el-tooltip>
<i @click="getOrgAndPeople(parseInt(item.id))">下级</i>
</div>
</li>
<li v-for="(item,index) in employees" :key="index" :class="{active: item.ispick}">
<div class="userboxdiv" @click="pickuserval(item)">
<svg-icon v-if="item.ispick" icon-class="select3" /><svg-icon v-else icon-class="select1" />
<img v-if="item.icon && item.icon != ''" :src="item.icon">
<img v-else-if="item.icon == '' && item.iconToBase64 && item.iconToBase64 != ''" :src="item.iconToBase64">
<img v-else src="@/assets/image/icon_people.png">
{{ item.employeeName }}
</div>
</li>
</ul>
</el-col>
<el-col :span="12" class="col_body biankuang_left">
<div class="pick_head input_box">
<span>已选择{{ countPick }}</span>
<span class="emptyPick" @click="emptyPickuserList">清空</span>
</div>
<ul class="pick_select_box">
<li v-for="(item,index) in pickDataList" :key="index">
<el-tooltip
class="box-item"
effect="dark"
:content="item.name"
placement="right"
>
<el-text truncated>
<img v-if="item.icon && item.icon != ''" :src="item.icon"><img v-else src="@/assets/image/icon_people.png">{{ item.name }}
</el-text>
</el-tooltip>
<svg-icon icon-class="cc_k" class="right_5" @click="delPickUserData(item,index)" />
</li>
</ul>
</el-col>
</el-row>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" :loading="addOrgUserLoading" @click="submitPickOrgOrUser" > </el-button>
<el-button @click="closeBox"> </el-button>
</div>
</template>
</el-dialog>
</template>
<style lang='scss' scoped>
.biankuang_all{
border: 1px solid rgb(220, 223, 230);
}
.biankuang_left{
border-left: 1px solid rgb(220, 223, 230);
}
.col_body{
height: 502px;
padding:0 0px;
}
.input_box{
border-bottom: 1px solid rgb(220, 223, 230);
}
.inputDeep {
:deep(.el-input__wrapper) {
box-shadow: 0 0 0 0px var(--el-input-border-color, var(--el-border-color)) inset;
cursor: default;
.el-input__inner {
cursor: default !important;
}
}
}
.mianbaoxue{
width: 100%;
overflow-x: auto;
white-space:nowrap;
padding: 5px 5px;
cursor: pointer;
}
.select-box {
height: 430px;
overflow-y: auto;
border-top: 1px solid rgb(220, 223, 230);
li{
padding: 5px 0;
.userboxdiv{
padding: 0 5px;
cursor: pointer;
}
.orgboxdiv{
display: flex;
justify-content: space-between;
align-items: center;
}
i{
min-width: 60px;
padding-left: 24px;
padding-right: 10px;
font-style: normal;
font-size: 12px;
cursor: pointer;
background: url(@/assets/image/next_level.png) no-repeat 10px center;
border-left: 1px solid rgb(238, 238, 238);
}
img {
width: 14px;
vertical-align: middle;
margin-right: 5px;
margin-left: 5px;
}
.el-text{
cursor: pointer;
}
}
li.active{
color: #3195f8;
i{
background: url(@/assets/image/next_level_active.png) no-repeat 10px center;
}
.el-text{
color: #3195f8;
}
}
}
.pick_head{
width: 100%;
height: 41px;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 5px;
}
.pick_select_box{
height: 460px;
overflow-y: auto;
li{
display: flex;
justify-content: space-between;
align-items: center;
padding: 5px 0;
img {
width: 14px;
vertical-align: middle;
margin-right: 5px;
margin-left: 5px;
}
.right_5{
min-width: 20px;
margin-right: 5px;
cursor: pointer;
}
}
}
.emptyPick{
cursor: pointer;
}
</style>

256
src/views/matrix/orgoruser/pickuser.vue

@ -0,0 +1,256 @@
<!--
@ 作者: 秦东
@ 时间: 2023-07-07 09:12:32
@ 备注: 选择人员
-->
<script lang='ts' setup>
import { Search,ArrowRight } from '@element-plus/icons-vue' //
import { ElDivider } from 'element-plus'
/**
* 引入图片
*/
const spacer = h(ElDivider, { direction: 'vertical' })
const props = defineProps({
orgBoxShow:{
type:Boolean,
default:false
},
tabledata:{
type:Object,
default(){
return {}
}
},
orglist:{
type:Object,
default(){
return {}
}
},
orgtree:{
type:Object,
default(){
return {}
}
}
});
const emits = defineEmits(["update:orgBoxShow"]); //
const dialogTitle = ref<string>()
const addOrgUserLoading = ref(false);
const searchKeywords = ref<string>()
const keywordsTitle = ref<string>()
/**
* 弹窗显示控制
*/
const pickorg_is_Show = computed({
get: () => props.orgBoxShow,
set: (val) => {
emits("update:orgBoxShow", val);
},
});
/**
* 关闭弹窗
*/
function closeBox(){
// eslint-disable-next-line vue/no-mutating-props
props.tabledata.isedit = false;
// eslint-disable-next-line vue/no-mutating-props
props.tabledata.namelist=["秦东","马飞"]
emits("update:orgBoxShow", false);
}
/**
* 监听数据
*/
watch(() => props.orgBoxShow,() => {
if(props.orgBoxShow){
console.log("监听数据-----sd3------>",props.tabledata)
switch(props.tabledata.types){
case 2:
dialogTitle.value = "选择行政组织"
keywordsTitle.value = "请输入关键字"
break;
case 3:
dialogTitle.value = "选择分部"
keywordsTitle.value = "请输入关键字"
break;
default:
dialogTitle.value = "选择成员"
keywordsTitle.value = "请输入姓名或工号"
}
}
})
/**
* 提交数据
*/
function submitPickOrgOrUser(){}
</script>
<template>
<el-dialog
v-model="pickorg_is_Show"
width="600px"
:title="dialogTitle"
append-to-body
draggable
:before-close="closeBox"
>
<el-row class="biankuang_all">
<el-col :span="12" class="col_body ">
<div class="input_box">
<el-input
v-model="searchKeywords"
:placeholder="keywordsTitle"
:prefix-icon="Search"
size="large"
class="inputDeep"
/>
</div>
<el-space :size="-2" :spacer="spacer" class="mianbaoxue">
<el-text class="allSearch">所有</el-text>
<el-text>恒信高科</el-text>
</el-space>
<ul class="select-box">
<li class="active">
<div class="orgboxdiv">
<div>
<img src="@/assets/image/icon_file.png">恒信高科
</div>
<i>下级</i>
</div>
</li>
<li class="active ">
<div class="userboxdiv">
<svg-icon icon-class="select1" /><img src="@/assets/image/icon_people.png">秦东
</div>
</li>
<li class="active ">
<div class="userboxdiv">
<svg-icon icon-class="select3" /><img src="@/assets/image/icon_people.png">秦东
</div>
</li>
</ul>
</el-col>
<el-col :span="12" class="col_body biankuang_left">
<div class="pick_head input_box">
<span>已选择1</span>
<span>清空</span>
</div>
<ul class="pick_select_box">
<li>
<div>
<img src="@/assets/image/icon_people.png">秦东
</div>
<svg-icon icon-class="cc_k" class="right_5" />
</li>
</ul>
</el-col>
</el-row>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" :loading="addOrgUserLoading" @click="submitPickOrgOrUser" > </el-button>
<el-button @click="closeBox"> </el-button>
</div>
</template>
</el-dialog>
</template>
<style lang='scss' scoped>
.biankuang_all{
border: 1px solid rgb(220, 223, 230);
}
.biankuang_left{
border-left: 1px solid rgb(220, 223, 230);
}
.col_body{
height: 502px;
padding:0 0px;
}
.input_box{
border-bottom: 1px solid rgb(220, 223, 230);
}
.inputDeep {
:deep(.el-input__wrapper) {
box-shadow: 0 0 0 0px var(--el-input-border-color, var(--el-border-color)) inset;
cursor: default;
.el-input__inner {
cursor: default !important;
}
}
}
.mianbaoxue{
width: 100%;
overflow-x: auto;
white-space:nowrap;
padding: 5px 5px;
}
.select-box {
height: 430px;
overflow-y: auto;
border-top: 1px solid rgb(220, 223, 230);
li{
padding: 5px 0;
.userboxdiv{
padding: 0 5px;
cursor: pointer;
}
.orgboxdiv{
display: flex;
justify-content: space-between;
align-items: center;
}
i{
padding-left: 24px;
padding-right: 10px;
font-style: normal;
font-size: 12px;
cursor: pointer;
background: url(@/assets/image/next_level.png) no-repeat 10px center;
border-left: 1px solid rgb(238, 238, 238);
}
img {
width: 14px;
vertical-align: middle;
margin-right: 5px;
margin-left: 5px;
}
}
li.active{
color: #3195f8;
i{
background: url(@/assets/image/next_level_active.png) no-repeat 10px center;
}
}
}
.pick_head{
width: 100%;
height: 41px;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 5px;
}
.pick_select_box{
height: 460px;
overflow-y: auto;
li{
display: flex;
justify-content: space-between;
align-items: center;
padding: 5px 0;
img {
width: 14px;
vertical-align: middle;
margin-right: 5px;
margin-left: 5px;
}
.right_5{
margin-right: 5px;
cursor: pointer;
}
}
}
</style>

244
src/views/sysworkflow/codepage/index.vue

@ -4,10 +4,252 @@
@ 备注:
-->
<script lang='ts' setup>
import '@/assets/scss/element-var.scss'
import '@/assets/scss/index.scss'
import '@/assets/iconfont/iconfont.css'
import { useDesignFormStore } from '@/store/DesignForm/designForm'
import { useRoute, useRouter } from 'vue-router'
import {
json2string,
objToStringify,
string2json,
stringToObj
} from '@/utils/DesignForm/form'
import { getRequest } from '@/api/DesignForm'
import { afterResponse, beforeRequest, onChange } from '@/api/DesignForm/utils'
//
import DragControl from '@/components/DesignForm/dragControl.vue';
import HeadTools from '@/components/DesignForm/public/headTools.vue';
import FormDesign from '@/components/DesignForm/public/form/form.vue'
const store = useDesignFormStore()
const router = useRouter()
const route: any = useRoute().query || {}
const vueFileEl = ref()
const state = reactive({
formData: {
list: [],
form: {
size: 'default'
},
config: {},
},
editor: {},
loading: false,
formDataPreview: {},
previewVisible: false, //
designType: route.type, // search
formDict: {},
formOtherData: {
source: route.source || '',
formName: '未命名表单'
}
})
const drawer = reactive({
visible: false,
type: '',
title: '',
codeType: '',
direction: undefined, //rtl / ltr
callback: '',
content:{}
})
const headToolClick = (type: string) => {
switch (type) {
case 'del':
state.formData.list = []
store.setActiveKey('')
store.setControlAttr({})
break
case 'eye':
//
store.setActiveKey('')
store.setControlAttr({})
state.previewVisible = true
// eslint-disable-next-line no-case-declarations
let stringPreview = objToStringify(state.formData) //
// eslint-disable-next-line no-case-declarations
const formName = state.formData.form.name
// eslint-disable-next-line no-case-declarations
const reg = new RegExp(`get${formName}ControlByName`, 'g')
stringPreview = stringPreview.replace(
reg,
`getPreview${formName}ControlByName`
)
state.formDataPreview = stringToObj(stringPreview)
state.formDataPreview.form.name = `Preview${formName}` //
break
case 'json':
//
openAceEditDrawer({
direction: 'rtl',
content: state.formData,
title: '可编辑修改或将已生成的脚本粘贴进来'
})
break
case 'save':
saveData()
break
case 'vue':
vueFileEl.value.open(state.formData)
break
}
}
//
const saveData = () => {
// url
const { addUrl, editUrl, requestUrl } = state.formData.config
if (
!state.formOtherData.source &&
(!addUrl || !editUrl || !requestUrl) &&
state.designType !== 'search'
) {
ElMessage.error('请选择数据源或配置接口url地址,否则表单无法提交保存')
return
}
let params: any = {
data: objToStringify(state.formData),
source: state.formOtherData.source, //
name: state.formOtherData.formName, //
type: 1, // 1 2
dict: json2string(state.formDict)
}
let apiKey = 'designSave'
if (route.id) {
// id
Object.assign(params, { id: route.id })
apiKey = 'designEdit'
}
//
if (state.designType === 'search') {
params = {
data: objToStringify(state.formData),
dict: json2string(state.formDict),
id: route.id
}
}
state.loading = true
getRequest(apiKey, params)
.then((res: any) => {
ElMessage({
message: res.message || '保存成功!',
type: 'success'
})
//
const path = route.redirect || '/design/form/list'
const query: any = {}
if (route.redirect && route.redirect.indexOf('?') !== -1) {
// pathid=1{id:1}
const p = route.redirect.split('?')[1]
const pSplit = p.split('&')
pSplit.forEach((item: string) => {
const splitItem = item.split('=')
query[splitItem[0]] = splitItem[1]
})
}
router.push({ path: path, query: query })
state.loading = false
})
.catch((res: any) => {
ElMessage.error(res.message || '保存异常')
state.loading = false
})
// session
if (!route.id) {
//
window.sessionStorage.removeItem('formMenuList')
}
//
store.setActiveKey('')
store.setControlAttr({})
}
const openAceEditDrawer = (params: any) => {
const { type, direction, codeType, title, callback, content } = params
drawer.direction = direction // ltr/rtl
drawer.type = type // type
drawer.codeType = codeType || '' //
drawer.title = title ? `提示:${title}` : ''
drawer.visible = true
drawer.callback = callback
let editData =
codeType === 'json'
? json2string(content, true)
: objToStringify(content, true)
switch (type) {
case 'css':
editData = state.formData.config?.style || ''
break
case 'dict':
//
editData = json2string(state.formDict, true)
break
case 'beforeRequest':
case 'beforeSubmit':
case 'afterResponse':
case 'afterSubmit':
case 'change':
// eslint-disable-next-line no-case-declarations
const beforeData = state.formData.events || {}
if (beforeData[type]) {
editData = objToStringify(beforeData[type], true)
} else {
if (['afterResponse', 'afterSubmit'].includes(type)) {
editData = afterResponse
} else if (type === 'change') {
editData = onChange
} else {
editData = beforeRequest
}
}
break
// case 'afterResponse':
// case 'afterSubmit':
// const newData = state.formData.events || {}
// if (newData[type]) {
// editData = objToStringify(newData[type], true)
// } else {
// editData = afterResponse
// }
// break
case 'optionsParams':
if (!content) {
editData = beforeRequest
}
break
case 'optionsResult':
if (!content) {
editData = afterResponse
}
break
}
drawer.content = editData
}
</script>
<template>
<div>表单设计</div>
<div class="design-container">
<DragControl />
<div class="main-body">
<HeadTools @click="headToolClick" />
<div class="main-form" v-loading="state.loading">
<div class="empty-tips" v-if="state.formData.list.length === 0">
从左侧拖拽来添加字段
</div>
<FormDesign
:type="5"
:formData="state.formData"
:dict="state.formDict"
/>
</div>
</div>
</div>
</template>
<style lang='scss' scoped>

Loading…
Cancel
Save