소스 검색

组件新增,mock更多的控件配置数据

刘洋 1 년 전
부모
커밋
8955ee426d

+ 4 - 0
components.d.ts

@@ -11,11 +11,13 @@ declare module 'vue' {
     MyDialog: typeof import('./src/components/global/my-dialog/index.vue')['default']
     MyDialog: typeof import('./src/components/global/my-dialog/index.vue')['default']
     RouterLink: typeof import('vue-router')['RouterLink']
     RouterLink: typeof import('vue-router')['RouterLink']
     RouterView: typeof import('vue-router')['RouterView']
     RouterView: typeof import('vue-router')['RouterView']
+    SButtons: typeof import('./src/components/global/s-buttons/index.vue')['default']
     SearchForm: typeof import('./src/components/global/search-form/index.vue')['default']
     SearchForm: typeof import('./src/components/global/search-form/index.vue')['default']
     SearchFormItem: typeof import('./src/components/global/search-form/components/search-form-item.vue')['default']
     SearchFormItem: typeof import('./src/components/global/search-form/components/search-form-item.vue')['default']
     TAside: typeof import('tdesign-vue-next')['Aside']
     TAside: typeof import('tdesign-vue-next')['Aside']
     TButton: typeof import('tdesign-vue-next')['Button']
     TButton: typeof import('tdesign-vue-next')['Button']
     TCheckbox: typeof import('tdesign-vue-next')['Checkbox']
     TCheckbox: typeof import('tdesign-vue-next')['Checkbox']
+    TCheckboxGroup: typeof import('tdesign-vue-next')['CheckboxGroup']
     TCol: typeof import('tdesign-vue-next')['Col']
     TCol: typeof import('tdesign-vue-next')['Col']
     TConfigProvider: typeof import('tdesign-vue-next')['ConfigProvider']
     TConfigProvider: typeof import('tdesign-vue-next')['ConfigProvider']
     TContent: typeof import('tdesign-vue-next')['Content']
     TContent: typeof import('tdesign-vue-next')['Content']
@@ -36,6 +38,7 @@ declare module 'vue' {
     TMenuItem: typeof import('tdesign-vue-next')['MenuItem']
     TMenuItem: typeof import('tdesign-vue-next')['MenuItem']
     TOption: typeof import('tdesign-vue-next')['Option']
     TOption: typeof import('tdesign-vue-next')['Option']
     TPopconfirm: typeof import('tdesign-vue-next')['Popconfirm']
     TPopconfirm: typeof import('tdesign-vue-next')['Popconfirm']
+    TRadioGroup: typeof import('tdesign-vue-next')['RadioGroup']
     TRow: typeof import('tdesign-vue-next')['Row']
     TRow: typeof import('tdesign-vue-next')['Row']
     TSelect: typeof import('tdesign-vue-next')['Select']
     TSelect: typeof import('tdesign-vue-next')['Select']
     TSpace: typeof import('tdesign-vue-next')['Space']
     TSpace: typeof import('tdesign-vue-next')['Space']
@@ -43,6 +46,7 @@ declare module 'vue' {
     TTable: typeof import('tdesign-vue-next')['Table']
     TTable: typeof import('tdesign-vue-next')['Table']
     TTabPanel: typeof import('tdesign-vue-next')['TabPanel']
     TTabPanel: typeof import('tdesign-vue-next')['TabPanel']
     TTabs: typeof import('tdesign-vue-next')['Tabs']
     TTabs: typeof import('tdesign-vue-next')['Tabs']
+    TTextarea: typeof import('tdesign-vue-next')['Textarea']
     TTimePicker: typeof import('tdesign-vue-next')['TimePicker']
     TTimePicker: typeof import('tdesign-vue-next')['TimePicker']
     TTimeRangePicker: typeof import('tdesign-vue-next')['TimeRangePicker']
     TTimeRangePicker: typeof import('tdesign-vue-next')['TimeRangePicker']
     TTransfer: typeof import('tdesign-vue-next')['Transfer']
     TTransfer: typeof import('tdesign-vue-next')['Transfer']

+ 2 - 0
src/components/global/index.js

@@ -18,6 +18,7 @@ import {
 import Chart from './chart/index.vue';
 import Chart from './chart/index.vue';
 import SearchForm from './search-form/index.vue';
 import SearchForm from './search-form/index.vue';
 import MyDialog from './my-dialog/index.vue';
 import MyDialog from './my-dialog/index.vue';
+import SButton from './s-buttons/index.vue';
 
 
 use([
 use([
   CanvasRenderer,
   CanvasRenderer,
@@ -38,5 +39,6 @@ export default {
     Vue.component('MyChart', Chart);
     Vue.component('MyChart', Chart);
     Vue.component('SearchForm', SearchForm);
     Vue.component('SearchForm', SearchForm);
     Vue.component('MyDialog', MyDialog);
     Vue.component('MyDialog', MyDialog);
+    Vue.component('SButton', SButton);
   },
   },
 };
 };

+ 21 - 0
src/components/global/s-buttons/index.vue

@@ -0,0 +1,21 @@
+<template>
+  <div class="s-button text-center">
+    <t-button theme="primary" @click="submitHandle">{{ confirmText }}</t-button>
+    <t-button theme="default" class="m-l-20px" @click="cancel">{{
+      cancelText
+    }}</t-button>
+  </div>
+</template>
+
+<script setup name="SButton">
+const { confirmText, cancelText } = defineProps(['confirmText', 'cancelText']);
+const emit = defineEmits(['confirm', 'cancel']);
+const submitHandle = () => {
+  emit('confirm');
+};
+const cancel = () => {
+  emit('cancel');
+};
+</script>
+
+<style></style>

+ 15 - 0
src/hooks/useClearDialog.js

@@ -0,0 +1,15 @@
+import { ref, watch } from 'vue';
+import { cloneDeep } from 'lodash';
+
+export default function useClearDialog(data, props) {
+  let resultData = ref(cloneDeep(data));
+  watch(
+    () => props.visible,
+    (val) => {
+      if (!val) {
+        resultData.value = cloneDeep(data);
+      }
+    }
+  );
+  return { data: resultData };
+}

+ 2 - 2
src/main.js

@@ -6,7 +6,7 @@ import router from './router';
 import store from './store';
 import store from './store';
 import directives from './directives';
 import directives from './directives';
 import { capsule } from '@/utils/tool';
 import { capsule } from '@/utils/tool';
-
+import { Loading } from 'tdesign-vue-next';
 import 'tdesign-vue-next/es/style/index.css';
 import 'tdesign-vue-next/es/style/index.css';
 // import 'tdesign-vue-next/dist/reset.css';
 // import 'tdesign-vue-next/dist/reset.css';
 import './style/index.less';
 import './style/index.less';
@@ -20,7 +20,7 @@ setGlobalOptions({
 });
 });
 const app = createApp(App);
 const app = createApp(App);
 
 
-app.use(router).use(store).use(directives).use(globalComponents);
+app.use(router).use(store).use(directives).use(globalComponents).use(Loading);
 
 
 app.config.globalProperties.$title = import.meta.env.VITE_APP_TITLE;
 app.config.globalProperties.$title = import.meta.env.VITE_APP_TITLE;
 
 

+ 9 - 0
src/router/modules/sop.js

@@ -37,6 +37,15 @@ export default {
             bind: 'OfficeSop',
             bind: 'OfficeSop',
           },
           },
         },
         },
