123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706 |
- import { CreateCrudOptionsProps, CreateCrudOptionsRet, AddReq, DelReq, EditReq, dict, compute } from '@fast-crud/fast-crud';
- import * as api from './api';
- import { dictionary } from '/@/utils/dictionary';
- import { successMessage, warningMessage } from '../../../utils/message';
- import { auth } from '/@/utils/authFunction';
- /* interface PositionContext {
- router: any;
- selectedRows: any[];
- openBatchTagsDialog: (selection: any[]) => void;
- } */
- /**
- *
- * @param crudExpose:index传递过来的示例
- * @param context:index传递过来的自定义参数
- * @returns
- */
- export const createCrudOptions = function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
- const pageRequest = async (query: any) => {
- return await api.GetList(query);
- };
- const editRequest = async ({ form, row }: EditReq) => {
- form.id = row.id;
- return await api.UpdateObj(form);
- };
- const delRequest = async ({ row }: DelReq) => {
- return await api.DelObj(row.id);
- };
- const addRequest = async ({ form }: AddReq) => {
- return await api.AddObj(form);
- };
- return {
- crudOptions: {
- toolbar:{
- buttons:{
- search:{show:false},
- // 刷新按钮
- refresh:{show:false},
- // 紧凑模式
- compact:{show:false},
- // 导出按钮
- export:{
- text: '导出',
- type: 'primary',
- size: 'small',
- icon: 'upload',
- circle: false,
- display: true,
- show:false
- },
- // 列设置按钮
- columns:{
- show:false
- },
- }
- },
- request: {
- pageRequest,
- addRequest,
- editRequest,
- delRequest,
- },
- pagination: {
- show: true,
- },
- search: {
- show: true,
- buttons: {
- search: {
- size: 'small',
- col:{ span:3},
- },
- reset: {
- size: 'small',
- col:{ span:3},
- },
- },
- },
- actionbar: {
- buttons: {
- add: {
- size: 'small',
- show: auth('role:Create'),
- click: () => {
- context.router.push('/position/create');
- }
- },
- // 添加批量绑定标签按钮
- batchBindTags: {
- text: '批量绑定标签',
- type: 'primary',
- size: 'small',
- show: false,
- order: 2,
- click: () => {
- // 使用存储的选中行
- const selection = context.selectedRows || [];
- console.log('选中的行:', selection);
-
- if (!selection || selection.length === 0) {
- warningMessage('请先选择要操作的职位');
- return;
- }
- console.log('context', context);
- // 打开批量绑定标签对话框
- context.openBatchTagsDialog(selection);
- },
- },
- //批量修改状态
- batchPublish: {
- text: '批量修改状态',
- type: 'primary',
- size: 'small',
- show: true,
- order: 3,
- click: () => {
- // 使用存储的选中行
- const selection = context.selectedRows || [];
- console.log('选中的行:', selection);
-
- if (!selection || selection.length === 0) {
- warningMessage('请先选择要操作的职位');
- return;
- }
-
- // 打开批量修改状态对话框
- context.openBatchStatusDialog(selection);
- },
- },
- // addDialog: {
- // text: '快速添加',
- // icon: 'Plus',
- // show: auth('role:Create'),
- // order: 2
- // },
- },
- },
- rowHandle: {
- //固定右侧
- fixed: 'right',
- width: 320,
- buttons: {
- view: {
- show: false,
- iconRight:"View",
- type:"text"
- },
- edit: {
- text: '查看',
- show: auth('role:Update'),
- iconRight:"Edit",
- type:"text",
- click: (ctx) => {
- context.router.push(`/position/detail?id=${ctx.row.id}`);
- }
- },
- remove: {
- show: auth('role:Delete'),
- iconRight:"Delete",
- type:"text"
- },
- qrcode: {
- text: '分享',
- type: "text",
- iconRight: 'Share',
- click: (ctx) => {
- context.generateQRCode(ctx.row);
- },
- order: 4
- },
- publish: {
- text: '发布',
- type: "text",
- iconRight: '',
- show:compute(({ row }) => {
- return row.status === 0; // 只在状态为"已面试"时显示
- }),
- click: (ctx) => {
- context.publishPosition(ctx.row);
- },
- },
- /* permission: {
- type: 'primary',
- text: '权限配置',
- show: auth('role:Permission'),
- click: (clickContext: any): void => {
- const { row } = clickContext;
- context.RoleDrawer.handleDrawerOpen(row);
- context.RoleMenuBtn.setState([]);
- context.RoleMenuField.setState([]);
- },
- }, */
- },
- },
- form: {
- col: { span: 24 },
- labelWidth: '100px',
- wrapper: {
- is: 'el-dialog',
- width: '600px',
- },
- },
- table: {
- remove: {
- confirmMessage: '确定要删除这个职位吗?删除后无法恢复!',
- },
- onSelectionChange: (selection: any[]) => {
- context.selectedRows = selection;
- console.log('选择变化:', selection);
- }
- },
- columns: {
- _selection: {
- title: '选择',
- form: { show: false },
- column: {
- type: 'selection',
- align: 'center',
- width: 50,
- fixed: 'left',
- columnSetDisabled: true,
- },
- },
- /* _index: {
- title: '序号',
- form: { show: false },
- column: {
- type: 'index',
- align: 'center',
- width: '70px',
- columnSetDisabled: true, //禁止在列设置中选择
- },
- }, */
- id: {
- title: 'ID',
- column: { show: false },
- search: { show: false
- },
- form: { show: false },
- },
- title: {
- title: '职位名称',
- search: {
- show: true,
- size: 'small',
- col:{ span:3},
- },
- column: {
- minWidth: 120,
- sortable: 'custom',
- },
- form: {
- rules: [{ required: true, message: '角色名称必填' }],
- component: {
- placeholder: '请输入角色名称',
- },
- },
- },
- /* key: {
- title: '权限标识',
- search: { show: false },
- column: {
- minWidth: 120,
- sortable: 'custom',
- columnSetDisabled: true,
- },
- form: {
- rules: [{ required: true, message: '权限标识必填' }],
- component: {
- placeholder: '输入权限标识',
- },
- },
- valueBuilder(context) {
- const { row, key } = context;
- return row[key];
- },
- },
- sort: {
- title: '排序',
- search: { show: false },
- type: 'number',
- column: {
- minWidth: 90,
- sortable: 'custom',
- },
- form: {
- rules: [{ required: true, message: '排序必填' }],
- value: 1,
- },
- },*/
- job_type: {
- title: '职位类型',
- search: { show: true,
- size: 'small',
- col:{ span:3},
- },
- type: 'dict-select',
- column: {
- width: 100,
- },
- dict: dict({
- data: [
- { value:0, label: '全职' },
- { value:1, label: '兼职' },
- { value: 2, label: '实习' },
- { value: 3, label: "其他" }
- ]
- }),
- form: {
- rules: [{ required: true, message: '职位类型必填' }],
- component: {
- placeholder: '职位类型',
- },
- },
- },
- competency_tags: {
- title: '胜任力标签',
- search: {
- show: true,
- size: 'small',
- col: { span: 3 },
- component: {
- props: {
- multiple: false, // 在搜索表单中使用单选模式
- filterable: true,
- }
- },
- },
- type: 'dict-select',
- column: {
- show: false,
- minWidth: 180,
- component: {
- // 自定义渲染组件,显示彩色标签
- name: 'fs-component',
- render: ({ row }: { row: any }) => {
- if (!row.competency_tags || row.competency_tags.length === 0) return <span>-</span>;
-
- const displayTags = row.competency_tags.slice(0, 2); // 只取前两个标签
- const remainingCount = row.competency_tags.length - 2; // 计算剩余标签数量
-
- return (
- <div style="display: flex; gap: 4px; align-items: center;">
- {displayTags.map((tag: any) => (
- <el-tag
- key={tag.id}
- type="warning"
- effect="plain"
- size="mini"
- style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap;"
- title={tag.name}
- >
- {tag.name.length > 4 ? tag.name.slice(0, 4) + '...' : tag.name}
- </el-tag>
- ))}
- {remainingCount > 0 && (
- <el-tooltip
- placement="top"
- effect="light"
- popper-class="tag-tooltip"
- >
- {{
- default: () => (
- <el-tag
- type="info"
- effect="plain"
- size="mini"
- >
- +{remainingCount}
- </el-tag>
- ),
- content: () => (
- <div>
- <div style="font-weight: bold; margin-bottom: 5px">剩余{remainingCount}个标签:</div>
- {row.competency_tags.slice(2).map((tag: any) => (
- <div key={tag.id} style="margin: 3px 0">{tag.name}</div>
- ))}
- </div>
- )
- }}
- </el-tooltip>
- )}
- </div>
- );
- }
- }
- },
- dict: dict({
- getData: async () => {
- const res = await api.GetCompetencyList({page:1, limit:30, tenant_id:1});
- return res.data.items;
- },
- label: 'name',
- value: 'id'
- }),
- form: {
- rules: [{ required: true, message: '胜任力标签必填' }],
- },
- },
- salary_range: {
- title: '薪资范围',
- search: { show: false,
- size: 'small',
- col:{ span:3},
- },
- column: {
- minWidth: 100,
- },
- form: {
- rules: [{ required: true, message: '薪资范围必填' }],
- component: {
- placeholder: '请输入薪资范围',
- },
- },
- },
- location: {
- title: '工作地点',
- search: {
- type: 'input',
- show: true,
- size: 'small',
- col:{ span:3},
- },
- column: {
- minWidth: 120,
- formatter: ({ row }) => {
- if (typeof row.location === 'string' && row.location.startsWith('[')) {
- try {
- // 解析字符串形式的数组
- const locationArray = JSON.parse(row.location.replace(/'/g, '"'));
- return locationArray.join(' ');
- } catch (e) {
- console.error('解析location失败:', e);
- return row.location;
- }
- }
- if (Array.isArray(row.location)) {
- return row.location.join(' ');
- }
- if (row.province && row.city) {
- return row.province + ' ' + row.city + (row.district ? ' ' + row.district : '');
- }
- return row.location || '';
- }
- },
- form: {
- component: {
- name: 'el-input',
- props: {
- options: [
- {
- value: '上海市',
- label: '上海市',
- children: [
- {
- value: '浦东新区',
- label: '浦东新区',
- children: [
- { value: '张江', label: '张江' },
- { value: '金桥', label: '金桥' },
- { value: '陆家嘴', label: '陆家嘴' }
- ]
- },
- {
- value: '徐汇区',
- label: '徐汇区',
- children: [
- { value: '漕河泾', label: '漕河泾' },
- { value: '徐家汇', label: '徐家汇' }
- ]
- },
- // 其他区域...
- ]
- },
- {
- value: '北京市',
- label: '北京市',
- children: [
- {
- value: '海淀区',
- label: '海淀区',
- children: [
- { value: '中关村', label: '中关村' },
- { value: '上地', label: '上地' }
- ]
- },
- {
- value: '朝阳区',
- label: '朝阳区',
- children: [
- { value: 'CBD', label: 'CBD' },
- { value: '望京', label: '望京' }
- ]
- },
- // 其他区域...
- ]
- },
- // 其他省市...
- ],
- props: {
- expandTrigger: 'hover',
- checkStrictly: false
- },
- placeholder: '请选择工作地点',
- clearable: true,
- showAllLevels: true
- },
- on: {
- change: (value) => {
- console.log('地址选择变化:', value);
- }
- }
- },
- valueResolve: (form: any) => {
- if (form.location && Array.isArray(form.location) && form.location.length > 0) {
- form.province = form.location[0];
- form.city = form.location[1] || '';
- form.district = form.location[2] || '';
- form.location = form.location.join(' ');
- }
- },
- valueBuilder: (form: any) => {
- if (form.province && form.city) {
- form.location = [form.province, form.city];
- if (form.district) {
- form.location.push(form.district);
- }
- } else if (typeof form.location === 'string' && form.location) {
- const parts = form.location.split(' ');
- if (parts.length > 0) {
- form.location = parts;
- }
- }
- }
- },
- },
- department: {
- title: '所属部门',
- search: { show: false,
- size: 'small',
- col:{ span:3},
- },
- column: {
- minWidth: 100,
- },
- form: {
- rules: [{ required: true, message: '所属部门必填' }],
- component: {
- placeholder: '请输入所属部门',
- },
- },
- },
- status: {
- title: '状态',
- search: { show: true,
- size: 'small',
- col:{ span:3},
- },
- type: 'dict-select',
- column: {
- minWidth: 100,
- },
- dict: dict({
- data: [
- { value: 0, label: '未发布' },
- { value: 1, label: '已发布' },
- { value: 2, label: '已过期' }
- ]
- }),
- form: {
- rules: [{ required: true, message: '职位类型必填' }],
- },
- },
- end_date: {
- title: '截止日期',
- type: 'datetime',
- search: { show: true,
- size: 'small',
- col:{ span:3},
- },
- column: {
- show: false,
- minWidth: 150,
- sortable: 'custom',
- },
- form: {
- rules: [{ required: true, message: '截止日期必填' }],
- component: {
- type: 'datetime',
- valueFormat: 'YYYY-MM-DD HH:mm:ss',
- placeholder: '请选择截止日期',
- },
- },
- },
- requirements: {
- title: '职位要求',
- search: { show: false,
- size: 'small',
- col:{ span:3},
- },
- column: {
- show: false,
- showOverflowTooltip: true,
- width: 120,
- sortable: 'custom',
- /* minWidth: 120, */
- formatter: ({ row }) => {
- // 创建一个临时元素来解析HTML
- const div = document.createElement('div');
- div.innerHTML = row.requirements || '';
- // 返回纯文本内容
- return div.textContent || div.innerText || '';
- }
- },
- form: {
- component: {
- type: 'textarea',
- rows: 4,
- },
- },
- },
- description: {
- title: '职位描述',
- search: { show: false },
- column: {
- show: false,
- showOverflowTooltip: true,
- width: 120,
- sortable: 'custom',
- /* minWidth: 120, */
- formatter: ({ row }) => {
- const div = document.createElement('div');
- div.innerHTML = row.description || '';
- return div.textContent || div.innerText || '';
- }
- },
- form: {
- component: {
- type: 'textarea',
- rows: 4,
- },
- },
- },
- province: {
- title: '省份',
- column: { show: false },
- form: { show: false }
- },
- city: {
- title: '城市',
- column: { show: false },
- form: { show: false }
- },
- district: {
- title: '区域',
- column: { show: false },
- form: { show: false }
- },
- },
- },
- };
- };
- export const useBatchUpdateTags = (crudExpose: any) => {
- const batchUpdateTags = async (questionIds: number[], tagIds: number[]) => {
- try {
- const res = await api.BatchUpdateTags({
- position_ids: questionIds,
- tag_ids: tagIds,
- tenant_id: 1
- });
- if (res.code === 2000) {
- successMessage('批量更新标签成功');
- // 刷新列表
- crudExpose.doRefresh();
- }
- } catch (error) {
- console.error('批量更新标签失败', error);
- }
- };
-
- return { batchUpdateTags };
- };
- export const useBatchUpdateStatus = (crudExpose: any) => {
- const batchUpdateStatus = async (jobIds: number[], status: number) => {
- try {
- const res = await api.batch_publish({
- job_ids: jobIds,
- status: status,
- tenant_id: 1
- });
- if (res.code === 2000) {
- successMessage('批量修改状态成功');
- // 刷新列表
- crudExpose.doRefresh();
- }
- } catch (error) {
- console.error('批量修改状态失败', error);
- }
- };
-
- return { batchUpdateStatus };
- };
|