+        {
+          name: 'SopStep',
+          path: '/sop/sop-manage/sop-step',
+          component: () => import('@/views/sop/sop-manage/sop-step/index.vue'),
+          meta: {
+            title: '当前SOP流程',
+            bind: 'OfficeSop',
+          },
+        },
         {
         {
           name: 'StudentSop',
           name: 'StudentSop',
           path: '/sop/sop-manage/student-sop',
           path: '/sop/sop-manage/student-sop',

+ 1 - 2
src/views/service-unit-manage/dispatch/dispatch-manage/add-dispatch-dialog.vue

@@ -4,10 +4,9 @@
     @close="emit('update:visible', false)"
     @close="emit('update:visible', false)"
     :header="title"
     :header="title"
     :width="600"
     :width="600"
-    labelWidth="140px"
     :closeOnOverlayClick="false"
     :closeOnOverlayClick="false"
   >
   >
-    <t-form ref="formRef" :model="formData">
+    <t-form ref="formRef" :model="formData" labelWidth="120px">
       <t-form-item label="项目单号:">
       <t-form-item label="项目单号:">
         <t-input v-model="formData.a"></t-input>
         <t-input v-model="formData.a"></t-input>
       </t-form-item>
       </t-form-item>

+ 9 - 6
src/views/service-unit-manage/dispatch/dispatch-manage/delineation-dialog.vue

@@ -5,11 +5,10 @@
     @close="emit('update:visible', false)"
     @close="emit('update:visible', false)"
     header="划定"
     header="划定"
     :width="600"
     :width="600"
-    labelWidth="140px"
     :closeOnOverlayClick="false"
     :closeOnOverlayClick="false"
   >
   >
     <div class="form-title">派单信息</div>
     <div class="form-title">派单信息</div>
-    <t-form ref="formRef" :model="formData">
+    <t-form ref="formRef" :model="formData" labelWidth="120px">
       <t-form-item label="服务单元名称:">
       <t-form-item label="服务单元名称:">
         <t-select v-model="formData.a"></t-select>
         <t-select v-model="formData.a"></t-select>
       </t-form-item>
       </t-form-item>
@@ -23,7 +22,8 @@
   </my-dialog>
   </my-dialog>
 </template>
 </template>
 <script setup name="DelineationDialog">
 <script setup name="DelineationDialog">
-import { ref, reactive } from 'vue';
+import { ref } from 'vue';
+import useClearDialog from '@/hooks/useClearDialog';
 const emit = defineEmits(['update:visible', 'success']);
 const emit = defineEmits(['update:visible', 'success']);
 const formRef = ref(null);
 const formRef = ref(null);
 
 
@@ -31,9 +31,12 @@ const props = defineProps({
   visible: Boolean,
   visible: Boolean,
   title: String,
   title: String,
 });
 });
-const formData = reactive({
-  a: 1,
-});
+const { data: formData } = useClearDialog(
+  {
+    a: '',
+  },
+  props
+);
 const save = () => {
 const save = () => {
   //ajax...
   //ajax...
   emit('success');
   emit('success');

+ 1 - 2
src/views/service-unit-manage/dispatch/dispatch-manage/mult-delineation-dialog.vue

@@ -5,10 +5,9 @@
     @close="emit('update:visible', false)"
     @close="emit('update:visible', false)"
     header="批量划定"
     header="批量划定"
     :width="500"
     :width="500"
-    labelWidth="140px"
     :closeOnOverlayClick="false"
     :closeOnOverlayClick="false"
   >
   >
-    <t-form ref="formRef" :model="formData">
+    <t-form ref="formRef" :model="formData" labelWidth="120px">
       <t-form-item label="服务单元名称:">
       <t-form-item label="服务单元名称:">
         <t-select v-model="formData.a"></t-select>
         <t-select v-model="formData.a"></t-select>
       </t-form-item>
       </t-form-item>

+ 1 - 2
src/views/service-unit-manage/service-unit/regional-planning/add-region-dialog.vue

@@ -4,10 +4,9 @@
     @close="emit('update:visible', false)"
     @close="emit('update:visible', false)"
     :header="title"
     :header="title"
     :width="750"
     :width="750"
-    labelWidth="140px"
     :closeOnOverlayClick="false"
     :closeOnOverlayClick="false"
   >
   >
-    <t-form ref="formRef" :model="formData" layout="inline">
+    <t-form ref="formRef" :model="formData" layout="inline" labelWidth="120px">
       <t-form-item label="服务单元名称:">
       <t-form-item label="服务单元名称:">
         <t-select v-model="formData.a"> </t-select>
         <t-select v-model="formData.a"> </t-select>
       </t-form-item>
       </t-form-item>

+ 1 - 2
src/views/service-unit-manage/service-unit/unit-manage/add-unit-dialog.vue

@@ -4,10 +4,9 @@
     @close="emit('update:visible', false)"
     @close="emit('update:visible', false)"
     :header="title"
     :header="title"
     :width="600"
     :width="600"
-    labelWidth="140px"
     :closeOnOverlayClick="false"
     :closeOnOverlayClick="false"
   >
   >
-    <t-form ref="formRef" :model="formData">
+    <t-form ref="formRef" :model="formData" labelWidth="120px">
       <t-form-item label="服务单元名称:">
       <t-form-item label="服务单元名称:">
         <t-input v-model="formData.a"></t-input>
         <t-input v-model="formData.a"></t-input>
       </t-form-item>
       </t-form-item>

+ 17 - 0
src/views/sop/components/CHECKBOX.vue

@@ -0,0 +1,17 @@
+<template>
+  <t-checkbox-group
+    v-model="value"
+    :name="config.binding"
+    :options="config.options || []"
+    @change="change"
+  ></t-checkbox-group>
+</template>
+
+<script setup name="CHECKBOX">
+import { ref } from 'vue';
+const { config, onChange } = defineProps(['config', 'onChange']);
+const value = ref([]);
+const change = () => {};
+</script>
+
+<style></style>

+ 12 - 0
src/views/sop/components/DATE.vue

@@ -0,0 +1,12 @@
+<template>
+  <t-date-picker v-model="value" @change="change" style="width: 100%" />
+</template>
+<script setup name="DATE">
+import { ref } from 'vue';
+const { config, onChange } = defineProps(['config', 'onChange']);
+const value = ref('');
+const change = () => {
+  onChange({ prop: config.binding, value: value.value });
+};
+</script>
+<style></style>

+ 144 - 3
src/views/sop/components/POP_SELECT.vue

@@ -1,16 +1,157 @@
 <template>
 <template>
-  <div class="pop-select"></div>
+  <div class="pop-select" @click="openDialog"></div>
+  <my-dialog
+    :visible="visible"
+    header="成员列表"
+    :width="700"
+    :closeOnOverlayClick="false"
+    @close="visible = false"
+  >
+    <div class="result-box"></div>
+    <div class="list-box">
+      <t-tabs v-model="type" theme="normal">
+        <t-tab-panel
+          v-for="item in tabList"
+          :key="item.value"
+          :value="item.value"
+          :label="item.label"
+        >
+          <div class="tab-content">
+            <div class="left-tree" v-if="type == '1'">
+              <t-tree :data="treeData" expand-all hover expandOnClickNode>
+              </t-tree>
+            </div>
+            <div class="flat-list">
+              <t-radio-group
+                v-model="result"
+                allow-uncheck
+                name="person"
+                :options="personOptions"
+              ></t-radio-group>
+            </div>
+          </div>
+        </t-tab-panel>
+      </t-tabs>
+    </div>
+  </my-dialog>
 </template>
 </template>
 <script setup name="POPSELECT">
 <script setup name="POPSELECT">
-import { ref } from 'vue';
+import { ref, watch } from 'vue';
 const { config, onChange } = defineProps(['config', 'onChange']);
 const { config, onChange } = defineProps(['config', 'onChange']);
-const value = ref('');
 //   onChange({ prop: config.binding, value: value.value });
 //   onChange({ prop: config.binding, value: value.value });
+const type = ref('1');
+
+const visible = ref(false);
+const openDialog = () => {
+  visible.value = true;
+};
+const tabList = ref([
+  { value: '1', label: '组织架构' },
+  { value: '2', label: '成员' },
+  { value: '3', label: '当前用户' },
+]);
+const treeData = ref([
+  {
+    value: '1',
+    label: '全体成员',
+    children: [
+      {
+        value: '2',
+        label: '武汉启明泰和软件服务有限公司',
+        children: [
+          {
+            value: '3',
+            label: '销售部',
+            children: [
+              {
+                value: '5',
+                label: '直销一部',
+              },
+              {
+                value: '6',
+                label: '直销二部',
+              },
+            ],
+          },
+          {
+            value: '4',
+            label: '技术实施部',
+          },
+        ],
+      },
+    ],
+  },
+]);
+
+const personOptions = ref([
+  {
+    value: '1',
+    label: '刘洋',
+  },
+  {
+    value: '2',
+    label: '燕琴',
+  },
+  {
+    value: '3',
+    label: '罗识',
+  },
+]);
+const result = ref('');
+
+watch(visible, () => {
+  type.value = '1';
+});
 </script>
 </script>
 <style lang="less" scoped>
 <style lang="less" scoped>
+.list-box {
+  margin-top: 10px;
+  border: 1px solid #ddd;
+  .tab-content {
+    height: 350px;
+    display: flex;
+    .left-tree {
+      width: 50%;
+      height: 100%;
+      padding: 10px 10px 5px;
+    }
+    .flat-list {
+      flex: 1;
+    }
+    .flat-list {
+      height: 100%;
+      padding: 10px 10px 5px;
+      :deep(.t-radio-group) {
+        width: 100%;
+        .t-radio {
+          margin-right: 0;
+          display: block;
+          width: 100%;
+          margin-bottom: 4px;
+          .t-radio__input {
+            float: right;
+            position: relative;
+            top: 3px;
+          }
+          .t-radio__label {
+            float: left;
+          }
+        }
+      }
+    }
+    .left-tree {
+      border-right: 1px solid #ddd;
+    }
+  }
+}
 .pop-select {
 .pop-select {
   width: 100%;
   width: 100%;
   height: 32px;
   height: 32px;
   border: 1px dashed #ddd;
   border: 1px dashed #ddd;
+  cursor: pointer;
+}
+.result-box {
+  height: 40px;
+  border: 1px dashed #ddd;
 }
 }
 </style>
 </style>

+ 16 - 0
src/views/sop/components/PROJECT_HEADER.vue

@@ -0,0 +1,16 @@
+<template>
+  <div class="project-header"></div>
+</template>
+
+<script setup name="PROJECTHEADER">
+const { config } = defineProps(['config']);
+</script>
+
+<style lang="less" scoped>
+.project-header {
+  width: 100%;
+  color: var(--td-text-color-primary);
+  padding-bottom: 3px;
+  border-bottom: 1px dashed #ddd;
+}
+</style>

+ 19 - 0
src/views/sop/components/RADIO.vue

@@ -0,0 +1,19 @@
+<template>
+  <t-radio-group
+    v-model="value"
+    allow-uncheck
+    :name="config.binding"
+    :options="config.options || []"
+    @change="change"
+    style="width: 100%"
+  ></t-radio-group>
+</template>
+
+<script setup name="RADIO">
+import { ref } from 'vue';
+const { config, onChange } = defineProps(['config', 'onChange']);
+const value = ref('');
+const change = () => {};
+</script>
+
+<style></style>

+ 136 - 0
src/views/sop/components/TABLE.vue

@@ -0,0 +1,136 @@
+<template>
+  <div class="flow-table">
+    <!-- 当前示例包含:输入框、单选、多选、日期 等场景 -->
+    <t-table
+      ref="tableRef"
+      row-key="key"
+      :columns="columns"
+      :data="tableData"
+      :editable-row-keys="editableRowKeys"
+      table-layout="auto"
+      bordered
+      @row-edit="onRowEdit"
+      @row-validate="onRowValidate"
+      @validate="onValidate"
+      size="small"
+    >
+      <template #key="{ row }">
+        <div class="flex items-center key-cell">
+          <Icon
+            name="delete"
+            class="delete-icon"
+            @click="deleteRow(row)"
+          ></Icon>
+          <span class="key-index">{{ row.key }}</span>
+        </div>
+      </template>
+    </t-table>
+    <t-button theme="primary" class="m-t-15px" @click="createOneRow">
+      <template #icon><Icon name="add"></Icon></template>
+      添加
+    </t-button>
+  </div>
+</template>
+
+<script setup name="TABLE">
+import { computed, ref, watch } from 'vue';
+import { Input, DatePicker } from 'tdesign-vue-next';
+import { Icon } from 'tdesign-icons-vue-next';
+const { config, onChange } = defineProps(['config', 'onChange']);
+let tablePropList = config.tablePropList || [];
+const createEditOption = (code) => {
+  let obj = {};
+  if (code === 'TEXT') {
+    obj = {
+      component: Input,
+      props: {
+        clearable: true,
+        autoFocus: true,
+        autoWidth: true,
+        style: { width: '100%' },
+      },
+      rules: [{ required: true, message: '不能为空' }],
+      showEditIcon: false,
+    };
+  } else if (code === 'DATE') {
+    obj = {
+      component: DatePicker,
+      rules: [{ required: true, message: '不能为空' }],
+      showEditIcon: false,
+      props: {
+        style: { width: '100%' },
+      },
+    };
+  }
+  return obj;
+};
+
+const columns = computed(() => {
+  let arr = tablePropList.map((item) => {
+    return {
+      title: item.title,
+      colKey: item.tdName,
+      minWidth: 160,
+      edit: createEditOption(item.tdFormWidget.code),
+    };
+  });
+  let firstColumn = {
+    title: '',
+    coleKey: 'key',
+    cell: 'key',
+    align: 'left',
+    width: 80,
+  };
+  return [firstColumn, ...arr];
+});
+const tableData = ref([]);
+const resetKeys = () => {
+  tableData.value.forEach((item, index) => {
+    item.key = index + 1 + '';
+  });
+};
+
+const createOneRow = () => {
+  let rowData = config.tablePropList.reduce((row, item) => {
+    row[item.tdName] = '';
+    return row;
+  }, {});
+  tableData.value.push({ ...rowData });
+  resetKeys();
+};
+
+createOneRow();
+
+const onRowEdit = () => {};
+const onRowValidate = () => {};
+const onValidate = () => {};
+
+const editableRowKeys = computed(() => {
+  return tableData.value.map((item) => item.key);
+});
+const deleteRow = (row) => {
+  let index = tableData.value.findIndex((item) => item.key == row.key);
+  tableData.value.splice(index, 1);
+  resetKeys();
+};
+</script>
+
+<style lang="less" name="TABLE">
+.flow-table {
+  width: 100%;
+  .key-cell {
+    .key-index {
+      font-size: 14px;
+    }
+    .delete-icon {
+      font-size: 18px;
+      color: #777;
+      margin-right: 10px;
+      cursor: pointer;
+      &:hover {
+        color: var(--td-brand-color);
+      }
+    }
+  }
+}
+</style>

+ 10 - 0
src/views/sop/components/TEXTAREA.vue

@@ -0,0 +1,10 @@
+<template>
+  <t-textarea v-model="value" @change="change"></t-textarea>
+</template>
+<script setup name="TEXTAREA">
+import { ref } from 'vue';
+const { config, onChange } = defineProps(['config', 'onChange']);
+const value = ref('');
+const change = () => {};
+</script>
+<style></style>

+ 23 - 0
src/views/sop/components/UPLOAD.vue

@@ -0,0 +1,23 @@
+<template>
+  <t-upload
+    style="width: 100%"
+    v-model="files"
+    :abridge-name="[8, 6]"
+    theme="file-input"
+    placeholder="请选择文件,20MB以内"
+    :request-method="requestMethod"
+    :size-limit="{ size: 20, unit: 'MB' }"
+  ></t-upload>
+</template>
+
+<script setup name="UPLOAD">
+import { ref } from 'vue';
+const files = ref([]);
+const requestMethod = (file) => {
+  return new Promise((rs) => {
+    rs({ status: 'success' });
+  });
+};
+</script>
+
+<style></style>

+ 65 - 3
src/views/sop/components/my-form-item.vue

@@ -1,5 +1,18 @@
 <template>
 <template>
-  <t-form-item :label="config.title" :name="config.binding">
+  <t-form-item :label="''" :name="config.binding" class="my-form-item">
+    <div class="top-label flex items-center">
+      <span class="require-icon" :class="{ hide: !config.required }">*</span>
+      <p>{{ config.title }}</p>
+    </div>
+    <div class="sub-title" v-if="config.subTitle">
+      <p
+        v-for="(item, index) in config.subTitle"
+        :key="index"
+        :style="{ color: item.color, fontSize: '13px', lineHeight: 1.4 }"
+      >
+        {{ item.content }}
+      </p>
+    </div>
     <RenderTest></RenderTest>
     <RenderTest></RenderTest>
   </t-form-item>
   </t-form-item>
 </template>
 </template>
@@ -7,8 +20,16 @@
 import { defineComponent } from 'vue';
 import { defineComponent } from 'vue';
 import TEXT from './TEXT.vue';
 import TEXT from './TEXT.vue';
 import SELECT from './SELECT.vue';
 import SELECT from './SELECT.vue';
+import POPSELECT from './POP_SELECT.vue';
 import LABELS from './LABELS';
 import LABELS from './LABELS';
 import LABEL from './LABEL';
 import LABEL from './LABEL';
+import DATE from './DATE';
+import UPLOAD from './UPLOAD';
+import TABLE from './TABLE';
+import PROJECTHEADER from './PROJECT_HEADER.vue';
+import RADIO from './RADIO.vue';
+import CHECKBOX from './CHECKBOX.vue';
+import TEXTAREA from './TEXTAREA.vue';
 const { config } = defineProps(['config']);
 const { config } = defineProps(['config']);
 const onChange = (obj) => {
 const onChange = (obj) => {
   console.log('obj', obj);
   console.log('obj', obj);
@@ -23,10 +44,28 @@ const RenderTest = defineComponent({
         return <TEXT config={config} onChange={onChange}></TEXT>;
         return <TEXT config={config} onChange={onChange}></TEXT>;
       case 'SELECT':
       case 'SELECT':
         return <SELECT config={config} onChange={onChange}></SELECT>;
         return <SELECT config={config} onChange={onChange}></SELECT>;
+      case 'POP_SELECT':
+        return <POPSELECT config={config} onChange={onChange}></POPSELECT>;
       case 'LABELS':
       case 'LABELS':
         return <LABELS config={config}></LABELS>;
         return <LABELS config={config}></LABELS>;
       case 'LABEL':
       case 'LABEL':
         return <LABEL config={config}></LABEL>;
         return <LABEL config={config}></LABEL>;
+      case 'DATE':
+        return <DATE config={config} onChange={onChange}></DATE>;
+      case 'FILE':
+        return <UPLOAD config={config} onChange={onChange}></UPLOAD>;
+      case 'TABLE':
+        return <TABLE config={config} onChange={onChange}></TABLE>;
+      case 'PROJECT_HEADER':
+        return <PROJECTHEADER config={config}></PROJECTHEADER>;
+      case 'RADIO':
+        return <RADIO config={config} onChange={onChange}></RADIO>;
+      case 'CHECKBOX':
+        return <CHECKBOX config={config} onChange={onChange}></CHECKBOX>;
+      case 'TEXTAREA':
+        return <TEXTAREA config={config} onChange={onChange}></TEXTAREA>;
+      case '':
+        return <div></div>;
       default:
       default:
         return <div>你传的code是什么破玩意</div>;
         return <div>你传的code是什么破玩意</div>;
     }
     }
@@ -35,7 +74,30 @@ const RenderTest = defineComponent({
 </script>
 </script>
 <style scoped lang="less">
 <style scoped lang="less">
 .my-form-item {
 .my-form-item {
-  width: 50%;
-  padding: 10px;
+  :deep(.t-form__controls-content) {
+    flex-direction: column;
+    align-items: flex-start;
+    .sub-title {
+      margin-bottom: 10px;
+    }
+    .top-label {
+      font-size: 14px;
+      margin-bottom: 5px;
+      margin-left: -8px;
+      span {
+        color: red;
+      }
+      p {
+        font-weight: bold;
+        flex: 1;
+      }
+      .require-icon {
+        margin-right: 3px;
+        &.hide {
+          opacity: 0;
+        }
+      }
+    }
+  }
 }
 }
 </style>
 </style>

+ 6 - 2
src/views/sop/sop-manage/office-sop/index.vue

@@ -60,7 +60,7 @@ const columns = [
             hover="color"
             hover="color"
             onClick={(e) => {
             onClick={(e) => {
               e.stopPropagation();
               e.stopPropagation();
-              enterSopFlow(row);
+              toCurSopFlow(row);
             }}
             }}
           >
           >
             填报
             填报
@@ -70,6 +70,7 @@ const columns = [
             hover="color"
             hover="color"
             onClick={(e) => {
             onClick={(e) => {
               e.stopPropagation();
               e.stopPropagation();
+              createSopFlow(row);
             }}
             }}
           >
           >
             新增SOP
             新增SOP
@@ -118,9 +119,12 @@ const {
   onChange,
   onChange,
 } = useFetchTable(getTableData);
 } = useFetchTable(getTableData);
 
 
-const enterSopFlow = (row) => {
+const createSopFlow = (row) => {
   router.push({ name: 'SopFlow' });
   router.push({ name: 'SopFlow' });
 };
 };
+const toCurSopFlow = (row) => {
+  router.push({ name: 'SopStep' });
+};
 </script>
 </script>
 
 
 <style></style>
 <style></style>

+ 13 - 6
src/views/sop/sop-manage/sop-flow/index.vue

@@ -1,19 +1,26 @@
 <template>
 <template>
   <div class="sop-flow">
   <div class="sop-flow">
     <div class="page-wrap">
     <div class="page-wrap">
-      <t-form ref="form" :labelWidth="130">
+      <t-form colon :label-width="0" class="p-l-20px p-r-20px">
         <t-row
         <t-row
           :gutter="[{ xs: 8, sm: 16, md: 24, lg: 32, xl: 32, xxl: 40 }, 24]"
           :gutter="[{ xs: 8, sm: 16, md: 24, lg: 32, xl: 32, xxl: 40 }, 24]"
         >
         >
-          <t-col :span="6" v-for="config in formConfig" :key="config.id">
+          <t-col
+            :span="config.span || 6"
+            v-for="config in formConfig"
+            :key="config.id"
+          >
             <MyFormItem :config="config"></MyFormItem>
             <MyFormItem :config="config"></MyFormItem>
           </t-col>
           </t-col>
         </t-row>
         </t-row>
       </t-form>
       </t-form>
-      <div class="m-t-30px m-b-30px text-center">
-        <t-button theme="primary" @click="submitHandle">提交</t-button>
-        <t-button theme="default" class="m-l-20px" @click="back">返回</t-button>
-      </div>
+      <s-button
+        confirm-text="提交"
+        cancel-text="返回"
+        @confirm="submitHandle"
+        @cancel="back"
+        class="m-t-30px m-b-30px"
+      ></s-button>
     </div>
     </div>
   </div>
   </div>
 </template>
 </template>

+ 93 - 0
src/views/sop/sop-manage/sop-step/index.vue

@@ -0,0 +1,93 @@
+<template>
+  <div class="sop-flow">
+    <div class="page-wrap">
+      <t-form colon :label-width="0" class="p-l-20px p-r-20px">
+        <t-row
+          :gutter="[{ xs: 8, sm: 16, md: 24, lg: 32, xl: 32, xxl: 40 }, 24]"
+        >
+          <t-col :span="6" v-for="config in baseConfig" :key="config.id">
+            <MyFormItem :config="config"></MyFormItem>
+          </t-col>
+        </t-row>
+      </t-form>
+      <p class="split-line"></p>
+      <t-tabs v-model="curStep" theme="normal" class="m-t-20px">
+        <t-tab-panel
+          v-for="item in tabs"
+          :key="item.taskKey"
+          :value="item.value"
+          :label="item.label"
+        >
+          <t-form ref="form" colon :label-width="0" class="cur-step-view">
+            <t-row
+              :gutter="[{ xs: 8, sm: 16, md: 24, lg: 32, xl: 32, xxl: 40 }, 24]"
+            >
+              <t-col
+                :span="
+                  fullWidthCodes.includes(config.code) ? 12 : config.span || 6
+                "
+                v-for="config in curFormConfig"
+                :key="config.id"
+              >
+                <MyFormItem :config="config"></MyFormItem>
+              </t-col>
+            </t-row>
+          </t-form>
+        </t-tab-panel>
+      </t-tabs>
+    </div>
+  </div>
+</template>
+
+<script setup name="SopStep">
+import { ref, computed } from 'vue';
+import MyFormItem from '../../components/my-form-item.vue';
+import testData from '../test';
+
+const fullWidthCodes = ref(['TABLE', 'PROJECT_HEADER']);
+const form = ref();
+const allConfigMap = ref(testData.setupMap);
+let baseConfig = ref(testData.setupMap.f_usertask_jwc_start.formProperty);
+
+// const curStep = ref('f_usertask_jwc_project');
+const curStep = ref('扫描仪出库登记');
+const curFormConfig = computed(() => {
+  return allConfigMap.value[curStep.value].formProperty;
+});
+let tabs = ref(
+  Object.values(testData.setupMap)
+    .slice(1)
+    .map((item) => {
+      return {
+        value: item.taskKey,
+        label: item.taskName,
+      };
+    })
+);
+
+const submitHandle = () => {
+  form.value.validate().then(async (result) => {
+    alert(result);
+    if (result === true) {
+    }
+  });
+};
+const back = () => {
+  history.back();
+};
+</script>
+
+<style lang="less" scoped>
+.sop-flow {
+  .page-wrap {
+    padding-right: 20%;
+    .split-line {
+      border-bottom: 1px dashed #ddd;
+      margin: 30px 0 10px;
+    }
+    .cur-step-view {
+      padding: 20px 0;
+    }
+  }
+}
+</style>

+ 772 - 0
src/views/sop/sop-manage/test.js

@@ -0,0 +1,772 @@
+export default {
+  id: '414471842594553856', //主键
+  flowDeploymentId: '414471841768275968', //流程部署id,后台用
+  flowName: 'testform1.bpmn', //流程名称
+  setupMap: {
+    f_usertask_jwc_start: {
+      //流程节点key
+      taskName: '新增sop', //流程节点名称
+      taskKey: 'f_usertask_jwc_start', //流程节点key
+      setup: 1, //流程步骤,1为初始,0为结束,-1为终止
+      formKey: 'start_1.form', //表单名称
+      formProperty: [
+        //表单数据,参考测试sop动态表单
+        {
+          id: '1',
+          code: 'TEXT',
+          type: 'FORM',
+          formId: 'f_usertask_jwc_start|crm_child_no',
+          formName: 'f_usertask_jwc_start|crm_child_no',
+          title: '项目子单编号',
+          inputType: 'STRING',
+          required: false,
+          readable: true,
+          writable: false,
+          visable: true,
+          binding: 'crm_child_no',
+          name: '文本',
+        },
+        {
+          id: '2',
+          code: 'SELECT',
+          type: 'FORM',
+          formId: 'f_usertask_jwc_start|custom_type',
+          formName: 'f_usertask_jwc_start|custom_type',
+          title: '客户类型',
+          required: true,
+          readable: false,
+          writable: true,
+          visable: true,
+          binding: 'custom_type',
+          dataGrid: '/api/admin/widget/custom/list',
+          name: '下拉框',
+        },
+        {
+          id: '3',
+          code: 'POP_SELECT',
+          type: 'FORM',
+          formId: 'f_usertask_jwc_start|crm_manager',
+          formName: 'f_usertask_jwc_start|crm_manager',
+          title: '派单客户经理',
+          required: true,
+          readable: false,
+          writable: true,
+          visable: true,
+          binding: 'crm_manager',
+          dataGrid: '/api/admin/widget/crm/manager',
+          name: '弹出选择框',
+        },
+        {
+          id: '4',
+          code: 'SELECT',
+          type: 'FORM',
+          formId: 'f_usertask_jwc_start|custom_name',
+          formName: 'f_usertask_jwc_start|custom_name',
+          title: '客户名称',
+          required: true,
+          readable: false,
+          writable: true,
+          visable: true,
+          binding: 'custom_name',
+          dataGrid: '/api/admin/widget/school/list',
+          name: '下拉框',
+        },
+        {
+          id: '5',
+          code: 'SELECT',
+          type: 'FORM',
+          formId: 'f_usertask_jwc_start|crm_parent_no',
+          formName: 'f_usertask_jwc_start|crm_parent_no',
+          title: '项目母单编号',
+          required: false,
+          readable: false,
+          writable: true,
+          visable: true,
+          binding: 'crm_parent_no',
+          dataGrid: '/api/admin/widget/crm/parent_no/list',
+          name: '下拉框',
+        },
+        {
+          id: '6',
+          code: 'TEXT',
+          type: 'FORM',
+          formId: 'f_usertask_jwc_start|crm_name',
+          formName: 'f_usertask_jwc_start|crm_name',
+          title: '项目名称',
+          inputType: 'STRING',
+          required: true,
+          readable: false,
+          writable: true,
+          visable: true,
+          name: '文本',
+        },
+        {
+          id: '7',
+          code: 'TEXT',
+          type: 'FORM',
+          formId: 'f_usertask_jwc_start|org_name',
+          formName: 'f_usertask_jwc_start|org_name',
+          title: '学院分(子)机构',
+          inputType: 'STRING',
+          required: true,
+          readable: false,
+          writable: true,
+          visable: true,
+          name: '文本',
+        },
+        {
+          id: '8',
+          code: 'SELECT',
+          type: 'FORM',
+          formId: 'f_usertask_jwc_start|product',
+          formName: 'f_usertask_jwc_start|product',
+          title: '实施产品',
+          required: true,
+          readable: false,
+          writable: true,
+          visable: true,
+          binding: 'product',
+          dataGrid: '/api/admin/widget/product/list',
+          name: '下拉框',
+        },
+        {
+          id: '9',
+          code: 'POP_SELECT',
+          type: 'FORM',
+          formId: 'f_usertask_jwc_start|child_manager',
+          formName: 'f_usertask_jwc_start|child_manager',
+          title: '子项目经理',
+          required: true,
+          readable: false,
+          writable: true,
+          visable: true,
+          binding: 'child_manager',
+          dataGrid: '/api/admin/widget/crm/manager',
+          name: '弹出选择框',
+        },
+        {
+          id: '10',
+          code: 'LABEL',
+          type: 'FORM',
+          formId: 'f_usertask_jwc_start|crm_info',
+          formName: 'f_usertask_jwc_start|crm_info',
+          title: '派单信息',
+          inputType: 'STRING',
+          required: false,
+          readable: true,
+          writable: false,
+          visable: true,
+          name: '标签',
+        },
+        {
+          id: '11',
+          code: 'TEXT',
+          type: 'FORM',
+          formId: 'f_usertask_jwc_start|exam_start_time',
+          formName: 'f_usertask_jwc_start|exam_start_time',
+          title: '考试开始时间',
+          inputType: 'STRING',
+          required: false,
+          readable: true,
+          writable: false,
+          visable: true,
+          binding: 'exam_start_time',
+          name: '文本',
+        },
+        {
+          id: '12',
+          code: 'TEXT',
+          type: 'FORM',
+          formId: 'f_usertask_jwc_start|exam_end_time',
+          formName: 'f_usertask_jwc_start|exam_end_time',
+          title: '考试结束时间',
+          inputType: 'STRING',
+          required: false,
+          readable: true,
+          writable: false,
+          visable: true,
+          binding: 'exam_end_time',
+          name: '文本',
+        },
+        {
+          id: '13',
+          code: 'TEXT',
+          type: 'FORM',
+          formId: 'f_usertask_jwc_start|remark',
+          formName: 'f_usertask_jwc_start|remark',
+          title: '特殊要求及备注',
+          inputType: 'STRING',
+          required: false,
+          readable: true,
+          writable: false,
+          visable: true,
+          binding: 'remark',
+          name: '文本',
+        },
+        {
+          id: '14',
+          code: 'TEXT',
+          type: 'FORM',
+          formId: 'f_usertask_jwc_start|project_type',
+          formName: 'f_usertask_jwc_start|project_type',
+          title: '项目类型',
+          inputType: 'STRING',
+          required: false,
+          readable: true,
+          writable: false,
+          visable: true,
+          binding: 'project_type',
+          name: '文本',
+        },
+      ],
+    },
+    f_usertask_jwc_project: {
+      taskName: '教务处sop_项目关键信息',
+      taskKey: 'f_usertask_jwc_project',
+      setup: 2,
+      formKey: 'project_2.form',
+      formProperty: [
+        {
+          id: '15',
+          code: 'FILE',
+          type: 'FORM',
+          formId: 'f_usertask_jwc_project|screen',
+          formName: 'f_usertask_jwc_project|screen',
+          title: '客户沟通或邮件截图',
+          inputType: 'STRING',
+          required: false,
+          readable: true,
+          writable: false,
+          visable: true,
+          name: '标签',
+          subTitle: [
+            {
+              content:
+                '提示:考虑到存在因客户原因信息收集不全,或客户无法确认的情况,因此客户确认截图不强制要求上传。但为了发生质量问题后,公司内部准确定责,保护项目经理的合理权益,请项目经理尽可能上传。',
+              color: 'green',
+            },
+          ],
+        },
+        {
+          id: '18',
+          code: 'TABLE',
+          type: 'FORM',
+          formId: 'f_usertask_jwc_project|exam_time_table',
+          formName: 'f_usertask_jwc_project|exam_time_table',
+          title: '考试时间安排表格',
+          required: true,
+          readable: false,
+          writable: true,
+          visable: true,
+          name: '表格',
+          tablePropList: [
+            {
+              id: '1',
+              widgetId: '18',
+              tdIndex: 1,
+              tdId: 'f_usertask_jwc_project|18|course_count',
+              tdName: 'f_usertask_jwc_project|18|course_count',
+              title: '科目数量',
+              tdOrder: true,
+              tdSearch: true,
+              editWidgetId: '19',
+              tdFormWidget: {
+                code: 'TEXT',
+                name: '文本',
+              },
+            },
+            {
+              id: '2',
+              widgetId: '18',
+              tdIndex: 2,
+              tdId: 'f_usertask_jwc_project|18|course_num',
+              tdName: 'f_usertask_jwc_project|18|course_num',
+              title: '科次',
+              tdOrder: true,
+              tdSearch: true,
+              editWidgetId: '19',
+              tdFormWidget: {
+                code: 'TEXT',
+                name: '文本',
+              },
+            },
+            {
+              id: '3',
+              widgetId: '18',
+              tdIndex: 3,
+              tdId: 'f_usertask_jwc_project|18|exam_start_time',
+              tdName: 'f_usertask_jwc_project|18|exam_start_time',
+              title: '考试开始时间',
+              tdOrder: true,
+              tdSearch: true,
+              editWidgetId: '20',
+              tdFormWidget: {
+                code: 'DATE',
+                name: '日期',
+                format: 'yyyy-MM-dd HH:mm:ss',
+              },
+            },
+            {
+              id: '4',
+              widgetId: '18',
+              tdIndex: 4,
+              tdId: 'f_usertask_jwc_project|18|exam_end_time',
+              tdName: 'f_usertask_jwc_project|18|exam_end_time',
+              title: '考试结束时间',
+              tdOrder: true,
+              tdSearch: true,
+              editWidgetId: '20',
+              tdFormWidget: {
+                code: 'DATE',
+                name: '日期',
+                format: 'yyyy-MM-dd HH:mm:ss',
+              },
+            },
+          ],
+        },
+        {
+          id: 'XXX',
+          code: 'PROJECT_HEADER',
+          title: '云阅卷',
+        },
+        {
+          id: 'XXX',
+          binding: 'XXX',
+          code: 'TEXT',
+          span: 12,
+          title: '扫描仪数量',
+          required: true,
+        },
+        {
+          id: 'XXX',
+          binding: 'XXX',
+          code: 'DATE',
+          title: '扫描开始时间',
+          required: true,
+        },
+        {
+          id: 'XXX',
+          binding: 'XXX',
+          code: 'DATE',
+          title: '扫描结束时间',
+          required: true,
+        },
+        {
+          id: 'XXX',
+          binding: 'XXX',
+          code: 'TEXT',
+          title: '扫描地址',
+          required: true,
+        },
+        {
+          id: 'XXX',
+          binding: 'XXX',
+          code: 'DATE',
+          title: '阅卷开始时间',
+          required: true,
+        },
+        {
+          id: 'XXX',
+          binding: 'XXX',
+          code: 'DATE',
+          title: '阅卷结束时间',
+          required: true,
+        },
+        {
+          id: 'XXX',
+          binding: 'XXX',
+          code: 'RADIO',
+          title: '阅卷方式',
+          required: true,
+          subTitle: [{ content: '提示:一般教务处分题阅', color: 'gray' }],
+          options: [
+            { value: '1', label: '整卷阅' },
+            { value: '2', label: '分题阅' },
+          ],
+        },
+        {
+          id: 'XXX',
+          binding: 'XXX',
+          code: 'RADIO',
+          title: '是否启用轨迹阅卷',
+          required: true,
+          subTitle: [
+            { content: '提示:一般教务处需要启用该项', color: 'gray' },
+          ],
+          options: [
+            { value: '1', label: '启用' },
+            { value: '2', label: '不器用' },
+          ],
+        },
+        {
+          id: 'XXX',
+          binding: 'XXX',
+          code: 'RADIO',
+          title: '评卷组织形式',
+          required: true,
+          subTitle: [
+            { content: '提示:评卷组织形式根据学校要求选择', color: 'gray' },
+            {
+              content:
+                '1.集中阅:老师集中在既定地点评阅,对现场网络环境的稳定性、外接带宽多少有依赖性,需要提前确认网络情况(详见“网络情况调研”)',
+              color: 'red',
+            },
+            {
+              content: '2.分散阅:老师可分散评阅,只要可上外网即可',
+              color: 'gray',
+            },
+          ],
+          options: [
+            { value: '1', label: '集中阅' },
+            { value: '2', label: '分散阅' },
+          ],
+        },
+        {
+          id: 'XXX',
+          binding: 'XXX',
+          code: 'CHECKBOX',
+          title: '集中阅-网络情况调研',
+          subTitle: [
+            {
+              content:
+                '提示:请根据检查项要求与客户进行核对确认后如实填写,检查项符合则勾选,不符合则不勾选,如果网络情况不满足集中阅的形式,则可参考如下建议:',
+              color: 'gray',
+            },
+            {
+              content: '1.与学校沟通,协助整改网络状况;',
+              color: 'gray',
+            },
+            {
+              content: '2.更换评卷组织形式。',
+              color: 'gray',
+            },
+            {
+              content:
+                '注意:若需要整改网络,整改情况无法立即落实,则检查项确认情况先如实填写,待整改完毕后,可对该信息进行变更操作。',
+              color: 'red',
+            },
+          ],
+          options: [
+            { value: '1', label: '能连接外网' },
+            { value: '2', label: '符合标准运行环境' },
+            { value: '3', label: '局域网络稳定' },
+          ],
+        },
+        {
+          id: 'XXX',
+          binding: 'XXX',
+          code: 'DATE',
+          title: '合分时间',
+          required: true,
+        },
+        {
+          id: 'XXX',
+          binding: 'XXX',
+          code: 'RADIO',
+          title: '是否需要教研分析',
+          required: true,
+          options: [
+            { value: '1', label: '是' },
+            { value: '2', label: '否' },
+          ],
+        },
+        {
+          id: 'XXX',
+          binding: 'XXX',
+          code: 'TEXTAREA',
+          title: '阅卷特殊需求备注',
+          required: true,
+          subTitle: [
+            { content: '提示:若没有特殊需求,则填写"无"', color: 'gray' },
+          ],
+        },
+      ],
+    },
+    f_usertask_jwc_inside_approve: {
+      taskName: '教务处sop_内审',
+      taskKey: 'f_usertask_jwc_inside_approve',
+      setup: 3,
+      formKey: 'inside_approve_3.form',
+      formProperty: [
+        {
+          id: 'XXX',
+          code: '', //code为空的话,则表示主控件没有,但是其他的:比如标题或者描述文字可能会有
+          binding: 'XXX',
+          title: '风险提示确认',
+          subTitle: [
+            { content: '请项目经理重点关注扫描风险点。例如:', color: 'gray' },
+            { content: '①答题卡印刷不规范;', color: 'gray' },
+            {
+              content: '②客观题填涂区域边界不清晰、线条不连贯;',
+              color: 'gray',
+            },
+            {
+              content:
+                '上述风险处置建议:请采用200DPI进行扫描,能很大程度改善客观题识别情况。',
+              color: 'blue',
+            },
+            {
+              content:
+                '注意:以上风险仅作项目经理预判风险的参考提示,并未穷尽全部风险点。若项目经理一旦发现其它风险点,例如非常规操作、印刷错误导致的连带风险点等,必须及时上报给实施部门负责人决策再处置。',
+              color: 'red',
+            },
+          ],
+        },
+        {
+          id: 'XXX',
+          binding: 'XXX',
+          code: 'RADIO',
+          title: '我已阅读风险提示内容,对风险点预判如下',
+          subTitle: [
+            {
+              content: '若预判有风险,则请简单填写预判的具体风险点',
+              color: 'blue',
+            },
+          ],
+          required: true,
+          options: [
+            { value: '1', label: '无风险' },
+            { value: '2', label: '其他' },
+          ],
+        },
+        {
+          id: 'XXX',
+          binding: 'XXX',
+          code: 'SIGN',
+          title: '手写签名',
+          required: true,
+        },
+        {
+          id: 'XXX',
+          binding: 'XXX',
+          code: 'TEXTAREA',
+          title: '审批意见',
+          required: true,
+        },
+        // {
+        //   id: '21',
+        //   code: 'LABEL',
+        //   type: 'FORM',
+        //   formId: 'f_usertask_jwc_inside_approve|risk_title',
+        //   formName: 'f_usertask_jwc_inside_approve|risk_title',
+        //   title: '风险提示确认',
+        //   inputType: 'STRING',
+        //   required: false,
+        //   readable: true,
+        //   writable: false,
+        //   visable: true,
+        //   value:
+        //     '请项目经理重点关注扫描风险点。例如:\n①答题卡印刷不规范;\n②客观题填涂区域边界不清晰、线条不连贯;\n上述风险处置建议:请采用200DP进行扫描,能很大程度改善容观题识别情况。\n注意:以上风险仅作项目经理预判风险的参考提示,并未安尽全部风险点。若项目经理一旦发现其亡风险点,例如非常规操作、印刷错误\n导致的连带风险点等,必须及时上报给实施部门负责人决策再处置。',
+        //   name: '标签',
+        // },
+        // {
+        //   id: '22',
+        //   code: 'LABEL',
+        //   type: 'FORM',
+        //   formId: 'f_usertask_jwc_inside_approve|risk_knowe_title',
+        //   formName: 'f_usertask_jwc_inside_approve|risk_knowe_title',
+        //   title: '我已阅读风险提示内容,对风险点预判如下:',
+        //   inputType: 'STRING',
+        //   required: true,
+        //   readable: true,
+        //   writable: false,
+        //   visable: true,
+        //   value: '若预判有风险,则请简要填写预判的具体风险点',
+        //   name: '标签',
+        // },
+        // {
+        //   id: '23',
+        //   code: 'RADIO',
+        //   type: 'FORM',
+        //   formId: 'f_usertask_jwc_inside_approve|risk_no',
+        //   formName: 'f_usertask_jwc_inside_approve|risk_no',
+        //   title: '无风险',
+        //   inputType: 'STRING',
+        //   required: true,
+        //   readable: false,
+        //   writable: true,
+        //   visable: true,
+        //   name: '单选框',
+        // },
+        // {
+        //   id: '24',
+        //   code: 'RADIO',
+        //   type: 'FORM',
+        //   formId: 'f_usertask_jwc_inside_approve|risk_other',
+        //   formName: 'f_usertask_jwc_inside_approve|risk_other',
+        //   title: '其他',
+        //   inputType: 'STRING',
+        //   required: true,
+        //   readable: false,
+        //   writable: true,
+        //   visable: true,
+        //   name: '单选框',
+        // },
+        // {
+        //   id: '25',
+        //   parentId: '24',
+        //   code: 'TEXTAREA',
+        //   type: 'FORM',
+        //   formId: 'f_usertask_jwc_inside_approve|risk_other_textarea',
+        //   formName: 'f_usertask_jwc_inside_approve|risk_other_textarea',
+        //   title: '其他风险文本域',
+        //   inputType: 'STRING',
+        //   required: false,
+        //   readable: false,
+        //   writable: true,
+        //   visable: false,
+        //   name: '文本域',
+        // },
+        // {
+        //   id: '26',
+        //   code: 'LABEL',
+        //   type: 'FORM',
+        //   formId: 'f_usertask_jwc_inside_approve|sign_label',
+        //   formName: 'f_usertask_jwc_inside_approve|sign_label',
+        //   title: '手写签名',
+        //   inputType: 'STRING',
+        //   required: true,
+        //   readable: true,
+        //   writable: false,
+        //   visable: true,
+        //   name: '标签',
+        // },
+        // {
+        //   id: '27',
+        //   code: 'SIGN',
+        //   type: 'FORM',
+        //   formId: 'f_usertask_jwc_inside_approve|sign',
+        //   formName: 'f_usertask_jwc_inside_approve|sign',
+        //   title: '添加签名',
+        //   inputType: 'STRING',
+        //   required: true,
+        //   readable: false,
+        //   writable: true,
+        //   visable: true,
+        //   name: '签名',
+        // },
+        // {
+        //   id: '28',
+        //   code: 'TEXTAREA',
+        //   type: 'FORM',
+        //   formId: 'f_usertask_jwc_inside_approve|approve_suggestion',
+        //   formName: 'f_usertask_jwc_inside_approve|approve_suggestion',
+        //   title: '审批意见',
+        //   inputType: 'STRING',
+        //   required: false,
+        //   readable: false,
+        //   writable: true,
+        //   visable: true,
+        //   name: '文本域',
+        // },
+      ],
+    },
+    // f_usertask_jwc_end: {
+    //   taskName: '结束',
+    //   taskKey: 'f_usertask_jwc_end',
+    //   setup: 0,
+    //   formKey: null,
+    //   formProperty: null,
+    // },
+    扫描仪出库登记: {
+      taskName: '扫描仪出库登记',
+      taskKey: '扫描仪出库登记',
+      formProperty: [
+        {
+          id: 'XXX',
+          binding: 'XXX',
+          code: 'RADIO',
+          title: '扫描仪出入库选择',
+          required: true,
+          options: [
+            { value: '1', label: '出库' },
+            { value: '2', label: '入库' },
+          ],
+        },
+        {
+          id: 'XXX',
+          binding: 'XXX',
+          code: 'DATE',
+          title: '设备出入库时间',
+          required: true,
+        },
+        {
+          id: 'XXX',
+          code: 'TABLE',
+          type: 'FORM',
+          formId: 'XXX',
+          formName: 'XXX',
+          title: '扫描仪设备出库登记',
+          required: true,
+          readable: false,
+          writable: true,
+          visable: true,
+          name: '表格',
+          tablePropList: [
+            {
+              id: 'XXX',
+              widgetId: 'XXX',
+              tdIndex: 1,
+              tdId: 'aaa',
+              tdName: 'aaa',
+              title: '设备编号',
+              tdOrder: true,
+              tdSearch: true,
+              editWidgetId: 'XXX',
+              tdFormWidget: {
+                code: 'TEXT',
+                name: '文本',
+              },
+            },
+            {
+              id: 'XXX',
+              widgetId: 'XXX',
+              tdIndex: 2,
+              tdId: 'bbb',
+              tdName: 'bbb',
+              title: '运行状态',
+              tdOrder: true,
+              tdSearch: true,
+              editWidgetId: 'XXX',
+              tdFormWidget: {
+                code: 'TEXT',
+                name: '文本',
+              },
+            },
+            {
+              id: 'XXX',
+              widgetId: 'XXX',
+              tdIndex: 3,
+              tdId: 'ccc',
+              tdName: 'ccc',
+              title: '总扫描量',
+              tdOrder: true,
+              tdSearch: true,
+              editWidgetId: 'XXX',
+              tdFormWidget: {
+                code: 'TEXT',
+                name: '文本',
+              },
+            },
+            {
+              id: 'XXX',
+              widgetId: 'XXX',
+              tdIndex: 1,
+              tdId: 'ddd',
+              tdName: 'ddd',
+              title: '当前所在地',
+              tdOrder: true,
+              tdSearch: true,
+              editWidgetId: 'XXX',
+              tdFormWidget: {
+                code: 'TEXT',
+                name: '文本',
+              },
+            },
+          ],
+        },
+      ],
+    },
+  },
+  version: 1,
+};